File indexing completed on 2026-05-10 08:43:24
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef LLVM_CODEGEN_GLOBALISEL_LEGACYLEGALIZERINFO_H
0016 #define LLVM_CODEGEN_GLOBALISEL_LEGACYLEGALIZERINFO_H
0017
0018 #include "llvm/ADT/DenseMap.h"
0019 #include "llvm/CodeGen/TargetOpcodes.h"
0020 #include "llvm/CodeGenTypes/LowLevelType.h"
0021 #include <unordered_map>
0022 #include <vector>
0023
0024 namespace llvm {
0025 struct LegalityQuery;
0026
0027 namespace LegacyLegalizeActions {
0028 enum LegacyLegalizeAction : std::uint8_t {
0029
0030
0031 Legal,
0032
0033
0034
0035
0036 NarrowScalar,
0037
0038
0039
0040
0041 WidenScalar,
0042
0043
0044
0045
0046 FewerElements,
0047
0048
0049
0050
0051
0052 MoreElements,
0053
0054
0055 Bitcast,
0056
0057
0058
0059 Lower,
0060
0061
0062
0063
0064 Libcall,
0065
0066
0067
0068 Custom,
0069
0070
0071
0072 Unsupported,
0073
0074
0075 NotFound,
0076 };
0077 }
0078 raw_ostream &operator<<(raw_ostream &OS,
0079 LegacyLegalizeActions::LegacyLegalizeAction Action);
0080
0081
0082
0083
0084 struct InstrAspect {
0085 unsigned Opcode;
0086 unsigned Idx = 0;
0087 LLT Type;
0088
0089 InstrAspect(unsigned Opcode, LLT Type) : Opcode(Opcode), Type(Type) {}
0090 InstrAspect(unsigned Opcode, unsigned Idx, LLT Type)
0091 : Opcode(Opcode), Idx(Idx), Type(Type) {}
0092
0093 bool operator==(const InstrAspect &RHS) const {
0094 return Opcode == RHS.Opcode && Idx == RHS.Idx && Type == RHS.Type;
0095 }
0096 };
0097
0098
0099
0100
0101 struct LegacyLegalizeActionStep {
0102
0103 LegacyLegalizeActions::LegacyLegalizeAction Action;
0104
0105 unsigned TypeIdx;
0106
0107 LLT NewType;
0108
0109 LegacyLegalizeActionStep(LegacyLegalizeActions::LegacyLegalizeAction Action,
0110 unsigned TypeIdx, const LLT NewType)
0111 : Action(Action), TypeIdx(TypeIdx), NewType(NewType) {}
0112
0113 bool operator==(const LegacyLegalizeActionStep &RHS) const {
0114 return std::tie(Action, TypeIdx, NewType) ==
0115 std::tie(RHS.Action, RHS.TypeIdx, RHS.NewType);
0116 }
0117 };
0118
0119
0120 class LegacyLegalizerInfo {
0121 public:
0122 using SizeAndAction =
0123 std::pair<uint16_t, LegacyLegalizeActions::LegacyLegalizeAction>;
0124 using SizeAndActionsVec = std::vector<SizeAndAction>;
0125 using SizeChangeStrategy =
0126 std::function<SizeAndActionsVec(const SizeAndActionsVec &v)>;
0127
0128 LegacyLegalizerInfo();
0129
0130 static bool needsLegalizingToDifferentSize(
0131 const LegacyLegalizeActions::LegacyLegalizeAction Action) {
0132 using namespace LegacyLegalizeActions;
0133 switch (Action) {
0134 case NarrowScalar:
0135 case WidenScalar:
0136 case FewerElements:
0137 case MoreElements:
0138 case Unsupported:
0139 return true;
0140 default:
0141 return false;
0142 }
0143 }
0144
0145
0146
0147
0148 void computeTables();
0149
0150
0151
0152
0153
0154 void setAction(const InstrAspect &Aspect,
0155 LegacyLegalizeActions::LegacyLegalizeAction Action) {
0156 assert(!needsLegalizingToDifferentSize(Action));
0157 TablesInitialized = false;
0158 const unsigned OpcodeIdx = Aspect.Opcode - FirstOp;
0159 if (SpecifiedActions[OpcodeIdx].size() <= Aspect.Idx)
0160 SpecifiedActions[OpcodeIdx].resize(Aspect.Idx + 1);
0161 SpecifiedActions[OpcodeIdx][Aspect.Idx][Aspect.Type] = Action;
0162 }
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180 void setLegalizeScalarToDifferentSizeStrategy(const unsigned Opcode,
0181 const unsigned TypeIdx,
0182 SizeChangeStrategy S) {
0183 const unsigned OpcodeIdx = Opcode - FirstOp;
0184 if (ScalarSizeChangeStrategies[OpcodeIdx].size() <= TypeIdx)
0185 ScalarSizeChangeStrategies[OpcodeIdx].resize(TypeIdx + 1);
0186 ScalarSizeChangeStrategies[OpcodeIdx][TypeIdx] = S;
0187 }
0188
0189
0190
0191 void setLegalizeVectorElementToDifferentSizeStrategy(const unsigned Opcode,
0192 const unsigned TypeIdx,
0193 SizeChangeStrategy S) {
0194 const unsigned OpcodeIdx = Opcode - FirstOp;
0195 if (VectorElementSizeChangeStrategies[OpcodeIdx].size() <= TypeIdx)
0196 VectorElementSizeChangeStrategies[OpcodeIdx].resize(TypeIdx + 1);
0197 VectorElementSizeChangeStrategies[OpcodeIdx][TypeIdx] = S;
0198 }
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209 static SizeAndActionsVec
0210 unsupportedForDifferentSizes(const SizeAndActionsVec &v) {
0211 using namespace LegacyLegalizeActions;
0212 return increaseToLargerTypesAndDecreaseToLargest(v, Unsupported,
0213 Unsupported);
0214 }
0215
0216
0217
0218
0219
0220 static SizeAndActionsVec
0221 widenToLargerTypesAndNarrowToLargest(const SizeAndActionsVec &v) {
0222 using namespace LegacyLegalizeActions;
0223 assert(v.size() > 0 &&
0224 "At least one size that can be legalized towards is needed"
0225 " for this SizeChangeStrategy");
0226 return increaseToLargerTypesAndDecreaseToLargest(v, WidenScalar,
0227 NarrowScalar);
0228 }
0229
0230 static SizeAndActionsVec
0231 widenToLargerTypesUnsupportedOtherwise(const SizeAndActionsVec &v) {
0232 using namespace LegacyLegalizeActions;
0233 return increaseToLargerTypesAndDecreaseToLargest(v, WidenScalar,
0234 Unsupported);
0235 }
0236
0237 static SizeAndActionsVec
0238 narrowToSmallerAndUnsupportedIfTooSmall(const SizeAndActionsVec &v) {
0239 using namespace LegacyLegalizeActions;
0240 return decreaseToSmallerTypesAndIncreaseToSmallest(v, NarrowScalar,
0241 Unsupported);
0242 }
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262 static SizeAndActionsVec
0263 moreToWiderTypesAndLessToWidest(const SizeAndActionsVec &v) {
0264 using namespace LegacyLegalizeActions;
0265 return increaseToLargerTypesAndDecreaseToLargest(v, MoreElements,
0266 FewerElements);
0267 }
0268
0269
0270 static SizeAndActionsVec increaseToLargerTypesAndDecreaseToLargest(
0271 const SizeAndActionsVec &v,
0272 LegacyLegalizeActions::LegacyLegalizeAction IncreaseAction,
0273 LegacyLegalizeActions::LegacyLegalizeAction DecreaseAction);
0274
0275 static SizeAndActionsVec decreaseToSmallerTypesAndIncreaseToSmallest(
0276 const SizeAndActionsVec &v,
0277 LegacyLegalizeActions::LegacyLegalizeAction DecreaseAction,
0278 LegacyLegalizeActions::LegacyLegalizeAction IncreaseAction);
0279
0280 LegacyLegalizeActionStep getAction(const LegalityQuery &Query) const;
0281
0282 unsigned getOpcodeIdxForOpcode(unsigned Opcode) const;
0283
0284 private:
0285
0286
0287
0288
0289
0290
0291 std::pair<LegacyLegalizeActions::LegacyLegalizeAction, LLT>
0292 getAspectAction(const InstrAspect &Aspect) const;
0293
0294
0295
0296
0297
0298
0299
0300
0301
0302
0303
0304
0305
0306
0307
0308
0309
0310
0311 void setScalarAction(const unsigned Opcode, const unsigned TypeIndex,
0312 const SizeAndActionsVec &SizeAndActions) {
0313 const unsigned OpcodeIdx = Opcode - FirstOp;
0314 SmallVector<SizeAndActionsVec, 1> &Actions = ScalarActions[OpcodeIdx];
0315 setActions(TypeIndex, Actions, SizeAndActions);
0316 }
0317 void setPointerAction(const unsigned Opcode, const unsigned TypeIndex,
0318 const unsigned AddressSpace,
0319 const SizeAndActionsVec &SizeAndActions) {
0320 const unsigned OpcodeIdx = Opcode - FirstOp;
0321 SmallVector<SizeAndActionsVec, 1> &Actions =
0322 AddrSpace2PointerActions[OpcodeIdx][AddressSpace];
0323 setActions(TypeIndex, Actions, SizeAndActions);
0324 }
0325
0326
0327
0328
0329
0330
0331 void setScalarInVectorAction(const unsigned Opcode, const unsigned TypeIndex,
0332 const SizeAndActionsVec &SizeAndActions) {
0333 unsigned OpcodeIdx = Opcode - FirstOp;
0334 SmallVector<SizeAndActionsVec, 1> &Actions =
0335 ScalarInVectorActions[OpcodeIdx];
0336 setActions(TypeIndex, Actions, SizeAndActions);
0337 }
0338
0339
0340
0341
0342 void setVectorNumElementAction(const unsigned Opcode,
0343 const unsigned TypeIndex,
0344 const unsigned ElementSize,
0345 const SizeAndActionsVec &SizeAndActions) {
0346 const unsigned OpcodeIdx = Opcode - FirstOp;
0347 SmallVector<SizeAndActionsVec, 1> &Actions =
0348 NumElements2Actions[OpcodeIdx][ElementSize];
0349 setActions(TypeIndex, Actions, SizeAndActions);
0350 }
0351
0352
0353
0354 static void checkPartialSizeAndActionsVector(const SizeAndActionsVec& v) {
0355 using namespace LegacyLegalizeActions;
0356 #ifndef NDEBUG
0357
0358 int prev_size = -1;
0359 for(auto SizeAndAction: v) {
0360 assert(SizeAndAction.first > prev_size);
0361 prev_size = SizeAndAction.first;
0362 }
0363
0364
0365
0366
0367
0368 int SmallestNarrowIdx = -1;
0369 int LargestWidenIdx = -1;
0370 int SmallestLegalizableToSameSizeIdx = -1;
0371 int LargestLegalizableToSameSizeIdx = -1;
0372 for(size_t i=0; i<v.size(); ++i) {
0373 switch (v[i].second) {
0374 case FewerElements:
0375 case NarrowScalar:
0376 if (SmallestNarrowIdx == -1)
0377 SmallestNarrowIdx = i;
0378 break;
0379 case WidenScalar:
0380 case MoreElements:
0381 LargestWidenIdx = i;
0382 break;
0383 case Unsupported:
0384 break;
0385 default:
0386 if (SmallestLegalizableToSameSizeIdx == -1)
0387 SmallestLegalizableToSameSizeIdx = i;
0388 LargestLegalizableToSameSizeIdx = i;
0389 }
0390 }
0391 if (SmallestNarrowIdx != -1) {
0392 assert(SmallestLegalizableToSameSizeIdx != -1);
0393 assert(SmallestNarrowIdx > SmallestLegalizableToSameSizeIdx);
0394 }
0395 if (LargestWidenIdx != -1)
0396 assert(LargestWidenIdx < LargestLegalizableToSameSizeIdx);
0397 #endif
0398 }
0399
0400
0401
0402 static void checkFullSizeAndActionsVector(const SizeAndActionsVec& v) {
0403 #ifndef NDEBUG
0404
0405 assert(v.size() >= 1);
0406 assert(v[0].first == 1);
0407 checkPartialSizeAndActionsVector(v);
0408 #endif
0409 }
0410
0411
0412
0413 void setActions(unsigned TypeIndex,
0414 SmallVector<SizeAndActionsVec, 1> &Actions,
0415 const SizeAndActionsVec &SizeAndActions) {
0416 checkFullSizeAndActionsVector(SizeAndActions);
0417 if (Actions.size() <= TypeIndex)
0418 Actions.resize(TypeIndex + 1);
0419 Actions[TypeIndex] = SizeAndActions;
0420 }
0421
0422 static SizeAndAction findAction(const SizeAndActionsVec &Vec,
0423 const uint32_t Size);
0424
0425
0426
0427
0428
0429
0430
0431
0432
0433
0434
0435
0436 std::pair<LegacyLegalizeActions::LegacyLegalizeAction, LLT>
0437 findScalarLegalAction(const InstrAspect &Aspect) const;
0438
0439
0440 std::pair<LegacyLegalizeActions::LegacyLegalizeAction, LLT>
0441 findVectorLegalAction(const InstrAspect &Aspect) const;
0442
0443 static const int FirstOp = TargetOpcode::PRE_ISEL_GENERIC_OPCODE_START;
0444 static const int LastOp = TargetOpcode::PRE_ISEL_GENERIC_OPCODE_END;
0445
0446
0447 using TypeMap = DenseMap<LLT, LegacyLegalizeActions::LegacyLegalizeAction>;
0448 SmallVector<TypeMap, 1> SpecifiedActions[LastOp - FirstOp + 1];
0449 SmallVector<SizeChangeStrategy, 1>
0450 ScalarSizeChangeStrategies[LastOp - FirstOp + 1];
0451 SmallVector<SizeChangeStrategy, 1>
0452 VectorElementSizeChangeStrategies[LastOp - FirstOp + 1];
0453 bool TablesInitialized = false;
0454
0455
0456 SmallVector<SizeAndActionsVec, 1> ScalarActions[LastOp - FirstOp + 1];
0457 SmallVector<SizeAndActionsVec, 1> ScalarInVectorActions[LastOp - FirstOp + 1];
0458 std::unordered_map<uint16_t, SmallVector<SizeAndActionsVec, 1>>
0459 AddrSpace2PointerActions[LastOp - FirstOp + 1];
0460 std::unordered_map<uint16_t, SmallVector<SizeAndActionsVec, 1>>
0461 NumElements2Actions[LastOp - FirstOp + 1];
0462 };
0463
0464 }
0465
0466 #endif