Index: include/clang/Basic/TargetInfo.h
===================================================================
--- include/clang/Basic/TargetInfo.h	(revision 109564)
+++ include/clang/Basic/TargetInfo.h	(working copy)
@@ -274,7 +274,7 @@
   // For example, on x86 it will return "ax" when "eax" is passed in.
   llvm::StringRef getNormalizedGCCRegisterName(llvm::StringRef Name) const;
 
-  struct ConstraintInfo {
+  struct SubConstraintInfo {
     enum {
       CI_None = 0x00,
       CI_AllowsMemory = 0x01,
@@ -286,14 +286,13 @@
     int TiedOperand;
 
     std::string ConstraintStr;  // constraint: "=rm"
-    std::string Name;           // Operand name: [foo] with no []'s.
   public:
-    ConstraintInfo(llvm::StringRef ConstraintStr, llvm::StringRef Name)
-      : Flags(0), TiedOperand(-1), ConstraintStr(ConstraintStr.str()), 
-      Name(Name.str()) {}
+    SubConstraintInfo() : Flags(0), TiedOperand(-1) {}
 
     const std::string &getConstraintStr() const { return ConstraintStr; }
-    const std::string &getName() const { return Name; }
+    void setConstraintStr(llvm::StringRef constraintStr)
+      { ConstraintStr = constraintStr; }
+ 
     bool isReadWrite() const { return (Flags & CI_ReadWrite) != 0; }
     bool allowsRegister() const { return (Flags & CI_AllowsRegister) != 0; }
     bool allowsMemory() const { return (Flags & CI_AllowsMemory) != 0; }
@@ -319,7 +318,7 @@
     /// setTiedOperand - Indicate that this is an input operand that is tied to
     /// the specified output operand.  Copy over the various constraint
     /// information from the output.
-    void setTiedOperand(unsigned N, ConstraintInfo &Output) {
+    void setTiedOperand(unsigned N, SubConstraintInfo &Output) {
       Output.setHasMatchingInput();
       Flags = Output.Flags;
       TiedOperand = N;
@@ -327,6 +326,92 @@
     }
   };
 
+  struct ConstraintInfo {
+    int count;    // number of sub-constraints.
+    int selected; // selected sub-constraint, or 0 if not selected yet.
+    static const unsigned MaxSubConstraintInfos = 4;
+    SubConstraintInfo constraints[MaxSubConstraintInfos];  // Sub-constraints
+    std::string AllConstraintStr;   // all sub-constraints: "=r,r"
+    std::string Name;           // Operand name: [foo] with no []'s.
+  public:
+    ConstraintInfo(llvm::StringRef constraintStr, llvm::StringRef name)
+        : count(1), selected(0), AllConstraintStr(constraintStr.str()),
+          Name(name.str()) {
+      setConstraintStr(constraintStr.str());
+    }
+
+    int getCount() const { return count; }
+    void setCount(int newCount) {
+      count = newCount;
+      assert((newCount <= MaxSubConstraintInfos)
+        && "Invalid count in ConstraintInfo::setCount");
+    }
+    int getSelectedIndex() const { return selected; }
+    void setSelectedIndex(int newSelectedIndex) {
+      selected = newSelectedIndex;
+      assert((selected <= count)
+        && "Invalid selected index in ConstraintInfo::setSelectedIndex");
+    }
+    const SubConstraintInfo& getSubConstraintConst() const {
+      assert((selected >= 0) && (selected < count)
+        && "Invalid selected index in ConstraintInfo.");
+      return constraints[selected];
+    }
+    SubConstraintInfo& getSubConstraint() {
+      assert((selected >= 0) && (selected < count)
+        && "Invalid selected index in ConstraintInfo.");
+      return constraints[selected];
+    }
+
+    const std::string &getAllConstraintStr() const
+      { return AllConstraintStr; }
+    void setAllConstraintStr(llvm::StringRef constraintStr)
+      { AllConstraintStr = constraintStr; }
+
+    const std::string &getConstraintStr() const
+      { return getSubConstraintConst().getConstraintStr(); }
+    void setConstraintStr(llvm::StringRef ConstraintStr)
+      { getSubConstraint().setConstraintStr(ConstraintStr); }
+
+    const std::string &getName() const
+      { return Name; }
+    void setName(llvm::StringRef name)
+      { Name = name.str(); }
+ 
+    bool isReadWrite() const
+      { return getSubConstraintConst().isReadWrite(); }
+    bool allowsRegister() const
+      { return getSubConstraintConst().allowsRegister(); }
+    bool allowsMemory() const
+      { return getSubConstraintConst().allowsMemory(); }
+
+    /// hasMatchingInput - Return true if this output operand has a matching
+    /// (tied) input operand.
+    bool hasMatchingInput() const
+      { return getSubConstraintConst().hasMatchingInput(); }
+
+    /// hasTiedOperand() - Return true if this input operand is a matching
+    /// constraint that ties it to an output operand.  If this returns true,
+    /// then getTiedOperand will indicate which output operand this is tied to.
+    bool hasTiedOperand() const
+      { return getSubConstraintConst().hasTiedOperand(); }
+    unsigned getTiedOperand() const
+      { return getSubConstraintConst().getTiedOperand(); }
+
+    void setIsReadWrite() { getSubConstraint().setIsReadWrite(); }
+    void setAllowsMemory() { getSubConstraint().setAllowsMemory(); }
+    void setAllowsRegister() { getSubConstraint().setAllowsRegister(); }
+    void setHasMatchingInput() { getSubConstraint().setHasMatchingInput(); }
+
+    /// setTiedOperand - Indicate that this is an input operand that is tied to
+    /// the specified output operand.  Copy over the various constraint
+    /// information from the output.
+    void setTiedOperand(unsigned N, ConstraintInfo &Output) {
+      getSubConstraint().setTiedOperand(N, Output.getSubConstraint());
+      // Don't copy Name or constraint string.
+    }
+  };
+
   // validateOutputConstraint, validateInputConstraint - Checks that
   // a constraint is valid and provides information about it.
   // FIXME: These should return a real error instead of just true/false.
Index: lib/Basic/TargetInfo.cpp
===================================================================
--- lib/Basic/TargetInfo.cpp	(revision 109564)
+++ lib/Basic/TargetInfo.cpp	(working copy)
@@ -253,11 +253,17 @@
 }
 
 bool TargetInfo::validateOutputConstraint(ConstraintInfo &Info) const {
-  const char *Name = Info.getConstraintStr().c_str();
+  const char *Name = Info.getAllConstraintStr().c_str();
   // An output constraint must start with '=' or '+'
   if (*Name != '=' && *Name != '+')
     return false;
 
+  const char *start = Name;
+  char prefix = *start;
+  size_t length;
+  int index;
+  char buffer[256];
+
   if (*Name == '+')
     Info.setIsReadWrite();
 
@@ -287,13 +293,40 @@
       Info.setAllowsRegister();
       Info.setAllowsMemory();
       break;
-    case ',': // FIXME: Until we handle multiple alternative constraints,
-      return true;  // ignore everything after the first comma.
+    case ',': // Multiple alternative constraints,
+      length = Name - start;
+      if (length > sizeof(buffer) - 1)
+        return false;
+      index = 0;
+      if ((*start != '=') && (*start != '+'))
+        buffer[index++] = prefix;
+      strncpy(&buffer[index], start, length);
+      buffer[index + length] = '\0';
+      Info.setConstraintStr(buffer);
+      Info.setCount(Info.getCount() + 1);
+      Info.setSelectedIndex(Info.getSelectedIndex() + 1);
+      if (prefix == '+')
+        Info.setIsReadWrite();
+      start = Name + 1;
+      break;
     }
 
     Name++;
   }
 
+  if (Info.getCount() > 1) { // Finish off alternate constraint.
+    length = Name - start;
+    if (length > sizeof(buffer) - 1)
+      return false;
+    index = 0;
+    if ((*start != '=') && (*start != '+'))
+      buffer[index++] = prefix;
+    strncpy(&buffer[index], start, length);
+    buffer[index + length] = '\0';
+    Info.setConstraintStr(buffer);
+    Info.setSelectedIndex(0); // reset selected index.
+  }
+
   return true;
 }
 
@@ -324,8 +357,12 @@
 bool TargetInfo::validateInputConstraint(ConstraintInfo *OutputConstraints,
                                          unsigned NumOutputs,
                                          ConstraintInfo &Info) const {
-  const char *Name = Info.ConstraintStr.c_str();
+  const char *Name = Info.getAllConstraintStr().c_str();
 
+  const char *start = Name;
+  size_t length;
+  char buffer[256];
+
   while (*Name) {
     switch (*Name) {
     default:
@@ -382,12 +419,31 @@
       Info.setAllowsRegister();
       Info.setAllowsMemory();
       break;
-    case ',': // FIXME: Until we handle multiple alternative constraints,
-      return true;  // ignore everything after the first comma.
+    case ',': // Multiple alternative constraints,
+      length = Name - start;
+      if (length > sizeof(buffer) - 1)
+        return false;
+      strncpy(buffer, start, length);
+      buffer[length] = '\0';
+      Info.setConstraintStr(buffer);
+      Info.setCount(Info.getCount() + 1);
+      Info.setSelectedIndex(Info.getSelectedIndex() + 1);
+      start = Name + 1;
+      break;
     }
 
     Name++;
   }
 
+  if (Info.getCount() > 1) { // Finish off alternate constraint.
+    length = Name - start;
+    if (length > sizeof(buffer) - 1)
+      return false;
+    strncpy(buffer, start, length);
+    buffer[length] = '\0';
+    Info.setConstraintStr(buffer);
+    Info.setSelectedIndex(0); // reset selected index.
+  }
+
   return true;
 }
Index: lib/CodeGen/CGStmt.cpp
===================================================================
--- lib/CodeGen/CGStmt.cpp	(revision 109564)
+++ lib/CodeGen/CGStmt.cpp	(working copy)
@@ -996,7 +996,7 @@
     TargetInfo::ConstraintInfo &Info = OutputConstraintInfos[i];
 
     // Simplify the output constraint.
-    std::string OutputConstraint(S.getOutputConstraint(i));
+    std::string OutputConstraint(Info.getConstraintStr());
     OutputConstraint = SimplifyConstraint(OutputConstraint.c_str() + 1, Target);
 
     const Expr *OutExpr = S.getOutputExpr(i);
@@ -1071,7 +1071,7 @@
       Constraints += ',';
 
     // Simplify the input constraint.
-    std::string InputConstraint(S.getInputConstraint(i));
+    std::string InputConstraint(Info.getConstraintStr());
     InputConstraint = SimplifyConstraint(InputConstraint.c_str(), Target,
                                          &OutputConstraintInfos);
 
