From 5c80760fdf71659c5bdf45cd85d173df454dfb41 Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Tue, 26 Feb 2008 02:33:44 +0000 Subject: [PATCH] Refactor inline asm constraint matching code out of SDIsel into TargetLowering. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@47587 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Target/TargetLowering.h | 91 ++++++++++++++- lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp | 106 +++--------------- lib/CodeGen/SelectionDAG/TargetLowering.cpp | 4 +- 3 files changed, 107 insertions(+), 94 deletions(-) diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h index 783c0f82d5c..396a6d1fc74 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -22,6 +22,8 @@ #ifndef LLVM_TARGET_TARGETLOWERING_H #define LLVM_TARGET_TARGETLOWERING_H +#include "llvm/Constants.h" +#include "llvm/InlineAsm.h" #include "llvm/CodeGen/SelectionDAGNodes.h" #include "llvm/CodeGen/RuntimeLibcalls.h" #include "llvm/ADT/APFloat.h" @@ -992,11 +994,98 @@ public: C_Unknown // Unsupported constraint. }; + /// AsmOperandInfo - This contains information for each constraint that we are + /// lowering. + struct AsmOperandInfo : public InlineAsm::ConstraintInfo { + /// ConstraintCode - This contains the actual string for the code, like "m". + std::string ConstraintCode; + + /// ConstraintType - Information about the constraint code, e.g. Register, + /// RegisterClass, Memory, Other, Unknown. + TargetLowering::ConstraintType ConstraintType; + + /// CallOperandval - If this is the result output operand or a + /// clobber, this is null, otherwise it is the incoming operand to the + /// CallInst. This gets modified as the asm is processed. + Value *CallOperandVal; + + /// ConstraintVT - The ValueType for the operand value. + MVT::ValueType ConstraintVT; + + AsmOperandInfo(const InlineAsm::ConstraintInfo &info) + : InlineAsm::ConstraintInfo(info), + 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); + if (Codes.size() == 1) { // Single-letter constraints ('r') are very common. + 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; + } + + if (ConstraintCode == "X" && CallOperandVal) { + if (isa(CallOperandVal) || isa(CallOperandVal)) + return; + // This matches anything. Labels and constants we handle elsewhere + // ('X' is the only thing that matches labels). Otherwise, try to + // resolve it to something we know about by looking at the actual + // operand type. + std::string s = ""; + TLI.lowerXConstraint(ConstraintVT, s); + if (s!="") { + ConstraintCode = s; + ConstraintType = TLI.getConstraintType(ConstraintCode); + } + } + } + }; + /// getConstraintType - Given a constraint, return the type of constraint it /// is for this target. virtual ConstraintType getConstraintType(const std::string &Constraint) const; - /// 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/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index aa18a5b2799..86abd4194fd 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -87,7 +87,7 @@ namespace { createDefaultScheduler); } // namespace -namespace { struct AsmOperandInfo; } +namespace { struct SDISelAsmOperandInfo; } namespace { /// RegsForValue - This struct represents the physical registers that a @@ -492,7 +492,7 @@ public: N = NewN; } - void GetRegistersForValue(AsmOperandInfo &OpInfo, bool HasEarlyClobber, + void GetRegistersForValue(SDISelAsmOperandInfo &OpInfo, bool HasEarlyClobber, std::set &OutputRegs, std::set &InputRegs); @@ -3347,35 +3347,20 @@ isAllocatableRegister(unsigned Reg, MachineFunction &MF, namespace { /// AsmOperandInfo - This contains information for each constraint that we are /// lowering. -struct AsmOperandInfo : public InlineAsm::ConstraintInfo { - /// ConstraintCode - This contains the actual string for the code, like "m". - std::string ConstraintCode; - - /// ConstraintType - Information about the constraint code, e.g. Register, - /// RegisterClass, Memory, Other, Unknown. - TargetLowering::ConstraintType ConstraintType; - - /// CallOperand/CallOperandval - If this is the result output operand or a - /// clobber, this is null, otherwise it is the incoming operand to the - /// CallInst. This gets modified as the asm is processed. +struct SDISelAsmOperandInfo : public TargetLowering::AsmOperandInfo { + /// CallOperand - If this is the result output operand or a clobber + /// this is null, otherwise it is the incoming operand to the CallInst. + /// This gets modified as the asm is processed. SDOperand CallOperand; - Value *CallOperandVal; - - /// ConstraintVT - The ValueType for the operand value. - MVT::ValueType ConstraintVT; - + /// AssignedRegs - If this is a register or register class operand, this /// contains the set of register corresponding to the operand. RegsForValue AssignedRegs; - AsmOperandInfo(const InlineAsm::ConstraintInfo &info) - : InlineAsm::ConstraintInfo(info), - ConstraintType(TargetLowering::C_Unknown), - CallOperand(0,0), CallOperandVal(0), ConstraintVT(MVT::Other) { + SDISelAsmOperandInfo(const InlineAsm::ConstraintInfo &info) + : TargetLowering::AsmOperandInfo(info), CallOperand(0,0) { } - void ComputeConstraintToUse(const TargetLowering &TLI); - /// MarkAllocatedRegs - Once AssignedRegs is set, mark the assigned registers /// busy in OutputRegs/InputRegs. void MarkAllocatedRegs(bool isOutReg, bool isInReg, @@ -3406,67 +3391,6 @@ private: }; } // end anon namespace. -/// 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; - } -} - -void AsmOperandInfo::ComputeConstraintToUse(const TargetLowering &TLI) { - assert(!Codes.empty() && "Must have at least one constraint"); - - std::string *Current = &Codes[0]; - TargetLowering::ConstraintType CurType = TLI.getConstraintType(*Current); - if (Codes.size() == 1) { // Single-letter constraints ('r') are very common. - 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; - } - - if (ConstraintCode == "X") { - if (isa(CallOperandVal) || isa(CallOperandVal)) - return; - // This matches anything. Labels and constants we handle elsewhere - // ('X' is the only thing that matches labels). Otherwise, try to - // resolve it to something we know about by looking at the actual - // operand type. - std::string s = ""; - TLI.lowerXConstraint(ConstraintVT, s); - if (s!="") { - ConstraintCode = s; - ConstraintType = TLI.getConstraintType(ConstraintCode); - } - } -} - /// GetRegistersForValue - Assign registers (virtual or physical) for the /// specified operand. We prefer to assign virtual registers, to allow the @@ -3480,7 +3404,7 @@ void AsmOperandInfo::ComputeConstraintToUse(const TargetLowering &TLI) { /// Input and OutputRegs are the set of already allocated physical registers. /// void SelectionDAGLowering:: -GetRegistersForValue(AsmOperandInfo &OpInfo, bool HasEarlyClobber, +GetRegistersForValue(SDISelAsmOperandInfo &OpInfo, bool HasEarlyClobber, std::set &OutputRegs, std::set &InputRegs) { // Compute whether this value requires an input register, an output register, @@ -3648,7 +3572,7 @@ void SelectionDAGLowering::visitInlineAsm(CallSite CS) { InlineAsm *IA = cast(CS.getCalledValue()); /// ConstraintOperands - Information about all of the constraints. - std::vector ConstraintOperands; + std::vector ConstraintOperands; SDOperand Chain = getRoot(); SDOperand Flag; @@ -3667,8 +3591,8 @@ void SelectionDAGLowering::visitInlineAsm(CallSite CS) { unsigned ArgNo = 0; // ArgNo - The argument of the CallInst. for (unsigned i = 0, e = ConstraintInfos.size(); i != e; ++i) { - ConstraintOperands.push_back(AsmOperandInfo(ConstraintInfos[i])); - AsmOperandInfo &OpInfo = ConstraintOperands.back(); + ConstraintOperands.push_back(SDISelAsmOperandInfo(ConstraintInfos[i])); + SDISelAsmOperandInfo &OpInfo = ConstraintOperands.back(); MVT::ValueType OpVT = MVT::Other; @@ -3798,7 +3722,7 @@ void SelectionDAGLowering::visitInlineAsm(CallSite CS) { // Second pass - Loop over all of the operands, assigning virtual or physregs // to registerclass operands. for (unsigned i = 0, e = ConstraintOperands.size(); i != e; ++i) { - AsmOperandInfo &OpInfo = ConstraintOperands[i]; + SDISelAsmOperandInfo &OpInfo = ConstraintOperands[i]; // C_Register operands have already been allocated, Other/Memory don't need // to be. @@ -3821,7 +3745,7 @@ void SelectionDAGLowering::visitInlineAsm(CallSite CS) { std::vector > IndirectStoresToEmit; for (unsigned i = 0, e = ConstraintOperands.size(); i != e; ++i) { - AsmOperandInfo &OpInfo = ConstraintOperands[i]; + SDISelAsmOperandInfo &OpInfo = ConstraintOperands[i]; switch (OpInfo.Type) { case InlineAsm::isOutput: { diff --git a/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/lib/CodeGen/SelectionDAG/TargetLowering.cpp index d43dc16ea09..22e2117bad8 100644 --- a/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -11,18 +11,18 @@ // //===----------------------------------------------------------------------===// +#include "llvm/Target/TargetAsmInfo.h" #include "llvm/Target/TargetLowering.h" #include "llvm/Target/TargetSubtarget.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/CallingConv.h" #include "llvm/DerivedTypes.h" #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/MathExtras.h" -#include "llvm/Target/TargetAsmInfo.h" -#include "llvm/CallingConv.h" using namespace llvm; /// InitLibcallNames - Set default libcall names. -- 2.34.1