[llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp

Chris Lattner sabre at nondot.org
Mon Apr 30 14:11:35 PDT 2007



Changes in directory llvm/lib/CodeGen/SelectionDAG:

SelectionDAGISel.cpp updated: 1.441 -> 1.442
---
Log message:

Continue refactoring inline asm code.  If there is an earlyclobber output
register, preallocate all input registers and the early clobbered output.

This fixes PR1357: http://llvm.org/PR1357  and CodeGen/PowerPC/2007-04-30-InlineAsmEarlyClobber.ll



---
Diffs of the changes:  (+108 -79)

 SelectionDAGISel.cpp |  187 +++++++++++++++++++++++++++++----------------------
 1 files changed, 108 insertions(+), 79 deletions(-)


Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
diff -u llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:1.441 llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:1.442
--- llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:1.441	Mon Apr 30 12:29:31 2007
+++ llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp	Mon Apr 30 16:11:17 2007
@@ -518,10 +518,9 @@
     N = NewN;
   }
   
-  RegsForValue GetRegistersForValue(AsmOperandInfo &OpInfo,
-                                    bool OutReg, bool InReg,
-                                    std::set<unsigned> &OutputRegs, 
-                                    std::set<unsigned> &InputRegs);
+  void GetRegistersForValue(AsmOperandInfo &OpInfo, bool HasEarlyClobber,
+                            std::set<unsigned> &OutputRegs, 
+                            std::set<unsigned> &InputRegs);
 
   void FindMergedConditions(Value *Cond, MachineBasicBlock *TBB,
                             MachineBasicBlock *FBB, MachineBasicBlock *CurBB,
@@ -3035,6 +3034,10 @@
   /// ConstraintVT - The ValueType for the operand value.
   MVT::ValueType ConstraintVT;
   
+  /// AssignedRegs - If this is a register or register class operand, this
+  /// contains the set of register corresponding to the operand.
+  RegsForValue AssignedRegs;
+  
   AsmOperandInfo(const InlineAsm::ConstraintInfo &info)
     : InlineAsm::ConstraintInfo(info), 
       ConstraintType(TargetLowering::C_Unknown),
@@ -3042,6 +3045,17 @@
   }
   
   void ComputeConstraintToUse(const TargetLowering &TLI);
+  
+  /// MarkAllocatedRegs - Once AssignedRegs is set, mark the assigned registers
+  /// busy in OutputRegs/InputRegs.
+  void MarkAllocatedRegs(bool isOutReg, bool isInReg,
+                         std::set<unsigned> &OutputRegs, 
+                         std::set<unsigned> &InputRegs) const {
+     if (isOutReg)
+       OutputRegs.insert(AssignedRegs.Regs.begin(), AssignedRegs.Regs.end());
+     if (isInReg)
+       InputRegs.insert(AssignedRegs.Regs.begin(), AssignedRegs.Regs.end());
+   }
 };
 } // end anon namespace.
 
@@ -3093,13 +3107,42 @@
 }
 
 
-RegsForValue SelectionDAGLowering::
-GetRegistersForValue(AsmOperandInfo &OpInfo, bool isOutReg, bool isInReg,
+void SelectionDAGLowering::
+GetRegistersForValue(AsmOperandInfo &OpInfo, bool HasEarlyClobber,
                      std::set<unsigned> &OutputRegs, 
                      std::set<unsigned> &InputRegs) {
-  std::pair<unsigned, const TargetRegisterClass*> PhysReg = 
-    TLI.getRegForInlineAsmConstraint(OpInfo.ConstraintCode,OpInfo.ConstraintVT);
+  // Compute whether this value requires an input register, an output register,
+  // or both.
+  bool isOutReg = false;
+  bool isInReg = false;
+  switch (OpInfo.Type) {
+  case InlineAsm::isOutput:
+    isOutReg = true;
+    
+    // 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.
+    isInReg = OpInfo.isEarlyClobber || OpInfo.hasMatchingInput;
+    break;
+  case InlineAsm::isInput:
+    isInReg = true;
+    isOutReg = false;
+    break;
+  case InlineAsm::isClobber:
+    isOutReg = true;
+    isInReg = true;
+    break;
+  }
+  
+  
+  MachineFunction &MF = DAG.getMachineFunction();
   std::vector<unsigned> Regs;
+  
+  // If this is a constraint for a single physreg, or a constraint for a
+  // register class, find it.
+  std::pair<unsigned, const TargetRegisterClass*> PhysReg = 
+    TLI.getRegForInlineAsmConstraint(OpInfo.ConstraintCode,
+                                     OpInfo.ConstraintVT);
 
   unsigned NumRegs = 1;
   if (OpInfo.ConstraintVT != MVT::Other)
@@ -3107,7 +3150,6 @@
   MVT::ValueType RegVT;
   MVT::ValueType ValueVT = OpInfo.ConstraintVT;
   
-  MachineFunction &MF = DAG.getMachineFunction();
 
   // If this is a constraint for a specific physical register, like {r17},
   // assign it now.
@@ -3137,7 +3179,9 @@
         Regs.push_back(*I);
       }
     }
-    return RegsForValue(Regs, RegVT, ValueVT);
+    OpInfo.AssignedRegs = RegsForValue(Regs, RegVT, ValueVT);
+    OpInfo.MarkAllocatedRegs(isOutReg, isInReg, OutputRegs, InputRegs);
+    return;
   }
   
   // Otherwise, if this was a reference to an LLVM register class, create vregs
@@ -3147,7 +3191,11 @@
     // If this is an early clobber or tied register, our regalloc doesn't know
     // how to maintain the constraint.  If it isn't, go ahead and create vreg
     // and let the regalloc do the right thing.
-    if (!isOutReg || !isInReg) {
+    if (!OpInfo.hasMatchingInput && !OpInfo.isEarlyClobber &&
+        // If there is some other early clobber and this is an input register,
+        // then we are forced to pre-allocate the input reg so it doesn't
+        // conflict with the earlyclobber.
+        !(OpInfo.Type == InlineAsm::isInput && HasEarlyClobber)) {
       RegVT = *PhysReg.second->vt_begin();
       
       if (OpInfo.ConstraintVT == MVT::Other)
@@ -3158,7 +3206,9 @@
       for (; NumRegs; --NumRegs)
         Regs.push_back(RegMap->createVirtualRegister(PhysReg.second));
       
-      return RegsForValue(Regs, RegVT, ValueVT);
+      OpInfo.AssignedRegs = RegsForValue(Regs, RegVT, ValueVT);
+      OpInfo.MarkAllocatedRegs(isOutReg, isInReg, OutputRegs, InputRegs);
+      return;
     }
     
     // Otherwise, we can't allocate it.  Let the code below figure out how to
@@ -3172,7 +3222,7 @@
     RegClassRegs = TLI.getRegClassForInlineAsmConstraint(OpInfo.ConstraintCode,
                                                          OpInfo.ConstraintVT);
   }
-
+  
   const MRegisterInfo *MRI = DAG.getTarget().getRegisterInfo();
   unsigned NumAllocated = 0;
   for (unsigned i = 0, e = RegClassRegs.size(); i != e; ++i) {
@@ -3202,19 +3252,18 @@
       unsigned RegStart = (i-NumAllocated)+1;
       unsigned RegEnd   = i+1;
       // Mark all of the allocated registers used.
-      for (unsigned i = RegStart; i != RegEnd; ++i) {
-        unsigned Reg = RegClassRegs[i];
-        Regs.push_back(Reg);
-        if (isOutReg) OutputRegs.insert(Reg);    // Mark reg used.
-        if (isInReg)  InputRegs.insert(Reg);     // Mark reg used.
-      }
+      for (unsigned i = RegStart; i != RegEnd; ++i)
+        Regs.push_back(RegClassRegs[i]);
       
-      return RegsForValue(Regs, *RC->vt_begin(), OpInfo.ConstraintVT);
+      OpInfo.AssignedRegs = RegsForValue(Regs, *RC->vt_begin(), 
+                                         OpInfo.ConstraintVT);
+      OpInfo.MarkAllocatedRegs(isOutReg, isInReg, OutputRegs, InputRegs);
+      return;
     }
   }
   
   // Otherwise, we couldn't allocate enough registers for this.
-  return RegsForValue();
+  return;
 }
 
 
@@ -3235,7 +3284,13 @@
   // ConstraintOperands list.
   std::vector<InlineAsm::ConstraintInfo>
     ConstraintInfos = IA->ParseConstraints();
-  unsigned OpNo = 1;
+
+  // SawEarlyClobber - Keep track of whether we saw an earlyclobber output
+  // constraint.  If so, we can't let the register allocator allocate any input
+  // registers, because it will not know to avoid the earlyclobbered output reg.
+  bool SawEarlyClobber = false;
+  
+  unsigned OpNo = 1;   // OpNo - The operand of the CallInst.
   for (unsigned i = 0, e = ConstraintInfos.size(); i != e; ++i) {
     ConstraintOperands.push_back(AsmOperandInfo(ConstraintInfos[i]));
     AsmOperandInfo &OpInfo = ConstraintOperands.back();
@@ -3295,6 +3350,8 @@
     // Compute the constraint code and ConstraintType to use.
     OpInfo.ComputeConstraintToUse(TLI);
 
+    // Keep track of whether we see an earlyclobber.
+    SawEarlyClobber |= OpInfo.isEarlyClobber;
     
     // If this is a memory input, and if the operand is not indirect, do what we
     // need to to provide an address for the memory input.
@@ -3333,42 +3390,25 @@
       OpInfo.isIndirect = true;
     }
     
-    
-    if (TLI.getRegForInlineAsmConstraint(OpInfo.ConstraintCode, OpVT).first ==0)
-      continue;  // Not assigned a fixed reg.
-    
-    // For GCC register classes where we don't have a direct match, we fully
-    // assign registers at isel time.  This is not optimal, but works.
-    
-    // Build a list of regs that this operand uses.  This always has a single
-    // element for promoted/expanded operands.
-    RegsForValue Regs = GetRegistersForValue(OpInfo, false, false,
-                                             OutputRegs, InputRegs);
-    
-    switch (OpInfo.Type) {
-    case InlineAsm::isOutput:
-      // We can't assign any other output to this register.
-      OutputRegs.insert(Regs.Regs.begin(), Regs.Regs.end());
-      // If this is an early-clobber output, it cannot be assigned to the same
-      // value as the input reg.
-      if (OpInfo.isEarlyClobber || OpInfo.hasMatchingInput)
-        InputRegs.insert(Regs.Regs.begin(), Regs.Regs.end());
-      break;
-    case InlineAsm::isInput:
-      // We can't assign any other input to this register.
-      InputRegs.insert(Regs.Regs.begin(), Regs.Regs.end());
-      break;
-    case InlineAsm::isClobber:
-      // Clobbered regs cannot be used as inputs or outputs.
-      InputRegs.insert(Regs.Regs.begin(), Regs.Regs.end());
-      OutputRegs.insert(Regs.Regs.begin(), Regs.Regs.end());
-      break;
-    }
+    // If this constraint is for a specific register, allocate it before
+    // anything else.
+    if (OpInfo.ConstraintType == TargetLowering::C_Register)
+      GetRegistersForValue(OpInfo, SawEarlyClobber, OutputRegs, InputRegs);
   }
-  
   ConstraintInfos.clear();
   
   
+  // Second pass - Loop over all of the operands, assigning virtual or physregs
+  // to registerclass operands.
+  for (unsigned i = 0, e = ConstraintOperands.size(); i != e; ++i) {
+    AsmOperandInfo &OpInfo = ConstraintOperands[i];
+    
+    // C_Register operands have already been allocated, Other/Memory don't need
+    // to be.
+    if (OpInfo.ConstraintType == TargetLowering::C_RegisterClass)
+      GetRegistersForValue(OpInfo, SawEarlyClobber, OutputRegs, InputRegs);
+  }    
+  
   // AsmNodeOperands - The operands for the ISD::INLINEASM node.
   std::vector<SDOperand> AsmNodeOperands;
   AsmNodeOperands.push_back(SDOperand());  // reserve space for input chain
@@ -3402,19 +3442,9 @@
 
       // Otherwise, this is a register or register class output.
 
-      // 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 (OpInfo.isEarlyClobber || OpInfo.hasMatchingInput)
-        UsesInputRegister = true;
-      
       // Copy the output from the appropriate register.  Find a register that
       // we can use.
-      RegsForValue Regs =
-        GetRegistersForValue(OpInfo, true, UsesInputRegister, 
-                             OutputRegs, InputRegs);
-      if (Regs.Regs.empty()) {
+      if (OpInfo.AssignedRegs.Regs.empty()) {
         cerr << "Couldn't allocate output reg for contraint '"
              << OpInfo.ConstraintCode << "'!\n";
         exit(1);
@@ -3425,15 +3455,16 @@
         assert(RetValRegs.Regs.empty() &&
                "Cannot have multiple output constraints yet!");
         assert(I.getType() != Type::VoidTy && "Bad inline asm!");
-        RetValRegs = Regs;
+        RetValRegs = OpInfo.AssignedRegs;
       } else {
-        IndirectStoresToEmit.push_back(std::make_pair(Regs,
+        IndirectStoresToEmit.push_back(std::make_pair(OpInfo.AssignedRegs,
                                                       OpInfo.CallOperandVal));
       }
       
       // Add information to the INLINEASM node to know that this register is
       // set.
-      Regs.AddInlineAsmOperands(2 /*REGDEF*/, DAG, AsmNodeOperands);
+      OpInfo.AssignedRegs.AddInlineAsmOperands(2 /*REGDEF*/, DAG,
+                                               AsmNodeOperands);
       break;
     }
     case InlineAsm::isInput: {
@@ -3518,24 +3549,22 @@
              "Don't know how to handle indirect register inputs yet!");
 
       // Copy the input into the appropriate registers.
-      RegsForValue InRegs =
-        GetRegistersForValue(OpInfo, false, true, OutputRegs, InputRegs);
-      // FIXME: should be match fail.
-      assert(!InRegs.Regs.empty() && "Couldn't allocate input reg!");
+      assert(!OpInfo.AssignedRegs.Regs.empty() &&
+             "Couldn't allocate input reg!");
 
-      InRegs.getCopyToRegs(InOperandVal, DAG, Chain, Flag, TLI.getPointerTy());
+      OpInfo.AssignedRegs.getCopyToRegs(InOperandVal, DAG, Chain, Flag, 
+                                        TLI.getPointerTy());
       
-      InRegs.AddInlineAsmOperands(1/*REGUSE*/, DAG, AsmNodeOperands);
+      OpInfo.AssignedRegs.AddInlineAsmOperands(1/*REGUSE*/, DAG,
+                                               AsmNodeOperands);
       break;
     }
     case InlineAsm::isClobber: {
-      RegsForValue ClobberedRegs =
-        GetRegistersForValue(OpInfo, false,
-                             false, OutputRegs, InputRegs);
       // Add the clobbered value to the operand list, so that the register
       // allocator is aware that the physreg got clobbered.
-      if (!ClobberedRegs.Regs.empty())
-        ClobberedRegs.AddInlineAsmOperands(2/*REGDEF*/, DAG, AsmNodeOperands);
+      if (!OpInfo.AssignedRegs.Regs.empty())
+        OpInfo.AssignedRegs.AddInlineAsmOperands(2/*REGDEF*/, DAG,
+                                                 AsmNodeOperands);
       break;
     }
     }






More information about the llvm-commits mailing list