mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-25 00:33:15 +00:00
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:
parent
9a8a88b72d
commit
5c80760fdf
@ -22,6 +22,8 @@
|
|||||||
#ifndef LLVM_TARGET_TARGETLOWERING_H
|
#ifndef LLVM_TARGET_TARGETLOWERING_H
|
||||||
#define 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/SelectionDAGNodes.h"
|
||||||
#include "llvm/CodeGen/RuntimeLibcalls.h"
|
#include "llvm/CodeGen/RuntimeLibcalls.h"
|
||||||
#include "llvm/ADT/APFloat.h"
|
#include "llvm/ADT/APFloat.h"
|
||||||
@ -992,11 +994,98 @@ public:
|
|||||||
C_Unknown // Unsupported constraint.
|
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
|
/// getConstraintType - Given a constraint, return the type of constraint it
|
||||||
/// is for this target.
|
/// is for this target.
|
||||||
virtual ConstraintType getConstraintType(const std::string &Constraint) const;
|
virtual ConstraintType getConstraintType(const std::string &Constraint) const;
|
||||||
|
|
||||||
|
|
||||||
/// getRegClassForInlineAsmConstraint - Given a constraint letter (e.g. "r"),
|
/// getRegClassForInlineAsmConstraint - Given a constraint letter (e.g. "r"),
|
||||||
/// return a list of registers that can be used to satisfy the constraint.
|
/// return a list of registers that can be used to satisfy the constraint.
|
||||||
/// This should only be used for C_RegisterClass constraints.
|
/// This should only be used for C_RegisterClass constraints.
|
||||||
|
@ -87,7 +87,7 @@ namespace {
|
|||||||
createDefaultScheduler);
|
createDefaultScheduler);
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace { struct AsmOperandInfo; }
|
namespace { struct SDISelAsmOperandInfo; }
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
/// RegsForValue - This struct represents the physical registers that a
|
/// RegsForValue - This struct represents the physical registers that a
|
||||||
@ -492,7 +492,7 @@ public:
|
|||||||
N = NewN;
|
N = NewN;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetRegistersForValue(AsmOperandInfo &OpInfo, bool HasEarlyClobber,
|
void GetRegistersForValue(SDISelAsmOperandInfo &OpInfo, bool HasEarlyClobber,
|
||||||
std::set<unsigned> &OutputRegs,
|
std::set<unsigned> &OutputRegs,
|
||||||
std::set<unsigned> &InputRegs);
|
std::set<unsigned> &InputRegs);
|
||||||
|
|
||||||
@ -3347,35 +3347,20 @@ isAllocatableRegister(unsigned Reg, MachineFunction &MF,
|
|||||||
namespace {
|
namespace {
|
||||||
/// AsmOperandInfo - This contains information for each constraint that we are
|
/// AsmOperandInfo - This contains information for each constraint that we are
|
||||||
/// lowering.
|
/// lowering.
|
||||||
struct AsmOperandInfo : public InlineAsm::ConstraintInfo {
|
struct SDISelAsmOperandInfo : public TargetLowering::AsmOperandInfo {
|
||||||
/// ConstraintCode - This contains the actual string for the code, like "m".
|
/// CallOperand - If this is the result output operand or a clobber
|
||||||
std::string ConstraintCode;
|
/// this is null, otherwise it is the incoming operand to the CallInst.
|
||||||
|
/// This gets modified as the asm is processed.
|
||||||
/// 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.
|
|
||||||
SDOperand CallOperand;
|
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
|
/// AssignedRegs - If this is a register or register class operand, this
|
||||||
/// contains the set of register corresponding to the operand.
|
/// contains the set of register corresponding to the operand.
|
||||||
RegsForValue AssignedRegs;
|
RegsForValue AssignedRegs;
|
||||||
|
|
||||||
AsmOperandInfo(const InlineAsm::ConstraintInfo &info)
|
SDISelAsmOperandInfo(const InlineAsm::ConstraintInfo &info)
|
||||||
: InlineAsm::ConstraintInfo(info),
|
: TargetLowering::AsmOperandInfo(info), CallOperand(0,0) {
|
||||||
ConstraintType(TargetLowering::C_Unknown),
|
|
||||||
CallOperand(0,0), CallOperandVal(0), ConstraintVT(MVT::Other) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ComputeConstraintToUse(const TargetLowering &TLI);
|
|
||||||
|
|
||||||
/// MarkAllocatedRegs - Once AssignedRegs is set, mark the assigned registers
|
/// MarkAllocatedRegs - Once AssignedRegs is set, mark the assigned registers
|
||||||
/// busy in OutputRegs/InputRegs.
|
/// busy in OutputRegs/InputRegs.
|
||||||
void MarkAllocatedRegs(bool isOutReg, bool isInReg,
|
void MarkAllocatedRegs(bool isOutReg, bool isInReg,
|
||||||
@ -3406,67 +3391,6 @@ private:
|
|||||||
};
|
};
|
||||||
} // end anon namespace.
|
} // 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
|
/// GetRegistersForValue - Assign registers (virtual or physical) for the
|
||||||
/// specified operand. We prefer to assign virtual registers, to allow 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.
|
/// Input and OutputRegs are the set of already allocated physical registers.
|
||||||
///
|
///
|
||||||
void SelectionDAGLowering::
|
void SelectionDAGLowering::
|
||||||
GetRegistersForValue(AsmOperandInfo &OpInfo, bool HasEarlyClobber,
|
GetRegistersForValue(SDISelAsmOperandInfo &OpInfo, bool HasEarlyClobber,
|
||||||
std::set<unsigned> &OutputRegs,
|
std::set<unsigned> &OutputRegs,
|
||||||
std::set<unsigned> &InputRegs) {
|
std::set<unsigned> &InputRegs) {
|
||||||
// Compute whether this value requires an input register, an output register,
|
// 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());
|
InlineAsm *IA = cast<InlineAsm>(CS.getCalledValue());
|
||||||
|
|
||||||
/// ConstraintOperands - Information about all of the constraints.
|
/// ConstraintOperands - Information about all of the constraints.
|
||||||
std::vector<AsmOperandInfo> ConstraintOperands;
|
std::vector<SDISelAsmOperandInfo> ConstraintOperands;
|
||||||
|
|
||||||
SDOperand Chain = getRoot();
|
SDOperand Chain = getRoot();
|
||||||
SDOperand Flag;
|
SDOperand Flag;
|
||||||
@ -3667,8 +3591,8 @@ void SelectionDAGLowering::visitInlineAsm(CallSite CS) {
|
|||||||
|
|
||||||
unsigned ArgNo = 0; // ArgNo - The argument of the CallInst.
|
unsigned ArgNo = 0; // ArgNo - The argument of the CallInst.
|
||||||
for (unsigned i = 0, e = ConstraintInfos.size(); i != e; ++i) {
|
for (unsigned i = 0, e = ConstraintInfos.size(); i != e; ++i) {
|
||||||
ConstraintOperands.push_back(AsmOperandInfo(ConstraintInfos[i]));
|
ConstraintOperands.push_back(SDISelAsmOperandInfo(ConstraintInfos[i]));
|
||||||
AsmOperandInfo &OpInfo = ConstraintOperands.back();
|
SDISelAsmOperandInfo &OpInfo = ConstraintOperands.back();
|
||||||
|
|
||||||
MVT::ValueType OpVT = MVT::Other;
|
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
|
// Second pass - Loop over all of the operands, assigning virtual or physregs
|
||||||
// to registerclass operands.
|
// to registerclass operands.
|
||||||
for (unsigned i = 0, e = ConstraintOperands.size(); i != e; ++i) {
|
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
|
// C_Register operands have already been allocated, Other/Memory don't need
|
||||||
// to be.
|
// to be.
|
||||||
@ -3821,7 +3745,7 @@ void SelectionDAGLowering::visitInlineAsm(CallSite CS) {
|
|||||||
std::vector<std::pair<RegsForValue, Value*> > IndirectStoresToEmit;
|
std::vector<std::pair<RegsForValue, Value*> > IndirectStoresToEmit;
|
||||||
|
|
||||||
for (unsigned i = 0, e = ConstraintOperands.size(); i != e; ++i) {
|
for (unsigned i = 0, e = ConstraintOperands.size(); i != e; ++i) {
|
||||||
AsmOperandInfo &OpInfo = ConstraintOperands[i];
|
SDISelAsmOperandInfo &OpInfo = ConstraintOperands[i];
|
||||||
|
|
||||||
switch (OpInfo.Type) {
|
switch (OpInfo.Type) {
|
||||||
case InlineAsm::isOutput: {
|
case InlineAsm::isOutput: {
|
||||||
|
@ -11,18 +11,18 @@
|
|||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "llvm/Target/TargetAsmInfo.h"
|
||||||
#include "llvm/Target/TargetLowering.h"
|
#include "llvm/Target/TargetLowering.h"
|
||||||
#include "llvm/Target/TargetSubtarget.h"
|
#include "llvm/Target/TargetSubtarget.h"
|
||||||
#include "llvm/Target/TargetData.h"
|
#include "llvm/Target/TargetData.h"
|
||||||
#include "llvm/Target/TargetMachine.h"
|
#include "llvm/Target/TargetMachine.h"
|
||||||
#include "llvm/Target/TargetRegisterInfo.h"
|
#include "llvm/Target/TargetRegisterInfo.h"
|
||||||
|
#include "llvm/CallingConv.h"
|
||||||
#include "llvm/DerivedTypes.h"
|
#include "llvm/DerivedTypes.h"
|
||||||
#include "llvm/CodeGen/SelectionDAG.h"
|
#include "llvm/CodeGen/SelectionDAG.h"
|
||||||
#include "llvm/ADT/StringExtras.h"
|
#include "llvm/ADT/StringExtras.h"
|
||||||
#include "llvm/ADT/STLExtras.h"
|
#include "llvm/ADT/STLExtras.h"
|
||||||
#include "llvm/Support/MathExtras.h"
|
#include "llvm/Support/MathExtras.h"
|
||||||
#include "llvm/Target/TargetAsmInfo.h"
|
|
||||||
#include "llvm/CallingConv.h"
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
/// InitLibcallNames - Set default libcall names.
|
/// InitLibcallNames - Set default libcall names.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user