Move a bunch of inline asm code out of line.

llvm-svn: 50313
This commit is contained in:
Chris Lattner 2008-04-27 00:09:47 +00:00
parent 724539c001
commit 4793515a9c
4 changed files with 104 additions and 68 deletions

View File

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

View File

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

View File

@ -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<unsigned, const TargetRegisterClass*>(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<BasicBlock>(OpInfo.CallOperandVal) ||
isa<ConstantInt>(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
//===----------------------------------------------------------------------===//

View File

@ -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) {