diff --git a/llvm/include/llvm/Target/TargetLowering.h b/llvm/include/llvm/Target/TargetLowering.h index 0ff58eb91ddd..559f0387ace1 100644 --- a/llvm/include/llvm/Target/TargetLowering.h +++ b/llvm/include/llvm/Target/TargetLowering.h @@ -1076,74 +1076,13 @@ public: ConstraintType(TargetLowering::C_Unknown), CallOperandVal(0), ConstraintVT(MVT::Other) { } - - /// getConstraintGenerality - Return an integer indicating how general CT is. - unsigned getConstraintGenerality(TargetLowering::ConstraintType CT) { - switch (CT) { - default: assert(0 && "Unknown constraint type!"); - 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: - return 3; - } - } - - /// ComputeConstraintToUse - Determines the constraint code and constraint - /// type to use. - void ComputeConstraintToUse(const TargetLowering &TLI) { - assert(!Codes.empty() && "Must have at least one constraint"); - - std::string *Current = &Codes[0]; - TargetLowering::ConstraintType CurType = TLI.getConstraintType(*Current); - // Single-letter constraints ('r') are very common. - if (Codes.size() == 1) { - ConstraintCode = *Current; - ConstraintType = CurType; - } else { - unsigned CurGenerality = getConstraintGenerality(CurType); - - // If we have multiple constraints, try to pick the most general one - // ahead of time. This isn't a wonderful solution, but handles common - // cases. - for (unsigned j = 1, e = Codes.size(); j != e; ++j) { - TargetLowering::ConstraintType ThisType = - TLI.getConstraintType(Codes[j]); - unsigned ThisGenerality = getConstraintGenerality(ThisType); - if (ThisGenerality > CurGenerality) { - // This constraint letter is more general than the previous one, - // use it. - CurType = ThisType; - Current = &Codes[j]; - CurGenerality = ThisGenerality; - } - } - - ConstraintCode = *Current; - ConstraintType = CurType; - } - - // 'X' matches anything. - if (ConstraintCode == "X" && CallOperandVal) { - // Labels and constants are handled elsewhere ('X' is the only thing - // that matches labels). - if (isa(CallOperandVal) || isa(CallOperandVal)) - return; - - // Otherwise, try to resolve it to something we know about by looking at - // the actual operand type. - if (const char *Repl = TLI.LowerXConstraint(ConstraintVT)) { - ConstraintCode = Repl; - ConstraintType = TLI.getConstraintType(ConstraintCode); - } - } - } }; + /// ComputeConstraintToUse - Determines the constraint code and constraint + /// type to use for the specific AsmOperandInfo, setting + /// OpInfo.ConstraintCode and OpInfo.ConstraintType. + virtual void ComputeConstraintToUse(AsmOperandInfo &OpInfo) const; + /// getConstraintType - Given a constraint, return the type of constraint it /// is for this target. virtual ConstraintType getConstraintType(const std::string &Constraint) const; diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 22e8ad8ef025..888d4605bd57 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -3824,7 +3824,7 @@ void SelectionDAGLowering::visitInlineAsm(CallSite CS) { OpInfo.ConstraintVT = OpVT; // Compute the constraint code and ConstraintType to use. - OpInfo.ComputeConstraintToUse(TLI); + TLI.ComputeConstraintToUse(OpInfo); // Keep track of whether we see an earlyclobber. SawEarlyClobber |= OpInfo.isEarlyClobber; diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp index 6c15ff91c940..cd43349411ee 100644 --- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -1498,6 +1498,7 @@ PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const { // Inline Assembler Implementation Methods //===----------------------------------------------------------------------===// + TargetLowering::ConstraintType TargetLowering::getConstraintType(const std::string &Constraint) const { // FIXME: lots more standard ones to handle. @@ -1646,6 +1647,102 @@ getRegForInlineAsmConstraint(const std::string &Constraint, return std::pair(0, 0); } +//===----------------------------------------------------------------------===// +// Constraint Selection. + +/// getConstraintGenerality - Return an integer indicating how general CT +/// is. +static unsigned getConstraintGenerality(TargetLowering::ConstraintType CT) { + switch (CT) { + default: assert(0 && "Unknown constraint type!"); + 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: + return 3; + } +} + +/// ChooseConstraint - If there are multiple different constraints that we +/// could pick for this operand (e.g. "imr") try to pick the 'best' one. +/// This is somewhat tricky: constraints fall into three four classes: +/// Other -> immediates and magic values +/// Register -> one specific register +/// RegisterClass -> a group of regs +/// Memory -> memory +/// Ideally, we would pick the most specific constraint possible: if we have +/// something that fits into a register, we would pick it. The problem here +/// is that if we have something that could either be in a register or in +/// memory that use of the register could cause selection of *other* +/// operands to fail: they might only succeed if we pick memory. Because of +/// this the heuristic we use is: +/// +/// 1) If there is an 'other' constraint, and if the operand is valid for +/// that constraint, use it. This makes us take advantage of 'i' +/// constraints when available. +/// 2) Otherwise, pick the most general constraint present. This prefers +/// 'm' over 'r', for example. +/// +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]); + + // 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; +} + +/// ComputeConstraintToUse - Determines the constraint code and constraint +/// type to use for the specific AsmOperandInfo, setting +/// OpInfo.ConstraintCode and OpInfo.ConstraintType. +void TargetLowering::ComputeConstraintToUse(AsmOperandInfo &OpInfo) const { + assert(!OpInfo.Codes.empty() && "Must have at least one constraint"); + + // Single-letter constraints ('r') are very common. + if (OpInfo.Codes.size() == 1) { + OpInfo.ConstraintCode = OpInfo.Codes[0]; + OpInfo.ConstraintType = getConstraintType(OpInfo.ConstraintCode); + } else { + ChooseConstraint(OpInfo, *this); + } + + // 'X' matches anything. + if (OpInfo.ConstraintCode == "X" && OpInfo.CallOperandVal) { + // Labels and constants are handled elsewhere ('X' is the only thing + // that matches labels). + if (isa(OpInfo.CallOperandVal) || + isa(OpInfo.CallOperandVal)) + return; + + // Otherwise, try to resolve it to something we know about by looking at + // the actual operand type. + if (const char *Repl = LowerXConstraint(OpInfo.ConstraintVT)) { + OpInfo.ConstraintCode = Repl; + OpInfo.ConstraintType = getConstraintType(OpInfo.ConstraintCode); + } + } +} + //===----------------------------------------------------------------------===// // Loop Strength Reduction hooks //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp b/llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp index 4be37a33cf44..cdabadeb3625 100644 --- a/llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp +++ b/llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp @@ -962,7 +962,7 @@ bool CodeGenPrepare::OptimizeInlineAsmInst(Instruction *I, CallSite CS, } // Compute the constraint code and ConstraintType to use. - OpInfo.ComputeConstraintToUse(*TLI); + TLI->ComputeConstraintToUse(OpInfo); if (OpInfo.ConstraintType == TargetLowering::C_Memory && OpInfo.isIndirect) {