[llvm-commits] [PATCH] Inline asm mult-alt constraints done for now

John Thompson john.thompson.jtsoftware at gmail.com
Mon Oct 25 11:59:14 PDT 2010


Thanks, Dale.  Though I'm still rebuilding my system after a crash, here a
revised patch which addresses some of the issues, with the following notes.
This is from an updated tree from Friday, with the 3 sets of llvm tests
re-run.

>There is too much duplication in the different versions of
getSingleConstraintMatchWeight.  Generic constraints like 'r' should be
handled only in the generic version.  I think several of the overloaded
versions can go away entirely.  The approach of substituting
ConstraintWeight for numbers is generally OK with this modification.

Yes, I noticed that, but I put it in anyway to be consistent with the
getConstraintType function already there, which I used as a guide.  I've
removed these in the new patch.  The platform implementer can probably
figure out when he needs to add one, using another platform as a guide.

> Should be followed by 'break' (several places).  It's disturbing that
testing didn't catch this.

Yes.  Sorry, I haven't tested all the platforms yet, only Linux x86.  Rather
than do this whole thing all at once, I've been trying to do it
incrementally.  My reasoning is that since multi-alt wouldn't work in Clang
anyway, as long as I don't regress on the existing tests, I should be okay,
now that I know how to run all three sets of tests.  I have a couple of test
files I'm working on locally, which I plan to convert to clang and LLVM test
files after I get the current patch in.

Having said that, it just occured to me that perhaps I should be running the
gcc tests for multiple platforms, rather than just the default one in the
makefile.  Do you guys do that?  If so, could you give me a list of the
triples that I should test?

To give it a shot, I ran the gcc tests with powerpc-apple-darwin for the
build and target in the top-level makefile.  Perhaps running the gcc
tests targeting platforms other than x86 would have caught this.  Here's my
results:

Modified summary:
# of expected passes        16082
# of unexpected failures    17933
# of unexpected successes    29
# of expected failures        28
# of unresolved testcases    8666
# of untested testcases        273
# of unsupported tests        671
/home/john/llvm/Release+Asserts/bin/clang  version 2.9 (trunk 117191)

Original summary:
# of expected passes        16082
# of unexpected failures    17933
# of unexpected successes    29
# of expected failures        28
# of unresolved testcases    8666
# of untested testcases        273
# of unsupported tests        671
/home/john/llvm_org/Release+Asserts/bin/clang  version 2.9 (trunk 117191)
Quite a lot fewer passes than in x86, but the results for the
modified/original trees are the same.

 > I need to look at the ParseConstraints bits more, I don't really
understand what you're doing there yet.

There are two main parts of it.  One part (the beginning and ending chunks
of code) was to take some of what was in
SelectionDAGBuilder::visitInlineAsm, and some other stuff in
SelectionDAGBuilder.cpp such as getCallOperandValEVT, and duplicate it here,
to the extent possible without having a DAG.  This was necessary because of
that one place where parsing the constraints was needed outside of the DAG
pass.

The second part (the code chunk in the middle) does the selection of the
constraint alternatives, if there are multiple, using the
getMultipleConstraintMatchWeight function to compute the best constraint
weight for one alternative, which might have multiple constraint letters.
The getSingleConstraintMatchWeight function computes the weight for one
constraint character, and is the part to be overidden for different
platforms.

The main idea was that I could inject the support for multiple-alternative
constraints without affecting the current logic.

There are a couple of architectural problems with this in that the parsing
could be done multiple times in some circumstances, as opposed to doing it
once and saving the results, and there is some duplication of functionality,
but changing this would be a much more significant change, and I thought it
best to just get it to work reasonably as-is, since the whole inline asm
lowering is a pretty complicated set of logic.

>The bits covered above can go in.

I think it would be dangerous to try to separate the parts now, so can I
just wait until you are comfortable with the whole patch?  I'm assuming it
won't take much more time.  I'm available if you would like me to come over
and look at it with you (I'm in Santa Clara).

Thanks again!

-John


On Thu, Oct 21, 2010 at 11:54 AM, Dale Johannesen <dalej at apple.com> wrote:

> OK, I've gotten to this now.  Thanks for your patience.
>
> The various changes of std::vector to SmallVector and uses of typedefs are
> OK.
>
> There is too much duplication in the different versions of
> getSingleConstraintMatchWeight.  Generic constraints like 'r' should be
> handled only in the generic version.  I think several of the overloaded
> versions can go away entirely.  The approach of substituting
> ConstraintWeight for numbers is generally OK with this modification.
>
>   +  default:
> +    weight = TargetLowering::getSingleConstraintMatchWeight(info,
> constraint);
>
>
> Should be followed by 'break' (several places).  It's disturbing that
> testing didn't catch this.
>
>  +    CW_Okay     = 0,      // Acceptible.
>
>
> Spelling.
>
> I need to look at the ParseConstraints bits more, I don't really understand
> what you're doing there yet.   The bits covered above can go in.
>
>  On Oct 15, 2010, at 10:42 AMPDT, John Thompson wrote:
>
>  Thanks for the heads up, Evan.
>
> I forgot to point out a couple of other changes I made.  One was to change
> some usages of std::vector to SmallVector typedefs on the stuff related to
> the constraints.  The other was that I changed some hard tabs in one file
> (not from me this time) to spaces, based on the report from a checking
> program I wrote and am now running on the files I touch.
> -John
> On Fri, Oct 15, 2010 at 10:02 AM, Evan Cheng <evan.cheng at apple.com> wrote:
>
>> Dale should review this once he gets back on Monday.
>>
>> Evan
>>
>>   On Oct 14, 2010, at 6:41 PM, John Thompson wrote:
>>
>>   I made a pass through all the platforms, and added support for the
>> weighting of the platform-specific constraints that seemed to have any kind
>> of support, which was not much, based on what was in the existing
>> getConstraintType functions.  There probably isn't much point
>> adding weighting for constraints not yet supported, but at least the now
>> framework is there for if and when they are added.  Therefore, I'm
>> considering Clang/LLVM mult-alt constraint support done for now, except for
>> some tests I'm getting in shape to check in for both the Clang and LLVM
>> sides.  I've run the regression tests, test-suite, and gcc tests on both
>> modified and unmodified trees from this morning on Linux with no
>> differences.
>>
>> May I check this in?
>>
>> Thanks.
>>
>> -John
>>
>> --
>> John Thompson
>> John.Thompson.JTSoftware at gmail.com
>>
>> <llvmmultalt15.patch>_______________________________________________
>> llvm-commits mailing list
>> llvm-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>>
>>
>>
>
>
> --
> John Thompson
> John.Thompson.JTSoftware at gmail.com
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
>
>


-- 
John Thompson
John.Thompson.JTSoftware at gmail.com
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20101025/4ba98126/attachment.html>
-------------- next part --------------
Index: include/llvm/Target/TargetLowering.h
===================================================================
--- include/llvm/Target/TargetLowering.h	(revision 117191)
+++ include/llvm/Target/TargetLowering.h	(working copy)
@@ -1320,6 +1320,22 @@
     C_Unknown              // Unsupported constraint.
   };
 
+  enum ConstraintWeight {
+    // Generic weights.
+    CW_Invalid  = -1,     // No match.
+    CW_Okay     = 0,      // Acceptable.
+    CW_Good     = 1,      // Good weight.
+    CW_Better   = 2,      // Better weight.
+    CW_Best     = 3,      // Best weight.
+    
+    // Well-known weights.
+    CW_SpecificReg  = CW_Okay,    // Specific register operands.
+    CW_Register     = CW_Good,    // Register operands.
+    CW_Memory       = CW_Better,  // Memory operands.
+    CW_Constant     = CW_Best,    // Constant operand.
+    CW_Default      = CW_Okay     // Default or don't know type.
+  };
+
   /// AsmOperandInfo - This contains information for each constraint that we are
   /// lowering.
   struct AsmOperandInfo : public InlineAsm::ConstraintInfo {
@@ -1365,24 +1381,23 @@
     }
   };
   
+  typedef SmallVector<AsmOperandInfo,16> AsmOperandInfoVector;
+  
   /// 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;
+  virtual AsmOperandInfoVector 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.
+  /// Examine constraint type and operand type and determine a weight value.
   /// The operand object must already have been set up with the operand type.
-  virtual int getMultipleConstraintMatchWeight(
+  virtual ConstraintWeight 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.
+  /// Examine constraint string and operand type and determine a weight value.
   /// The operand object must already have been set up with the operand type.
-  virtual int getSingleConstraintMatchWeight(
+  virtual ConstraintWeight getSingleConstraintMatchWeight(
       AsmOperandInfo &info, const char *constraint) const;
 
   /// ComputeConstraintToUse - Determines the constraint code and constraint
Index: include/llvm/InlineAsm.h
===================================================================
--- include/llvm/InlineAsm.h	(revision 117191)
+++ include/llvm/InlineAsm.h	(working copy)
@@ -16,8 +16,8 @@
 #ifndef LLVM_INLINEASM_H
 #define LLVM_INLINEASM_H
 
+#include "llvm/ADT/SmallVector.h"
 #include "llvm/Value.h"
-#include <vector>
 
 namespace llvm {
 
@@ -87,6 +87,8 @@
     isClobber           // '~x'
   };
   
+  typedef SmallVector<std::string,8> ConstraintCodeVector;
+  
   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
@@ -95,10 +97,14 @@
     signed char MatchingInput;
     /// Code - The constraint code, either the register name (in braces) or the
     /// constraint letter/number.
-    std::vector<std::string> Codes;
+    ConstraintCodeVector Codes;
     /// Default constructor.
     SubConstraintInfo() : MatchingInput(-1) {}
   };
+
+  typedef SmallVector<SubConstraintInfo,4> SubConstraintInfoVector;
+  struct ConstraintInfo;
+  typedef SmallVector<ConstraintInfo,16> ConstraintInfoVector;
   
   struct ConstraintInfo {
     /// Type - The basic type of the constraint: input/output/clobber
@@ -131,14 +137,14 @@
     
     /// Code - The constraint code, either the register name (in braces) or the
     /// constraint letter/number.
-    std::vector<std::string> Codes;
+    ConstraintCodeVector 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;
+    SubConstraintInfoVector multipleAlternatives;
     
     /// The currently selected alternative constraint index.
     unsigned currentAlternativeIndex;
@@ -152,8 +158,7 @@
     /// 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);
+    bool Parse(StringRef Str, ConstraintInfoVector &ConstraintsSoFar);
                
     /// selectAlternative - Point this constraint to the alternative constraint
     /// indicated by the index.
@@ -163,13 +168,11 @@
   /// ParseConstraints - Split up the constraint string into the specific
   /// constraints and their prefixes.  If this returns an empty vector, and if
   /// the constraint string itself isn't empty, there was an error parsing.
-  static std::vector<ConstraintInfo> 
-    ParseConstraints(StringRef ConstraintString);
+  static ConstraintInfoVector ParseConstraints(StringRef ConstraintString);
   
   /// ParseConstraints - Parse the constraints of this inlineasm object, 
   /// returning them the same way that ParseConstraints(str) does.
-  std::vector<ConstraintInfo> 
-  ParseConstraints() const {
+  ConstraintInfoVector ParseConstraints() const {
     return ParseConstraints(Constraints);
   }
   
Index: include/llvm/CodeGen/Analysis.h
===================================================================
--- include/llvm/CodeGen/Analysis.h	(revision 117191)
+++ include/llvm/CodeGen/Analysis.h	(working copy)
@@ -52,7 +52,7 @@
 
 /// hasInlineAsmMemConstraint - Return true if the inline asm instruction being
 /// processed uses a memory 'm' constraint.
-bool hasInlineAsmMemConstraint(std::vector<InlineAsm::ConstraintInfo> &CInfos,
+bool hasInlineAsmMemConstraint(InlineAsm::ConstraintInfoVector &CInfos,
                                const TargetLowering &TLI);
 
 /// getFCmpCondCode - Return the ISD condition code corresponding to
Index: lib/Target/X86/X86ISelLowering.cpp
===================================================================
--- lib/Target/X86/X86ISelLowering.cpp	(revision 117191)
+++ lib/Target/X86/X86ISelLowering.cpp	(working copy)
@@ -11423,7 +11423,7 @@
 
 bool X86TargetLowering::ExpandInlineAsm(CallInst *CI) const {
   InlineAsm *IA = cast<InlineAsm>(CI->getCalledValue());
-  std::vector<InlineAsm::ConstraintInfo> Constraints = IA->ParseConstraints();
+  InlineAsm::ConstraintInfoVector Constraints = IA->ParseConstraints();
 
   std::string AsmStr = IA->getAsmString();
 
@@ -11503,18 +11503,32 @@
 X86TargetLowering::getConstraintType(const std::string &Constraint) const {
   if (Constraint.size() == 1) {
     switch (Constraint[0]) {
-    case 'A':
-      return C_Register;
-    case 'f':
-    case 'r':
     case 'R':
-    case 'l':
     case 'q':
     case 'Q':
+    case 'f':
+    case 't':
+    case 'u':
+    case 'y':
     case 'x':
-    case 'y':
     case 'Y':
       return C_RegisterClass;
+    case 'a':
+    case 'b':
+    case 'c':
+    case 'd':
+    case 'S':
+    case 'D':
+    case 'A':
+      return C_Register;
+    case 'I':
+    case 'J':
+    case 'K':
+    case 'L':
+    case 'M':
+    case 'N':
+    case 'G':
+    case 'C':
     case 'e':
     case 'Z':
       return C_Other;
@@ -11525,30 +11539,106 @@
   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.
+/// Examine constraint type and operand type and determine a weight value.
 /// This object must already have been set up with the operand type
 /// and the current alternative constraint selected.
-int X86TargetLowering::getSingleConstraintMatchWeight(
+TargetLowering::ConstraintWeight
+  X86TargetLowering::getSingleConstraintMatchWeight(
     AsmOperandInfo &info, const char *constraint) const {
-  int weight = -1;
+  ConstraintWeight weight = CW_Invalid;
   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;
+    return CW_Default;
+  const Type *type = CallOperandVal->getType();
   // Look at the constraint type.
   switch (*constraint) {
   default:
-    return TargetLowering::getSingleConstraintMatchWeight(info, constraint);
+    weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint);
+  case 'R':
+  case 'q':
+  case 'Q':
+  case 'a':
+  case 'b':
+  case 'c':
+  case 'd':
+  case 'S':
+  case 'D':
+  case 'A':
+    if (CallOperandVal->getType()->isIntegerTy())
+      weight = CW_SpecificReg;
     break;
+  case 'f':
+  case 't':
+  case 'u':
+      if (type->isX86_FP80Ty())
+        weight = CW_SpecificReg;
+      break;
+  case 'y':
+      if (type->isX86_MMXTy())
+        weight = CW_SpecificReg;
+      break;
+  case 'x':
+  case 'Y':
+    if (type->isVectorTy() && type->isFloatingPointTy())
+      weight = CW_Register;
+    break;
   case 'I':
     if (ConstantInt *C = dyn_cast<ConstantInt>(info.CallOperandVal)) {
       if (C->getZExtValue() <= 31)
-        weight = 3;
+        weight = CW_Constant;
     }
     break;
-  // etc.
+  case 'J':
+    if (ConstantInt *C = dyn_cast<ConstantInt>(CallOperandVal)) {
+      if (C->getZExtValue() <= 63)
+        weight = CW_Constant;
+    }
+    break;
+  case 'K':
+    if (ConstantInt *C = dyn_cast<ConstantInt>(CallOperandVal)) {
+      if ((C->getSExtValue() >= -0x80) && (C->getSExtValue() <= 0x7f))
+        weight = CW_Constant;
+    }
+    break;
+  case 'L':
+    if (ConstantInt *C = dyn_cast<ConstantInt>(CallOperandVal)) {
+      if ((C->getZExtValue() == 0xff) || (C->getZExtValue() == 0xffff))
+        weight = CW_Constant;
+    }
+    break;
+  case 'M':
+    if (ConstantInt *C = dyn_cast<ConstantInt>(CallOperandVal)) {
+      if (C->getZExtValue() <= 3)
+        weight = CW_Constant;
+    }
+    break;
+  case 'N':
+    if (ConstantInt *C = dyn_cast<ConstantInt>(CallOperandVal)) {
+      if (C->getZExtValue() <= 0xff)
+        weight = CW_Constant;
+    }
+    break;
+  case 'G':
+  case 'C':
+    if (dyn_cast<ConstantFP>(CallOperandVal)) {
+      weight = CW_Constant;
+    }
+    break;
+  case 'e':
+    if (ConstantInt *C = dyn_cast<ConstantInt>(CallOperandVal)) {
+      if ((C->getSExtValue() >= -0x80000000LL) &&
+          (C->getSExtValue() <= 0x7fffffffLL))
+        weight = CW_Constant;
+    }
+    break;
+  case 'Z':
+    if (ConstantInt *C = dyn_cast<ConstantInt>(CallOperandVal)) {
+      if (C->getZExtValue() <= 0xffffffff)
+        weight = CW_Constant;
+    }
+    break;
   }
   return weight;
 }
Index: lib/Target/X86/X86ISelLowering.h
===================================================================
--- lib/Target/X86/X86ISelLowering.h	(revision 117191)
+++ lib/Target/X86/X86ISelLowering.h	(working copy)
@@ -542,10 +542,9 @@
 
     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.
+    /// Examine constraint string and operand type and determine a weight value.
     /// The operand object must already have been set up with the operand type.
-    virtual int getSingleConstraintMatchWeight(
+    virtual ConstraintWeight getSingleConstraintMatchWeight(
       AsmOperandInfo &info, const char *constraint) const;
 
     std::vector<unsigned>
Index: lib/Target/CBackend/CBackend.cpp
===================================================================
--- lib/Target/CBackend/CBackend.cpp	(revision 117191)
+++ lib/Target/CBackend/CBackend.cpp	(working copy)
@@ -3193,7 +3193,7 @@
 //      handle communitivity
 void CWriter::visitInlineAsm(CallInst &CI) {
   InlineAsm* as = cast<InlineAsm>(CI.getCalledValue());
-  std::vector<InlineAsm::ConstraintInfo> Constraints = as->ParseConstraints();
+  InlineAsm::ConstraintInfoVector Constraints = as->ParseConstraints();
 
   std::vector<std::pair<Value*, int> > ResultVals;
   if (CI.getType() == Type::getVoidTy(CI.getContext()))
@@ -3213,7 +3213,7 @@
   bool IsFirst = true;
 
   // Convert over all the output constraints.
-  for (std::vector<InlineAsm::ConstraintInfo>::iterator I = Constraints.begin(),
+  for (InlineAsm::ConstraintInfoVector::iterator I = Constraints.begin(),
        E = Constraints.end(); I != E; ++I) {
 
     if (I->Type != InlineAsm::isOutput) {
@@ -3255,7 +3255,7 @@
   Out << "\n        :";
   IsFirst = true;
   ValueCount = 0;
-  for (std::vector<InlineAsm::ConstraintInfo>::iterator I = Constraints.begin(),
+  for (InlineAsm::ConstraintInfoVector::iterator I = Constraints.begin(),
        E = Constraints.end(); I != E; ++I) {
     if (I->Type != InlineAsm::isInput) {
       ++ValueCount;
@@ -3284,7 +3284,7 @@
 
   // Convert over the clobber constraints.
   IsFirst = true;
-  for (std::vector<InlineAsm::ConstraintInfo>::iterator I = Constraints.begin(),
+  for (InlineAsm::ConstraintInfoVector::iterator I = Constraints.begin(),
        E = Constraints.end(); I != E; ++I) {
     if (I->Type != InlineAsm::isClobber)
       continue;  // Ignore non-input constraints.
Index: lib/Target/CellSPU/SPUISelLowering.h
===================================================================
--- lib/Target/CellSPU/SPUISelLowering.h	(revision 117191)
+++ lib/Target/CellSPU/SPUISelLowering.h	(working copy)
@@ -129,6 +129,11 @@
 
     ConstraintType getConstraintType(const std::string &ConstraintLetter) const;
 
+    /// Examine constraint string and operand type and determine a weight value.
+    /// The operand object must already have been set up with the operand type.
+    ConstraintWeight getSingleConstraintMatchWeight(
+      AsmOperandInfo &info, const char *constraint) const;
+
     std::pair<unsigned, const TargetRegisterClass*>
       getRegForInlineAsmConstraint(const std::string &Constraint,
                                    EVT VT) const;
Index: lib/Target/CellSPU/SPUISelLowering.cpp
===================================================================
--- lib/Target/CellSPU/SPUISelLowering.cpp	(revision 117191)
+++ lib/Target/CellSPU/SPUISelLowering.cpp	(working copy)
@@ -20,6 +20,7 @@
 #include "llvm/Function.h"
 #include "llvm/Intrinsics.h"
 #include "llvm/CallingConv.h"
+#include "llvm/Type.h"
 #include "llvm/CodeGen/CallingConvLower.h"
 #include "llvm/CodeGen/MachineFrameInfo.h"
 #include "llvm/CodeGen/MachineFunction.h"
@@ -2989,6 +2990,38 @@
   return TargetLowering::getConstraintType(ConstraintLetter);
 }
 
+/// Examine constraint type and operand type and determine a weight value.
+/// This object must already have been set up with the operand type
+/// and the current alternative constraint selected.
+TargetLowering::ConstraintWeight
+SPUTargetLowering::getSingleConstraintMatchWeight(
+    AsmOperandInfo &info, const char *constraint) const {
+  ConstraintWeight weight = CW_Invalid;
+  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 CW_Default;
+  // Look at the constraint type.
+  switch (*constraint) {
+  default:
+    weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint);
+    break;
+    //FIXME: Seems like the supported constraint letters were just copied
+    // from PPC, as the following doesn't correspond to the GCC docs.
+    // I'm leaving it so until someone adds the corresponding lowering support.
+  case 'b':
+  case 'r':
+  case 'f':
+  case 'd':
+  case 'v':
+  case 'y':
+    weight = CW_Register;
+    break;
+  }
+  return weight;
+}
+
 std::pair<unsigned, const TargetRegisterClass*>
 SPUTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint,
                                                 EVT VT) const
Index: lib/Target/MBlaze/MBlazeISelLowering.h
===================================================================
--- lib/Target/MBlaze/MBlazeISelLowering.h	(revision 117191)
+++ lib/Target/MBlaze/MBlazeISelLowering.h	(working copy)
@@ -153,6 +153,11 @@
     // Inline asm support
     ConstraintType getConstraintType(const std::string &Constraint) const;
 
+    /// Examine constraint string and operand type and determine a weight value.
+    /// The operand object must already have been set up with the operand type.
+    ConstraintWeight getSingleConstraintMatchWeight(
+      AsmOperandInfo &info, const char *constraint) const;
+
     std::pair<unsigned, const TargetRegisterClass*>
               getRegForInlineAsmConstraint(const std::string &Constraint,
               EVT VT) const;
Index: lib/Target/MBlaze/MBlazeISelLowering.cpp
===================================================================
--- lib/Target/MBlaze/MBlazeISelLowering.cpp	(revision 117191)
+++ lib/Target/MBlaze/MBlazeISelLowering.cpp	(working copy)
@@ -908,6 +908,37 @@
   return TargetLowering::getConstraintType(Constraint);
 }
 
+/// Examine constraint type and operand type and determine a weight value.
+/// This object must already have been set up with the operand type
+/// and the current alternative constraint selected.
+TargetLowering::ConstraintWeight
+MBlazeTargetLowering::getSingleConstraintMatchWeight(
+    AsmOperandInfo &info, const char *constraint) const {
+  ConstraintWeight weight = CW_Invalid;
+  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 CW_Default;
+  const Type *type = CallOperandVal->getType();
+  // Look at the constraint type.
+  switch (*constraint) {
+  default:
+    weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint);
+    break;
+  case 'd':     
+  case 'y': 
+    if (type->isIntegerTy())
+      weight = CW_Register;
+    break;
+  case 'f':
+    if (type->isFloatTy())
+      weight = CW_Register;
+    break;
+  }
+  return weight;
+}
+
 /// getRegClassForInlineAsmConstraint - Given a constraint letter (e.g. "r"),
 /// return a list of registers that can be used to satisfy the constraint.
 /// This should only be used for C_RegisterClass constraints.
Index: lib/Target/ARM/ARMISelLowering.h
===================================================================
--- lib/Target/ARM/ARMISelLowering.h	(revision 117191)
+++ lib/Target/ARM/ARMISelLowering.h	(working copy)
@@ -241,6 +241,12 @@
 
 
     ConstraintType getConstraintType(const std::string &Constraint) const;
+
+    /// Examine constraint string and operand type and determine a weight value.
+    /// The operand object must already have been set up with the operand type.
+    ConstraintWeight getSingleConstraintMatchWeight(
+      AsmOperandInfo &info, const char *constraint) const;
+
     std::pair<unsigned, const TargetRegisterClass*>
       getRegForInlineAsmConstraint(const std::string &Constraint,
                                    EVT VT) const;
Index: lib/Target/ARM/ARMISelLowering.cpp
===================================================================
--- lib/Target/ARM/ARMISelLowering.cpp	(revision 117191)
+++ lib/Target/ARM/ARMISelLowering.cpp	(working copy)
@@ -5390,6 +5390,40 @@
   return TargetLowering::getConstraintType(Constraint);
 }
 
+/// Examine constraint type and operand type and determine a weight value.
+/// This object must already have been set up with the operand type
+/// and the current alternative constraint selected.
+TargetLowering::ConstraintWeight
+ARMTargetLowering::getSingleConstraintMatchWeight(
+    AsmOperandInfo &info, const char *constraint) const {
+  ConstraintWeight weight = CW_Invalid;
+  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 CW_Default;
+  const Type *type = CallOperandVal->getType();
+  // Look at the constraint type.
+  switch (*constraint) {
+  default:
+    weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint);
+    break;
+  case 'l':
+    if (type->isIntegerTy()) {
+      if (Subtarget->isThumb())
+        weight = CW_SpecificReg;
+      else
+        weight = CW_Register;
+    }
+    break;
+  case 'w':
+    if (type->isFloatingPointTy())
+      weight = CW_Register;
+    break;
+  }
+  return weight;
+}
+
 std::pair<unsigned, const TargetRegisterClass*>
 ARMTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint,
                                                 EVT VT) const {
Index: lib/Target/PowerPC/PPCISelLowering.h
===================================================================
--- lib/Target/PowerPC/PPCISelLowering.h	(revision 117191)
+++ lib/Target/PowerPC/PPCISelLowering.h	(working copy)
@@ -308,6 +308,12 @@
                                             bool is8bit, unsigned Opcode) const;
     
     ConstraintType getConstraintType(const std::string &Constraint) const;
+
+    /// Examine constraint string and operand type and determine a weight value.
+    /// The operand object must already have been set up with the operand type.
+    ConstraintWeight getSingleConstraintMatchWeight(
+      AsmOperandInfo &info, const char *constraint) const;
+
     std::pair<unsigned, const TargetRegisterClass*> 
       getRegForInlineAsmConstraint(const std::string &Constraint,
                                    EVT VT) const;
Index: lib/Target/PowerPC/PPCISelLowering.cpp
===================================================================
--- lib/Target/PowerPC/PPCISelLowering.cpp	(revision 117191)
+++ lib/Target/PowerPC/PPCISelLowering.cpp	(working copy)
@@ -2473,13 +2473,13 @@
     // node so that legalize doesn't hack it.
     if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
       Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl,
-					  Callee.getValueType());
+            Callee.getValueType());
       needIndirectCall = false;
     }
   }
   if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) {
       Callee = DAG.getTargetExternalSymbol(S->getSymbol(),
-					   Callee.getValueType());
+             Callee.getValueType());
       needIndirectCall = false;
   }
   if (needIndirectCall) {
@@ -5374,6 +5374,51 @@
   return TargetLowering::getConstraintType(Constraint);
 }
 
+/// Examine constraint type and operand type and determine a weight value.
+/// This object must already have been set up with the operand type
+/// and the current alternative constraint selected.
+TargetLowering::ConstraintWeight
+PPCTargetLowering::getSingleConstraintMatchWeight(
+    AsmOperandInfo &info, const char *constraint) const {
+  ConstraintWeight weight = CW_Invalid;
+  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 CW_Default;
+  const Type *type = CallOperandVal->getType();
+  // Look at the constraint type.
+  switch (*constraint) {
+  default:
+    weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint);
+    break;
+  case 'b':
+    if (type->isIntegerTy())
+      weight = CW_Register;
+    break;
+  case 'r':
+    if (type->isIntegerTy())
+      weight = CW_Register;
+    break;
+  case 'f':
+    if (type->isFloatTy())
+      weight = CW_Register;
+    break;
+  case 'd':
+    if (type->isDoubleTy())
+      weight = CW_Register;
+    break;
+  case 'v':
+    if (type->isVectorTy())
+      weight = CW_Register;
+    break;
+  case 'y':
+    weight = CW_Register;
+    break;
+  }
+  return weight;
+}
+
 std::pair<unsigned, const TargetRegisterClass*>
 PPCTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint,
                                                 EVT VT) const {
Index: lib/Target/Alpha/AlphaISelLowering.h
===================================================================
--- lib/Target/Alpha/AlphaISelLowering.h	(revision 117191)
+++ lib/Target/Alpha/AlphaISelLowering.h	(working copy)
@@ -87,6 +87,11 @@
 
     ConstraintType getConstraintType(const std::string &Constraint) const;
 
+    /// Examine constraint string and operand type and determine a weight value.
+    /// The operand object must already have been set up with the operand type.
+    ConstraintWeight getSingleConstraintMatchWeight(
+      AsmOperandInfo &info, const char *constraint) const;
+
     std::vector<unsigned> 
       getRegClassForInlineAsmConstraint(const std::string &Constraint,
                                         EVT VT) const;
Index: lib/Target/Alpha/AlphaISelLowering.cpp
===================================================================
--- lib/Target/Alpha/AlphaISelLowering.cpp	(revision 117191)
+++ lib/Target/Alpha/AlphaISelLowering.cpp	(working copy)
@@ -27,6 +27,7 @@
 #include "llvm/Function.h"
 #include "llvm/Module.h"
 #include "llvm/Intrinsics.h"
+#include "llvm/Type.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/raw_ostream.h"
@@ -803,6 +804,30 @@
   return TargetLowering::getConstraintType(Constraint);
 }
 
+/// Examine constraint type and operand type and determine a weight value.
+/// This object must already have been set up with the operand type
+/// and the current alternative constraint selected.
+TargetLowering::ConstraintWeight
+AlphaTargetLowering::getSingleConstraintMatchWeight(
+    AsmOperandInfo &info, const char *constraint) const {
+  ConstraintWeight weight = CW_Invalid;
+  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 CW_Default;
+  // Look at the constraint type.
+  switch (*constraint) {
+  default:
+    weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint);
+    break;
+  case 'f':
+    weight = CW_Register;
+    break;
+  }
+  return weight;
+}
+
 std::vector<unsigned> AlphaTargetLowering::
 getRegClassForInlineAsmConstraint(const std::string &Constraint,
                                   EVT VT) const {
Index: lib/Target/Mips/MipsISelLowering.h
===================================================================
--- lib/Target/Mips/MipsISelLowering.h	(revision 117191)
+++ lib/Target/Mips/MipsISelLowering.h	(working copy)
@@ -139,6 +139,11 @@
     // Inline asm support
     ConstraintType getConstraintType(const std::string &Constraint) const;
 
+    /// Examine constraint string and operand type and determine a weight value.
+    /// The operand object must already have been set up with the operand type.
+    ConstraintWeight getSingleConstraintMatchWeight(
+      AsmOperandInfo &info, const char *constraint) const;
+
     std::pair<unsigned, const TargetRegisterClass*> 
               getRegForInlineAsmConstraint(const std::string &Constraint,
               EVT VT) const;
Index: lib/Target/Mips/MipsISelLowering.cpp
===================================================================
--- lib/Target/Mips/MipsISelLowering.cpp	(revision 117191)
+++ lib/Target/Mips/MipsISelLowering.cpp	(working copy)
@@ -1269,6 +1269,37 @@
   return TargetLowering::getConstraintType(Constraint);
 }
 
+/// Examine constraint type and operand type and determine a weight value.
+/// This object must already have been set up with the operand type
+/// and the current alternative constraint selected.
+TargetLowering::ConstraintWeight
+MipsTargetLowering::getSingleConstraintMatchWeight(
+    AsmOperandInfo &info, const char *constraint) const {
+  ConstraintWeight weight = CW_Invalid;
+  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 CW_Default;
+  const Type *type = CallOperandVal->getType();
+  // Look at the constraint type.
+  switch (*constraint) {
+  default:
+    weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint);
+    break;
+  case 'd':     
+  case 'y': 
+    if (type->isIntegerTy())
+      weight = CW_Register;
+    break;
+  case 'f':
+    if (type->isFloatTy())
+      weight = CW_Register;
+    break;
+  }
+  return weight;
+}
+
 /// getRegClassForInlineAsmConstraint - Given a constraint letter (e.g. "r"),
 /// return a list of registers that can be used to satisfy the constraint.
 /// This should only be used for C_RegisterClass constraints.
Index: lib/Target/Blackfin/BlackfinISelLowering.h
===================================================================
--- lib/Target/Blackfin/BlackfinISelLowering.h	(revision 117191)
+++ lib/Target/Blackfin/BlackfinISelLowering.h	(working copy)
@@ -39,6 +39,12 @@
                                     SelectionDAG &DAG) const;
 
     ConstraintType getConstraintType(const std::string &Constraint) const;
+
+    /// Examine constraint string and operand type and determine a weight value.
+    /// The operand object must already have been set up with the operand type.
+    ConstraintWeight getSingleConstraintMatchWeight(
+      AsmOperandInfo &info, const char *constraint) const;
+
     std::pair<unsigned, const TargetRegisterClass*>
     getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const;
     std::vector<unsigned>
Index: lib/Target/Blackfin/BlackfinISelLowering.cpp
===================================================================
--- lib/Target/Blackfin/BlackfinISelLowering.cpp	(revision 117191)
+++ lib/Target/Blackfin/BlackfinISelLowering.cpp	(working copy)
@@ -15,6 +15,7 @@
 #include "BlackfinISelLowering.h"
 #include "BlackfinTargetMachine.h"
 #include "llvm/Function.h"
+#include "llvm/Type.h"
 #include "llvm/CodeGen/CallingConvLower.h"
 #include "llvm/CodeGen/MachineFrameInfo.h"
 #include "llvm/CodeGen/MachineFunction.h"
@@ -549,6 +550,52 @@
   return TargetLowering::getConstraintType(Constraint);
 }
 
+/// Examine constraint type and operand type and determine a weight value.
+/// This object must already have been set up with the operand type
+/// and the current alternative constraint selected.
+TargetLowering::ConstraintWeight
+BlackfinTargetLowering::getSingleConstraintMatchWeight(
+    AsmOperandInfo &info, const char *constraint) const {
+  ConstraintWeight weight = CW_Invalid;
+  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 CW_Default;
+  // Look at the constraint type.
+  switch (*constraint) {
+  default:
+    weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint);
+    break;
+
+    // Blackfin-specific constraints
+  case 'a':
+  case 'd':
+  case 'z':
+  case 'D':
+  case 'W':
+  case 'e':
+  case 'b':
+  case 'v':
+  case 'f':
+  case 'c':
+  case 't':
+  case 'u':
+  case 'k':
+  case 'x':
+  case 'y':
+  case 'w':
+    return CW_Register;
+  case 'A':
+  case 'B':
+  case 'C':
+  case 'Z':
+  case 'Y':
+    return CW_SpecificReg;
+  }
+  return weight;
+}
+
 /// getRegForInlineAsmConstraint - Return register no and class for a C_Register
 /// constraint.
 std::pair<unsigned, const TargetRegisterClass*> BlackfinTargetLowering::
Index: lib/VMCore/InlineAsm.cpp
===================================================================
--- lib/VMCore/InlineAsm.cpp	(revision 117191)
+++ lib/VMCore/InlineAsm.cpp	(working copy)
@@ -76,11 +76,11 @@
 /// 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) {
+                     InlineAsm::ConstraintInfoVector &ConstraintsSoFar) {
   StringRef::iterator I = Str.begin(), E = Str.end();
   unsigned multipleAlternativeCount = Str.count('|') + 1;
   unsigned multipleAlternativeIndex = 0;
-  std::vector<std::string> *pCodes = &Codes;
+  ConstraintCodeVector *pCodes = &Codes;
   
   // Initialize
   isMultipleAlternative = (multipleAlternativeCount > 1 ? true : false);
@@ -202,9 +202,9 @@
   }
 }
 
-std::vector<InlineAsm::ConstraintInfo>
+InlineAsm::ConstraintInfoVector
 InlineAsm::ParseConstraints(StringRef Constraints) {
-  std::vector<ConstraintInfo> Result;
+  ConstraintInfoVector Result;
   
   // Scan the constraints string.
   for (StringRef::iterator I = Constraints.begin(),
@@ -239,7 +239,7 @@
 bool InlineAsm::Verify(const FunctionType *Ty, StringRef ConstStr) {
   if (Ty->isVarArg()) return false;
   
-  std::vector<ConstraintInfo> Constraints = ParseConstraints(ConstStr);
+  ConstraintInfoVector Constraints = ParseConstraints(ConstStr);
   
   // Error parsing constraints.
   if (Constraints.empty() && !ConstStr.empty()) return false;
Index: lib/Transforms/Utils/AddrModeMatcher.cpp
===================================================================
--- lib/Transforms/Utils/AddrModeMatcher.cpp	(revision 117191)
+++ lib/Transforms/Utils/AddrModeMatcher.cpp	(working copy)
@@ -380,7 +380,7 @@
 /// return false.
 static bool IsOperandAMemoryOperand(CallInst *CI, InlineAsm *IA, Value *OpVal,
                                     const TargetLowering &TLI) {
-  std::vector<TargetLowering::AsmOperandInfo> TargetConstraints = TLI.ParseConstraints(ImmutableCallSite(CI));
+  TargetLowering::AsmOperandInfoVector TargetConstraints = TLI.ParseConstraints(ImmutableCallSite(CI));
   for (unsigned i = 0, e = TargetConstraints.size(); i != e; ++i) {
     TargetLowering::AsmOperandInfo &OpInfo = TargetConstraints[i];
     
Index: lib/Transforms/Scalar/CodeGenPrepare.cpp
===================================================================
--- lib/Transforms/Scalar/CodeGenPrepare.cpp	(revision 117191)
+++ lib/Transforms/Scalar/CodeGenPrepare.cpp	(working copy)
@@ -743,7 +743,7 @@
                                            DenseMap<Value*,Value*> &SunkAddrs) {
   bool MadeChange = false;
 
-  std::vector<TargetLowering::AsmOperandInfo> TargetConstraints = TLI->ParseConstraints(CS);
+  TargetLowering::AsmOperandInfoVector TargetConstraints = TLI->ParseConstraints(CS);
   unsigned ArgNo = 0;
   for (unsigned i = 0, e = TargetConstraints.size(); i != e; ++i) {
     TargetLowering::AsmOperandInfo &OpInfo = TargetConstraints[i];
Index: lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
===================================================================
--- lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp	(revision 117191)
+++ lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp	(working copy)
@@ -5210,6 +5210,8 @@
   }
 };
 
+typedef SmallVector<SDISelAsmOperandInfo,16> SDISelAsmOperandInfoVector;
+
 } // end llvm namespace.
 
 /// isAllocatableRegister - If the specified register is safe to allocate,
@@ -5447,11 +5449,11 @@
   const InlineAsm *IA = cast<InlineAsm>(CS.getCalledValue());
 
   /// ConstraintOperands - Information about all of the constraints.
-  std::vector<SDISelAsmOperandInfo> ConstraintOperands;
+  SDISelAsmOperandInfoVector ConstraintOperands;
 
   std::set<unsigned> OutputRegs, InputRegs;
 
-  std::vector<TargetLowering::AsmOperandInfo> TargetConstraints = TLI.ParseConstraints(CS);
+  TargetLowering::AsmOperandInfoVector TargetConstraints = TLI.ParseConstraints(CS);
   bool hasMemory = false;
 
   unsigned ArgNo = 0;   // ArgNo - The argument of the CallInst.
Index: lib/CodeGen/SelectionDAG/TargetLowering.cpp
===================================================================
--- lib/CodeGen/SelectionDAG/TargetLowering.cpp	(revision 117191)
+++ lib/CodeGen/SelectionDAG/TargetLowering.cpp	(working copy)
@@ -2664,16 +2664,16 @@
 /// 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(
+TargetLowering::AsmOperandInfoVector TargetLowering::ParseConstraints(
     ImmutableCallSite CS) const {
   /// ConstraintOperands - Information about all of the constraints.
-  std::vector<AsmOperandInfo> ConstraintOperands;
+  AsmOperandInfoVector ConstraintOperands;
   const InlineAsm *IA = cast<InlineAsm>(CS.getCalledValue());
   unsigned maCount = 0; // Largest number of multiple alternative constraints.
 
   // Do a prepass over the constraints, canonicalizing them, and building up the
   // ConstraintOperands list.
-  std::vector<InlineAsm::ConstraintInfo>
+  InlineAsm::ConstraintInfoVector
     ConstraintInfos = IA->ParseConstraints();
     
   unsigned ArgNo = 0;   // ArgNo - The argument of the CallInst.
@@ -2687,7 +2687,7 @@
     if (OpInfo.multipleAlternatives.size() > maCount)
       maCount = OpInfo.multipleAlternatives.size();
 
-    EVT OpVT = MVT::Other;
+    OpInfo.ConstraintVT = MVT::Other;
 
     // Compute the value type for each operand.
     switch (OpInfo.Type) {
@@ -2703,10 +2703,10 @@
       assert(!CS.getType()->isVoidTy() &&
              "Bad inline asm!");
       if (const StructType *STy = dyn_cast<StructType>(CS.getType())) {
-        OpVT = getValueType(STy->getElementType(ResNo));
+        OpInfo.ConstraintVT = getValueType(STy->getElementType(ResNo));
       } else {
         assert(ResNo == 0 && "Asm only has one result!");
-        OpVT = getValueType(CS.getType());
+        OpInfo.ConstraintVT = getValueType(CS.getType());
       }
       ++ResNo;
       break;
@@ -2717,6 +2717,36 @@
       // Nothing to do.
       break;
     }
+    
+    if (OpInfo.CallOperandVal) {
+      const llvm::Type *OpTy = OpInfo.CallOperandVal->getType();
+      if (OpInfo.isIndirect) {
+        const llvm::PointerType *PtrTy = dyn_cast<PointerType>(OpTy);
+        if (!PtrTy)
+          report_fatal_error("Indirect operand for inline asm not a pointer!");
+        OpTy = PtrTy->getElementType();
+      }
+      // If OpTy is not a single value, it may be a struct/union that we
+      // can tile with integers.
+      if (!OpTy->isSingleValueType() && OpTy->isSized()) {
+        unsigned BitSize = TD->getTypeSizeInBits(OpTy);
+        switch (BitSize) {
+        default: break;
+        case 1:
+        case 8:
+        case 16:
+        case 32:
+        case 64:
+        case 128:
+          OpTy = IntegerType::get(OpTy->getContext(), BitSize);
+          break;
+        }
+      } else if (dyn_cast<PointerType>(OpTy)) {
+        OpInfo.ConstraintVT = MVT::getIntegerVT(8*TD->getPointerSize());
+      } else {
+        OpInfo.ConstraintVT = EVT::getEVT(OpTy, true);
+      }
+    }
   }
 
   // If we have multiple alternative constraints, select the best alternative.
@@ -2737,13 +2767,12 @@
           if (OpInfo.Type == InlineAsm::isClobber)
             continue;
 
-          // 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 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()) ||
@@ -2752,10 +2781,8 @@
                 weightSum = -1;  // Can't match.
                 break;
               }
-              Input.ConstraintVT = OpInfo.ConstraintVT;
             }
           }
-          
           weight = getMultipleConstraintMatchWeight(OpInfo, maIndex);
           if (weight == -1) {
             weightSum = -1;
@@ -2792,7 +2819,7 @@
     // error.
     if (OpInfo.hasMatchingInput()) {
       AsmOperandInfo &Input = ConstraintOperands[OpInfo.MatchingInput];
-      
+
       if (OpInfo.ConstraintVT != Input.ConstraintVT) {
         if ((OpInfo.ConstraintVT.isInteger() !=
              Input.ConstraintVT.isInteger()) ||
@@ -2802,8 +2829,8 @@
                              " with a matching output constraint of"
                              " incompatible type!");
         }
-        Input.ConstraintVT = OpInfo.ConstraintVT;
       }
+
     }
   }
 
@@ -2828,22 +2855,23 @@
   }
 }
 
-/// Examine constraint type and operand type and determine a weight value,
-/// where: -1 = invalid match, and 0 = so-so match to 3 = good match.
+/// Examine constraint type and operand type and determine a weight value.
 /// This object must already have been set up with the operand type
 /// and the current alternative constraint selected.
-int TargetLowering::getMultipleConstraintMatchWeight(
+TargetLowering::ConstraintWeight
+  TargetLowering::getMultipleConstraintMatchWeight(
     AsmOperandInfo &info, int maIndex) const {
-  std::vector<std::string> *rCodes;
+  InlineAsm::ConstraintCodeVector *rCodes;
   if (maIndex >= (int)info.multipleAlternatives.size())
     rCodes = &info.Codes;
   else
     rCodes = &info.multipleAlternatives[maIndex].Codes;
-  int BestWeight = -1;
+  ConstraintWeight BestWeight = CW_Invalid;
 
   // 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());
+    ConstraintWeight weight =
+      getSingleConstraintMatchWeight(info, (*rCodes)[i].c_str());
     if (weight > BestWeight)
       BestWeight = weight;
   }
@@ -2851,50 +2879,50 @@
   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.
+/// Examine constraint type and operand type and determine a weight value.
 /// This object must already have been set up with the operand type
 /// and the current alternative constraint selected.
-int TargetLowering::getSingleConstraintMatchWeight(
+TargetLowering::ConstraintWeight
+  TargetLowering::getSingleConstraintMatchWeight(
     AsmOperandInfo &info, const char *constraint) const {
-  int weight = -1;
+  ConstraintWeight weight = CW_Invalid;
   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;
+    return CW_Default;
   // 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;
-      }
+      if (isa<ConstantInt>(CallOperandVal))
+        weight = CW_Constant;
       break;
     case 's': // non-explicit intregal immediate.
-      weight = 0;
-      if (info.CallOperandVal) {
-        if (isa<GlobalValue>(info.CallOperandVal))
-          weight = 3;
-        else
-          weight = -1;
-      }
+      if (isa<GlobalValue>(CallOperandVal))
+        weight = CW_Constant;
       break;
+    case 'E': // immediate float if host format.
+    case 'F': // immediate float.
+      if (isa<ConstantFP>(CallOperandVal))
+        weight = CW_Constant;
+      break;
+    case '<': // memory operand with autodecrement.
+    case '>': // memory operand with autoincrement.
     case 'm': // memory operand.
     case 'o': // offsettable memory operand
     case 'V': // non-offsettable memory operand
-      weight = 2;
+      weight = CW_Memory;
       break;
+    case 'r': // general register.
     case 'g': // general register, memory operand or immediate integer.
+              // note: Clang converts "g" to "imr".
+      if (CallOperandVal->getType()->isIntegerTy())
+        weight = CW_Register;
+      break;
     case 'X': // any operand.
-      weight = 1;
-      break;
     default:
-      weight = 0;
+      weight = CW_Default;
       break;
   }
   return weight;
Index: lib/CodeGen/Analysis.cpp
===================================================================
--- lib/CodeGen/Analysis.cpp	(revision 117191)
+++ lib/CodeGen/Analysis.cpp	(working copy)
@@ -125,7 +125,7 @@
 /// hasInlineAsmMemConstraint - Return true if the inline asm instruction being
 /// processed uses a memory 'm' constraint.
 bool
-llvm::hasInlineAsmMemConstraint(std::vector<InlineAsm::ConstraintInfo> &CInfos,
+llvm::hasInlineAsmMemConstraint(InlineAsm::ConstraintInfoVector &CInfos,
                                 const TargetLowering &TLI) {
   for (unsigned i = 0, e = CInfos.size(); i != e; ++i) {
     InlineAsm::ConstraintInfo &CI = CInfos[i];


More information about the llvm-commits mailing list