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}});
99 setScalarAction(TargetOpcode::G_FNEG, 0, {{1,
Lower}});
103 assert(TablesInitialized ==
false);
105 for (
unsigned OpcodeIdx = 0; OpcodeIdx <= LastOp - FirstOp; ++OpcodeIdx) {
106 const unsigned Opcode = FirstOp + OpcodeIdx;
107 for (
unsigned TypeIdx = 0; TypeIdx != SpecifiedActions[OpcodeIdx].size();
114 std::map<uint16_t, SizeAndActionsVec> AddressSpace2SpecifiedActions;
116 std::map<uint16_t, SizeAndActionsVec> ElemSize2SpecifiedActions;
117 for (
auto LLT2Action : SpecifiedActions[OpcodeIdx][TypeIdx]) {
118 const LLT Type = LLT2Action.first;
121 auto SizeAction = std::make_pair(
Type.getSizeInBits(), Action);
122 if (
Type.isPointer())
123 AddressSpace2SpecifiedActions[
Type.getAddressSpace()].push_back(
125 else if (
Type.isVector())
126 ElemSize2SpecifiedActions[
Type.getElementType().getSizeInBits()]
127 .push_back(SizeAction);
129 ScalarSpecifiedActions.push_back(SizeAction);
137 if (TypeIdx < ScalarSizeChangeStrategies[OpcodeIdx].
size() &&
138 ScalarSizeChangeStrategies[OpcodeIdx][TypeIdx] !=
nullptr)
139 S = ScalarSizeChangeStrategies[OpcodeIdx][TypeIdx];
141 checkPartialSizeAndActionsVector(ScalarSpecifiedActions);
142 setScalarAction(Opcode, TypeIdx, S(ScalarSpecifiedActions));
146 for (
auto PointerSpecifiedActions : AddressSpace2SpecifiedActions) {
148 checkPartialSizeAndActionsVector(PointerSpecifiedActions.second);
152 Opcode, TypeIdx, PointerSpecifiedActions.first,
158 for (
auto VectorSpecifiedActions : ElemSize2SpecifiedActions) {
160 const uint16_t ElementSize = VectorSpecifiedActions.first;
161 ElementSizesSeen.push_back({ElementSize,
Legal});
162 checkPartialSizeAndActionsVector(VectorSpecifiedActions.second);
168 for (
SizeAndAction BitsizeAndAction : VectorSpecifiedActions.second) {
169 assert(BitsizeAndAction.first % ElementSize == 0);
170 const uint16_t NumElements = BitsizeAndAction.first / ElementSize;
171 NumElementsActions.push_back({NumElements, BitsizeAndAction.second});
173 setVectorNumElementAction(
174 Opcode, TypeIdx, ElementSize,
180 if (TypeIdx < VectorElementSizeChangeStrategies[OpcodeIdx].
size() &&
181 VectorElementSizeChangeStrategies[OpcodeIdx][TypeIdx] !=
nullptr)
182 VectorElementSizeChangeStrategy =
183 VectorElementSizeChangeStrategies[OpcodeIdx][TypeIdx];
184 setScalarInVectorAction(
185 Opcode, TypeIdx, VectorElementSizeChangeStrategy(ElementSizesSeen));
189 TablesInitialized =
true;
196std::pair<LegacyLegalizeAction, LLT>
197LegacyLegalizerInfo::getAspectAction(
const InstrAspect &Aspect)
const {
198 assert(TablesInitialized &&
"backend forgot to call computeTables");
202 return findScalarLegalAction(Aspect);
204 return findVectorLegalAction(Aspect);
212 unsigned LargestSizeSoFar = 0;
213 if (v.size() >= 1 && v[0].first != 1)
214 result.push_back({1, IncreaseAction});
215 for (
size_t i = 0; i < v.size(); ++i) {
216 result.push_back(v[i]);
217 LargestSizeSoFar = v[i].first;
218 if (i + 1 < v.size() && v[i + 1].first != v[i].first + 1) {
219 result.push_back({LargestSizeSoFar + 1, IncreaseAction});
220 LargestSizeSoFar = v[i].first + 1;
223 result.push_back({LargestSizeSoFar + 1, DecreaseAction});
232 if (v.size() == 0 || v[0].first != 1)
233 result.push_back({1, IncreaseAction});
234 for (
size_t i = 0; i < v.size(); ++i) {
235 result.push_back(v[i]);
236 if (i + 1 == v.size() || v[i + 1].first != v[i].first + 1) {
237 result.push_back({v[i].first + 1, DecreaseAction});
244LegacyLegalizerInfo::findAction(
const SizeAndActionsVec &Vec,
const uint32_t Size) {
251 assert(It != Vec.begin() &&
"Does Vec not start with size 1?");
252 int VecIdx = It - Vec.begin() - 1;
261 return {
Size, Action};
276 for (
int i = VecIdx - 1; i >= 0; --i)
279 return {Vec[i].first,
Action};
285 for (std::size_t i = VecIdx + 1; i < Vec.size(); ++i)
288 return {Vec[i].first,
Action};
299std::pair<LegacyLegalizeAction, LLT>
300LegacyLegalizerInfo::findScalarLegalAction(
const InstrAspect &Aspect)
const {
307 AddrSpace2PointerActions[OpcodeIdx].end()) {
312 ? AddrSpace2PointerActions[OpcodeIdx]
315 : ScalarActions[OpcodeIdx];
316 if (Aspect.
Idx >= Actions.
size())
328std::pair<LegacyLegalizeAction, LLT>
329LegacyLegalizerInfo::findVectorLegalAction(
const InstrAspect &Aspect)
const {
336 const unsigned TypeIdx = Aspect.
Idx;
337 if (TypeIdx >= ScalarInVectorActions[OpcodeIdx].
size())
340 ScalarInVectorActions[OpcodeIdx][TypeIdx];
342 LLT IntermediateType;
343 auto ElementSizeAndAction =
346 ElementSizeAndAction.first);
347 if (ElementSizeAndAction.second !=
Legal)
348 return {ElementSizeAndAction.second, IntermediateType};
350 auto i = NumElements2Actions[OpcodeIdx].find(
352 if (i == NumElements2Actions[OpcodeIdx].
end()) {
353 return {
NotFound, IntermediateType};
356 auto NumElementsAndAction =
358 return {NumElementsAndAction.second,
364 assert(Opcode >= FirstOp && Opcode <= LastOp &&
"Unsupported opcode");
365 return Opcode - FirstOp;
371 for (
unsigned i = 0; i < Query.
Types.size(); ++i) {
372 auto Action = getAspectAction({Query.
Opcode, i, Query.
Types[i]});
373 if (Action.first !=
Legal) {
375 << Action.first <<
", " << Action.second <<
"\n");
376 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...
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.
AddressSpace getAddressSpace(T *V)
@ 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.
ManagedStatic< cl::opt< FnT >, OptCreatorT > Action
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...