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 AddrSpace2PointerActions[OpcodeIdx].end()) {
315 ? AddrSpace2PointerActions[OpcodeIdx]
318 : ScalarActions[OpcodeIdx];
319 if (Aspect.
Idx >= Actions.
size())
331std::pair<LegacyLegalizeAction, LLT>
332LegacyLegalizerInfo::findVectorLegalAction(
const InstrAspect &Aspect)
const {
339 const unsigned TypeIdx = Aspect.
Idx;
340 if (TypeIdx >= ScalarInVectorActions[OpcodeIdx].
size())
343 ScalarInVectorActions[OpcodeIdx][TypeIdx];
345 LLT IntermediateType;
346 auto ElementSizeAndAction =
349 ElementSizeAndAction.first);
350 if (ElementSizeAndAction.second !=
Legal)
351 return {ElementSizeAndAction.second, IntermediateType};
353 auto i = NumElements2Actions[OpcodeIdx].find(
355 if (i == NumElements2Actions[OpcodeIdx].
end()) {
356 return {
NotFound, IntermediateType};
359 auto NumElementsAndAction =
361 return {NumElementsAndAction.second,
367 assert(Opcode >= FirstOp && Opcode <= LastOp &&
"Unsupported opcode");
368 return Opcode - FirstOp;
374 for (
unsigned i = 0; i < Query.
Types.size(); ++i) {
375 auto Action = getAspectAction({Query.
Opcode, i, Query.
Types[i]});
376 if (Action.first !=
Legal) {
378 << Action.first <<
", " << Action.second <<
"\n");
379 return {Action.first, i, Action.second};
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)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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 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...
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)
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...
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 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
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
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.
const_iterator end(StringRef path)
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)
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...