[llvm-commits] [125328] Improve CanonicalizeConstraint to support canonicalization of multiple-alternative inline asm constraints , e.g., turn:
clattner at apple.com
clattner at apple.com
Sat Mar 24 21:03:00 PDT 2007
Revision: 125328
Author: clattner
Date: 2007-03-24 21:02:59 -0700 (Sat, 24 Mar 2007)
Log Message:
-----------
Improve CanonicalizeConstraint to support canonicalization of multiple-alternative inline asm constraints, e.g., turn:
__asm__ volatile("inw %w1, %w0" : "=a" (datum) : "Nd" (port));
into:
"={ax},N{dx},...
instead of:
"={ax},Nd,...
This allows us to correctly compile inline asm like the example above.
Modified Paths:
--------------
apple-local/branches/llvm/gcc/llvm-convert.cpp
Modified: apple-local/branches/llvm/gcc/llvm-convert.cpp
===================================================================
--- apple-local/branches/llvm/gcc/llvm-convert.cpp 2007-03-25 03:39:48 UTC (rev 125327)
+++ apple-local/branches/llvm/gcc/llvm-convert.cpp 2007-03-25 04:02:59 UTC (rev 125328)
@@ -3415,11 +3415,9 @@
/// CanonicalizeConstraint - If we can canonicalize the constraint into
/// something simpler, do so now. This turns register classes with a single
/// register into the register itself, expands builtin constraints to multiple
-/// alternatives, etc. If the constraint cannot be simplified, this returns an
-/// empty string.
+/// alternatives, etc.
static std::string CanonicalizeConstraint(const char *Constraint) {
std::string Result;
- unsigned RegClass;
// Skip over modifier characters.
bool DoneModifiers = false;
@@ -3436,51 +3434,67 @@
++Constraint;
break;
case '#': // No constraint letters left.
- return "";
+ return Result;
}
}
+ while (*Constraint) {
+ char ConstraintChar = *Constraint++;
+
+ // 'g' is just short-hand for 'imr'.
+ if (ConstraintChar == 'g') {
+ Result += "imr";
+ continue;
+ }
- if (*Constraint == 'r') // r is a special case for some reason.
- RegClass = GENERAL_REGS;
- else if (*Constraint == 'g')
- return "imr";
- else
- RegClass = REG_CLASS_FROM_CONSTRAINT(*Constraint, Constraint);
+ // See if this is a regclass constraint.
+ unsigned RegClass;
+ if (ConstraintChar == 'r')
+ // REG_CLASS_FROM_CONSTRAINT doesn't support 'r' for some reason.
+ RegClass = GENERAL_REGS;
+ else
+ RegClass = REG_CLASS_FROM_CONSTRAINT(Constraint[-1], Constraint-1);
- if (RegClass == NO_REGS) return Result; // not a reg class.
+ if (RegClass == NO_REGS) { // not a reg class.
+ Result += ConstraintChar;
+ continue;
+ }
- // Look to see if the specified regclass has exactly one member, and if so,
- // what it is. Cache this information in AnalyzedRegClasses once computed.
- static std::map<unsigned, int> AnalyzedRegClasses;
+ // Look to see if the specified regclass has exactly one member, and if so,
+ // what it is. Cache this information in AnalyzedRegClasses once computed.
+ static std::map<unsigned, int> AnalyzedRegClasses;
- std::map<unsigned, int>::iterator I =AnalyzedRegClasses.lower_bound(RegClass);
+ std::map<unsigned, int>::iterator I =
+ AnalyzedRegClasses.lower_bound(RegClass);
- int RegMember;
- if (I != AnalyzedRegClasses.end() && I->first == RegClass) {
- // We've already computed this, reuse value.
- RegMember = I->second;
- } else {
- // Otherwise, scan the regclass, looking for exactly one member.
- RegMember = -1; // -1 => not one thing
- for (unsigned j = 0; j != FIRST_PSEUDO_REGISTER; ++j)
- if (TEST_HARD_REG_BIT(reg_class_contents[RegClass], j)) {
- if (RegMember == -1) {
- RegMember = j;
- } else {
- RegMember = -1;
- break;
+ int RegMember;
+ if (I != AnalyzedRegClasses.end() && I->first == RegClass) {
+ // We've already computed this, reuse value.
+ RegMember = I->second;
+ } else {
+ // Otherwise, scan the regclass, looking for exactly one member.
+ RegMember = -1; // -1 => not a single-register class.
+ for (unsigned j = 0; j != FIRST_PSEUDO_REGISTER; ++j)
+ if (TEST_HARD_REG_BIT(reg_class_contents[RegClass], j)) {
+ if (RegMember == -1) {
+ RegMember = j;
+ } else {
+ RegMember = -1;
+ break;
+ }
}
- }
- // Remember this answer for the next query of this regclass.
- AnalyzedRegClasses.insert(I, std::make_pair(RegClass, RegMember));
- }
+ // Remember this answer for the next query of this regclass.
+ AnalyzedRegClasses.insert(I, std::make_pair(RegClass, RegMember));
+ }
- // If we found a single register register class, return the register.
- if (RegMember != -1) {
- Result = '{';
- Result += reg_names[RegMember];
- Result += '}';
+ // If we found a single register register class, return the register.
+ if (RegMember != -1) {
+ Result += '{';
+ Result += reg_names[RegMember];
+ Result += '}';
+ } else {
+ Result += ConstraintChar;
+ }
}
return Result;
@@ -3556,14 +3570,7 @@
// If we can simplify the constraint into something else, do so now. This
// avoids LLVM having to know about all the (redundant) GCC constraints.
- std::string Simplified = CanonicalizeConstraint(Constraint+1);
- if (!Simplified.empty()) {
- char *NewConstraint = (char*)alloca(Simplified.size()+2);
- NewConstraint[0] = '=';
- memcpy(NewConstraint+1, &Simplified[0], Simplified.size());
- NewConstraint[Simplified.size()+1] = 0;
- Constraint = NewConstraint;
- }
+ std::string SimplifiedConstraint = '='+CanonicalizeConstraint(Constraint+1);
LValue Dest = EmitLV(Operand);
assert(!Dest.isBitfield() && "Cannot assign into a bitfield!");
@@ -3571,11 +3578,11 @@
assert(StoreCallResultAddr == 0 && "Already have a result val?");
StoreCallResultAddr = Dest.Ptr;
ConstraintStr += ",";
- ConstraintStr += Constraint;
+ ConstraintStr += SimplifiedConstraint;
CallResultType = cast<PointerType>(Dest.Ptr->getType())->getElementType();
} else {
ConstraintStr += ",=";
- ConstraintStr += Constraint;
+ ConstraintStr += SimplifiedConstraint;
CallOps.push_back(Dest.Ptr);
CallArgTypes.push_back(Dest.Ptr->getType());
}
@@ -3624,12 +3631,7 @@
} else {
// If there is a simpler form for the register constraint, use it.
std::string Simplified = CanonicalizeConstraint(Constraint);
- if (!Simplified.empty()) {
- ConstraintStr += Simplified;
- } else {
- // Otherwise, just add the constraint!
- ConstraintStr += Constraint;
- }
+ ConstraintStr += Simplified;
}
}
More information about the llvm-commits
mailing list