mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-14 11:32:34 +00:00
Added skeleton for inline asm multiple alternative constraint support.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@113766 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
c32a2260a6
commit
eac6e1d0c7
@ -87,6 +87,19 @@ public:
|
||||
isClobber // '~x'
|
||||
};
|
||||
|
||||
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
|
||||
/// constraint number that matches this one (for example, if this is
|
||||
/// constraint #0 and constraint #4 has the value "0", this will be 4).
|
||||
signed char MatchingInput;
|
||||
/// Code - The constraint code, either the register name (in braces) or the
|
||||
/// constraint letter/number.
|
||||
std::vector<std::string> Codes;
|
||||
/// Default constructor.
|
||||
SubConstraintInfo() : MatchingInput(-1) {}
|
||||
};
|
||||
|
||||
struct ConstraintInfo {
|
||||
/// Type - The basic type of the constraint: input/output/clobber
|
||||
///
|
||||
@ -120,11 +133,31 @@ public:
|
||||
/// constraint letter/number.
|
||||
std::vector<std::string> 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<SubConstraintInfo> multipleAlternatives;
|
||||
|
||||
/// The currently selected alternative constraint index.
|
||||
unsigned currentAlternativeIndex;
|
||||
|
||||
///Default constructor.
|
||||
ConstraintInfo();
|
||||
|
||||
/// Copy constructor.
|
||||
ConstraintInfo(const ConstraintInfo &other);
|
||||
|
||||
/// 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<InlineAsm::ConstraintInfo> &ConstraintsSoFar);
|
||||
|
||||
/// selectAlternative - Point this constraint to the alternative constraint
|
||||
/// indicated by the index.
|
||||
void selectAlternative(unsigned index);
|
||||
};
|
||||
|
||||
/// ParseConstraints - Split up the constraint string into the specific
|
||||
|
@ -45,6 +45,7 @@ namespace llvm {
|
||||
class Function;
|
||||
class FastISel;
|
||||
class FunctionLoweringInfo;
|
||||
class ImmutableCallSite;
|
||||
class MachineBasicBlock;
|
||||
class MachineFunction;
|
||||
class MachineFrameInfo;
|
||||
@ -1356,6 +1357,16 @@ public:
|
||||
/// returns the output operand it matches.
|
||||
unsigned getMatchedOperand() const;
|
||||
|
||||
/// Copy constructor for copying from an AsmOperandInfo.
|
||||
AsmOperandInfo(const AsmOperandInfo &info)
|
||||
: InlineAsm::ConstraintInfo(info),
|
||||
ConstraintCode(info.ConstraintCode),
|
||||
ConstraintType(info.ConstraintType),
|
||||
CallOperandVal(info.CallOperandVal),
|
||||
ConstraintVT(info.ConstraintVT) {
|
||||
}
|
||||
|
||||
/// Copy constructor for copying from a ConstraintInfo.
|
||||
AsmOperandInfo(const InlineAsm::ConstraintInfo &info)
|
||||
: InlineAsm::ConstraintInfo(info),
|
||||
ConstraintType(TargetLowering::C_Unknown),
|
||||
@ -1363,6 +1374,26 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/// 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<AsmOperandInfo> 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.
|
||||
/// The operand object must already have been set up with the operand type.
|
||||
virtual int 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.
|
||||
/// The operand object must already have been set up with the operand type.
|
||||
virtual int getSingleConstraintMatchWeight(
|
||||
AsmOperandInfo &info, const char *constraint) const;
|
||||
|
||||
/// ComputeConstraintToUse - Determines the constraint code and constraint
|
||||
/// type to use for the specific AsmOperandInfo, setting
|
||||
/// OpInfo.ConstraintCode and OpInfo.ConstraintType. If the actual operand
|
||||
|
@ -5008,7 +5008,7 @@ public:
|
||||
/// contains the set of register corresponding to the operand.
|
||||
RegsForValue AssignedRegs;
|
||||
|
||||
explicit SDISelAsmOperandInfo(const InlineAsm::ConstraintInfo &info)
|
||||
explicit SDISelAsmOperandInfo(const TargetLowering::AsmOperandInfo &info)
|
||||
: TargetLowering::AsmOperandInfo(info), CallOperand(0,0) {
|
||||
}
|
||||
|
||||
@ -5324,26 +5324,13 @@ void SelectionDAGBuilder::visitInlineAsm(ImmutableCallSite CS) {
|
||||
|
||||
std::set<unsigned> OutputRegs, InputRegs;
|
||||
|
||||
// Do a prepass over the constraints, canonicalizing them, and building up the
|
||||
// ConstraintOperands list.
|
||||
std::vector<InlineAsm::ConstraintInfo>
|
||||
ConstraintInfos = IA->ParseConstraints();
|
||||
|
||||
bool hasMemory = hasInlineAsmMemConstraint(ConstraintInfos, TLI);
|
||||
|
||||
SDValue Chain, Flag;
|
||||
|
||||
// We won't need to flush pending loads if this asm doesn't touch
|
||||
// memory and is nonvolatile.
|
||||
if (hasMemory || IA->hasSideEffects())
|
||||
Chain = getRoot();
|
||||
else
|
||||
Chain = DAG.getRoot();
|
||||
std::vector<TargetLowering::AsmOperandInfo> TargetConstraints = TLI.ParseConstraints(CS);
|
||||
bool hasMemory = false;
|
||||
|
||||
unsigned ArgNo = 0; // ArgNo - The argument of the CallInst.
|
||||
unsigned ResNo = 0; // ResNo - The result number of the next output.
|
||||
for (unsigned i = 0, e = ConstraintInfos.size(); i != e; ++i) {
|
||||
ConstraintOperands.push_back(SDISelAsmOperandInfo(ConstraintInfos[i]));
|
||||
for (unsigned i = 0, e = TargetConstraints.size(); i != e; ++i) {
|
||||
ConstraintOperands.push_back(SDISelAsmOperandInfo(TargetConstraints[i]));
|
||||
SDISelAsmOperandInfo &OpInfo = ConstraintOperands.back();
|
||||
|
||||
EVT OpVT = MVT::Other;
|
||||
@ -5393,33 +5380,35 @@ void SelectionDAGBuilder::visitInlineAsm(ImmutableCallSite CS) {
|
||||
}
|
||||
|
||||
OpInfo.ConstraintVT = OpVT;
|
||||
|
||||
// Indirect operand accesses access memory.
|
||||
if (OpInfo.isIndirect)
|
||||
hasMemory = true;
|
||||
else {
|
||||
for (unsigned j = 0, ee = OpInfo.Codes.size(); j != ee; ++j) {
|
||||
TargetLowering::ConstraintType CType = TLI.getConstraintType(OpInfo.Codes[j]);
|
||||
if (CType == TargetLowering::C_Memory) {
|
||||
hasMemory = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SDValue Chain, Flag;
|
||||
|
||||
// We won't need to flush pending loads if this asm doesn't touch
|
||||
// memory and is nonvolatile.
|
||||
if (hasMemory || IA->hasSideEffects())
|
||||
Chain = getRoot();
|
||||
else
|
||||
Chain = DAG.getRoot();
|
||||
|
||||
// Second pass over the constraints: compute which constraint option to use
|
||||
// and assign registers to constraints that want a specific physreg.
|
||||
for (unsigned i = 0, e = ConstraintInfos.size(); i != e; ++i) {
|
||||
for (unsigned i = 0, e = ConstraintOperands.size(); i != e; ++i) {
|
||||
SDISelAsmOperandInfo &OpInfo = ConstraintOperands[i];
|
||||
|
||||
// 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
|
||||
// error.
|
||||
if (OpInfo.hasMatchingInput()) {
|
||||
SDISelAsmOperandInfo &Input = ConstraintOperands[OpInfo.MatchingInput];
|
||||
|
||||
if (OpInfo.ConstraintVT != Input.ConstraintVT) {
|
||||
if ((OpInfo.ConstraintVT.isInteger() !=
|
||||
Input.ConstraintVT.isInteger()) ||
|
||||
(OpInfo.ConstraintVT.getSizeInBits() !=
|
||||
Input.ConstraintVT.getSizeInBits())) {
|
||||
report_fatal_error("Unsupported asm: input constraint"
|
||||
" with a matching output constraint of"
|
||||
" incompatible type!");
|
||||
}
|
||||
Input.ConstraintVT = OpInfo.ConstraintVT;
|
||||
}
|
||||
}
|
||||
|
||||
// Compute the constraint code and ConstraintType to use.
|
||||
TLI.ComputeConstraintToUse(OpInfo, OpInfo.CallOperand, &DAG);
|
||||
|
||||
@ -5427,7 +5416,7 @@ void SelectionDAGBuilder::visitInlineAsm(ImmutableCallSite CS) {
|
||||
// need to to provide an address for the memory input.
|
||||
if (OpInfo.ConstraintType == TargetLowering::C_Memory &&
|
||||
!OpInfo.isIndirect) {
|
||||
assert(OpInfo.Type == InlineAsm::isInput &&
|
||||
assert((OpInfo.isMultipleAlternative || (OpInfo.Type == InlineAsm::isInput)) &&
|
||||
"Can only indirectify direct input operands!");
|
||||
|
||||
// Memory operands really want the address of the value. If we don't have
|
||||
@ -5469,8 +5458,6 @@ void SelectionDAGBuilder::visitInlineAsm(ImmutableCallSite CS) {
|
||||
GetRegistersForValue(OpInfo, OutputRegs, InputRegs);
|
||||
}
|
||||
|
||||
ConstraintInfos.clear();
|
||||
|
||||
// Second pass - Loop over all of the operands, assigning virtual or physregs
|
||||
// to register class operands.
|
||||
for (unsigned i = 0, e = ConstraintOperands.size(); i != e; ++i) {
|
||||
|
@ -2655,6 +2655,156 @@ unsigned TargetLowering::AsmOperandInfo::getMatchedOperand() const {
|
||||
}
|
||||
|
||||
|
||||
/// 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.
|
||||
std::vector<TargetLowering::AsmOperandInfo> TargetLowering::ParseConstraints(
|
||||
ImmutableCallSite CS) const {
|
||||
/// ConstraintOperands - Information about all of the constraints.
|
||||
std::vector<AsmOperandInfo> ConstraintOperands;
|
||||
const InlineAsm *IA = cast<InlineAsm>(CS.getCalledValue());
|
||||
|
||||
// Do a prepass over the constraints, canonicalizing them, and building up the
|
||||
// ConstraintOperands list.
|
||||
std::vector<InlineAsm::ConstraintInfo>
|
||||
ConstraintInfos = IA->ParseConstraints();
|
||||
|
||||
unsigned ArgNo = 0; // ArgNo - The argument of the CallInst.
|
||||
unsigned ResNo = 0; // ResNo - The result number of the next output.
|
||||
|
||||
for (unsigned i = 0, e = ConstraintInfos.size(); i != e; ++i) {
|
||||
ConstraintOperands.push_back(AsmOperandInfo(ConstraintInfos[i]));
|
||||
AsmOperandInfo &OpInfo = ConstraintOperands.back();
|
||||
|
||||
EVT OpVT = MVT::Other;
|
||||
|
||||
// Compute the value type for each operand.
|
||||
switch (OpInfo.Type) {
|
||||
case InlineAsm::isOutput:
|
||||
// Indirect outputs just consume an argument.
|
||||
if (OpInfo.isIndirect) {
|
||||
OpInfo.CallOperandVal = const_cast<Value *>(CS.getArgument(ArgNo++));
|
||||
break;
|
||||
}
|
||||
|
||||
// The return value of the call is this value. As such, there is no
|
||||
// corresponding argument.
|
||||
assert(!CS.getType()->isVoidTy() &&
|
||||
"Bad inline asm!");
|
||||
if (const StructType *STy = dyn_cast<StructType>(CS.getType())) {
|
||||
OpVT = getValueType(STy->getElementType(ResNo));
|
||||
} else {
|
||||
assert(ResNo == 0 && "Asm only has one result!");
|
||||
OpVT = getValueType(CS.getType());
|
||||
}
|
||||
++ResNo;
|
||||
break;
|
||||
case InlineAsm::isInput:
|
||||
OpInfo.CallOperandVal = const_cast<Value *>(CS.getArgument(ArgNo++));
|
||||
break;
|
||||
case InlineAsm::isClobber:
|
||||
// Nothing to do.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If we have multiple alternative constraints, select the best alternative.
|
||||
if (ConstraintInfos.size()) {
|
||||
unsigned maCount = ConstraintInfos[0].multipleAlternatives.size();
|
||||
if (maCount) {
|
||||
unsigned bestMAIndex = 0;
|
||||
int bestWeight = -1;
|
||||
// weight: -1 = invalid match, and 0 = so-so match to 5 = good match.
|
||||
int weight = -1;
|
||||
unsigned maIndex;
|
||||
// Compute the sums of the weights for each alternative, keeping track
|
||||
// of the best (highest weight) one so far.
|
||||
for (maIndex = 0; maIndex < maCount; ++maIndex) {
|
||||
int weightSum = 0;
|
||||
for (unsigned cIndex = 0, eIndex = ConstraintOperands.size();
|
||||
cIndex != eIndex; ++cIndex) {
|
||||
AsmOperandInfo& OpInfo = ConstraintOperands[cIndex];
|
||||
if (OpInfo.Type == InlineAsm::isClobber)
|
||||
continue;
|
||||
assert((OpInfo.multipleAlternatives.size() == maCount)
|
||||
&& "Constraint has inconsistent multiple alternative count.");
|
||||
|
||||
// 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()) ||
|
||||
(OpInfo.ConstraintVT.getSizeInBits() !=
|
||||
Input.ConstraintVT.getSizeInBits())) {
|
||||
weightSum = -1; // Can't match.
|
||||
break;
|
||||
}
|
||||
Input.ConstraintVT = OpInfo.ConstraintVT;
|
||||
}
|
||||
}
|
||||
|
||||
weight = getMultipleConstraintMatchWeight(OpInfo, maIndex);
|
||||
if (weight == -1) {
|
||||
weightSum = -1;
|
||||
break;
|
||||
}
|
||||
weightSum += weight;
|
||||
}
|
||||
// Update best.
|
||||
if (weightSum > bestWeight) {
|
||||
bestWeight = weightSum;
|
||||
bestMAIndex = maIndex;
|
||||
}
|
||||
}
|
||||
|
||||
// Now select chosen alternative in each constraint.
|
||||
for (unsigned cIndex = 0, eIndex = ConstraintOperands.size();
|
||||
cIndex != eIndex; ++cIndex) {
|
||||
AsmOperandInfo& cInfo = ConstraintOperands[cIndex];
|
||||
if (cInfo.Type == InlineAsm::isClobber)
|
||||
continue;
|
||||
cInfo.selectAlternative(bestMAIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check and hook up tied operands, choose constraint code to use.
|
||||
for (unsigned cIndex = 0, eIndex = ConstraintOperands.size();
|
||||
cIndex != eIndex; ++cIndex) {
|
||||
AsmOperandInfo& OpInfo = ConstraintOperands[cIndex];
|
||||
|
||||
// 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
|
||||
// error.
|
||||
if (OpInfo.hasMatchingInput()) {
|
||||
AsmOperandInfo &Input = ConstraintOperands[OpInfo.MatchingInput];
|
||||
|
||||
if (OpInfo.ConstraintVT != Input.ConstraintVT) {
|
||||
if ((OpInfo.ConstraintVT.isInteger() !=
|
||||
Input.ConstraintVT.isInteger()) ||
|
||||
(OpInfo.ConstraintVT.getSizeInBits() !=
|
||||
Input.ConstraintVT.getSizeInBits())) {
|
||||
report_fatal_error("Unsupported asm: input constraint"
|
||||
" with a matching output constraint of"
|
||||
" incompatible type!");
|
||||
}
|
||||
Input.ConstraintVT = OpInfo.ConstraintVT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ConstraintOperands;
|
||||
}
|
||||
|
||||
|
||||
/// getConstraintGenerality - Return an integer indicating how general CT
|
||||
/// is.
|
||||
static unsigned getConstraintGenerality(TargetLowering::ConstraintType CT) {
|
||||
@ -2672,6 +2822,76 @@ 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.
|
||||
/// This object must already have been set up with the operand type
|
||||
/// and the current alternative constraint selected.
|
||||
int TargetLowering::getMultipleConstraintMatchWeight(
|
||||
AsmOperandInfo &info, int maIndex) const {
|
||||
std::vector<std::string> &rCodes = info.multipleAlternatives[maIndex].Codes;
|
||||
int matchingInput = info.multipleAlternatives[maIndex].MatchingInput;
|
||||
TargetLowering::ConstraintType BestType = TargetLowering::C_Unknown;
|
||||
int BestWeight = -1;
|
||||
|
||||
// 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());
|
||||
if (weight > BestWeight)
|
||||
BestWeight = weight;
|
||||
}
|
||||
|
||||
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.
|
||||
/// This object must already have been set up with the operand type
|
||||
/// and the current alternative constraint selected.
|
||||
int TargetLowering::getSingleConstraintMatchWeight(
|
||||
AsmOperandInfo &info, const char *constraint) const {
|
||||
int weight = -1;
|
||||
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;
|
||||
// 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<ConstantInt>(info.CallOperandVal))
|
||||
weight = 3;
|
||||
else
|
||||
weight = -1;
|
||||
}
|
||||
break;
|
||||
case 's': // non-explicit intregal immediate.
|
||||
weight = 0;
|
||||
if (info.CallOperandVal) {
|
||||
if (isa<GlobalValue>(info.CallOperandVal))
|
||||
weight = 3;
|
||||
else
|
||||
weight = -1;
|
||||
}
|
||||
break;
|
||||
case 'm': // memory operand.
|
||||
case 'o': // offsettable memory operand
|
||||
case 'V': // non-offsettable memory operand
|
||||
weight = 2;
|
||||
break;
|
||||
case 'g': // general register, memory operand or immediate integer.
|
||||
case 'X': // any operand.
|
||||
weight = 1;
|
||||
break;
|
||||
default:
|
||||
weight = 0;
|
||||
break;
|
||||
}
|
||||
return weight;
|
||||
}
|
||||
|
||||
/// 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 four classes:
|
||||
|
@ -11193,6 +11193,34 @@ 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.
|
||||
/// This object must already have been set up with the operand type
|
||||
/// and the current alternative constraint selected.
|
||||
int X86TargetLowering::getSingleConstraintMatchWeight(
|
||||
AsmOperandInfo &info, const char *constraint) const {
|
||||
int weight = -1;
|
||||
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;
|
||||
// Look at the constraint type.
|
||||
switch (*constraint) {
|
||||
default:
|
||||
return TargetLowering::getSingleConstraintMatchWeight(info, constraint);
|
||||
break;
|
||||
case 'I':
|
||||
if (ConstantInt *C = dyn_cast<ConstantInt>(info.CallOperandVal)) {
|
||||
if (C->getZExtValue() <= 31)
|
||||
weight = 3;
|
||||
}
|
||||
break;
|
||||
// etc.
|
||||
}
|
||||
return weight;
|
||||
}
|
||||
|
||||
/// LowerXConstraint - try to replace an X constraint, which matches anything,
|
||||
/// with another that has more specific requirements based on the type of the
|
||||
/// corresponding operand.
|
||||
|
@ -532,6 +532,12 @@ 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.
|
||||
/// The operand object must already have been set up with the operand type.
|
||||
virtual int getSingleConstraintMatchWeight(
|
||||
AsmOperandInfo &info, const char *constraint) const;
|
||||
|
||||
std::vector<unsigned>
|
||||
getRegClassForInlineAsmConstraint(const std::string &Constraint,
|
||||
EVT VT) const;
|
||||
|
@ -738,32 +738,9 @@ bool CodeGenPrepare::OptimizeInlineAsmInst(Instruction *I, CallSite CS,
|
||||
bool MadeChange = false;
|
||||
InlineAsm *IA = cast<InlineAsm>(CS.getCalledValue());
|
||||
|
||||
// Do a prepass over the constraints, canonicalizing them, and building up the
|
||||
// ConstraintOperands list.
|
||||
std::vector<InlineAsm::ConstraintInfo>
|
||||
ConstraintInfos = IA->ParseConstraints();
|
||||
|
||||
/// ConstraintOperands - Information about all of the constraints.
|
||||
std::vector<TargetLowering::AsmOperandInfo> ConstraintOperands;
|
||||
unsigned ArgNo = 0; // ArgNo - The argument of the CallInst.
|
||||
for (unsigned i = 0, e = ConstraintInfos.size(); i != e; ++i) {
|
||||
ConstraintOperands.
|
||||
push_back(TargetLowering::AsmOperandInfo(ConstraintInfos[i]));
|
||||
TargetLowering::AsmOperandInfo &OpInfo = ConstraintOperands.back();
|
||||
|
||||
// Compute the value type for each operand.
|
||||
switch (OpInfo.Type) {
|
||||
case InlineAsm::isOutput:
|
||||
if (OpInfo.isIndirect)
|
||||
OpInfo.CallOperandVal = CS.getArgument(ArgNo++);
|
||||
break;
|
||||
case InlineAsm::isInput:
|
||||
OpInfo.CallOperandVal = CS.getArgument(ArgNo++);
|
||||
break;
|
||||
case InlineAsm::isClobber:
|
||||
// Nothing to do.
|
||||
break;
|
||||
}
|
||||
std::vector<TargetLowering::AsmOperandInfo> TargetConstraints = TLI->ParseConstraints(CS);
|
||||
for (unsigned i = 0, e = TargetConstraints.size(); i != e; ++i) {
|
||||
TargetLowering::AsmOperandInfo &OpInfo = TargetConstraints[i];
|
||||
|
||||
// Compute the constraint code and ConstraintType to use.
|
||||
TLI->ComputeConstraintToUse(OpInfo, SDValue());
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "llvm/Support/GetElementPtrTypeIterator.h"
|
||||
#include "llvm/Support/PatternMatch.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Support/CallSite.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::PatternMatch;
|
||||
@ -379,26 +380,9 @@ bool AddressingModeMatcher::MatchAddr(Value *Addr, unsigned Depth) {
|
||||
/// return false.
|
||||
static bool IsOperandAMemoryOperand(CallInst *CI, InlineAsm *IA, Value *OpVal,
|
||||
const TargetLowering &TLI) {
|
||||
std::vector<InlineAsm::ConstraintInfo>
|
||||
Constraints = IA->ParseConstraints();
|
||||
|
||||
unsigned ArgNo = 0; // The argument of the CallInst.
|
||||
for (unsigned i = 0, e = Constraints.size(); i != e; ++i) {
|
||||
TargetLowering::AsmOperandInfo OpInfo(Constraints[i]);
|
||||
|
||||
// Compute the value type for each operand.
|
||||
switch (OpInfo.Type) {
|
||||
case InlineAsm::isOutput:
|
||||
if (OpInfo.isIndirect)
|
||||
OpInfo.CallOperandVal = CI->getArgOperand(ArgNo++);
|
||||
break;
|
||||
case InlineAsm::isInput:
|
||||
OpInfo.CallOperandVal = CI->getArgOperand(ArgNo++);
|
||||
break;
|
||||
case InlineAsm::isClobber:
|
||||
// Nothing to do.
|
||||
break;
|
||||
}
|
||||
std::vector<TargetLowering::AsmOperandInfo> TargetConstraints = TLI.ParseConstraints(ImmutableCallSite(CI));
|
||||
for (unsigned i = 0, e = TargetConstraints.size(); i != e; ++i) {
|
||||
TargetLowering::AsmOperandInfo &OpInfo = TargetConstraints[i];
|
||||
|
||||
// Compute the constraint code and ConstraintType to use.
|
||||
TLI.ComputeConstraintToUse(OpInfo, SDValue());
|
||||
|
@ -54,19 +54,46 @@ const FunctionType *InlineAsm::getFunctionType() const {
|
||||
return cast<FunctionType>(getType()->getElementType());
|
||||
}
|
||||
|
||||
///Default constructor.
|
||||
InlineAsm::ConstraintInfo::ConstraintInfo() :
|
||||
isMultipleAlternative(false),
|
||||
Type(isInput), isEarlyClobber(false),
|
||||
MatchingInput(-1), isCommutative(false),
|
||||
isIndirect(false), currentAlternativeIndex(0) {
|
||||
}
|
||||
|
||||
/// Copy constructor.
|
||||
InlineAsm::ConstraintInfo::ConstraintInfo(const ConstraintInfo &other) :
|
||||
isMultipleAlternative(other.isMultipleAlternative),
|
||||
Type(other.Type), isEarlyClobber(other.isEarlyClobber),
|
||||
MatchingInput(other.MatchingInput), isCommutative(other.isCommutative),
|
||||
isIndirect(other.isIndirect), Codes(other.Codes),
|
||||
multipleAlternatives(other.multipleAlternatives),
|
||||
currentAlternativeIndex(other.currentAlternativeIndex) {
|
||||
}
|
||||
|
||||
/// 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 InlineAsm::ConstraintInfo::Parse(StringRef Str,
|
||||
std::vector<InlineAsm::ConstraintInfo> &ConstraintsSoFar) {
|
||||
StringRef::iterator I = Str.begin(), E = Str.end();
|
||||
unsigned multipleAlternativeCount = Str.count('|') + 1;
|
||||
unsigned multipleAlternativeIndex = 0;
|
||||
std::vector<std::string> *pCodes = &Codes;
|
||||
|
||||
// Initialize
|
||||
isMultipleAlternative = (multipleAlternativeCount > 1 ? true : false);
|
||||
if (isMultipleAlternative) {
|
||||
multipleAlternatives.resize(multipleAlternativeCount);
|
||||
pCodes = &multipleAlternatives[0].Codes;
|
||||
}
|
||||
Type = isInput;
|
||||
isEarlyClobber = false;
|
||||
MatchingInput = -1;
|
||||
isCommutative = false;
|
||||
isIndirect = false;
|
||||
currentAlternativeIndex = 0;
|
||||
|
||||
// Parse prefixes.
|
||||
if (*I == '~') {
|
||||
@ -120,15 +147,15 @@ bool InlineAsm::ConstraintInfo::Parse(StringRef Str,
|
||||
// Find the end of the register name.
|
||||
StringRef::iterator ConstraintEnd = std::find(I+1, E, '}');
|
||||
if (ConstraintEnd == E) return true; // "{foo"
|
||||
Codes.push_back(std::string(I, ConstraintEnd+1));
|
||||
pCodes->push_back(std::string(I, ConstraintEnd+1));
|
||||
I = ConstraintEnd+1;
|
||||
} else if (isdigit(*I)) { // Matching Constraint
|
||||
// Maximal munch numbers.
|
||||
StringRef::iterator NumStart = I;
|
||||
while (I != E && isdigit(*I))
|
||||
++I;
|
||||
Codes.push_back(std::string(NumStart, I));
|
||||
unsigned N = atoi(Codes.back().c_str());
|
||||
pCodes->push_back(std::string(NumStart, I));
|
||||
unsigned N = atoi(pCodes->back().c_str());
|
||||
// Check that this is a valid matching constraint!
|
||||
if (N >= ConstraintsSoFar.size() || ConstraintsSoFar[N].Type != isOutput||
|
||||
Type != isInput)
|
||||
@ -136,14 +163,26 @@ bool InlineAsm::ConstraintInfo::Parse(StringRef Str,
|
||||
|
||||
// If Operand N already has a matching input, reject this. An output
|
||||
// can't be constrained to the same value as multiple inputs.
|
||||
if (ConstraintsSoFar[N].hasMatchingInput())
|
||||
return true;
|
||||
|
||||
// Note that operand #n has a matching input.
|
||||
ConstraintsSoFar[N].MatchingInput = ConstraintsSoFar.size();
|
||||
if (isMultipleAlternative) {
|
||||
InlineAsm::SubConstraintInfo &scInfo =
|
||||
ConstraintsSoFar[N].multipleAlternatives[multipleAlternativeIndex];
|
||||
if (scInfo.MatchingInput != -1)
|
||||
return true;
|
||||
// Note that operand #n has a matching input.
|
||||
scInfo.MatchingInput = ConstraintsSoFar.size();
|
||||
} else {
|
||||
if (ConstraintsSoFar[N].hasMatchingInput())
|
||||
return true;
|
||||
// Note that operand #n has a matching input.
|
||||
ConstraintsSoFar[N].MatchingInput = ConstraintsSoFar.size();
|
||||
}
|
||||
} else if (*I == '|') {
|
||||
multipleAlternativeIndex++;
|
||||
pCodes = &multipleAlternatives[multipleAlternativeIndex].Codes;
|
||||
++I;
|
||||
} else {
|
||||
// Single letter constraint.
|
||||
Codes.push_back(std::string(I, I+1));
|
||||
pCodes->push_back(std::string(I, I+1));
|
||||
++I;
|
||||
}
|
||||
}
|
||||
@ -151,6 +190,18 @@ bool InlineAsm::ConstraintInfo::Parse(StringRef Str,
|
||||
return false;
|
||||
}
|
||||
|
||||
/// selectAlternative - Point this constraint to the alternative constraint
|
||||
/// indicated by the index.
|
||||
void InlineAsm::ConstraintInfo::selectAlternative(unsigned index) {
|
||||
if (index < multipleAlternatives.size()) {
|
||||
currentAlternativeIndex = index;
|
||||
InlineAsm::SubConstraintInfo &scInfo =
|
||||
multipleAlternatives[currentAlternativeIndex];
|
||||
MatchingInput = scInfo.MatchingInput;
|
||||
Codes = scInfo.Codes;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<InlineAsm::ConstraintInfo>
|
||||
InlineAsm::ParseConstraints(StringRef Constraints) {
|
||||
std::vector<ConstraintInfo> Result;
|
||||
@ -183,7 +234,6 @@ InlineAsm::ParseConstraints(StringRef Constraints) {
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
||||
/// Verify - Verify that the specified constraint string is reasonable for the
|
||||
/// specified function type, and otherwise validate the constraint string.
|
||||
bool InlineAsm::Verify(const FunctionType *Ty, StringRef ConstStr) {
|
||||
|
Loading…
Reference in New Issue
Block a user