split register class handling from explicit physreg handling.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@26308 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index c8e9401..d16b070 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -1187,6 +1187,7 @@
   bool hasSideEffects = IA->hasSideEffects();
 
   std::vector<InlineAsm::ConstraintInfo> Constraints = IA->ParseConstraints();
+  std::vector<MVT::ValueType> ConstraintVTs;
   
   /// AsmNodeOperands - A list of pairs.  The first element is a register, the
   /// second is a bitfield where bit #0 is set if it is a use and bit #1 is set
@@ -1203,14 +1204,43 @@
   // could let the LLVM RA do its thing, but we currently don't.  Do a prepass
   // over the constraints, collecting fixed registers that we know we can't use.
   std::set<unsigned> OutputRegs, InputRegs;
+  unsigned OpNum = 1;
   for (unsigned i = 0, e = Constraints.size(); i != e; ++i) {
     assert(Constraints[i].Codes.size() == 1 && "Only handles one code so far!");
     std::string &ConstraintCode = Constraints[i].Codes[0];
     
-    std::vector<unsigned> Regs =
-      TLI.getRegForInlineAsmConstraint(ConstraintCode, MVT::Other);
-    if (Regs.size() != 1) continue;  // Not assigned a fixed reg.
-    unsigned TheReg = Regs[0];
+    MVT::ValueType OpVT;
+
+    // Compute the value type for each operand and add it to ConstraintVTs.
+    switch (Constraints[i].Type) {
+    case InlineAsm::isOutput:
+      if (!Constraints[i].isIndirectOutput) {
+        assert(I.getType() != Type::VoidTy && "Bad inline asm!");
+        OpVT = TLI.getValueType(I.getType());
+      } else {
+        Value *CallOperand = I.getOperand(OpNum);
+        const Type *OpTy = CallOperand->getType();
+        OpVT = TLI.getValueType(cast<PointerType>(OpTy)->getElementType());
+        OpNum++;  // Consumes a call operand.
+      }
+      break;
+    case InlineAsm::isInput:
+      OpVT = TLI.getValueType(I.getOperand(OpNum)->getType());
+      OpNum++;  // Consumes a call operand.
+      break;
+    case InlineAsm::isClobber:
+      OpVT = MVT::Other;
+      break;
+    }
+    
+    ConstraintVTs.push_back(OpVT);
+
+    std::pair<unsigned, const TargetRegisterClass*> Reg = 
+       TLI.getRegForInlineAsmConstraint(ConstraintCode, OpVT);
+    if (Reg.first == 0) continue;  // Not assigned a fixed reg.
+    unsigned TheReg = Reg.first;
+    
+    // FIXME: Handle expanded physreg refs!
     
     switch (Constraints[i].Type) {
     case InlineAsm::isOutput:
@@ -1221,15 +1251,15 @@
       if (Constraints[i].isEarlyClobber || Constraints[i].hasMatchingInput)
         InputRegs.insert(TheReg);
       break;
+    case InlineAsm::isInput:
+      // We can't assign any other input to this register.
+      InputRegs.insert(TheReg);
+      break;
     case InlineAsm::isClobber:
       // Clobbered regs cannot be used as inputs or outputs.
       InputRegs.insert(TheReg);
       OutputRegs.insert(TheReg);
       break;
-    case InlineAsm::isInput:
-      // We can't assign any other input to this register.
-      InputRegs.insert(TheReg);
-      break;
     }
   }      
   
@@ -1238,28 +1268,32 @@
   unsigned RetValReg = 0;
   std::vector<std::pair<unsigned, Value*> > IndirectStoresToEmit;
   bool FoundOutputConstraint = false;
-  unsigned OpNum = 1;
+  OpNum = 1;
   
   for (unsigned i = 0, e = Constraints.size(); i != e; ++i) {
     assert(Constraints[i].Codes.size() == 1 && "Only handles one code so far!");
     std::string &ConstraintCode = Constraints[i].Codes[0];
-    Value *CallOperand = I.getOperand(OpNum);
-    MVT::ValueType CallOpVT = TLI.getValueType(CallOperand->getType());
+
     switch (Constraints[i].Type) {
     case InlineAsm::isOutput: {
-      // Copy the output from the appropriate register.
-      std::vector<unsigned> Regs =
-        TLI.getRegForInlineAsmConstraint(ConstraintCode, CallOpVT);
-
-      // Find a regsister that we can use.
+      // Copy the output from the appropriate register.  Find a regsister that
+      // we can use.
+      
+      // Check to see if this is a physreg reference.
+      std::pair<unsigned, const TargetRegisterClass*> PhysReg = 
+         TLI.getRegForInlineAsmConstraint(ConstraintCode, ConstraintVTs[i]);
       unsigned DestReg;
-      if (Regs.size() == 1)
-        DestReg = Regs[0];
+      if (PhysReg.first)
+        DestReg = PhysReg.first;
       else {
-        bool UsesInputRegister = false;
+        std::vector<unsigned> Regs =
+          TLI.getRegClassForInlineAsmConstraint(ConstraintCode, 
+                                                ConstraintVTs[i]);
+
         // If this is an early-clobber output, or if there is an input
         // constraint that matches this, we need to reserve the input register
         // so no other inputs allocate to it.
+        bool UsesInputRegister = false;
         if (Constraints[i].isEarlyClobber || Constraints[i].hasMatchingInput)
           UsesInputRegister = true;
         DestReg = GetAvailableRegister(true, UsesInputRegister, 
@@ -1276,24 +1310,21 @@
         assert(I.getType() != Type::VoidTy && "Bad inline asm!");
         
         RetValReg = DestReg;
-        OpTy = I.getType();
       } else {
+        Value *CallOperand = I.getOperand(OpNum);
         IndirectStoresToEmit.push_back(std::make_pair(DestReg, CallOperand));
-        OpTy = CallOperand->getType();
-        OpTy = cast<PointerType>(OpTy)->getElementType();
         OpNum++;  // Consumes a call operand.
       }
       
       // Add information to the INLINEASM node to know that this register is
       // set.
-      AsmNodeOperands.push_back(DAG.getRegister(DestReg,
-                                                TLI.getValueType(OpTy)));
+      AsmNodeOperands.push_back(DAG.getRegister(DestReg, ConstraintVTs[i]));
       AsmNodeOperands.push_back(DAG.getConstant(2, MVT::i32)); // ISDEF
       
       break;
     }
     case InlineAsm::isInput: {
-      const Type *OpTy = CallOperand->getType();
+      Value *CallOperand = I.getOperand(OpNum);
       OpNum++;  // Consumes a call operand.
 
       unsigned SrcReg;
@@ -1306,33 +1337,45 @@
         // just use its register.
         unsigned OperandNo = atoi(ConstraintCode.c_str());
         SrcReg = cast<RegisterSDNode>(AsmNodeOperands[OperandNo*2+2])->getReg();
-        ResOp = DAG.getRegister(SrcReg, CallOpVT);
+        ResOp = DAG.getRegister(SrcReg, ConstraintVTs[i]);
         ResOpType = 1;
         
         Chain = DAG.getCopyToReg(Chain, SrcReg, InOperandVal, Flag);
         Flag = Chain.getValue(1);
       } else {
-        TargetLowering::ConstraintType CTy = TargetLowering::C_RegisterClass;
+        TargetLowering::ConstraintType CTy = TargetLowering::C_Register;
         if (ConstraintCode.size() == 1)   // not a physreg name.
           CTy = TLI.getConstraintType(ConstraintCode[0]);
         
         switch (CTy) {
         default: assert(0 && "Unknown constraint type! FAIL!");
+        case TargetLowering::C_Register: {
+          std::pair<unsigned, const TargetRegisterClass*> PhysReg = 
+            TLI.getRegForInlineAsmConstraint(ConstraintCode, ConstraintVTs[i]);
+          // FIXME: should be match fail.
+          assert(PhysReg.first && "Unknown physical register name!");
+          SrcReg = PhysReg.first;
+
+          Chain = DAG.getCopyToReg(Chain, SrcReg, InOperandVal, Flag);
+          Flag = Chain.getValue(1);
+          
+          ResOp = DAG.getRegister(SrcReg, ConstraintVTs[i]);
+          ResOpType = 1;
+          break;
+        }
         case TargetLowering::C_RegisterClass: {
           // Copy the input into the appropriate register.
           std::vector<unsigned> Regs =
-            TLI.getRegForInlineAsmConstraint(ConstraintCode, CallOpVT);
-          if (Regs.size() == 1)
-            SrcReg = Regs[0];
-          else
-            SrcReg = GetAvailableRegister(false, true, Regs, 
-                                          OutputRegs, InputRegs);
+            TLI.getRegClassForInlineAsmConstraint(ConstraintCode, 
+                                                  ConstraintVTs[i]);
+          SrcReg = GetAvailableRegister(false, true, Regs, 
+                                        OutputRegs, InputRegs);
           // FIXME: should be match fail.
           assert(SrcReg && "Wasn't able to allocate register!");
           Chain = DAG.getCopyToReg(Chain, SrcReg, InOperandVal, Flag);
           Flag = Chain.getValue(1);
           
-          ResOp = DAG.getRegister(SrcReg, CallOpVT);
+          ResOp = DAG.getRegister(SrcReg, ConstraintVTs[i]);
           ResOpType = 1;
           break;
         }
diff --git a/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index 79211de..e82e7f7 100644
--- a/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -745,24 +745,34 @@
 
 
 std::vector<unsigned> TargetLowering::
+getRegClassForInlineAsmConstraint(const std::string &Constraint,
+                                  MVT::ValueType VT) const {
+  return std::vector<unsigned>();
+}
+
+
+std::pair<unsigned, const TargetRegisterClass*> TargetLowering::
 getRegForInlineAsmConstraint(const std::string &Constraint,
                              MVT::ValueType VT) const {
-  // Not a physreg, must not be a register reference or something.
-  if (Constraint[0] != '{') return std::vector<unsigned>();
+  if (Constraint[0] != '{')
+    return std::pair<unsigned, const TargetRegisterClass*>(0, 0);
   assert(*(Constraint.end()-1) == '}' && "Not a brace enclosed constraint?");
 
   // Remove the braces from around the name.
   std::string RegName(Constraint.begin()+1, Constraint.end()-1);
-  
-  // Scan to see if this constraint is a register name.
+
+  // Figure out which register class contains this reg.
   const MRegisterInfo *RI = TM.getRegisterInfo();
-  for (unsigned i = 1, e = RI->getNumRegs(); i != e; ++i) {
-    if (const char *Name = RI->get(i).Name)
-      if (StringsEqualNoCase(RegName, Name))
-        return std::vector<unsigned>(1, i);
+  for (MRegisterInfo::regclass_iterator RCI = RI->regclass_begin(),
+       E = RI->regclass_end(); RCI != E; ++RCI) {
+    const TargetRegisterClass *RC = *RCI;
+    for (TargetRegisterClass::iterator I = RC->begin(), E = RC->end(); 
+         I != E; ++I) {
+      if (StringsEqualNoCase(RegName, RI->get(*I).Name)) {
+        return std::make_pair(*I, RC);
+      }
+    }
   }
   
-  // Unknown physreg.
-  return std::vector<unsigned>();
+  return std::pair<unsigned, const TargetRegisterClass*>(0, 0);
 }
-
diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp
index 243c51d..003d16c 100644
--- a/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -999,8 +999,8 @@
 
 
 std::vector<unsigned> PPCTargetLowering::
-getRegForInlineAsmConstraint(const std::string &Constraint,
-                             MVT::ValueType VT) const {
+getRegClassForInlineAsmConstraint(const std::string &Constraint,
+                                  MVT::ValueType VT) const {
   if (Constraint.size() == 1) {
     switch (Constraint[0]) {      // GCC RS6000 Constraint Letters
     default: break;  // Unknown constriant letter
@@ -1051,8 +1051,7 @@
     }
   }
   
-  // Handle explicit register names.
-  return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT);
+  return std::vector<unsigned>();
 }
 
 // isOperandValidForConstraint
diff --git a/lib/Target/PowerPC/PPCISelLowering.h b/lib/Target/PowerPC/PPCISelLowering.h
index a1ce554..86264ae 100644
--- a/lib/Target/PowerPC/PPCISelLowering.h
+++ b/lib/Target/PowerPC/PPCISelLowering.h
@@ -99,8 +99,8 @@
     
     ConstraintType getConstraintType(char ConstraintLetter) const;
     std::vector<unsigned> 
-      getRegForInlineAsmConstraint(const std::string &Constraint,
-                                   MVT::ValueType VT) const;
+      getRegClassForInlineAsmConstraint(const std::string &Constraint,
+                                        MVT::ValueType VT) const;
     bool isOperandValidForConstraint(SDOperand Op, char ConstraintLetter);
   };
 }
diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp
index bbf590b..e32cc0f 100644
--- a/lib/Target/X86/X86ISelLowering.cpp
+++ b/lib/Target/X86/X86ISelLowering.cpp
@@ -1961,8 +1961,8 @@
 }
 
 std::vector<unsigned> X86TargetLowering::
-getRegForInlineAsmConstraint(const std::string &Constraint,
-                             MVT::ValueType VT) const {
+getRegClassForInlineAsmConstraint(const std::string &Constraint,
+                                  MVT::ValueType VT) const {
   if (Constraint.size() == 1) {
     // FIXME: not handling fp-stack yet!
     // FIXME: not handling MMX registers yet ('y' constraint).
@@ -1993,6 +1993,5 @@
     }
   }
   
-  // Handle explicit register names.
-  return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT);
+  return std::vector<unsigned>();
 }
diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h
index 375320c..d45afa4 100644
--- a/lib/Target/X86/X86ISelLowering.h
+++ b/lib/Target/X86/X86ISelLowering.h
@@ -224,8 +224,8 @@
     SDOperand getReturnAddressFrameIndex(SelectionDAG &DAG);
 
     std::vector<unsigned> 
-      getRegForInlineAsmConstraint(const std::string &Constraint,
-                                   MVT::ValueType VT) const;
+      getRegClassForInlineAsmConstraint(const std::string &Constraint,
+                                        MVT::ValueType VT) const;
   private:
     // C Calling Convention implementation.
     std::vector<SDOperand> LowerCCCArguments(Function &F, SelectionDAG &DAG);