From 9d40003fa8e24f501d719ff3e7fedc6204bac305 Mon Sep 17 00:00:00 2001 From: Nick Desaulniers Date: Thu, 21 Sep 2023 10:16:27 -0700 Subject: [PATCH 1/6] [TargetLowering] Deduplicate choosing InlineAsm constraint between ISels Given a list of constraints for InlineAsm (ex. "imr") I'm looking to modify the order in which is chosen. Before doing so, I noticed a fair amount of logic is duplicated between SelectionDAGISel and GlobalISel for this. That is because SelectionDAGISel is also trying to lower immediates during selection. If we detangle these concerns into: 1. choose the preferred constraint 2. attempt to lower that constraint Then we can slide down the list of constraints until we find one that can be lowered. That allows the implementation to be shared between instruction selection frameworks. This makes it so that later I might only need to adjust the priority of constraints in one place, and have both selectors behave the same. --- llvm/include/llvm/CodeGen/TargetLowering.h | 9 ++ .../CodeGen/GlobalISel/InlineAsmLowering.cpp | 76 ++------------- .../CodeGen/SelectionDAG/TargetLowering.cpp | 95 ++++++++++--------- 3 files changed, 71 insertions(+), 109 deletions(-) diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h index dabf1bedafe63..ff3ef38cef90d 100644 --- a/llvm/include/llvm/CodeGen/TargetLowering.h +++ b/llvm/include/llvm/CodeGen/TargetLowering.h @@ -4820,6 +4820,15 @@ class TargetLowering : public TargetLoweringBase { /// Given a constraint, return the type of constraint it is for this target. virtual ConstraintType getConstraintType(StringRef Constraint) const; + using ConstraintPair = std::pair; + using ConstraintGroup = SmallVector; + /// Given an OpInfo with list of constraints codes as strings, return a + /// sorted Vector of pairs of constraint codes and their types in priority of + /// what we'd prefer to lower them as. This may contains immediates that + /// cannot be lowered, but it is meant to be a machine agnostic order of + /// preferences. + ConstraintGroup getConstraintPreferences(AsmOperandInfo &OpInfo) const; + /// Given a physical register constraint (e.g. {edx}), return the register /// number and the register class for the register. /// diff --git a/llvm/lib/CodeGen/GlobalISel/InlineAsmLowering.cpp b/llvm/lib/CodeGen/GlobalISel/InlineAsmLowering.cpp index 00dba57fcb802..a6d802c91f309 100644 --- a/llvm/lib/CodeGen/GlobalISel/InlineAsmLowering.cpp +++ b/llvm/lib/CodeGen/GlobalISel/InlineAsmLowering.cpp @@ -133,71 +133,6 @@ static void getRegistersForValue(MachineFunction &MF, } } -/// Return an integer indicating how general CT is. -static unsigned getConstraintGenerality(TargetLowering::ConstraintType CT) { - switch (CT) { - case TargetLowering::C_Immediate: - case TargetLowering::C_Other: - case TargetLowering::C_Unknown: - return 0; - case TargetLowering::C_Register: - return 1; - case TargetLowering::C_RegisterClass: - return 2; - case TargetLowering::C_Memory: - case TargetLowering::C_Address: - return 3; - } - llvm_unreachable("Invalid constraint type"); -} - -static void chooseConstraint(TargetLowering::AsmOperandInfo &OpInfo, - const TargetLowering *TLI) { - assert(OpInfo.Codes.size() > 1 && "Doesn't have multiple constraint options"); - unsigned BestIdx = 0; - TargetLowering::ConstraintType BestType = TargetLowering::C_Unknown; - int BestGenerality = -1; - - // Loop over the options, keeping track of the most general one. - for (unsigned i = 0, e = OpInfo.Codes.size(); i != e; ++i) { - TargetLowering::ConstraintType CType = - TLI->getConstraintType(OpInfo.Codes[i]); - - // Indirect 'other' or 'immediate' constraints are not allowed. - if (OpInfo.isIndirect && !(CType == TargetLowering::C_Memory || - CType == TargetLowering::C_Register || - CType == TargetLowering::C_RegisterClass)) - continue; - - // If this is an 'other' or 'immediate' constraint, see if the operand is - // valid for it. For example, on X86 we might have an 'rI' constraint. If - // the operand is an integer in the range [0..31] we want to use I (saving a - // load of a register), otherwise we must use 'r'. - if (CType == TargetLowering::C_Other || - CType == TargetLowering::C_Immediate) { - assert(OpInfo.Codes[i].size() == 1 && - "Unhandled multi-letter 'other' constraint"); - // FIXME: prefer immediate constraints if the target allows it - } - - // Things with matching constraints can only be registers, per gcc - // documentation. This mainly affects "g" constraints. - if (CType == TargetLowering::C_Memory && OpInfo.hasMatchingInput()) - continue; - - // This constraint letter is more general than the previous one, use it. - int Generality = getConstraintGenerality(CType); - if (Generality > BestGenerality) { - BestType = CType; - BestIdx = i; - BestGenerality = Generality; - } - } - - OpInfo.ConstraintCode = OpInfo.Codes[BestIdx]; - OpInfo.ConstraintType = BestType; -} - static void computeConstraintToUse(const TargetLowering *TLI, TargetLowering::AsmOperandInfo &OpInfo) { assert(!OpInfo.Codes.empty() && "Must have at least one constraint"); @@ -207,7 +142,16 @@ static void computeConstraintToUse(const TargetLowering *TLI, OpInfo.ConstraintCode = OpInfo.Codes[0]; OpInfo.ConstraintType = TLI->getConstraintType(OpInfo.ConstraintCode); } else { - chooseConstraint(OpInfo, TLI); + TargetLowering::ConstraintGroup G = TLI->getConstraintPreferences(OpInfo); + if (G.empty()) + return; + // FIXME: prefer immediate constraints if the target allows it + unsigned BestIdx = 0; + while (G[BestIdx].second == TargetLowering::C_Other || + G[BestIdx].second == TargetLowering::C_Immediate) + ++BestIdx; + OpInfo.ConstraintCode = G[BestIdx].first; + OpInfo.ConstraintType = G[BestIdx].second; } // 'X' matches anything. diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp index bd1940994a87f..c20ed63783669 100644 --- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -5701,13 +5701,19 @@ TargetLowering::ParseConstraints(const DataLayout &DL, return ConstraintOperands; } -/// Return an integer indicating how general CT is. -static unsigned getConstraintGenerality(TargetLowering::ConstraintType CT) { +/// Return a number indicating our preference for chosing a type of constraint +/// over another, for the purpose of sorting them. Immediates are almost always +/// preferrable (when they can be emitted). +/// FIXME: We should prefer registers over memory but doing so may lead to +/// unrecoverable register exhaustion later. +/// https://github.com/llvm/llvm-project/issues/20571 +static unsigned getConstraintPiority(TargetLowering::ConstraintType CT) { switch (CT) { - case TargetLowering::C_Immediate: - case TargetLowering::C_Other: case TargetLowering::C_Unknown: return 0; + case TargetLowering::C_Immediate: + case TargetLowering::C_Other: + return 4; case TargetLowering::C_Register: return 1; case TargetLowering::C_RegisterClass: @@ -5812,18 +5818,13 @@ TargetLowering::ConstraintWeight /// 2) Otherwise, pick the most general constraint present. This prefers /// 'm' over 'r', for example. /// -static void ChooseConstraint(TargetLowering::AsmOperandInfo &OpInfo, - const TargetLowering &TLI, - SDValue Op, SelectionDAG *DAG) { - assert(OpInfo.Codes.size() > 1 && "Doesn't have multiple constraint options"); - unsigned BestIdx = 0; - TargetLowering::ConstraintType BestType = TargetLowering::C_Unknown; - int BestGenerality = -1; +TargetLowering::ConstraintGroup TargetLowering::getConstraintPreferences( + TargetLowering::AsmOperandInfo &OpInfo) const { + ConstraintGroup Ret; - // Loop over the options, keeping track of the most general one. - for (unsigned i = 0, e = OpInfo.Codes.size(); i != e; ++i) { - TargetLowering::ConstraintType CType = - TLI.getConstraintType(OpInfo.Codes[i]); + Ret.reserve(OpInfo.Codes.size()); + for (StringRef Code : OpInfo.Codes) { + TargetLowering::ConstraintType CType = getConstraintType(Code); // Indirect 'other' or 'immediate' constraints are not allowed. if (OpInfo.isIndirect && !(CType == TargetLowering::C_Memory || @@ -5831,40 +5832,36 @@ static void ChooseConstraint(TargetLowering::AsmOperandInfo &OpInfo, CType == TargetLowering::C_RegisterClass)) continue; - // If this is an 'other' or 'immediate' constraint, see if the operand is - // valid for it. For example, on X86 we might have an 'rI' constraint. If - // the operand is an integer in the range [0..31] we want to use I (saving a - // load of a register), otherwise we must use 'r'. - if ((CType == TargetLowering::C_Other || - CType == TargetLowering::C_Immediate) && Op.getNode()) { - assert(OpInfo.Codes[i].size() == 1 && - "Unhandled multi-letter 'other' constraint"); - std::vector ResultOps; - TLI.LowerAsmOperandForConstraint(Op, OpInfo.Codes[i], - ResultOps, *DAG); - if (!ResultOps.empty()) { - BestType = CType; - BestIdx = i; - break; - } - } - // Things with matching constraints can only be registers, per gcc // documentation. This mainly affects "g" constraints. if (CType == TargetLowering::C_Memory && OpInfo.hasMatchingInput()) continue; - // This constraint letter is more general than the previous one, use it. - int Generality = getConstraintGenerality(CType); - if (Generality > BestGenerality) { - BestType = CType; - BestIdx = i; - BestGenerality = Generality; - } + Ret.emplace_back(Code, CType); } - OpInfo.ConstraintCode = OpInfo.Codes[BestIdx]; - OpInfo.ConstraintType = BestType; + std::sort(Ret.begin(), Ret.end(), [](ConstraintPair a, ConstraintPair b) { + return getConstraintPiority(a.second) > getConstraintPiority(b.second); + }); + + return Ret; +} + +// If we have an immediate, see if we can lower it. Return true if we can, or +// don't have an immediate, false otherwise. +static bool lowerImmediateIfPossible(TargetLowering::ConstraintPair &P, + SDValue Op, SelectionDAG *DAG, + const TargetLowering &TLI) { + + if (P.second != TargetLowering::C_Other && + P.second != TargetLowering::C_Immediate) + return true; + if (!Op.getNode()) + return false; + + std::vector ResultOps; + TLI.LowerAsmOperandForConstraint(Op, P.first, ResultOps, *DAG); + return !ResultOps.empty(); } /// Determines the constraint code and constraint type to use for the specific @@ -5879,7 +5876,19 @@ void TargetLowering::ComputeConstraintToUse(AsmOperandInfo &OpInfo, OpInfo.ConstraintCode = OpInfo.Codes[0]; OpInfo.ConstraintType = getConstraintType(OpInfo.ConstraintCode); } else { - ChooseConstraint(OpInfo, *this, Op, DAG); + ConstraintGroup G = getConstraintPreferences(OpInfo); + if (G.empty()) + return; + + unsigned BestIdx = 0; + while (!lowerImmediateIfPossible(G[BestIdx], Op, DAG, *this)) { + if (BestIdx + 1 > G.size() - 1) + return; + ++BestIdx; + } + + OpInfo.ConstraintCode = G[BestIdx].first; + OpInfo.ConstraintType = G[BestIdx].second; } // 'X' matches anything. From 3ac190b1af30db5c1b3e33c84d2b009997d26745 Mon Sep 17 00:00:00 2001 From: Nick Desaulniers Date: Thu, 21 Sep 2023 11:23:55 -0700 Subject: [PATCH 2/6] [TargetLowering] use less std::string I want to use StringRef, let me replace one use of std::string. --- llvm/include/llvm/CodeGen/TargetLowering.h | 5 +++-- llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp | 5 +++-- llvm/lib/Target/AArch64/AArch64ISelLowering.cpp | 4 ++-- llvm/lib/Target/AArch64/AArch64ISelLowering.h | 2 +- llvm/lib/Target/AMDGPU/SIISelLowering.cpp | 5 ++--- llvm/lib/Target/AMDGPU/SIISelLowering.h | 6 ++---- llvm/lib/Target/ARM/ARMISelLowering.cpp | 12 ++++++------ llvm/lib/Target/ARM/ARMISelLowering.h | 2 +- llvm/lib/Target/AVR/AVRISelLowering.cpp | 4 ++-- llvm/lib/Target/AVR/AVRISelLowering.h | 2 +- llvm/lib/Target/Lanai/LanaiISelLowering.cpp | 4 ++-- llvm/lib/Target/Lanai/LanaiISelLowering.h | 2 +- llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp | 4 ++-- llvm/lib/Target/LoongArch/LoongArchISelLowering.h | 2 +- llvm/lib/Target/M68k/M68kISelLowering.cpp | 2 +- llvm/lib/Target/M68k/M68kISelLowering.h | 2 +- llvm/lib/Target/Mips/MipsISelLowering.cpp | 9 +++++---- llvm/lib/Target/Mips/MipsISelLowering.h | 4 +--- llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp | 7 +++---- llvm/lib/Target/NVPTX/NVPTXISelLowering.h | 2 +- llvm/lib/Target/PowerPC/PPCISelLowering.cpp | 7 ++++--- llvm/lib/Target/PowerPC/PPCISelLowering.h | 3 +-- llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 4 ++-- llvm/lib/Target/RISCV/RISCVISelLowering.h | 2 +- llvm/lib/Target/Sparc/SparcISelLowering.cpp | 10 ++++------ llvm/lib/Target/Sparc/SparcISelLowering.h | 3 +-- llvm/lib/Target/SystemZ/SystemZISelLowering.cpp | 9 ++++----- llvm/lib/Target/SystemZ/SystemZISelLowering.h | 3 +-- llvm/lib/Target/X86/X86ISelLowering.cpp | 7 ++++--- llvm/lib/Target/X86/X86ISelLowering.h | 3 +-- 30 files changed, 64 insertions(+), 72 deletions(-) diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h index ff3ef38cef90d..fd41d6a5ab751 100644 --- a/llvm/include/llvm/CodeGen/TargetLowering.h +++ b/llvm/include/llvm/CodeGen/TargetLowering.h @@ -4820,7 +4820,7 @@ class TargetLowering : public TargetLoweringBase { /// Given a constraint, return the type of constraint it is for this target. virtual ConstraintType getConstraintType(StringRef Constraint) const; - using ConstraintPair = std::pair; + using ConstraintPair = std::pair; using ConstraintGroup = SmallVector; /// Given an OpInfo with list of constraints codes as strings, return a /// sorted Vector of pairs of constraint codes and their types in priority of @@ -4862,7 +4862,8 @@ class TargetLowering : public TargetLoweringBase { /// Lower the specified operand into the Ops vector. If it is invalid, don't /// add anything to Ops. - virtual void LowerAsmOperandForConstraint(SDValue Op, std::string &Constraint, + virtual void LowerAsmOperandForConstraint(SDValue Op, + const StringRef Constraint, std::vector &Ops, SelectionDAG &DAG) const; diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp index c20ed63783669..a6ac340937fc0 100644 --- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -5378,11 +5378,12 @@ SDValue TargetLowering::LowerAsmOutputForConstraint( /// Lower the specified operand into the Ops vector. /// If it is invalid, don't add anything to Ops. void TargetLowering::LowerAsmOperandForConstraint(SDValue Op, - std::string &Constraint, + StringRef Constraint, std::vector &Ops, SelectionDAG &DAG) const { - if (Constraint.length() > 1) return; + if (Constraint.size() > 1) + return; char ConstraintLetter = Constraint[0]; switch (ConstraintLetter) { diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index fd6068c9787e6..0f11fd96e6bf3 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -10325,12 +10325,12 @@ EVT AArch64TargetLowering::getAsmOperandValueType(const DataLayout &DL, /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops /// vector. If it is invalid, don't add anything to Ops. void AArch64TargetLowering::LowerAsmOperandForConstraint( - SDValue Op, std::string &Constraint, std::vector &Ops, + SDValue Op, StringRef Constraint, std::vector &Ops, SelectionDAG &DAG) const { SDValue Result; // Currently only support length 1 constraints. - if (Constraint.length() != 1) + if (Constraint.size() != 1) return; char ConstraintLetter = Constraint[0]; diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.h b/llvm/lib/Target/AArch64/AArch64ISelLowering.h index 48b5bc16b3653..822d926e77b48 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.h +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.h @@ -1165,7 +1165,7 @@ class AArch64TargetLowering : public TargetLowering { const char *LowerXConstraint(EVT ConstraintVT) const override; - void LowerAsmOperandForConstraint(SDValue Op, std::string &Constraint, + void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector &Ops, SelectionDAG &DAG) const override; diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp index 1c85ec3f9f521..7d4812e20811a 100644 --- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp +++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp @@ -13817,7 +13817,7 @@ static uint64_t clearUnusedBits(uint64_t Val, unsigned Size) { } void SITargetLowering::LowerAsmOperandForConstraint(SDValue Op, - std::string &Constraint, + StringRef Constraint, std::vector &Ops, SelectionDAG &DAG) const { if (isImmConstraint(Constraint)) { @@ -13866,8 +13866,7 @@ bool SITargetLowering::getAsmOperandConstVal(SDValue Op, uint64_t &Val) const { return false; } -bool SITargetLowering::checkAsmConstraintVal(SDValue Op, - const std::string &Constraint, +bool SITargetLowering::checkAsmConstraintVal(SDValue Op, StringRef Constraint, uint64_t Val) const { if (Constraint.size() == 1) { switch (Constraint[0]) { diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.h b/llvm/lib/Target/AMDGPU/SIISelLowering.h index ffe49f651fdb3..1a3f829d787bc 100644 --- a/llvm/lib/Target/AMDGPU/SIISelLowering.h +++ b/llvm/lib/Target/AMDGPU/SIISelLowering.h @@ -468,13 +468,11 @@ class SITargetLowering final : public AMDGPUTargetLowering { getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const override; ConstraintType getConstraintType(StringRef Constraint) const override; - void LowerAsmOperandForConstraint(SDValue Op, - std::string &Constraint, + void LowerAsmOperandForConstraint(SDValue Op, const StringRef Constraint, std::vector &Ops, SelectionDAG &DAG) const override; bool getAsmOperandConstVal(SDValue Op, uint64_t &Val) const; - bool checkAsmConstraintVal(SDValue Op, - const std::string &Constraint, + bool checkAsmConstraintVal(SDValue Op, StringRef Constraint, uint64_t Val) const; bool checkAsmConstraintValA(SDValue Op, uint64_t Val, diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp index 21489a61e576f..b9b118f821038 100644 --- a/llvm/lib/Target/ARM/ARMISelLowering.cpp +++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -111,7 +111,6 @@ #include #include #include -#include #include #include #include @@ -20252,14 +20251,14 @@ bool ARMTargetLowering::ExpandInlineAsm(CallInst *CI) const { return false; InlineAsm *IA = cast(CI->getCalledOperand()); - std::string AsmStr = IA->getAsmString(); + StringRef AsmStr = IA->getAsmString(); SmallVector AsmPieces; SplitString(AsmStr, AsmPieces, ";\n"); switch (AsmPieces.size()) { default: return false; case 1: - AsmStr = std::string(AsmPieces[0]); + AsmStr = AsmPieces[0]; AsmPieces.clear(); SplitString(AsmStr, AsmPieces, " \t,"); @@ -20439,13 +20438,14 @@ RCPair ARMTargetLowering::getRegForInlineAsmConstraint( /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops /// vector. If it is invalid, don't add anything to Ops. void ARMTargetLowering::LowerAsmOperandForConstraint(SDValue Op, - std::string &Constraint, - std::vector&Ops, + StringRef Constraint, + std::vector &Ops, SelectionDAG &DAG) const { SDValue Result; // Currently only support length 1 constraints. - if (Constraint.length() != 1) return; + if (Constraint.size() != 1) + return; char ConstraintLetter = Constraint[0]; switch (ConstraintLetter) { diff --git a/llvm/lib/Target/ARM/ARMISelLowering.h b/llvm/lib/Target/ARM/ARMISelLowering.h index efa8238676860..6c2b92de7a1df 100644 --- a/llvm/lib/Target/ARM/ARMISelLowering.h +++ b/llvm/lib/Target/ARM/ARMISelLowering.h @@ -530,7 +530,7 @@ class VectorType; /// vector. If it is invalid, don't add anything to Ops. If hasMemory is /// true it means one of the asm constraint of the inline asm instruction /// being processed is 'm'. - void LowerAsmOperandForConstraint(SDValue Op, std::string &Constraint, + void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector &Ops, SelectionDAG &DAG) const override; diff --git a/llvm/lib/Target/AVR/AVRISelLowering.cpp b/llvm/lib/Target/AVR/AVRISelLowering.cpp index 4f5a48bd05a4e..cd1dcfaea0eb1 100644 --- a/llvm/lib/Target/AVR/AVRISelLowering.cpp +++ b/llvm/lib/Target/AVR/AVRISelLowering.cpp @@ -2722,7 +2722,7 @@ AVRTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, } void AVRTargetLowering::LowerAsmOperandForConstraint(SDValue Op, - std::string &Constraint, + StringRef Constraint, std::vector &Ops, SelectionDAG &DAG) const { SDValue Result; @@ -2730,7 +2730,7 @@ void AVRTargetLowering::LowerAsmOperandForConstraint(SDValue Op, EVT Ty = Op.getValueType(); // Currently only support length 1 constraints. - if (Constraint.length() != 1) { + if (Constraint.size() != 1) { return; } diff --git a/llvm/lib/Target/AVR/AVRISelLowering.h b/llvm/lib/Target/AVR/AVRISelLowering.h index 6815b519bebf7..f605795934532 100644 --- a/llvm/lib/Target/AVR/AVRISelLowering.h +++ b/llvm/lib/Target/AVR/AVRISelLowering.h @@ -136,7 +136,7 @@ class AVRTargetLowering : public TargetLowering { InlineAsm::ConstraintCode getInlineAsmMemConstraint(StringRef ConstraintCode) const override; - void LowerAsmOperandForConstraint(SDValue Op, std::string &Constraint, + void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector &Ops, SelectionDAG &DAG) const override; diff --git a/llvm/lib/Target/Lanai/LanaiISelLowering.cpp b/llvm/lib/Target/Lanai/LanaiISelLowering.cpp index 157f860274339..cbb5c2b998e27 100644 --- a/llvm/lib/Target/Lanai/LanaiISelLowering.cpp +++ b/llvm/lib/Target/Lanai/LanaiISelLowering.cpp @@ -278,12 +278,12 @@ LanaiTargetLowering::getSingleConstraintMatchWeight( // LowerAsmOperandForConstraint - Lower the specified operand into the Ops // vector. If it is invalid, don't add anything to Ops. void LanaiTargetLowering::LowerAsmOperandForConstraint( - SDValue Op, std::string &Constraint, std::vector &Ops, + SDValue Op, StringRef Constraint, std::vector &Ops, SelectionDAG &DAG) const { SDValue Result; // Only support length 1 constraints for now. - if (Constraint.length() > 1) + if (Constraint.size() > 1) return; char ConstraintLetter = Constraint[0]; diff --git a/llvm/lib/Target/Lanai/LanaiISelLowering.h b/llvm/lib/Target/Lanai/LanaiISelLowering.h index ea1159db9e596..5fa5444b51618 100644 --- a/llvm/lib/Target/Lanai/LanaiISelLowering.h +++ b/llvm/lib/Target/Lanai/LanaiISelLowering.h @@ -103,7 +103,7 @@ class LanaiTargetLowering : public TargetLowering { ConstraintWeight getSingleConstraintMatchWeight(AsmOperandInfo &Info, const char *Constraint) const override; - void LowerAsmOperandForConstraint(SDValue Op, std::string &Constraint, + void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector &Ops, SelectionDAG &DAG) const override; diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp index a4fa79cb0aade..a97523d17c181 100644 --- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp @@ -4371,10 +4371,10 @@ LoongArchTargetLowering::getRegForInlineAsmConstraint( } void LoongArchTargetLowering::LowerAsmOperandForConstraint( - SDValue Op, std::string &Constraint, std::vector &Ops, + SDValue Op, StringRef Constraint, std::vector &Ops, SelectionDAG &DAG) const { // Currently only support length 1 constraints. - if (Constraint.length() == 1) { + if (Constraint.size() == 1) { switch (Constraint[0]) { case 'l': // Validate & create a 16-bit signed immediate operand. diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h index 9d531894a1378..49d563a51389b 100644 --- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h +++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h @@ -290,7 +290,7 @@ class LoongArchTargetLowering : public TargetLowering { getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const override; - void LowerAsmOperandForConstraint(SDValue Op, std::string &Constraint, + void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector &Ops, SelectionDAG &DAG) const override; diff --git a/llvm/lib/Target/M68k/M68kISelLowering.cpp b/llvm/lib/Target/M68k/M68kISelLowering.cpp index 82f6d7323cf60..d1ed26457fbcf 100644 --- a/llvm/lib/Target/M68k/M68kISelLowering.cpp +++ b/llvm/lib/Target/M68k/M68kISelLowering.cpp @@ -2897,7 +2897,7 @@ M68kTargetLowering::getConstraintType(StringRef Constraint) const { } void M68kTargetLowering::LowerAsmOperandForConstraint(SDValue Op, - std::string &Constraint, + StringRef Constraint, std::vector &Ops, SelectionDAG &DAG) const { SDValue Result; diff --git a/llvm/lib/Target/M68k/M68kISelLowering.h b/llvm/lib/Target/M68k/M68kISelLowering.h index 37e66695fde90..02427a4e749e0 100644 --- a/llvm/lib/Target/M68k/M68kISelLowering.h +++ b/llvm/lib/Target/M68k/M68kISelLowering.h @@ -163,7 +163,7 @@ class M68kTargetLowering : public TargetLowering { StringRef Constraint, MVT VT) const override; // Lower operand with C_Immediate and C_Other constraint type - void LowerAsmOperandForConstraint(SDValue Op, std::string &Constraint, + void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector &Ops, SelectionDAG &DAG) const override; diff --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp index 18d7773067f13..6ff829261f5c2 100644 --- a/llvm/lib/Target/Mips/MipsISelLowering.cpp +++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp @@ -4198,14 +4198,15 @@ MipsTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops /// vector. If it is invalid, don't add anything to Ops. void MipsTargetLowering::LowerAsmOperandForConstraint(SDValue Op, - std::string &Constraint, - std::vector&Ops, - SelectionDAG &DAG) const { + StringRef Constraint, + std::vector &Ops, + SelectionDAG &DAG) const { SDLoc DL(Op); SDValue Result; // Only support length 1 constraints for now. - if (Constraint.length() > 1) return; + if (Constraint.size() > 1) + return; char ConstraintLetter = Constraint[0]; switch (ConstraintLetter) { diff --git a/llvm/lib/Target/Mips/MipsISelLowering.h b/llvm/lib/Target/Mips/MipsISelLowering.h index 4b5700b7e28dd..81d37ff2f065f 100644 --- a/llvm/lib/Target/Mips/MipsISelLowering.h +++ b/llvm/lib/Target/Mips/MipsISelLowering.h @@ -33,7 +33,6 @@ #include #include #include -#include #include #include @@ -641,8 +640,7 @@ class TargetRegisterClass; /// vector. If it is invalid, don't add anything to Ops. If hasMemory is /// true it means one of the asm constraint of the inline asm instruction /// being processed is 'm'. - void LowerAsmOperandForConstraint(SDValue Op, - std::string &Constraint, + void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector &Ops, SelectionDAG &DAG) const override; diff --git a/llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp b/llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp index e4d5e5c71b7e1..16e96d20ffbc8 100644 --- a/llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp +++ b/llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp @@ -3088,12 +3088,11 @@ NVPTXTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, } void NVPTXTargetLowering::LowerAsmOperandForConstraint( - SDValue Op, std::string &Constraint, std::vector &Ops, + SDValue Op, StringRef Constraint, std::vector &Ops, SelectionDAG &DAG) const { - if (Constraint.length() > 1) + if (Constraint.size() > 1) return; - else - TargetLowering::LowerAsmOperandForConstraint(Op, Constraint, Ops, DAG); + TargetLowering::LowerAsmOperandForConstraint(Op, Constraint, Ops, DAG); } static unsigned getOpcForTextureInstr(unsigned Intrinsic) { diff --git a/llvm/lib/Target/NVPTX/NVPTXISelLowering.h b/llvm/lib/Target/NVPTX/NVPTXISelLowering.h index 0b760d06743ee..cd1985cc4219b 100644 --- a/llvm/lib/Target/NVPTX/NVPTXISelLowering.h +++ b/llvm/lib/Target/NVPTX/NVPTXISelLowering.h @@ -520,7 +520,7 @@ class NVPTXTargetLowering : public TargetLowering { const SmallVectorImpl &OutVals, const SDLoc &dl, SelectionDAG &DAG) const override; - void LowerAsmOperandForConstraint(SDValue Op, std::string &Constraint, + void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector &Ops, SelectionDAG &DAG) const override; diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp index f4e3531980d16..740e5e2ff4b4c 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -16718,13 +16718,14 @@ PPCTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops /// vector. If it is invalid, don't add anything to Ops. void PPCTargetLowering::LowerAsmOperandForConstraint(SDValue Op, - std::string &Constraint, - std::vector&Ops, + StringRef Constraint, + std::vector &Ops, SelectionDAG &DAG) const { SDValue Result; // Only support length 1 constraints. - if (Constraint.length() > 1) return; + if (Constraint.size() > 1) + return; char Letter = Constraint[0]; switch (Letter) { diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.h b/llvm/lib/Target/PowerPC/PPCISelLowering.h index 7c62e370f1536..d8679dcf40180 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.h +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.h @@ -975,8 +975,7 @@ namespace llvm { /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops /// vector. If it is invalid, don't add anything to Ops. - void LowerAsmOperandForConstraint(SDValue Op, - std::string &Constraint, + void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector &Ops, SelectionDAG &DAG) const override; diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index a89961dccc70f..2043189dec8db 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -17434,10 +17434,10 @@ RISCVTargetLowering::getInlineAsmMemConstraint(StringRef ConstraintCode) const { } void RISCVTargetLowering::LowerAsmOperandForConstraint( - SDValue Op, std::string &Constraint, std::vector &Ops, + SDValue Op, StringRef Constraint, std::vector &Ops, SelectionDAG &DAG) const { // Currently only support length 1 constraints. - if (Constraint.length() == 1) { + if (Constraint.size() == 1) { switch (Constraint[0]) { case 'I': // Validate & create a 12-bit signed immediate operand. diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.h b/llvm/lib/Target/RISCV/RISCVISelLowering.h index e4481a0f6752f..5e1e0c4f53665 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.h +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.h @@ -573,7 +573,7 @@ class RISCVTargetLowering : public TargetLowering { getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const override; - void LowerAsmOperandForConstraint(SDValue Op, std::string &Constraint, + void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector &Ops, SelectionDAG &DAG) const override; diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp index 0091cb7b8bbe7..4d1acc9ad1453 100644 --- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp +++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp @@ -3428,15 +3428,13 @@ getSingleConstraintMatchWeight(AsmOperandInfo &info, /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops /// vector. If it is invalid, don't add anything to Ops. -void SparcTargetLowering:: -LowerAsmOperandForConstraint(SDValue Op, - std::string &Constraint, - std::vector &Ops, - SelectionDAG &DAG) const { +void SparcTargetLowering::LowerAsmOperandForConstraint( + SDValue Op, StringRef Constraint, std::vector &Ops, + SelectionDAG &DAG) const { SDValue Result; // Only support length 1 constraints for now. - if (Constraint.length() > 1) + if (Constraint.size() > 1) return; char ConstraintLetter = Constraint[0]; diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.h b/llvm/lib/Target/Sparc/SparcISelLowering.h index 5504dcd464fb2..b7b48decef3d7 100644 --- a/llvm/lib/Target/Sparc/SparcISelLowering.h +++ b/llvm/lib/Target/Sparc/SparcISelLowering.h @@ -88,8 +88,7 @@ namespace llvm { ConstraintWeight getSingleConstraintMatchWeight(AsmOperandInfo &info, const char *constraint) const override; - void LowerAsmOperandForConstraint(SDValue Op, - std::string &Constraint, + void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector &Ops, SelectionDAG &DAG) const override; diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp index 6a56869ca20f8..886b5e93bffc0 100644 --- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp +++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp @@ -1289,12 +1289,11 @@ SystemZTargetLowering::getRegisterByName(const char *RegName, LLT VT, report_fatal_error("Invalid register name global variable"); } -void SystemZTargetLowering:: -LowerAsmOperandForConstraint(SDValue Op, std::string &Constraint, - std::vector &Ops, - SelectionDAG &DAG) const { +void SystemZTargetLowering::LowerAsmOperandForConstraint( + SDValue Op, StringRef Constraint, std::vector &Ops, + SelectionDAG &DAG) const { // Only support length 1 constraints for now. - if (Constraint.length() == 1) { + if (Constraint.size() == 1) { switch (Constraint[0]) { case 'I': // Unsigned 8-bit constant if (auto *C = dyn_cast(Op)) diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.h b/llvm/lib/Target/SystemZ/SystemZISelLowering.h index 8feeb61abd798..0d4b4873e9d73 100644 --- a/llvm/lib/Target/SystemZ/SystemZISelLowering.h +++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.h @@ -487,8 +487,7 @@ class SystemZTargetLowering : public TargetLowering { TargetLowering::ConstraintWeight getSingleConstraintMatchWeight(AsmOperandInfo &info, const char *constraint) const override; - void LowerAsmOperandForConstraint(SDValue Op, - std::string &Constraint, + void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector &Ops, SelectionDAG &DAG) const override; diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 5c0c3af364259..a9838ef30a73e 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -56541,13 +56541,14 @@ SDValue X86TargetLowering::LowerAsmOutputForConstraint( /// Lower the specified operand into the Ops vector. /// If it is invalid, don't add anything to Ops. void X86TargetLowering::LowerAsmOperandForConstraint(SDValue Op, - std::string &Constraint, - std::vector&Ops, + StringRef Constraint, + std::vector &Ops, SelectionDAG &DAG) const { SDValue Result; // Only support length 1 constraints for now. - if (Constraint.length() > 1) return; + if (Constraint.size() > 1) + return; char ConstraintLetter = Constraint[0]; switch (ConstraintLetter) { diff --git a/llvm/lib/Target/X86/X86ISelLowering.h b/llvm/lib/Target/X86/X86ISelLowering.h index 4d45a0a584421..3cbede2cead56 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.h +++ b/llvm/lib/Target/X86/X86ISelLowering.h @@ -1274,8 +1274,7 @@ namespace llvm { /// Lower the specified operand into the Ops vector. If it is invalid, don't /// add anything to Ops. If hasMemory is true it means one of the asm /// constraint of the inline asm instruction being processed is 'm'. - void LowerAsmOperandForConstraint(SDValue Op, - std::string &Constraint, + void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector &Ops, SelectionDAG &DAG) const override; From 5d1d8abef203f0457ce5d7cd47d7e25074cc85fb Mon Sep 17 00:00:00 2001 From: Nick Desaulniers Date: Thu, 21 Sep 2023 14:33:38 -0700 Subject: [PATCH 3/6] remove const --- llvm/include/llvm/CodeGen/TargetLowering.h | 3 +-- llvm/lib/Target/AMDGPU/SIISelLowering.h | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h index fd41d6a5ab751..6fda35f0c0400 100644 --- a/llvm/include/llvm/CodeGen/TargetLowering.h +++ b/llvm/include/llvm/CodeGen/TargetLowering.h @@ -4862,8 +4862,7 @@ class TargetLowering : public TargetLoweringBase { /// Lower the specified operand into the Ops vector. If it is invalid, don't /// add anything to Ops. - virtual void LowerAsmOperandForConstraint(SDValue Op, - const StringRef Constraint, + virtual void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector &Ops, SelectionDAG &DAG) const; diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.h b/llvm/lib/Target/AMDGPU/SIISelLowering.h index 1a3f829d787bc..2cc42b9ac2e1f 100644 --- a/llvm/lib/Target/AMDGPU/SIISelLowering.h +++ b/llvm/lib/Target/AMDGPU/SIISelLowering.h @@ -468,7 +468,7 @@ class SITargetLowering final : public AMDGPUTargetLowering { getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const override; ConstraintType getConstraintType(StringRef Constraint) const override; - void LowerAsmOperandForConstraint(SDValue Op, const StringRef Constraint, + void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector &Ops, SelectionDAG &DAG) const override; bool getAsmOperandConstVal(SDValue Op, uint64_t &Val) const; From 2d16f27727b10937e76a715c9142a5d7e68f5173 Mon Sep 17 00:00:00 2001 From: Nick Desaulniers Date: Thu, 21 Sep 2023 14:34:29 -0700 Subject: [PATCH 4/6] fix typo --- llvm/include/llvm/CodeGen/TargetLowering.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h index 6fda35f0c0400..a94b9f79b9f61 100644 --- a/llvm/include/llvm/CodeGen/TargetLowering.h +++ b/llvm/include/llvm/CodeGen/TargetLowering.h @@ -4824,7 +4824,7 @@ class TargetLowering : public TargetLoweringBase { using ConstraintGroup = SmallVector; /// Given an OpInfo with list of constraints codes as strings, return a /// sorted Vector of pairs of constraint codes and their types in priority of - /// what we'd prefer to lower them as. This may contains immediates that + /// what we'd prefer to lower them as. This may contain immediates that /// cannot be lowered, but it is meant to be a machine agnostic order of /// preferences. ConstraintGroup getConstraintPreferences(AsmOperandInfo &OpInfo) const; From a542e81ffc8a7d178f4a661c40c6155e04388e63 Mon Sep 17 00:00:00 2001 From: Nick Desaulniers Date: Thu, 21 Sep 2023 14:36:18 -0700 Subject: [PATCH 5/6] improve fn comment for getConstraintPiority, reorder case statements --- llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp index a6ac340937fc0..78c2e3ba0b5f4 100644 --- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -5704,24 +5704,25 @@ TargetLowering::ParseConstraints(const DataLayout &DL, /// Return a number indicating our preference for chosing a type of constraint /// over another, for the purpose of sorting them. Immediates are almost always -/// preferrable (when they can be emitted). +/// preferrable (when they can be emitted). A higher return value means a +/// stronger preference for one constraint type relative to another. /// FIXME: We should prefer registers over memory but doing so may lead to /// unrecoverable register exhaustion later. /// https://github.com/llvm/llvm-project/issues/20571 static unsigned getConstraintPiority(TargetLowering::ConstraintType CT) { switch (CT) { - case TargetLowering::C_Unknown: - return 0; case TargetLowering::C_Immediate: case TargetLowering::C_Other: return 4; - case TargetLowering::C_Register: - return 1; - case TargetLowering::C_RegisterClass: - return 2; case TargetLowering::C_Memory: case TargetLowering::C_Address: return 3; + case TargetLowering::C_RegisterClass: + return 2; + case TargetLowering::C_Register: + return 1; + case TargetLowering::C_Unknown: + return 0; } llvm_unreachable("Invalid constraint type"); } From a0cb4cb60f3ee83876929a152ed0a11abe34fe6c Mon Sep 17 00:00:00 2001 From: Nick Desaulniers Date: Fri, 22 Sep 2023 08:35:58 -0700 Subject: [PATCH 6/6] bound lowerImmediateIfPossible loop --- .../CodeGen/GlobalISel/InlineAsmLowering.cpp | 8 ++++--- .../CodeGen/SelectionDAG/TargetLowering.cpp | 22 ++++++++++--------- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/llvm/lib/CodeGen/GlobalISel/InlineAsmLowering.cpp b/llvm/lib/CodeGen/GlobalISel/InlineAsmLowering.cpp index a6d802c91f309..4089a5e941b05 100644 --- a/llvm/lib/CodeGen/GlobalISel/InlineAsmLowering.cpp +++ b/llvm/lib/CodeGen/GlobalISel/InlineAsmLowering.cpp @@ -147,9 +147,11 @@ static void computeConstraintToUse(const TargetLowering *TLI, return; // FIXME: prefer immediate constraints if the target allows it unsigned BestIdx = 0; - while (G[BestIdx].second == TargetLowering::C_Other || - G[BestIdx].second == TargetLowering::C_Immediate) - ++BestIdx; + for (const unsigned E = G.size(); + BestIdx < E && (G[BestIdx].second == TargetLowering::C_Other || + G[BestIdx].second == TargetLowering::C_Immediate); + ++BestIdx) + ; OpInfo.ConstraintCode = G[BestIdx].first; OpInfo.ConstraintType = G[BestIdx].second; } diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp index 78c2e3ba0b5f4..ae76489d9f308 100644 --- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -5849,15 +5849,16 @@ TargetLowering::ConstraintGroup TargetLowering::getConstraintPreferences( return Ret; } -// If we have an immediate, see if we can lower it. Return true if we can, or -// don't have an immediate, false otherwise. +/// If we have an immediate, see if we can lower it. Return true if we can, +/// false otherwise. static bool lowerImmediateIfPossible(TargetLowering::ConstraintPair &P, SDValue Op, SelectionDAG *DAG, const TargetLowering &TLI) { - if (P.second != TargetLowering::C_Other && - P.second != TargetLowering::C_Immediate) - return true; + assert((P.second == TargetLowering::C_Other || + P.second == TargetLowering::C_Immediate) && + "need immediate or other"); + if (!Op.getNode()) return false; @@ -5883,11 +5884,12 @@ void TargetLowering::ComputeConstraintToUse(AsmOperandInfo &OpInfo, return; unsigned BestIdx = 0; - while (!lowerImmediateIfPossible(G[BestIdx], Op, DAG, *this)) { - if (BestIdx + 1 > G.size() - 1) - return; - ++BestIdx; - } + for (const unsigned E = G.size(); + BestIdx < E && (G[BestIdx].second == TargetLowering::C_Other || + G[BestIdx].second == TargetLowering::C_Immediate); + ++BestIdx) + if (lowerImmediateIfPossible(G[BestIdx], Op, DAG, *this)) + break; OpInfo.ConstraintCode = G[BestIdx].first; OpInfo.ConstraintType = G[BestIdx].second;