LLVM: lib/CodeGen/GlobalISel/LegacyLegalizerInfo.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
21#include
22
23using namespace llvm;
25
26#define DEBUG_TYPE "legalizer-info"
27
29 switch (Action) {
31 OS << "Legal";
32 break;
34 OS << "NarrowScalar";
35 break;
37 OS << "WidenScalar";
38 break;
40 OS << "FewerElements";
41 break;
43 OS << "MoreElements";
44 break;
46 OS << "Bitcast";
47 break;
49 OS << "Lower";
50 break;
52 OS << "Libcall";
53 break;
55 OS << "Custom";
56 break;
58 OS << "Unsupported";
59 break;
61 OS << "NotFound";
62 break;
63 }
64 return OS;
65}
66
68
69
70
71 setScalarAction(TargetOpcode::G_ANYEXT, 1, {{1, Legal}});
72 setScalarAction(TargetOpcode::G_ZEXT, 1, {{1, Legal}});
73 setScalarAction(TargetOpcode::G_SEXT, 1, {{1, Legal}});
74 setScalarAction(TargetOpcode::G_TRUNC, 0, {{1, Legal}});
75 setScalarAction(TargetOpcode::G_TRUNC, 1, {{1, Legal}});
76
77 setScalarAction(TargetOpcode::G_INTRINSIC, 0, {{1, Legal}});
78 setScalarAction(TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS, 0, {{1, Legal}});
79 setScalarAction(TargetOpcode::G_INTRINSIC_CONVERGENT, 0, {{1, Legal}});
80 setScalarAction(TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS, 0,
82
93
102 setScalarAction(TargetOpcode::G_FNEG, 0, {{1, Lower}});
103}
104
106 assert(TablesInitialized == false);
107
108 for (unsigned OpcodeIdx = 0; OpcodeIdx <= LastOp - FirstOp; ++OpcodeIdx) {
109 const unsigned Opcode = FirstOp + OpcodeIdx;
110 for (unsigned TypeIdx = 0; TypeIdx != SpecifiedActions[OpcodeIdx].size();
111 ++TypeIdx) {
112
113
114
116
117 std::map<uint16_t, SizeAndActionsVec> AddressSpace2SpecifiedActions;
118
119 std::map<uint16_t, SizeAndActionsVec> ElemSize2SpecifiedActions;
120 for (auto LLT2Action : SpecifiedActions[OpcodeIdx][TypeIdx]) {
121 const LLT Type = LLT2Action.first;
123
124 auto SizeAction = std::make_pair(Type.getSizeInBits(), Action);
125 if (Type.isPointer())
126 AddressSpace2SpecifiedActions[Type.getAddressSpace()].push_back(
127 SizeAction);
128 else if (Type.isVector())
129 ElemSize2SpecifiedActions[Type.getElementType().getSizeInBits()]
130 .push_back(SizeAction);
131 else
132 ScalarSpecifiedActions.push_back(SizeAction);
133 }
134
135
136 {
137
138
140 if (TypeIdx < ScalarSizeChangeStrategies[OpcodeIdx].size() &&
141 ScalarSizeChangeStrategies[OpcodeIdx][TypeIdx] != nullptr)
142 S = ScalarSizeChangeStrategies[OpcodeIdx][TypeIdx];
144 checkPartialSizeAndActionsVector(ScalarSpecifiedActions);
145 setScalarAction(Opcode, TypeIdx, S(ScalarSpecifiedActions));
146 }
147
148
149 for (auto PointerSpecifiedActions : AddressSpace2SpecifiedActions) {
150 llvm::sort(PointerSpecifiedActions.second);
151 checkPartialSizeAndActionsVector(PointerSpecifiedActions.second);
152
153
154 setPointerAction(
155 Opcode, TypeIdx, PointerSpecifiedActions.first,
157 }
158
159
161 for (auto VectorSpecifiedActions : ElemSize2SpecifiedActions) {
162 llvm::sort(VectorSpecifiedActions.second);
163 const uint16_t ElementSize = VectorSpecifiedActions.first;
164 ElementSizesSeen.push_back({ElementSize, Legal});
165 checkPartialSizeAndActionsVector(VectorSpecifiedActions.second);
166
167
168
169
171 for (SizeAndAction BitsizeAndAction : VectorSpecifiedActions.second) {
172 assert(BitsizeAndAction.first % ElementSize == 0);
173 const uint16_t NumElements = BitsizeAndAction.first / ElementSize;
174 NumElementsActions.push_back({NumElements, BitsizeAndAction.second});
175 }
176 setVectorNumElementAction(
177 Opcode, TypeIdx, ElementSize,
179 }
183 if (TypeIdx < VectorElementSizeChangeStrategies[OpcodeIdx].size() &&
184 VectorElementSizeChangeStrategies[OpcodeIdx][TypeIdx] != nullptr)
185 VectorElementSizeChangeStrategy =
186 VectorElementSizeChangeStrategies[OpcodeIdx][TypeIdx];
187 setScalarInVectorAction(
188 Opcode, TypeIdx, VectorElementSizeChangeStrategy(ElementSizesSeen));
189 }
190 }
191
192 TablesInitialized = true;
193}
194
195
196
197
198
199std::pair<LegacyLegalizeAction, LLT>
200LegacyLegalizerInfo::getAspectAction(const InstrAspect &Aspect) const {
201 assert(TablesInitialized && "backend forgot to call computeTables");
202
203
205 return findScalarLegalAction(Aspect);
207 return findVectorLegalAction(Aspect);
208}
209
215 unsigned LargestSizeSoFar = 0;
216 if (v.size() >= 1 && v[0].first != 1)
217 result.push_back({1, IncreaseAction});
218 for (size_t i = 0; i < v.size(); ++i) {
219 result.push_back(v[i]);
220 LargestSizeSoFar = v[i].first;
221 if (i + 1 < v.size() && v[i + 1].first != v[i].first + 1) {
222 result.push_back({LargestSizeSoFar + 1, IncreaseAction});
223 LargestSizeSoFar = v[i].first + 1;
224 }
225 }
226 result.push_back({LargestSizeSoFar + 1, DecreaseAction});
227 return result;
228}
229
235 if (v.size() == 0 || v[0].first != 1)
236 result.push_back({1, IncreaseAction});
237 for (size_t i = 0; i < v.size(); ++i) {
238 result.push_back(v[i]);
239 if (i + 1 == v.size() || v[i + 1].first != v[i].first + 1) {
240 result.push_back({v[i].first + 1, DecreaseAction});
241 }
242 }
243 return result;
244}
245
247LegacyLegalizerInfo::findAction(const SizeAndActionsVec &Vec, const uint32_t Size) {
249
250
251
254 assert(It != Vec.begin() && "Does Vec not start with size 1?");
255 int VecIdx = It - Vec.begin() - 1;
256
258 switch (Action) {
264 return {Size, Action};
266
267
270 [[fallthrough]];
272
273
274
275
276
277
278
279 for (int i = VecIdx - 1; i >= 0; --i)
282 return {Vec[i].first, Action};
284 }
287
288 for (std::size_t i = VecIdx + 1; i < Vec.size(); ++i)
291 return {Vec[i].first, Action};
293 }
298 }
300}
301
302std::pair<LegacyLegalizeAction, LLT>
303LegacyLegalizerInfo::findScalarLegalAction(const InstrAspect &Aspect) const {
305 if (Aspect.Opcode < FirstOp || Aspect.Opcode > LastOp)
310 auto &PA = AddrSpace2PointerActions[OpcodeIdx];
312 if (It == PA.end())
314 Actions = It->second;
315 } else {
316 Actions = ScalarActions[OpcodeIdx];
317 }
318 if (Aspect.Idx >= Actions.size())
321
322
328}
329
330std::pair<LegacyLegalizeAction, LLT>
331LegacyLegalizerInfo::findVectorLegalAction(const InstrAspect &Aspect) const {
333
334
335 if (Aspect.Opcode < FirstOp || Aspect.Opcode > LastOp)
338 const unsigned TypeIdx = Aspect.Idx;
339 if (TypeIdx >= ScalarInVectorActions[OpcodeIdx].size())
342 ScalarInVectorActions[OpcodeIdx][TypeIdx];
343
344 LLT IntermediateType;
345 auto ElementSizeAndAction =
348 ElementSizeAndAction.first);
349 if (ElementSizeAndAction.second != Legal)
350 return {ElementSizeAndAction.second, IntermediateType};
351
352 auto i = NumElements2Actions[OpcodeIdx].find(
354 if (i == NumElements2Actions[OpcodeIdx].end()) {
355 return {NotFound, IntermediateType};
356 }
358 auto NumElementsAndAction =
359 findAction(NumElementsVec, IntermediateType.getNumElements());
360 return {NumElementsAndAction.second,
363}
364
366 assert(Opcode >= FirstOp && Opcode <= LastOp && "Unsupported opcode");
367 return Opcode - FirstOp;
368}
369
370
373 for (unsigned i = 0; i < Query.Types.size(); ++i) {
374 auto Action = getAspectAction({Query.Opcode, i, Query.Types[i]});
375 if (Action.first != Legal) {
376 LLVM_DEBUG(dbgs() << ".. (legacy) Type " << i << " Action="
377 << Action.first << ", " << Action.second << "\n");
378 return {Action.first, i, Action.second};
379 } else
380 LLVM_DEBUG(dbgs() << ".. (legacy) Type " << i << " Legal\n");
381 }
384}
385
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
Interface for Targets to specify which operations they can successfully select and how the others sho...
Interface for Targets to specify which operations they can successfully select and how the others sho...
static unsigned getAddressSpace(const Value *V, unsigned MaxLookup)
size_t size() const
size - Get the array size.
constexpr unsigned getScalarSizeInBits() const
constexpr bool isScalar() const
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr uint16_t getNumElements() const
Returns the number of elements in a vector LLT.
constexpr bool isVector() const
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
constexpr bool isPointer() const
constexpr unsigned getAddressSpace() const
static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
std::function< SizeAndActionsVec(const SizeAndActionsVec &v)> SizeChangeStrategy
static LLVM_ABI SizeAndActionsVec decreaseToSmallerTypesAndIncreaseToSmallest(const SizeAndActionsVec &v, LegacyLegalizeActions::LegacyLegalizeAction DecreaseAction, LegacyLegalizeActions::LegacyLegalizeAction IncreaseAction)
Helper function to implement many typical SizeChangeStrategy functions.
Definition LegacyLegalizerInfo.cpp:231
static SizeAndActionsVec widenToLargerTypesUnsupportedOtherwise(const SizeAndActionsVec &v)
static SizeAndActionsVec moreToWiderTypesAndLessToWidest(const SizeAndActionsVec &v)
A SizeChangeStrategy for the common case where legalization for a particular vector operation consist...
LLVM_ABI void computeTables()
Compute any ancillary tables needed to quickly decide how an operation should be handled.
Definition LegacyLegalizerInfo.cpp:105
std::vector< SizeAndAction > SizeAndActionsVec
static bool needsLegalizingToDifferentSize(const LegacyLegalizeActions::LegacyLegalizeAction Action)
LLVM_ABI unsigned getOpcodeIdxForOpcode(unsigned Opcode) const
Definition LegacyLegalizerInfo.cpp:365
static SizeAndActionsVec widenToLargerTypesAndNarrowToLargest(const SizeAndActionsVec &v)
A SizeChangeStrategy for the common case where legalization for a particular operation consists of wi...
LLVM_ABI LegacyLegalizeActionStep getAction(const LegalityQuery &Query) const
Definition LegacyLegalizerInfo.cpp:372
void setLegalizeScalarToDifferentSizeStrategy(const unsigned Opcode, const unsigned TypeIdx, SizeChangeStrategy S)
The setAction calls record the non-size-changing legalization actions to take on specificly-sized typ...
std::pair< uint16_t, LegacyLegalizeActions::LegacyLegalizeAction > SizeAndAction
static SizeAndActionsVec unsupportedForDifferentSizes(const SizeAndActionsVec &v)
A SizeChangeStrategy for the common case where legalization for a particular operation consists of on...
static LLVM_ABI SizeAndActionsVec increaseToLargerTypesAndDecreaseToLargest(const SizeAndActionsVec &v, LegacyLegalizeActions::LegacyLegalizeAction IncreaseAction, LegacyLegalizeActions::LegacyLegalizeAction DecreaseAction)
Helper function to implement many typical SizeChangeStrategy functions.
Definition LegacyLegalizerInfo.cpp:211
static SizeAndActionsVec narrowToSmallerAndUnsupportedIfTooSmall(const SizeAndActionsVec &v)
LLVM_ABI LegacyLegalizerInfo()
Definition LegacyLegalizerInfo.cpp:67
The instances of the Type class are immutable: once they are created, they are never changed.
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ Bitcast
Perform the operation on a different, but equivalently sized type.
@ MoreElements
The (vector) operation should be implemented by widening the input vector and ignoring the lanes adde...
@ FewerElements
The (vector) operation should be implemented by splitting it into sub-vectors where the operation is ...
@ Unsupported
This operation is completely unsupported on the target.
@ NarrowScalar
The operation should be synthesized from multiple instructions acting on a narrower scalar base-type.
@ Lower
The operation itself must be expressed in terms of simpler actions on this target.
@ Custom
The target wants to do something special with this combination of operand and type.
@ NotFound
Sentinel value for when no action was found in the specified table.
@ WidenScalar
The operation should be implemented in terms of a wider scalar base-type.
@ Libcall
The operation should be implemented as a call to some kind of runtime support library.
This is an optimization pass for GlobalISel generic memory operations.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
auto partition_point(R &&Range, Predicate P)
Binary search for the first iterator in a range where a predicate is false.
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
ArrayRef(const T &OneElt) -> ArrayRef< T >
Legalization is decided based on an instruction's opcode, which type slot we're considering,...
The LegalityQuery object bundles together all the information that's needed to decide whether a given...