diff --git a/include/llvm/CodeGen/Analysis.h b/include/llvm/CodeGen/Analysis.h index ee2e5201f92..a8292ea649e 100644 --- a/include/llvm/CodeGen/Analysis.h +++ b/include/llvm/CodeGen/Analysis.h @@ -52,7 +52,7 @@ GlobalVariable *ExtractTypeInfo(Value *V); /// hasInlineAsmMemConstraint - Return true if the inline asm instruction being /// processed uses a memory 'm' constraint. -bool hasInlineAsmMemConstraint(std::vector &CInfos, +bool hasInlineAsmMemConstraint(InlineAsm::ConstraintInfoVector &CInfos, const TargetLowering &TLI); /// getFCmpCondCode - Return the ISD condition code corresponding to diff --git a/include/llvm/InlineAsm.h b/include/llvm/InlineAsm.h index 0cb55b7f6e3..93438343255 100644 --- a/include/llvm/InlineAsm.h +++ b/include/llvm/InlineAsm.h @@ -16,8 +16,8 @@ #ifndef LLVM_INLINEASM_H #define LLVM_INLINEASM_H +#include "llvm/ADT/SmallVector.h" #include "llvm/Value.h" -#include namespace llvm { @@ -87,6 +87,8 @@ public: isClobber // '~x' }; + typedef SmallVector ConstraintCodeVector; + struct SubConstraintInfo { /// MatchingInput - If this is not -1, this is an output constraint where an /// input constraint is required to match it (e.g. "0"). The value is the @@ -95,10 +97,14 @@ public: signed char MatchingInput; /// Code - The constraint code, either the register name (in braces) or the /// constraint letter/number. - std::vector Codes; + ConstraintCodeVector Codes; /// Default constructor. SubConstraintInfo() : MatchingInput(-1) {} }; + + typedef SmallVector SubConstraintInfoVector; + struct ConstraintInfo; + typedef SmallVector ConstraintInfoVector; struct ConstraintInfo { /// Type - The basic type of the constraint: input/output/clobber @@ -131,14 +137,14 @@ public: /// Code - The constraint code, either the register name (in braces) or the /// constraint letter/number. - std::vector Codes; + ConstraintCodeVector Codes; /// isMultipleAlternative - '|': has multiple-alternative constraints. bool isMultipleAlternative; /// multipleAlternatives - If there are multiple alternative constraints, /// this array will contain them. Otherwise it will be empty. - std::vector multipleAlternatives; + SubConstraintInfoVector multipleAlternatives; /// The currently selected alternative constraint index. unsigned currentAlternativeIndex; @@ -152,8 +158,7 @@ public: /// Parse - Analyze the specified string (e.g. "=*&{eax}") and fill in the /// fields in this structure. If the constraint string is not understood, /// return true, otherwise return false. - bool Parse(StringRef Str, - std::vector &ConstraintsSoFar); + bool Parse(StringRef Str, ConstraintInfoVector &ConstraintsSoFar); /// selectAlternative - Point this constraint to the alternative constraint /// indicated by the index. @@ -163,13 +168,11 @@ public: /// ParseConstraints - Split up the constraint string into the specific /// constraints and their prefixes. If this returns an empty vector, and if /// the constraint string itself isn't empty, there was an error parsing. - static std::vector - ParseConstraints(StringRef ConstraintString); + static ConstraintInfoVector ParseConstraints(StringRef ConstraintString); /// ParseConstraints - Parse the constraints of this inlineasm object, /// returning them the same way that ParseConstraints(str) does. - std::vector - ParseConstraints() const { + ConstraintInfoVector ParseConstraints() const { return ParseConstraints(Constraints); } diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h index 7849752d0df..d9b01314467 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -1320,6 +1320,22 @@ public: C_Unknown // Unsupported constraint. }; + enum ConstraintWeight { + // Generic weights. + CW_Invalid = -1, // No match. + CW_Okay = 0, // Acceptable. + CW_Good = 1, // Good weight. + CW_Better = 2, // Better weight. + CW_Best = 3, // Best weight. + + // Well-known weights. + CW_SpecificReg = CW_Okay, // Specific register operands. + CW_Register = CW_Good, // Register operands. + CW_Memory = CW_Better, // Memory operands. + CW_Constant = CW_Best, // Constant operand. + CW_Default = CW_Okay // Default or don't know type. + }; + /// AsmOperandInfo - This contains information for each constraint that we are /// lowering. struct AsmOperandInfo : public InlineAsm::ConstraintInfo { @@ -1365,24 +1381,23 @@ public: } }; + typedef SmallVector AsmOperandInfoVector; + /// ParseConstraints - Split up the constraint string from the inline /// assembly value into the specific constraints and their prefixes, /// and also tie in the associated operand values. /// If this returns an empty vector, and if the constraint string itself /// isn't empty, there was an error parsing. - virtual std::vector ParseConstraints( - ImmutableCallSite CS) const; + virtual AsmOperandInfoVector ParseConstraints(ImmutableCallSite CS) const; - /// Examine constraint type and operand type and determine a weight value, - /// where: -1 = invalid match, and 0 = so-so match to 5 = good match. + /// Examine constraint type and operand type and determine a weight value. /// The operand object must already have been set up with the operand type. - virtual int getMultipleConstraintMatchWeight( + virtual ConstraintWeight getMultipleConstraintMatchWeight( AsmOperandInfo &info, int maIndex) const; - /// Examine constraint string and operand type and determine a weight value, - /// where: -1 = invalid match, and 0 = so-so match to 3 = good match. + /// Examine constraint string and operand type and determine a weight value. /// The operand object must already have been set up with the operand type. - virtual int getSingleConstraintMatchWeight( + virtual ConstraintWeight getSingleConstraintMatchWeight( AsmOperandInfo &info, const char *constraint) const; /// ComputeConstraintToUse - Determines the constraint code and constraint diff --git a/lib/CodeGen/Analysis.cpp b/lib/CodeGen/Analysis.cpp index 57e305ea108..2cf3c6666cd 100644 --- a/lib/CodeGen/Analysis.cpp +++ b/lib/CodeGen/Analysis.cpp @@ -125,7 +125,7 @@ GlobalVariable *llvm::ExtractTypeInfo(Value *V) { /// hasInlineAsmMemConstraint - Return true if the inline asm instruction being /// processed uses a memory 'm' constraint. bool -llvm::hasInlineAsmMemConstraint(std::vector &CInfos, +llvm::hasInlineAsmMemConstraint(InlineAsm::ConstraintInfoVector &CInfos, const TargetLowering &TLI) { for (unsigned i = 0, e = CInfos.size(); i != e; ++i) { InlineAsm::ConstraintInfo &CI = CInfos[i]; diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 1d7519b3b44..9881ebce08c 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -5221,6 +5221,8 @@ private: } }; +typedef SmallVector SDISelAsmOperandInfoVector; + } // end llvm namespace. /// isAllocatableRegister - If the specified register is safe to allocate, @@ -5458,11 +5460,11 @@ void SelectionDAGBuilder::visitInlineAsm(ImmutableCallSite CS) { const InlineAsm *IA = cast(CS.getCalledValue()); /// ConstraintOperands - Information about all of the constraints. - std::vector ConstraintOperands; + SDISelAsmOperandInfoVector ConstraintOperands; std::set OutputRegs, InputRegs; - std::vector TargetConstraints = TLI.ParseConstraints(CS); + TargetLowering::AsmOperandInfoVector TargetConstraints = TLI.ParseConstraints(CS); bool hasMemory = false; unsigned ArgNo = 0; // ArgNo - The argument of the CallInst. diff --git a/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/lib/CodeGen/SelectionDAG/TargetLowering.cpp index fdd467a794c..1c9fcc12933 100644 --- a/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -2664,16 +2664,16 @@ unsigned TargetLowering::AsmOperandInfo::getMatchedOperand() const { /// and also tie in the associated operand values. /// If this returns an empty vector, and if the constraint string itself /// isn't empty, there was an error parsing. -std::vector TargetLowering::ParseConstraints( +TargetLowering::AsmOperandInfoVector TargetLowering::ParseConstraints( ImmutableCallSite CS) const { /// ConstraintOperands - Information about all of the constraints. - std::vector ConstraintOperands; + AsmOperandInfoVector ConstraintOperands; const InlineAsm *IA = cast(CS.getCalledValue()); unsigned maCount = 0; // Largest number of multiple alternative constraints. // Do a prepass over the constraints, canonicalizing them, and building up the // ConstraintOperands list. - std::vector + InlineAsm::ConstraintInfoVector ConstraintInfos = IA->ParseConstraints(); unsigned ArgNo = 0; // ArgNo - The argument of the CallInst. @@ -2687,7 +2687,7 @@ std::vector TargetLowering::ParseConstraints( if (OpInfo.multipleAlternatives.size() > maCount) maCount = OpInfo.multipleAlternatives.size(); - EVT OpVT = MVT::Other; + OpInfo.ConstraintVT = MVT::Other; // Compute the value type for each operand. switch (OpInfo.Type) { @@ -2703,10 +2703,10 @@ std::vector TargetLowering::ParseConstraints( assert(!CS.getType()->isVoidTy() && "Bad inline asm!"); if (const StructType *STy = dyn_cast(CS.getType())) { - OpVT = getValueType(STy->getElementType(ResNo)); + OpInfo.ConstraintVT = getValueType(STy->getElementType(ResNo)); } else { assert(ResNo == 0 && "Asm only has one result!"); - OpVT = getValueType(CS.getType()); + OpInfo.ConstraintVT = getValueType(CS.getType()); } ++ResNo; break; @@ -2717,6 +2717,36 @@ std::vector TargetLowering::ParseConstraints( // Nothing to do. break; } + + if (OpInfo.CallOperandVal) { + const llvm::Type *OpTy = OpInfo.CallOperandVal->getType(); + if (OpInfo.isIndirect) { + const llvm::PointerType *PtrTy = dyn_cast(OpTy); + if (!PtrTy) + report_fatal_error("Indirect operand for inline asm not a pointer!"); + OpTy = PtrTy->getElementType(); + } + // If OpTy is not a single value, it may be a struct/union that we + // can tile with integers. + if (!OpTy->isSingleValueType() && OpTy->isSized()) { + unsigned BitSize = TD->getTypeSizeInBits(OpTy); + switch (BitSize) { + default: break; + case 1: + case 8: + case 16: + case 32: + case 64: + case 128: + OpTy = IntegerType::get(OpTy->getContext(), BitSize); + break; + } + } else if (dyn_cast(OpTy)) { + OpInfo.ConstraintVT = MVT::getIntegerVT(8*TD->getPointerSize()); + } else { + OpInfo.ConstraintVT = EVT::getEVT(OpTy, true); + } + } } // If we have multiple alternative constraints, select the best alternative. @@ -2737,13 +2767,12 @@ std::vector TargetLowering::ParseConstraints( if (OpInfo.Type == InlineAsm::isClobber) continue; - // If this is an output operand with a matching input operand, look up the - // matching input. If their types mismatch, e.g. one is an integer, the - // other is floating point, or their sizes are different, flag it as an - // maCantMatch. + // If this is an output operand with a matching input operand, + // look up the matching input. If their types mismatch, e.g. one + // is an integer, the other is floating point, or their sizes are + // different, flag it as an maCantMatch. if (OpInfo.hasMatchingInput()) { AsmOperandInfo &Input = ConstraintOperands[OpInfo.MatchingInput]; - if (OpInfo.ConstraintVT != Input.ConstraintVT) { if ((OpInfo.ConstraintVT.isInteger() != Input.ConstraintVT.isInteger()) || @@ -2752,10 +2781,8 @@ std::vector TargetLowering::ParseConstraints( weightSum = -1; // Can't match. break; } - Input.ConstraintVT = OpInfo.ConstraintVT; } } - weight = getMultipleConstraintMatchWeight(OpInfo, maIndex); if (weight == -1) { weightSum = -1; @@ -2792,7 +2819,7 @@ std::vector TargetLowering::ParseConstraints( // error. if (OpInfo.hasMatchingInput()) { AsmOperandInfo &Input = ConstraintOperands[OpInfo.MatchingInput]; - + if (OpInfo.ConstraintVT != Input.ConstraintVT) { if ((OpInfo.ConstraintVT.isInteger() != Input.ConstraintVT.isInteger()) || @@ -2802,8 +2829,8 @@ std::vector TargetLowering::ParseConstraints( " with a matching output constraint of" " incompatible type!"); } - Input.ConstraintVT = OpInfo.ConstraintVT; } + } } @@ -2828,22 +2855,23 @@ static unsigned getConstraintGenerality(TargetLowering::ConstraintType CT) { } } -/// Examine constraint type and operand type and determine a weight value, -/// where: -1 = invalid match, and 0 = so-so match to 3 = good match. +/// Examine constraint type and operand type and determine a weight value. /// This object must already have been set up with the operand type /// and the current alternative constraint selected. -int TargetLowering::getMultipleConstraintMatchWeight( +TargetLowering::ConstraintWeight + TargetLowering::getMultipleConstraintMatchWeight( AsmOperandInfo &info, int maIndex) const { - std::vector *rCodes; + InlineAsm::ConstraintCodeVector *rCodes; if (maIndex >= (int)info.multipleAlternatives.size()) rCodes = &info.Codes; else rCodes = &info.multipleAlternatives[maIndex].Codes; - int BestWeight = -1; + ConstraintWeight BestWeight = CW_Invalid; // Loop over the options, keeping track of the most general one. for (unsigned i = 0, e = rCodes->size(); i != e; ++i) { - int weight = getSingleConstraintMatchWeight(info, (*rCodes)[i].c_str()); + ConstraintWeight weight = + getSingleConstraintMatchWeight(info, (*rCodes)[i].c_str()); if (weight > BestWeight) BestWeight = weight; } @@ -2851,50 +2879,50 @@ int TargetLowering::getMultipleConstraintMatchWeight( return BestWeight; } -/// Examine constraint type and operand type and determine a weight value, -/// where: -1 = invalid match, and 0 = so-so match to 3 = good match. +/// Examine constraint type and operand type and determine a weight value. /// This object must already have been set up with the operand type /// and the current alternative constraint selected. -int TargetLowering::getSingleConstraintMatchWeight( +TargetLowering::ConstraintWeight + TargetLowering::getSingleConstraintMatchWeight( AsmOperandInfo &info, const char *constraint) const { - int weight = -1; + ConstraintWeight weight = CW_Invalid; Value *CallOperandVal = info.CallOperandVal; // If we don't have a value, we can't do a match, // but allow it at the lowest weight. if (CallOperandVal == NULL) - return 0; + return CW_Default; // Look at the constraint type. switch (*constraint) { case 'i': // immediate integer. case 'n': // immediate integer with a known value. - weight = 0; - if (info.CallOperandVal) { - if (isa(info.CallOperandVal)) - weight = 3; - else - weight = -1; - } + if (isa(CallOperandVal)) + weight = CW_Constant; break; case 's': // non-explicit intregal immediate. - weight = 0; - if (info.CallOperandVal) { - if (isa(info.CallOperandVal)) - weight = 3; - else - weight = -1; - } + if (isa(CallOperandVal)) + weight = CW_Constant; break; + case 'E': // immediate float if host format. + case 'F': // immediate float. + if (isa(CallOperandVal)) + weight = CW_Constant; + break; + case '<': // memory operand with autodecrement. + case '>': // memory operand with autoincrement. case 'm': // memory operand. case 'o': // offsettable memory operand case 'V': // non-offsettable memory operand - weight = 2; + weight = CW_Memory; break; + case 'r': // general register. case 'g': // general register, memory operand or immediate integer. - case 'X': // any operand. - weight = 1; + // note: Clang converts "g" to "imr". + if (CallOperandVal->getType()->isIntegerTy()) + weight = CW_Register; break; + case 'X': // any operand. default: - weight = 0; + weight = CW_Default; break; } return weight; diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index 85093874478..39f8f05423b 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -5441,6 +5441,40 @@ ARMTargetLowering::getConstraintType(const std::string &Constraint) const { return TargetLowering::getConstraintType(Constraint); } +/// Examine constraint type and operand type and determine a weight value. +/// This object must already have been set up with the operand type +/// and the current alternative constraint selected. +TargetLowering::ConstraintWeight +ARMTargetLowering::getSingleConstraintMatchWeight( + AsmOperandInfo &info, const char *constraint) const { + ConstraintWeight weight = CW_Invalid; + Value *CallOperandVal = info.CallOperandVal; + // If we don't have a value, we can't do a match, + // but allow it at the lowest weight. + if (CallOperandVal == NULL) + return CW_Default; + const Type *type = CallOperandVal->getType(); + // Look at the constraint type. + switch (*constraint) { + default: + weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint); + break; + case 'l': + if (type->isIntegerTy()) { + if (Subtarget->isThumb()) + weight = CW_SpecificReg; + else + weight = CW_Register; + } + break; + case 'w': + if (type->isFloatingPointTy()) + weight = CW_Register; + break; + } + return weight; +} + std::pair ARMTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const { diff --git a/lib/Target/ARM/ARMISelLowering.h b/lib/Target/ARM/ARMISelLowering.h index a689f809f78..bf3553becc8 100644 --- a/lib/Target/ARM/ARMISelLowering.h +++ b/lib/Target/ARM/ARMISelLowering.h @@ -241,6 +241,12 @@ namespace llvm { ConstraintType getConstraintType(const std::string &Constraint) const; + + /// Examine constraint string and operand type and determine a weight value. + /// The operand object must already have been set up with the operand type. + ConstraintWeight getSingleConstraintMatchWeight( + AsmOperandInfo &info, const char *constraint) const; + std::pair getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const; diff --git a/lib/Target/Alpha/AlphaISelLowering.cpp b/lib/Target/Alpha/AlphaISelLowering.cpp index efd0d2c4a94..9ae06eab753 100644 --- a/lib/Target/Alpha/AlphaISelLowering.cpp +++ b/lib/Target/Alpha/AlphaISelLowering.cpp @@ -27,6 +27,7 @@ #include "llvm/Function.h" #include "llvm/Module.h" #include "llvm/Intrinsics.h" +#include "llvm/Type.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" @@ -803,6 +804,30 @@ AlphaTargetLowering::getConstraintType(const std::string &Constraint) const { return TargetLowering::getConstraintType(Constraint); } +/// Examine constraint type and operand type and determine a weight value. +/// This object must already have been set up with the operand type +/// and the current alternative constraint selected. +TargetLowering::ConstraintWeight +AlphaTargetLowering::getSingleConstraintMatchWeight( + AsmOperandInfo &info, const char *constraint) const { + ConstraintWeight weight = CW_Invalid; + Value *CallOperandVal = info.CallOperandVal; + // If we don't have a value, we can't do a match, + // but allow it at the lowest weight. + if (CallOperandVal == NULL) + return CW_Default; + // Look at the constraint type. + switch (*constraint) { + default: + weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint); + break; + case 'f': + weight = CW_Register; + break; + } + return weight; +} + std::vector AlphaTargetLowering:: getRegClassForInlineAsmConstraint(const std::string &Constraint, EVT VT) const { diff --git a/lib/Target/Alpha/AlphaISelLowering.h b/lib/Target/Alpha/AlphaISelLowering.h index 46e0c7dc9f8..b429e9fc139 100644 --- a/lib/Target/Alpha/AlphaISelLowering.h +++ b/lib/Target/Alpha/AlphaISelLowering.h @@ -87,6 +87,11 @@ namespace llvm { ConstraintType getConstraintType(const std::string &Constraint) const; + /// Examine constraint string and operand type and determine a weight value. + /// The operand object must already have been set up with the operand type. + ConstraintWeight getSingleConstraintMatchWeight( + AsmOperandInfo &info, const char *constraint) const; + std::vector getRegClassForInlineAsmConstraint(const std::string &Constraint, EVT VT) const; diff --git a/lib/Target/Blackfin/BlackfinISelLowering.cpp b/lib/Target/Blackfin/BlackfinISelLowering.cpp index 96d54aa03ef..c07f1f22785 100644 --- a/lib/Target/Blackfin/BlackfinISelLowering.cpp +++ b/lib/Target/Blackfin/BlackfinISelLowering.cpp @@ -15,6 +15,7 @@ #include "BlackfinISelLowering.h" #include "BlackfinTargetMachine.h" #include "llvm/Function.h" +#include "llvm/Type.h" #include "llvm/CodeGen/CallingConvLower.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" @@ -549,6 +550,52 @@ BlackfinTargetLowering::getConstraintType(const std::string &Constraint) const { return TargetLowering::getConstraintType(Constraint); } +/// Examine constraint type and operand type and determine a weight value. +/// This object must already have been set up with the operand type +/// and the current alternative constraint selected. +TargetLowering::ConstraintWeight +BlackfinTargetLowering::getSingleConstraintMatchWeight( + AsmOperandInfo &info, const char *constraint) const { + ConstraintWeight weight = CW_Invalid; + Value *CallOperandVal = info.CallOperandVal; + // If we don't have a value, we can't do a match, + // but allow it at the lowest weight. + if (CallOperandVal == NULL) + return CW_Default; + // Look at the constraint type. + switch (*constraint) { + default: + weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint); + break; + + // Blackfin-specific constraints + case 'a': + case 'd': + case 'z': + case 'D': + case 'W': + case 'e': + case 'b': + case 'v': + case 'f': + case 'c': + case 't': + case 'u': + case 'k': + case 'x': + case 'y': + case 'w': + return CW_Register; + case 'A': + case 'B': + case 'C': + case 'Z': + case 'Y': + return CW_SpecificReg; + } + return weight; +} + /// getRegForInlineAsmConstraint - Return register no and class for a C_Register /// constraint. std::pair BlackfinTargetLowering:: diff --git a/lib/Target/Blackfin/BlackfinISelLowering.h b/lib/Target/Blackfin/BlackfinISelLowering.h index 6bebcc320ce..15a745fa872 100644 --- a/lib/Target/Blackfin/BlackfinISelLowering.h +++ b/lib/Target/Blackfin/BlackfinISelLowering.h @@ -39,6 +39,12 @@ namespace llvm { SelectionDAG &DAG) const; ConstraintType getConstraintType(const std::string &Constraint) const; + + /// Examine constraint string and operand type and determine a weight value. + /// The operand object must already have been set up with the operand type. + ConstraintWeight getSingleConstraintMatchWeight( + AsmOperandInfo &info, const char *constraint) const; + std::pair getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const; std::vector diff --git a/lib/Target/CBackend/CBackend.cpp b/lib/Target/CBackend/CBackend.cpp index f594d5d9b7c..4e6d39e00ad 100644 --- a/lib/Target/CBackend/CBackend.cpp +++ b/lib/Target/CBackend/CBackend.cpp @@ -3193,7 +3193,7 @@ static std::string gccifyAsm(std::string asmstr) { // handle communitivity void CWriter::visitInlineAsm(CallInst &CI) { InlineAsm* as = cast(CI.getCalledValue()); - std::vector Constraints = as->ParseConstraints(); + InlineAsm::ConstraintInfoVector Constraints = as->ParseConstraints(); std::vector > ResultVals; if (CI.getType() == Type::getVoidTy(CI.getContext())) @@ -3213,7 +3213,7 @@ void CWriter::visitInlineAsm(CallInst &CI) { bool IsFirst = true; // Convert over all the output constraints. - for (std::vector::iterator I = Constraints.begin(), + for (InlineAsm::ConstraintInfoVector::iterator I = Constraints.begin(), E = Constraints.end(); I != E; ++I) { if (I->Type != InlineAsm::isOutput) { @@ -3255,7 +3255,7 @@ void CWriter::visitInlineAsm(CallInst &CI) { Out << "\n :"; IsFirst = true; ValueCount = 0; - for (std::vector::iterator I = Constraints.begin(), + for (InlineAsm::ConstraintInfoVector::iterator I = Constraints.begin(), E = Constraints.end(); I != E; ++I) { if (I->Type != InlineAsm::isInput) { ++ValueCount; @@ -3284,7 +3284,7 @@ void CWriter::visitInlineAsm(CallInst &CI) { // Convert over the clobber constraints. IsFirst = true; - for (std::vector::iterator I = Constraints.begin(), + for (InlineAsm::ConstraintInfoVector::iterator I = Constraints.begin(), E = Constraints.end(); I != E; ++I) { if (I->Type != InlineAsm::isClobber) continue; // Ignore non-input constraints. diff --git a/lib/Target/CellSPU/SPUISelLowering.cpp b/lib/Target/CellSPU/SPUISelLowering.cpp index 2a82988ce0a..eb6134c6178 100644 --- a/lib/Target/CellSPU/SPUISelLowering.cpp +++ b/lib/Target/CellSPU/SPUISelLowering.cpp @@ -20,6 +20,7 @@ #include "llvm/Function.h" #include "llvm/Intrinsics.h" #include "llvm/CallingConv.h" +#include "llvm/Type.h" #include "llvm/CodeGen/CallingConvLower.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" @@ -2989,6 +2990,38 @@ SPUTargetLowering::getConstraintType(const std::string &ConstraintLetter) const return TargetLowering::getConstraintType(ConstraintLetter); } +/// Examine constraint type and operand type and determine a weight value. +/// This object must already have been set up with the operand type +/// and the current alternative constraint selected. +TargetLowering::ConstraintWeight +SPUTargetLowering::getSingleConstraintMatchWeight( + AsmOperandInfo &info, const char *constraint) const { + ConstraintWeight weight = CW_Invalid; + Value *CallOperandVal = info.CallOperandVal; + // If we don't have a value, we can't do a match, + // but allow it at the lowest weight. + if (CallOperandVal == NULL) + return CW_Default; + // Look at the constraint type. + switch (*constraint) { + default: + weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint); + break; + //FIXME: Seems like the supported constraint letters were just copied + // from PPC, as the following doesn't correspond to the GCC docs. + // I'm leaving it so until someone adds the corresponding lowering support. + case 'b': + case 'r': + case 'f': + case 'd': + case 'v': + case 'y': + weight = CW_Register; + break; + } + return weight; +} + std::pair SPUTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const diff --git a/lib/Target/CellSPU/SPUISelLowering.h b/lib/Target/CellSPU/SPUISelLowering.h index 23726435b83..41d08267586 100644 --- a/lib/Target/CellSPU/SPUISelLowering.h +++ b/lib/Target/CellSPU/SPUISelLowering.h @@ -129,6 +129,11 @@ namespace llvm { ConstraintType getConstraintType(const std::string &ConstraintLetter) const; + /// Examine constraint string and operand type and determine a weight value. + /// The operand object must already have been set up with the operand type. + ConstraintWeight getSingleConstraintMatchWeight( + AsmOperandInfo &info, const char *constraint) const; + std::pair getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const; diff --git a/lib/Target/MBlaze/MBlazeISelLowering.cpp b/lib/Target/MBlaze/MBlazeISelLowering.cpp index a81a01cff52..855060f9ea1 100644 --- a/lib/Target/MBlaze/MBlazeISelLowering.cpp +++ b/lib/Target/MBlaze/MBlazeISelLowering.cpp @@ -908,6 +908,37 @@ getConstraintType(const std::string &Constraint) const return TargetLowering::getConstraintType(Constraint); } +/// Examine constraint type and operand type and determine a weight value. +/// This object must already have been set up with the operand type +/// and the current alternative constraint selected. +TargetLowering::ConstraintWeight +MBlazeTargetLowering::getSingleConstraintMatchWeight( + AsmOperandInfo &info, const char *constraint) const { + ConstraintWeight weight = CW_Invalid; + Value *CallOperandVal = info.CallOperandVal; + // If we don't have a value, we can't do a match, + // but allow it at the lowest weight. + if (CallOperandVal == NULL) + return CW_Default; + const Type *type = CallOperandVal->getType(); + // Look at the constraint type. + switch (*constraint) { + default: + weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint); + break; + case 'd': + case 'y': + if (type->isIntegerTy()) + weight = CW_Register; + break; + case 'f': + if (type->isFloatTy()) + weight = CW_Register; + break; + } + return weight; +} + /// getRegClassForInlineAsmConstraint - Given a constraint letter (e.g. "r"), /// return a list of registers that can be used to satisfy the constraint. /// This should only be used for C_RegisterClass constraints. diff --git a/lib/Target/MBlaze/MBlazeISelLowering.h b/lib/Target/MBlaze/MBlazeISelLowering.h index b900341b670..4f09851e7f3 100644 --- a/lib/Target/MBlaze/MBlazeISelLowering.h +++ b/lib/Target/MBlaze/MBlazeISelLowering.h @@ -153,6 +153,11 @@ namespace llvm { // Inline asm support ConstraintType getConstraintType(const std::string &Constraint) const; + /// Examine constraint string and operand type and determine a weight value. + /// The operand object must already have been set up with the operand type. + ConstraintWeight getSingleConstraintMatchWeight( + AsmOperandInfo &info, const char *constraint) const; + std::pair getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const; diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp index 6262a0bb2ce..5af123219ba 100644 --- a/lib/Target/Mips/MipsISelLowering.cpp +++ b/lib/Target/Mips/MipsISelLowering.cpp @@ -1269,6 +1269,37 @@ getConstraintType(const std::string &Constraint) const return TargetLowering::getConstraintType(Constraint); } +/// Examine constraint type and operand type and determine a weight value. +/// This object must already have been set up with the operand type +/// and the current alternative constraint selected. +TargetLowering::ConstraintWeight +MipsTargetLowering::getSingleConstraintMatchWeight( + AsmOperandInfo &info, const char *constraint) const { + ConstraintWeight weight = CW_Invalid; + Value *CallOperandVal = info.CallOperandVal; + // If we don't have a value, we can't do a match, + // but allow it at the lowest weight. + if (CallOperandVal == NULL) + return CW_Default; + const Type *type = CallOperandVal->getType(); + // Look at the constraint type. + switch (*constraint) { + default: + weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint); + break; + case 'd': + case 'y': + if (type->isIntegerTy()) + weight = CW_Register; + break; + case 'f': + if (type->isFloatTy()) + weight = CW_Register; + break; + } + return weight; +} + /// getRegClassForInlineAsmConstraint - Given a constraint letter (e.g. "r"), /// return a list of registers that can be used to satisfy the constraint. /// This should only be used for C_RegisterClass constraints. diff --git a/lib/Target/Mips/MipsISelLowering.h b/lib/Target/Mips/MipsISelLowering.h index 460747bf543..1e8cc80b642 100644 --- a/lib/Target/Mips/MipsISelLowering.h +++ b/lib/Target/Mips/MipsISelLowering.h @@ -139,6 +139,11 @@ namespace llvm { // Inline asm support ConstraintType getConstraintType(const std::string &Constraint) const; + /// Examine constraint string and operand type and determine a weight value. + /// The operand object must already have been set up with the operand type. + ConstraintWeight getSingleConstraintMatchWeight( + AsmOperandInfo &info, const char *constraint) const; + std::pair getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const; diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp index 0df9fa2df5c..7fbbb6f463d 100644 --- a/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/lib/Target/PowerPC/PPCISelLowering.cpp @@ -2473,13 +2473,13 @@ unsigned PrepareCall(SelectionDAG &DAG, SDValue &Callee, SDValue &InFlag, // node so that legalize doesn't hack it. if (GlobalAddressSDNode *G = dyn_cast(Callee)) { Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, - Callee.getValueType()); + Callee.getValueType()); needIndirectCall = false; } } if (ExternalSymbolSDNode *S = dyn_cast(Callee)) { Callee = DAG.getTargetExternalSymbol(S->getSymbol(), - Callee.getValueType()); + Callee.getValueType()); needIndirectCall = false; } if (needIndirectCall) { @@ -5374,6 +5374,47 @@ PPCTargetLowering::getConstraintType(const std::string &Constraint) const { return TargetLowering::getConstraintType(Constraint); } +/// Examine constraint type and operand type and determine a weight value. +/// This object must already have been set up with the operand type +/// and the current alternative constraint selected. +TargetLowering::ConstraintWeight +PPCTargetLowering::getSingleConstraintMatchWeight( + AsmOperandInfo &info, const char *constraint) const { + ConstraintWeight weight = CW_Invalid; + Value *CallOperandVal = info.CallOperandVal; + // If we don't have a value, we can't do a match, + // but allow it at the lowest weight. + if (CallOperandVal == NULL) + return CW_Default; + const Type *type = CallOperandVal->getType(); + // Look at the constraint type. + switch (*constraint) { + default: + weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint); + break; + case 'b': + if (type->isIntegerTy()) + weight = CW_Register; + break; + case 'f': + if (type->isFloatTy()) + weight = CW_Register; + break; + case 'd': + if (type->isDoubleTy()) + weight = CW_Register; + break; + case 'v': + if (type->isVectorTy()) + weight = CW_Register; + break; + case 'y': + weight = CW_Register; + break; + } + return weight; +} + std::pair PPCTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const { diff --git a/lib/Target/PowerPC/PPCISelLowering.h b/lib/Target/PowerPC/PPCISelLowering.h index 700816f5a12..2e1b99b7b12 100644 --- a/lib/Target/PowerPC/PPCISelLowering.h +++ b/lib/Target/PowerPC/PPCISelLowering.h @@ -308,6 +308,12 @@ namespace llvm { bool is8bit, unsigned Opcode) const; ConstraintType getConstraintType(const std::string &Constraint) const; + + /// Examine constraint string and operand type and determine a weight value. + /// The operand object must already have been set up with the operand type. + ConstraintWeight getSingleConstraintMatchWeight( + AsmOperandInfo &info, const char *constraint) const; + std::pair getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const; diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index d293081449e..d8ec6a38f6a 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -11428,7 +11428,7 @@ static bool LowerToBSwap(CallInst *CI) { bool X86TargetLowering::ExpandInlineAsm(CallInst *CI) const { InlineAsm *IA = cast(CI->getCalledValue()); - std::vector Constraints = IA->ParseConstraints(); + InlineAsm::ConstraintInfoVector Constraints = IA->ParseConstraints(); std::string AsmStr = IA->getAsmString(); @@ -11508,18 +11508,32 @@ X86TargetLowering::ConstraintType X86TargetLowering::getConstraintType(const std::string &Constraint) const { if (Constraint.size() == 1) { switch (Constraint[0]) { - case 'A': - return C_Register; - case 'f': - case 'r': case 'R': - case 'l': case 'q': case 'Q': - case 'x': + case 'f': + case 't': + case 'u': case 'y': + case 'x': case 'Y': return C_RegisterClass; + case 'a': + case 'b': + case 'c': + case 'd': + case 'S': + case 'D': + case 'A': + return C_Register; + case 'I': + case 'J': + case 'K': + case 'L': + case 'M': + case 'N': + case 'G': + case 'C': case 'e': case 'Z': return C_Other; @@ -11530,30 +11544,106 @@ X86TargetLowering::getConstraintType(const std::string &Constraint) const { return TargetLowering::getConstraintType(Constraint); } -/// Examine constraint type and operand type and determine a weight value, -/// where: -1 = invalid match, and 0 = so-so match to 3 = good match. +/// Examine constraint type and operand type and determine a weight value. /// This object must already have been set up with the operand type /// and the current alternative constraint selected. -int X86TargetLowering::getSingleConstraintMatchWeight( +TargetLowering::ConstraintWeight + X86TargetLowering::getSingleConstraintMatchWeight( AsmOperandInfo &info, const char *constraint) const { - int weight = -1; + ConstraintWeight weight = CW_Invalid; Value *CallOperandVal = info.CallOperandVal; // If we don't have a value, we can't do a match, // but allow it at the lowest weight. if (CallOperandVal == NULL) - return 0; + return CW_Default; + const Type *type = CallOperandVal->getType(); // Look at the constraint type. switch (*constraint) { default: - return TargetLowering::getSingleConstraintMatchWeight(info, constraint); + weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint); + case 'R': + case 'q': + case 'Q': + case 'a': + case 'b': + case 'c': + case 'd': + case 'S': + case 'D': + case 'A': + if (CallOperandVal->getType()->isIntegerTy()) + weight = CW_SpecificReg; + break; + case 'f': + case 't': + case 'u': + if (type->isFloatingPointTy()) + weight = CW_SpecificReg; + break; + case 'y': + if (type->isX86_MMXTy() && !DisableMMX && Subtarget->hasMMX()) + weight = CW_SpecificReg; + break; + case 'x': + case 'Y': + if ((type->getPrimitiveSizeInBits() == 128) && Subtarget->hasSSE1()) + weight = CW_Register; break; case 'I': if (ConstantInt *C = dyn_cast(info.CallOperandVal)) { if (C->getZExtValue() <= 31) - weight = 3; + weight = CW_Constant; + } + break; + case 'J': + if (ConstantInt *C = dyn_cast(CallOperandVal)) { + if (C->getZExtValue() <= 63) + weight = CW_Constant; + } + break; + case 'K': + if (ConstantInt *C = dyn_cast(CallOperandVal)) { + if ((C->getSExtValue() >= -0x80) && (C->getSExtValue() <= 0x7f)) + weight = CW_Constant; + } + break; + case 'L': + if (ConstantInt *C = dyn_cast(CallOperandVal)) { + if ((C->getZExtValue() == 0xff) || (C->getZExtValue() == 0xffff)) + weight = CW_Constant; + } + break; + case 'M': + if (ConstantInt *C = dyn_cast(CallOperandVal)) { + if (C->getZExtValue() <= 3) + weight = CW_Constant; + } + break; + case 'N': + if (ConstantInt *C = dyn_cast(CallOperandVal)) { + if (C->getZExtValue() <= 0xff) + weight = CW_Constant; + } + break; + case 'G': + case 'C': + if (dyn_cast(CallOperandVal)) { + weight = CW_Constant; + } + break; + case 'e': + if (ConstantInt *C = dyn_cast(CallOperandVal)) { + if ((C->getSExtValue() >= -0x80000000LL) && + (C->getSExtValue() <= 0x7fffffffLL)) + weight = CW_Constant; + } + break; + case 'Z': + if (ConstantInt *C = dyn_cast(CallOperandVal)) { + if (C->getZExtValue() <= 0xffffffff) + weight = CW_Constant; } break; - // etc. } return weight; } diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h index e10c64d7edd..287853f6e83 100644 --- a/lib/Target/X86/X86ISelLowering.h +++ b/lib/Target/X86/X86ISelLowering.h @@ -542,10 +542,9 @@ namespace llvm { ConstraintType getConstraintType(const std::string &Constraint) const; - /// Examine constraint string and operand type and determine a weight value, - /// where: -1 = invalid match, and 0 = so-so match to 3 = good match. + /// Examine constraint string and operand type and determine a weight value. /// The operand object must already have been set up with the operand type. - virtual int getSingleConstraintMatchWeight( + virtual ConstraintWeight getSingleConstraintMatchWeight( AsmOperandInfo &info, const char *constraint) const; std::vector diff --git a/lib/Transforms/Scalar/CodeGenPrepare.cpp b/lib/Transforms/Scalar/CodeGenPrepare.cpp index 1d05196d2a0..35d02d97401 100644 --- a/lib/Transforms/Scalar/CodeGenPrepare.cpp +++ b/lib/Transforms/Scalar/CodeGenPrepare.cpp @@ -743,7 +743,7 @@ bool CodeGenPrepare::OptimizeInlineAsmInst(Instruction *I, CallSite CS, DenseMap &SunkAddrs) { bool MadeChange = false; - std::vector TargetConstraints = TLI->ParseConstraints(CS); + TargetLowering::AsmOperandInfoVector TargetConstraints = TLI->ParseConstraints(CS); unsigned ArgNo = 0; for (unsigned i = 0, e = TargetConstraints.size(); i != e; ++i) { TargetLowering::AsmOperandInfo &OpInfo = TargetConstraints[i]; diff --git a/lib/Transforms/Utils/AddrModeMatcher.cpp b/lib/Transforms/Utils/AddrModeMatcher.cpp index b803521e871..b1cef965035 100644 --- a/lib/Transforms/Utils/AddrModeMatcher.cpp +++ b/lib/Transforms/Utils/AddrModeMatcher.cpp @@ -380,7 +380,7 @@ bool AddressingModeMatcher::MatchAddr(Value *Addr, unsigned Depth) { /// return false. static bool IsOperandAMemoryOperand(CallInst *CI, InlineAsm *IA, Value *OpVal, const TargetLowering &TLI) { - std::vector TargetConstraints = TLI.ParseConstraints(ImmutableCallSite(CI)); + TargetLowering::AsmOperandInfoVector TargetConstraints = TLI.ParseConstraints(ImmutableCallSite(CI)); for (unsigned i = 0, e = TargetConstraints.size(); i != e; ++i) { TargetLowering::AsmOperandInfo &OpInfo = TargetConstraints[i]; diff --git a/lib/VMCore/InlineAsm.cpp b/lib/VMCore/InlineAsm.cpp index 7bbf0ba1ca4..d951a29f43c 100644 --- a/lib/VMCore/InlineAsm.cpp +++ b/lib/VMCore/InlineAsm.cpp @@ -76,11 +76,11 @@ InlineAsm::ConstraintInfo::ConstraintInfo(const ConstraintInfo &other) : /// fields in this structure. If the constraint string is not understood, /// return true, otherwise return false. bool InlineAsm::ConstraintInfo::Parse(StringRef Str, - std::vector &ConstraintsSoFar) { + InlineAsm::ConstraintInfoVector &ConstraintsSoFar) { StringRef::iterator I = Str.begin(), E = Str.end(); unsigned multipleAlternativeCount = Str.count('|') + 1; unsigned multipleAlternativeIndex = 0; - std::vector *pCodes = &Codes; + ConstraintCodeVector *pCodes = &Codes; // Initialize isMultipleAlternative = (multipleAlternativeCount > 1 ? true : false); @@ -202,9 +202,9 @@ void InlineAsm::ConstraintInfo::selectAlternative(unsigned index) { } } -std::vector +InlineAsm::ConstraintInfoVector InlineAsm::ParseConstraints(StringRef Constraints) { - std::vector Result; + ConstraintInfoVector Result; // Scan the constraints string. for (StringRef::iterator I = Constraints.begin(), @@ -239,7 +239,7 @@ InlineAsm::ParseConstraints(StringRef Constraints) { bool InlineAsm::Verify(const FunctionType *Ty, StringRef ConstStr) { if (Ty->isVarArg()) return false; - std::vector Constraints = ParseConstraints(ConstStr); + ConstraintInfoVector Constraints = ParseConstraints(ConstStr); // Error parsing constraints. if (Constraints.empty() && !ConstStr.empty()) return false;