File indexing completed on 2026-05-10 08:43:26
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef LLVM_CODEGEN_GLOBALISEL_UTILS_H
0015 #define LLVM_CODEGEN_GLOBALISEL_UTILS_H
0016
0017 #include "GISelWorkList.h"
0018 #include "llvm/ADT/APFloat.h"
0019 #include "llvm/ADT/StringRef.h"
0020 #include "llvm/CodeGen/Register.h"
0021 #include "llvm/CodeGenTypes/LowLevelType.h"
0022 #include "llvm/IR/DebugLoc.h"
0023 #include "llvm/Support/Alignment.h"
0024 #include "llvm/Support/Casting.h"
0025
0026 #include <cstdint>
0027
0028 namespace llvm {
0029
0030 class AnalysisUsage;
0031 class LostDebugLocObserver;
0032 class MachineBasicBlock;
0033 class BlockFrequencyInfo;
0034 class GISelKnownBits;
0035 class MachineFunction;
0036 class MachineInstr;
0037 class MachineIRBuilder;
0038 class MachineOperand;
0039 class MachineOptimizationRemarkEmitter;
0040 class MachineOptimizationRemarkMissed;
0041 struct MachinePointerInfo;
0042 class MachineRegisterInfo;
0043 class MCInstrDesc;
0044 class ProfileSummaryInfo;
0045 class RegisterBankInfo;
0046 class TargetInstrInfo;
0047 class TargetLowering;
0048 class TargetPassConfig;
0049 class TargetRegisterInfo;
0050 class TargetRegisterClass;
0051 class ConstantFP;
0052 class APFloat;
0053
0054
0055 #define GISEL_VECREDUCE_CASES_ALL \
0056 case TargetOpcode::G_VECREDUCE_SEQ_FADD: \
0057 case TargetOpcode::G_VECREDUCE_SEQ_FMUL: \
0058 case TargetOpcode::G_VECREDUCE_FADD: \
0059 case TargetOpcode::G_VECREDUCE_FMUL: \
0060 case TargetOpcode::G_VECREDUCE_FMAX: \
0061 case TargetOpcode::G_VECREDUCE_FMIN: \
0062 case TargetOpcode::G_VECREDUCE_FMAXIMUM: \
0063 case TargetOpcode::G_VECREDUCE_FMINIMUM: \
0064 case TargetOpcode::G_VECREDUCE_ADD: \
0065 case TargetOpcode::G_VECREDUCE_MUL: \
0066 case TargetOpcode::G_VECREDUCE_AND: \
0067 case TargetOpcode::G_VECREDUCE_OR: \
0068 case TargetOpcode::G_VECREDUCE_XOR: \
0069 case TargetOpcode::G_VECREDUCE_SMAX: \
0070 case TargetOpcode::G_VECREDUCE_SMIN: \
0071 case TargetOpcode::G_VECREDUCE_UMAX: \
0072 case TargetOpcode::G_VECREDUCE_UMIN:
0073
0074 #define GISEL_VECREDUCE_CASES_NONSEQ \
0075 case TargetOpcode::G_VECREDUCE_FADD: \
0076 case TargetOpcode::G_VECREDUCE_FMUL: \
0077 case TargetOpcode::G_VECREDUCE_FMAX: \
0078 case TargetOpcode::G_VECREDUCE_FMIN: \
0079 case TargetOpcode::G_VECREDUCE_FMAXIMUM: \
0080 case TargetOpcode::G_VECREDUCE_FMINIMUM: \
0081 case TargetOpcode::G_VECREDUCE_ADD: \
0082 case TargetOpcode::G_VECREDUCE_MUL: \
0083 case TargetOpcode::G_VECREDUCE_AND: \
0084 case TargetOpcode::G_VECREDUCE_OR: \
0085 case TargetOpcode::G_VECREDUCE_XOR: \
0086 case TargetOpcode::G_VECREDUCE_SMAX: \
0087 case TargetOpcode::G_VECREDUCE_SMIN: \
0088 case TargetOpcode::G_VECREDUCE_UMAX: \
0089 case TargetOpcode::G_VECREDUCE_UMIN:
0090
0091
0092
0093
0094
0095 Register constrainRegToClass(MachineRegisterInfo &MRI,
0096 const TargetInstrInfo &TII,
0097 const RegisterBankInfo &RBI, Register Reg,
0098 const TargetRegisterClass &RegClass);
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108 Register constrainOperandRegClass(const MachineFunction &MF,
0109 const TargetRegisterInfo &TRI,
0110 MachineRegisterInfo &MRI,
0111 const TargetInstrInfo &TII,
0112 const RegisterBankInfo &RBI,
0113 MachineInstr &InsertPt,
0114 const TargetRegisterClass &RegClass,
0115 MachineOperand &RegMO);
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127 Register constrainOperandRegClass(const MachineFunction &MF,
0128 const TargetRegisterInfo &TRI,
0129 MachineRegisterInfo &MRI,
0130 const TargetInstrInfo &TII,
0131 const RegisterBankInfo &RBI,
0132 MachineInstr &InsertPt, const MCInstrDesc &II,
0133 MachineOperand &RegMO, unsigned OpIdx);
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144 bool constrainSelectedInstRegOperands(MachineInstr &I,
0145 const TargetInstrInfo &TII,
0146 const TargetRegisterInfo &TRI,
0147 const RegisterBankInfo &RBI);
0148
0149
0150
0151 bool canReplaceReg(Register DstReg, Register SrcReg, MachineRegisterInfo &MRI);
0152
0153
0154
0155 bool isTriviallyDead(const MachineInstr &MI, const MachineRegisterInfo &MRI);
0156
0157
0158
0159 void reportGISelFailure(MachineFunction &MF, const TargetPassConfig &TPC,
0160 MachineOptimizationRemarkEmitter &MORE,
0161 MachineOptimizationRemarkMissed &R);
0162
0163 void reportGISelFailure(MachineFunction &MF, const TargetPassConfig &TPC,
0164 MachineOptimizationRemarkEmitter &MORE,
0165 const char *PassName, StringRef Msg,
0166 const MachineInstr &MI);
0167
0168
0169
0170 void reportGISelWarning(MachineFunction &MF, const TargetPassConfig &TPC,
0171 MachineOptimizationRemarkEmitter &MORE,
0172 MachineOptimizationRemarkMissed &R);
0173
0174
0175
0176 unsigned getInverseGMinMaxOpcode(unsigned MinMaxOpc);
0177
0178
0179 std::optional<APInt> getIConstantVRegVal(Register VReg,
0180 const MachineRegisterInfo &MRI);
0181
0182
0183 std::optional<int64_t> getIConstantVRegSExtVal(Register VReg,
0184 const MachineRegisterInfo &MRI);
0185
0186
0187 const APInt &getIConstantFromReg(Register VReg, const MachineRegisterInfo &MRI);
0188
0189
0190
0191 struct ValueAndVReg {
0192 APInt Value;
0193 Register VReg;
0194 };
0195
0196
0197
0198 std::optional<ValueAndVReg>
0199 getIConstantVRegValWithLookThrough(Register VReg,
0200 const MachineRegisterInfo &MRI,
0201 bool LookThroughInstrs = true);
0202
0203
0204
0205 std::optional<ValueAndVReg> getAnyConstantVRegValWithLookThrough(
0206 Register VReg, const MachineRegisterInfo &MRI,
0207 bool LookThroughInstrs = true, bool LookThroughAnyExt = false);
0208
0209 struct FPValueAndVReg {
0210 APFloat Value;
0211 Register VReg;
0212 };
0213
0214
0215
0216 std::optional<FPValueAndVReg>
0217 getFConstantVRegValWithLookThrough(Register VReg,
0218 const MachineRegisterInfo &MRI,
0219 bool LookThroughInstrs = true);
0220
0221 const ConstantFP* getConstantFPVRegVal(Register VReg,
0222 const MachineRegisterInfo &MRI);
0223
0224
0225
0226
0227 MachineInstr *getOpcodeDef(unsigned Opcode, Register Reg,
0228 const MachineRegisterInfo &MRI);
0229
0230
0231
0232 struct DefinitionAndSourceRegister {
0233 MachineInstr *MI;
0234 Register Reg;
0235 };
0236
0237
0238
0239
0240
0241 std::optional<DefinitionAndSourceRegister>
0242 getDefSrcRegIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI);
0243
0244
0245
0246
0247
0248 MachineInstr *getDefIgnoringCopies(Register Reg,
0249 const MachineRegisterInfo &MRI);
0250
0251
0252
0253
0254
0255
0256
0257 Register getSrcRegIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI);
0258
0259
0260
0261
0262 void extractParts(Register Reg, LLT Ty, int NumParts,
0263 SmallVectorImpl<Register> &VRegs,
0264 MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI);
0265
0266
0267 bool extractParts(Register Reg, LLT RegTy, LLT MainTy, LLT &LeftoverTy,
0268 SmallVectorImpl<Register> &VRegs,
0269 SmallVectorImpl<Register> &LeftoverVRegs,
0270 MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI);
0271
0272
0273 void extractVectorParts(Register Reg, unsigned NumElts,
0274 SmallVectorImpl<Register> &VRegs,
0275 MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI);
0276
0277
0278
0279
0280
0281 template <class T>
0282 T *getOpcodeDef(Register Reg, const MachineRegisterInfo &MRI) {
0283 MachineInstr *DefMI = getDefIgnoringCopies(Reg, MRI);
0284 return dyn_cast_or_null<T>(DefMI);
0285 }
0286
0287
0288 APFloat getAPFloatFromSize(double Val, unsigned Size);
0289
0290
0291
0292 void getSelectionDAGFallbackAnalysisUsage(AnalysisUsage &AU);
0293
0294 std::optional<APInt> ConstantFoldBinOp(unsigned Opcode, const Register Op1,
0295 const Register Op2,
0296 const MachineRegisterInfo &MRI);
0297 std::optional<APFloat> ConstantFoldFPBinOp(unsigned Opcode, const Register Op1,
0298 const Register Op2,
0299 const MachineRegisterInfo &MRI);
0300
0301
0302
0303 SmallVector<APInt> ConstantFoldVectorBinop(unsigned Opcode, const Register Op1,
0304 const Register Op2,
0305 const MachineRegisterInfo &MRI);
0306
0307 std::optional<APInt> ConstantFoldCastOp(unsigned Opcode, LLT DstTy,
0308 const Register Op0,
0309 const MachineRegisterInfo &MRI);
0310
0311 std::optional<APInt> ConstantFoldExtOp(unsigned Opcode, const Register Op1,
0312 uint64_t Imm,
0313 const MachineRegisterInfo &MRI);
0314
0315 std::optional<APFloat> ConstantFoldIntToFloat(unsigned Opcode, LLT DstTy,
0316 Register Src,
0317 const MachineRegisterInfo &MRI);
0318
0319
0320
0321
0322 std::optional<SmallVector<unsigned>>
0323 ConstantFoldCountZeros(Register Src, const MachineRegisterInfo &MRI,
0324 std::function<unsigned(APInt)> CB);
0325
0326 std::optional<SmallVector<APInt>>
0327 ConstantFoldICmp(unsigned Pred, const Register Op1, const Register Op2,
0328 const MachineRegisterInfo &MRI);
0329
0330
0331
0332
0333 bool isKnownToBeAPowerOfTwo(Register Val, const MachineRegisterInfo &MRI,
0334 GISelKnownBits *KnownBits = nullptr);
0335
0336
0337
0338 bool isKnownNeverNaN(Register Val, const MachineRegisterInfo &MRI,
0339 bool SNaN = false);
0340
0341
0342 inline bool isKnownNeverSNaN(Register Val, const MachineRegisterInfo &MRI) {
0343 return isKnownNeverNaN(Val, MRI, true);
0344 }
0345
0346 Align inferAlignFromPtrInfo(MachineFunction &MF, const MachinePointerInfo &MPO);
0347
0348
0349
0350
0351
0352
0353
0354 Register getFunctionLiveInPhysReg(MachineFunction &MF,
0355 const TargetInstrInfo &TII,
0356 MCRegister PhysReg,
0357 const TargetRegisterClass &RC,
0358 const DebugLoc &DL, LLT RegTy = LLT());
0359
0360
0361
0362
0363
0364
0365
0366
0367 LLVM_READNONE
0368 LLT getLCMType(LLT OrigTy, LLT TargetTy);
0369
0370 LLVM_READNONE
0371
0372
0373 LLT getCoverTy(LLT OrigTy, LLT TargetTy);
0374
0375
0376
0377
0378
0379
0380
0381
0382
0383
0384
0385
0386
0387
0388
0389
0390
0391 LLVM_READNONE
0392 LLT getGCDType(LLT OrigTy, LLT TargetTy);
0393
0394
0395
0396
0397
0398
0399 class RegOrConstant {
0400 int64_t Cst;
0401 Register Reg;
0402 bool IsReg;
0403
0404 public:
0405 explicit RegOrConstant(Register Reg) : Reg(Reg), IsReg(true) {}
0406 explicit RegOrConstant(int64_t Cst) : Cst(Cst), IsReg(false) {}
0407 bool isReg() const { return IsReg; }
0408 bool isCst() const { return !IsReg; }
0409 Register getReg() const {
0410 assert(isReg() && "Expected a register!");
0411 return Reg;
0412 }
0413 int64_t getCst() const {
0414 assert(isCst() && "Expected a constant!");
0415 return Cst;
0416 }
0417 };
0418
0419
0420
0421 std::optional<int> getSplatIndex(MachineInstr &MI);
0422
0423
0424 std::optional<APInt> getIConstantSplatVal(const Register Reg,
0425 const MachineRegisterInfo &MRI);
0426
0427
0428 std::optional<APInt> getIConstantSplatVal(const MachineInstr &MI,
0429 const MachineRegisterInfo &MRI);
0430
0431
0432
0433 std::optional<int64_t> getIConstantSplatSExtVal(const Register Reg,
0434 const MachineRegisterInfo &MRI);
0435
0436
0437
0438 std::optional<int64_t> getIConstantSplatSExtVal(const MachineInstr &MI,
0439 const MachineRegisterInfo &MRI);
0440
0441
0442
0443 std::optional<FPValueAndVReg> getFConstantSplat(Register VReg,
0444 const MachineRegisterInfo &MRI,
0445 bool AllowUndef = true);
0446
0447
0448
0449 bool isBuildVectorConstantSplat(const Register Reg,
0450 const MachineRegisterInfo &MRI,
0451 int64_t SplatValue, bool AllowUndef);
0452
0453
0454
0455 bool isBuildVectorConstantSplat(const MachineInstr &MI,
0456 const MachineRegisterInfo &MRI,
0457 int64_t SplatValue, bool AllowUndef);
0458
0459
0460
0461 bool isBuildVectorAllZeros(const MachineInstr &MI,
0462 const MachineRegisterInfo &MRI,
0463 bool AllowUndef = false);
0464
0465
0466
0467 bool isBuildVectorAllOnes(const MachineInstr &MI,
0468 const MachineRegisterInfo &MRI,
0469 bool AllowUndef = false);
0470
0471
0472
0473
0474
0475
0476
0477 bool isConstantOrConstantVector(const MachineInstr &MI,
0478 const MachineRegisterInfo &MRI,
0479 bool AllowFP = true,
0480 bool AllowOpaqueConstants = true);
0481
0482
0483
0484
0485
0486 bool isNullOrNullSplat(const MachineInstr &MI, const MachineRegisterInfo &MRI,
0487 bool AllowUndefs = false);
0488
0489
0490
0491 bool isAllOnesOrAllOnesSplat(const MachineInstr &MI,
0492 const MachineRegisterInfo &MRI,
0493 bool AllowUndefs = false);
0494
0495
0496
0497
0498
0499
0500
0501
0502
0503
0504
0505
0506
0507
0508
0509
0510
0511
0512
0513
0514 std::optional<RegOrConstant> getVectorSplat(const MachineInstr &MI,
0515 const MachineRegisterInfo &MRI);
0516
0517
0518
0519 bool isConstantOrConstantVector(MachineInstr &MI,
0520 const MachineRegisterInfo &MRI);
0521
0522
0523
0524
0525 std::optional<APInt>
0526 isConstantOrConstantSplatVector(MachineInstr &MI,
0527 const MachineRegisterInfo &MRI);
0528
0529
0530
0531
0532 std::optional<APFloat>
0533 isConstantOrConstantSplatVectorFP(MachineInstr &MI,
0534 const MachineRegisterInfo &MRI);
0535
0536
0537
0538
0539 bool matchUnaryPredicate(const MachineRegisterInfo &MRI, Register Reg,
0540 std::function<bool(const Constant *ConstVal)> Match,
0541 bool AllowUndefs = false);
0542
0543
0544
0545 bool isConstTrueVal(const TargetLowering &TLI, int64_t Val, bool IsVector,
0546 bool IsFP);
0547
0548
0549 bool isConstFalseVal(const TargetLowering &TLI, int64_t Val, bool IsVector,
0550 bool IsFP);
0551
0552
0553
0554 int64_t getICmpTrueVal(const TargetLowering &TLI, bool IsVector, bool IsFP);
0555
0556 using SmallInstListTy = GISelWorkList<4>;
0557 void saveUsesAndErase(MachineInstr &MI, MachineRegisterInfo &MRI,
0558 LostDebugLocObserver *LocObserver,
0559 SmallInstListTy &DeadInstChain);
0560 void eraseInstrs(ArrayRef<MachineInstr *> DeadInstrs, MachineRegisterInfo &MRI,
0561 LostDebugLocObserver *LocObserver = nullptr);
0562 void eraseInstr(MachineInstr &MI, MachineRegisterInfo &MRI,
0563 LostDebugLocObserver *LocObserver = nullptr);
0564
0565
0566
0567 void salvageDebugInfo(const MachineRegisterInfo &MRI, MachineInstr &MI);
0568
0569
0570
0571 bool isPreISelGenericFloatingPointOpcode(unsigned Opc);
0572
0573
0574
0575
0576
0577
0578
0579 bool canCreateUndefOrPoison(Register Reg, const MachineRegisterInfo &MRI,
0580 bool ConsiderFlagsAndMetadata = true);
0581
0582
0583 bool canCreatePoison(Register Reg, const MachineRegisterInfo &MRI,
0584 bool ConsiderFlagsAndMetadata = true);
0585
0586
0587 bool isGuaranteedNotToBeUndefOrPoison(Register Reg,
0588 const MachineRegisterInfo &MRI,
0589 unsigned Depth = 0);
0590
0591
0592 bool isGuaranteedNotToBePoison(Register Reg, const MachineRegisterInfo &MRI,
0593 unsigned Depth = 0);
0594
0595
0596 bool isGuaranteedNotToBeUndef(Register Reg, const MachineRegisterInfo &MRI,
0597 unsigned Depth = 0);
0598
0599
0600
0601 Type *getTypeForLLT(LLT Ty, LLVMContext &C);
0602
0603
0604
0605
0606
0607
0608
0609
0610
0611
0612
0613
0614
0615
0616
0617 class GIConstant {
0618 public:
0619 enum class GIConstantKind { Scalar, FixedVector, ScalableVector };
0620
0621 private:
0622 GIConstantKind Kind;
0623 SmallVector<APInt> Values;
0624 APInt Value;
0625
0626 public:
0627 GIConstant(ArrayRef<APInt> Values)
0628 : Kind(GIConstantKind::FixedVector), Values(Values) {};
0629 GIConstant(const APInt &Value, GIConstantKind Kind)
0630 : Kind(Kind), Value(Value) {};
0631
0632
0633 GIConstantKind getKind() const { return Kind; }
0634
0635
0636 APInt getScalarValue() const;
0637
0638 static std::optional<GIConstant> getConstant(Register Const,
0639 const MachineRegisterInfo &MRI);
0640 };
0641
0642
0643
0644
0645
0646
0647
0648
0649
0650
0651
0652
0653
0654
0655
0656 class GFConstant {
0657 public:
0658 enum class GFConstantKind { Scalar, FixedVector, ScalableVector };
0659
0660 private:
0661 GFConstantKind Kind;
0662 SmallVector<APFloat> Values;
0663
0664 public:
0665 GFConstant(ArrayRef<APFloat> Values)
0666 : Kind(GFConstantKind::FixedVector), Values(Values) {};
0667 GFConstant(const APFloat &Value, GFConstantKind Kind) : Kind(Kind) {
0668 Values.push_back(Value);
0669 }
0670
0671
0672 GFConstantKind getKind() const { return Kind; }
0673
0674
0675 APFloat getScalarValue() const;
0676
0677 static std::optional<GFConstant> getConstant(Register Const,
0678 const MachineRegisterInfo &MRI);
0679 };
0680
0681 }
0682 #endif