Add a bit to mark operands of asm's that conflict
with an earlyclobber operand elsewhere.  Propagate
this bit and the earlyclobber bit through SDISel.
Change linear-scan RA not to allocate regs in a way 
that conflicts with an earlyclobber.  See also comments.



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@56290 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp
index 62a6b4f..9492b33 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp
@@ -4909,8 +4909,10 @@
         assert(OpInfo.isIndirect && "Memory output must be indirect operand");
 
         // Add information to the INLINEASM node to know about this output.
-        unsigned ResOpType = 4/*MEM*/ | (1 << 3);
-        AsmNodeOperands.push_back(DAG.getTargetConstant(ResOpType, 
+        unsigned ResOpType = SawEarlyClobber ? 
+                                  7 /* MEM OVERLAPS EARLYCLOBBER */ :
+                                  4/*MEM*/;
+        AsmNodeOperands.push_back(DAG.getTargetConstant(ResOpType | (1<<3), 
                                                         TLI.getPointerTy()));
         AsmNodeOperands.push_back(OpInfo.CallOperand);
         break;
@@ -4963,7 +4965,8 @@
             cast<ConstantSDNode>(AsmNodeOperands[CurOp])->getZExtValue();
           assert(((NumOps & 7) == 2 /*REGDEF*/ ||
                   (NumOps & 7) == 6 /*EARLYCLOBBER REGDEF*/ ||
-                  (NumOps & 7) == 4 /*MEM*/) &&
+                  (NumOps & 7) == 4 /*MEM*/ ||
+                  (NumOps & 7) == 7 /*MEM OVERLAPS EARLYCLOBBER*/) &&
                  "Skipped past definitions?");
           CurOp += (NumOps>>3)+1;
         }
@@ -4985,14 +4988,17 @@
         
           // Use the produced MatchedRegs object to 
           MatchedRegs.getCopyToRegs(InOperandVal, DAG, Chain, &Flag);
-          MatchedRegs.AddInlineAsmOperands(1 /*REGUSE*/, DAG, AsmNodeOperands);
+          MatchedRegs.AddInlineAsmOperands(SawEarlyClobber ? 
+                                           1 /*REGUSE*/ :
+                                           5 /*REGUSE OVERLAPS EARLYCLOBBER*/, 
+                                           DAG, AsmNodeOperands);
           break;
         } else {
-          assert((NumOps & 7) == 4/*MEM*/ && "Unknown matching constraint!");
+          assert(((NumOps & 7) == 7/*MEM OVERLAPS EARLYCLOBBER */ ||
+                  (NumOps & 7) == 4) && "Unknown matching constraint!");
           assert((NumOps >> 3) == 1 && "Unexpected number of operands"); 
           // Add information to the INLINEASM node to know about this input.
-          unsigned ResOpType = 4/*MEM*/ | (1 << 3);
-          AsmNodeOperands.push_back(DAG.getTargetConstant(ResOpType,
+          AsmNodeOperands.push_back(DAG.getTargetConstant(NumOps,
                                                           TLI.getPointerTy()));
           AsmNodeOperands.push_back(AsmNodeOperands[CurOp+1]);
           break;
@@ -5024,8 +5030,10 @@
                "Memory operands expect pointer values");
                
         // Add information to the INLINEASM node to know about this input.
-        unsigned ResOpType = 4/*MEM*/ | (1 << 3);
-        AsmNodeOperands.push_back(DAG.getTargetConstant(ResOpType,
+        unsigned ResOpType = SawEarlyClobber ? 
+                                7 /* MEM OVERLAPS EARLYCLOBBER */ : 
+                                4/*MEM*/;
+        AsmNodeOperands.push_back(DAG.getTargetConstant(ResOpType | (1<<3),
                                                         TLI.getPointerTy()));
         AsmNodeOperands.push_back(InOperandVal);
         break;
@@ -5043,16 +5051,18 @@
 
       OpInfo.AssignedRegs.getCopyToRegs(InOperandVal, DAG, Chain, &Flag);
       
-      OpInfo.AssignedRegs.AddInlineAsmOperands(1/*REGUSE*/, DAG,
-                                               AsmNodeOperands);
+      OpInfo.AssignedRegs.AddInlineAsmOperands(SawEarlyClobber ?
+                                           5 /*REGUSE OVERLAPS EARLYCLOBBER*/:
+                                           1/*REGUSE*/,
+                                           DAG, AsmNodeOperands);
       break;
     }
     case InlineAsm::isClobber: {
       // Add the clobbered value to the operand list, so that the register
       // allocator is aware that the physreg got clobbered.
       if (!OpInfo.AssignedRegs.Regs.empty())
-        OpInfo.AssignedRegs.AddInlineAsmOperands(2/*REGDEF*/, DAG,
-                                                 AsmNodeOperands);
+        OpInfo.AssignedRegs.AddInlineAsmOperands(6 /* EARLYCLOBBER REGDEF */,
+                                                 DAG, AsmNodeOperands);
       break;
     }
     }