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
This commit is contained in:
Evan Cheng 2008-02-26 02:33:44 +00:00
parent 9a8a88b72d
commit 5c80760fdf
3 changed files with 107 additions and 94 deletions

View File

@ -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<BasicBlock>(CallOperandVal) || isa<ConstantInt>(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.

View File

@ -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<unsigned> &OutputRegs,
std::set<unsigned> &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<BasicBlock>(CallOperandVal) || isa<ConstantInt>(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<unsigned> &OutputRegs,
std::set<unsigned> &InputRegs) {
// Compute whether this value requires an input register, an output register,
@ -3648,7 +3572,7 @@ void SelectionDAGLowering::visitInlineAsm(CallSite CS) {
InlineAsm *IA = cast<InlineAsm>(CS.getCalledValue());
/// ConstraintOperands - Information about all of the constraints.
std::vector<AsmOperandInfo> ConstraintOperands;
std::vector<SDISelAsmOperandInfo> 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<std::pair<RegsForValue, Value*> > 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: {

View File

@ -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.