24using namespace LegacyLegalizeActions;
26#define DEBUG_TYPE "legalizer-info"
40 OS <<
"FewerElements";
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}});
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,
102 setScalarAction(TargetOpcode::G_FNEG, 0, {{1,
Lower}});
106 assert(TablesInitialized ==
false);
108 for (
unsigned OpcodeIdx = 0; OpcodeIdx <= LastOp - FirstOp; ++OpcodeIdx) {
109 const unsigned Opcode = FirstOp + OpcodeIdx;
110 for (
unsigned TypeIdx = 0; TypeIdx != SpecifiedActions[OpcodeIdx].size();
117 std::map<uint16_t, SizeAndActionsVec> AddressSpace2SpecifiedActions;
119 std::map<uint16_t, SizeAndActionsVec> ElemSize2SpecifiedActions;
120 for (
auto LLT2Action : SpecifiedActions[OpcodeIdx][TypeIdx]) {
121 const LLT Type = LLT2Action.first;
124 auto SizeAction = std::make_pair(
Type.getSizeInBits(), Action);
125 if (
Type.isPointer())
126 AddressSpace2SpecifiedActions[
Type.getAddressSpace()].push_back(
128 else if (
Type.isVector())
129 ElemSize2SpecifiedActions[
Type.getElementType().getSizeInBits()]
130 .push_back(SizeAction);
132 ScalarSpecifiedActions.push_back(SizeAction);
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));
149 for (
auto PointerSpecifiedActions : AddressSpace2SpecifiedActions) {
151 checkPartialSizeAndActionsVector(PointerSpecifiedActions.second);
155 Opcode, TypeIdx, PointerSpecifiedActions.first,
161 for (
auto VectorSpecifiedActions : ElemSize2SpecifiedActions) {
163 const uint16_t ElementSize = VectorSpecifiedActions.first;
164 ElementSizesSeen.push_back({ElementSize,
Legal});
165 checkPartialSizeAndActionsVector(VectorSpecifiedActions.second);
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});
176 setVectorNumElementAction(
177 Opcode, TypeIdx, ElementSize,
183 if (TypeIdx < VectorElementSizeChangeStrategies[OpcodeIdx].
size() &&
184 VectorElementSizeChangeStrategies[OpcodeIdx][TypeIdx] !=
nullptr)
185 VectorElementSizeChangeStrategy =
186 VectorElementSizeChangeStrategies[OpcodeIdx][TypeIdx];
187 setScalarInVectorAction(
188 Opcode, TypeIdx, VectorElementSizeChangeStrategy(ElementSizesSeen));
192 TablesInitialized =
true;
199std::pair<LegacyLegalizeAction, LLT>
200LegacyLegalizerInfo::getAspectAction(
const InstrAspect &Aspect)
const {
201 assert(TablesInitialized &&
"backend forgot to call computeTables");
205 return findScalarLegalAction(Aspect);
207 return findVectorLegalAction(Aspect);
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;
226 result.push_back({LargestSizeSoFar + 1, DecreaseAction});
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});
247LegacyLegalizerInfo::findAction(
const SizeAndActionsVec &Vec,
const uint32_t Size) {
254 assert(It != Vec.begin() &&
"Does Vec not start with size 1?");
255 int VecIdx = It - Vec.begin() - 1;
264 return {
Size, Action};
279 for (
int i = VecIdx - 1; i >= 0; --i)
282 return {Vec[i].first, Action};
288 for (std::size_t i = VecIdx + 1; i < Vec.size(); ++i)
291 return {Vec[i].first, Action};
302std::pair<LegacyLegalizeAction, LLT>
303LegacyLegalizerInfo::findScalarLegalAction(
const InstrAspect &Aspect)
const {
310 auto &PA = AddrSpace2PointerActions[OpcodeIdx];
314 Actions = It->second;
316 Actions = ScalarActions[OpcodeIdx];
318 if (Aspect.
Idx >= Actions.
size())
330std::pair<LegacyLegalizeAction, LLT>
331LegacyLegalizerInfo::findVectorLegalAction(
const InstrAspect &Aspect)
const {
338 const unsigned TypeIdx = Aspect.
Idx;
339 if (TypeIdx >= ScalarInVectorActions[OpcodeIdx].
size())
342 ScalarInVectorActions[OpcodeIdx][TypeIdx];
344 LLT IntermediateType;
345 auto ElementSizeAndAction =
348 ElementSizeAndAction.first);
349 if (ElementSizeAndAction.second !=
Legal)
350 return {ElementSizeAndAction.second, IntermediateType};
352 auto i = NumElements2Actions[OpcodeIdx].find(
354 if (i == NumElements2Actions[OpcodeIdx].
end()) {
355 return {
NotFound, IntermediateType};
358 auto NumElementsAndAction =
360 return {NumElementsAndAction.second,
366 assert(Opcode >= FirstOp && Opcode <= LastOp &&
"Unsupported opcode");
367 return Opcode - FirstOp;
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) {
377 << Action.first <<
", " << Action.second <<
"\n");
378 return {Action.first, i, Action.second};
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)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
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::pair< uint16_t, LegacyLegalizeActions::LegacyLegalizeAction > SizeAndAction
static LLVM_ABI SizeAndActionsVec decreaseToSmallerTypesAndIncreaseToSmallest(const SizeAndActionsVec &v, LegacyLegalizeActions::LegacyLegalizeAction DecreaseAction, LegacyLegalizeActions::LegacyLegalizeAction IncreaseAction)
Helper function to implement many typical SizeChangeStrategy functions.
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.
std::vector< SizeAndAction > SizeAndActionsVec
static bool needsLegalizingToDifferentSize(const LegacyLegalizeActions::LegacyLegalizeAction Action)
LLVM_ABI unsigned getOpcodeIdxForOpcode(unsigned Opcode) const
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
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...
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.
static SizeAndActionsVec narrowToSmallerAndUnsupportedIfTooSmall(const SizeAndActionsVec &v)
std::function< SizeAndActionsVec(const SizeAndActionsVec &v)> SizeChangeStrategy
LLVM_ABI LegacyLegalizerInfo()
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.
LLVM_ABI const_iterator end(StringRef path LLVM_LIFETIME_BOUND)
Get end iterator over path.
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)
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...