[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