[llvm-commits] [llvm] r62356 - in /llvm/trunk: include/llvm/CodeGen/ScheduleDAG.h include/llvm/CodeGen/ScheduleDAGSDNodes.h lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp test/CodeGen/X86/2009-01-16-SchedulerBug.ll

Evan Cheng evan.cheng at apple.com
Fri Jan 16 12:57:19 PST 2009


Author: evancheng
Date: Fri Jan 16 14:57:18 2009
New Revision: 62356

URL: http://llvm.org/viewvc/llvm-project?rev=62356&view=rev
Log:
CreateVirtualRegisters does trivial copy coalescing. If a node def is used by a single CopyToReg, it reuses the virtual register assigned to the CopyToReg. This won't work for SDNode that is a clone or is itself cloned. Disable this optimization for those nodes or it can end up with non-SSA machine instructions.

Added:
    llvm/trunk/test/CodeGen/X86/2009-01-16-SchedulerBug.ll
Modified:
    llvm/trunk/include/llvm/CodeGen/ScheduleDAG.h
    llvm/trunk/include/llvm/CodeGen/ScheduleDAGSDNodes.h
    llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp
    llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp

Modified: llvm/trunk/include/llvm/CodeGen/ScheduleDAG.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/ScheduleDAG.h?rev=62356&r1=62355&r2=62356&view=diff

==============================================================================
--- llvm/trunk/include/llvm/CodeGen/ScheduleDAG.h (original)
+++ llvm/trunk/include/llvm/CodeGen/ScheduleDAG.h Fri Jan 16 14:57:18 2009
@@ -250,6 +250,7 @@
     bool isAvailable      : 1;          // True once available.
     bool isScheduled      : 1;          // True once scheduled.
     bool isScheduleHigh   : 1;          // True if preferable to schedule high.
+    bool isCloned         : 1;          // True if this node has been cloned.
   private:
     bool isDepthCurrent   : 1;          // True if Depth is current.
     bool isHeightCurrent  : 1;          // True if Height is current.
@@ -266,8 +267,8 @@
         Latency(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0), NumSuccsLeft(0),
         isTwoAddress(false), isCommutable(false), hasPhysRegDefs(false),
         isPending(false), isAvailable(false), isScheduled(false),
-        isScheduleHigh(false), isDepthCurrent(false), isHeightCurrent(false),
-        Depth(0), Height(0),
+        isScheduleHigh(false), isCloned(false),
+        isDepthCurrent(false), isHeightCurrent(false), Depth(0), Height(0),
         CopyDstRC(NULL), CopySrcRC(NULL) {}
 
     /// SUnit - Construct an SUnit for post-regalloc scheduling to represent
@@ -277,8 +278,8 @@
         Latency(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0), NumSuccsLeft(0),
         isTwoAddress(false), isCommutable(false), hasPhysRegDefs(false),
         isPending(false), isAvailable(false), isScheduled(false),
-        isScheduleHigh(false), isDepthCurrent(false), isHeightCurrent(false),
-        Depth(0), Height(0),
+        isScheduleHigh(false), isCloned(false),
+        isDepthCurrent(false), isHeightCurrent(false), Depth(0), Height(0),
         CopyDstRC(NULL), CopySrcRC(NULL) {}
 
     /// setNode - Assign the representative SDNode for this SUnit.

Modified: llvm/trunk/include/llvm/CodeGen/ScheduleDAGSDNodes.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/ScheduleDAGSDNodes.h?rev=62356&r1=62355&r2=62356&view=diff

==============================================================================
--- llvm/trunk/include/llvm/CodeGen/ScheduleDAGSDNodes.h (original)
+++ llvm/trunk/include/llvm/CodeGen/ScheduleDAGSDNodes.h Fri Jan 16 14:57:18 2009
@@ -107,7 +107,7 @@
     /// VRBaseMap contains, for each already emitted node, the first virtual
     /// register number for the results of the node.
     ///
-    void EmitNode(SDNode *Node, bool IsClone,
+    void EmitNode(SDNode *Node, bool IsClone, bool HasClone,
                   DenseMap<SDValue, unsigned> &VRBaseMap);
     
     virtual MachineBasicBlock *EmitSchedule();
@@ -144,11 +144,12 @@
     /// EmitCopyFromReg - Generate machine code for an CopyFromReg node or an
     /// implicit physical register output.
     void EmitCopyFromReg(SDNode *Node, unsigned ResNo, bool IsClone,
-                         unsigned SrcReg,
+                         bool IsCloned, unsigned SrcReg,
                          DenseMap<SDValue, unsigned> &VRBaseMap);
     
     void CreateVirtualRegisters(SDNode *Node, MachineInstr *MI,
                                 const TargetInstrDesc &II, bool IsClone,
+                                bool IsCloned,
                                 DenseMap<SDValue, unsigned> &VRBaseMap);
 
     /// BuildSchedUnits, AddSchedEdges - Helper functions for BuildSchedGraph.

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp?rev=62356&r1=62355&r2=62356&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp Fri Jan 16 14:57:18 2009
@@ -33,6 +33,7 @@
   SU->isTwoAddress = Old->isTwoAddress;
   SU->isCommutable = Old->isCommutable;
   SU->hasPhysRegDefs = Old->hasPhysRegDefs;
+  Old->isCloned = true;
   return SU;
 }
 

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp?rev=62356&r1=62355&r2=62356&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp Fri Jan 16 14:57:18 2009
@@ -46,7 +46,8 @@
 /// EmitCopyFromReg - Generate machine code for an CopyFromReg node or an
 /// implicit physical register output.
 void ScheduleDAGSDNodes::EmitCopyFromReg(SDNode *Node, unsigned ResNo,
-                                         bool IsClone, unsigned SrcReg,
+                                         bool IsClone, bool IsCloned,
+                                         unsigned SrcReg,
                                          DenseMap<SDValue, unsigned> &VRBaseMap) {
   unsigned VRBase = 0;
   if (TargetRegisterInfo::isVirtualRegister(SrcReg)) {
@@ -64,44 +65,45 @@
   // the CopyToReg'd destination register instead of creating a new vreg.
   bool MatchReg = true;
   const TargetRegisterClass *UseRC = NULL;
-  for (SDNode::use_iterator UI = Node->use_begin(), E = Node->use_end();
-       UI != E; ++UI) {
-    SDNode *User = *UI;
-    bool Match = true;
-    if (User->getOpcode() == ISD::CopyToReg && 
-        User->getOperand(2).getNode() == Node &&
-        User->getOperand(2).getResNo() == ResNo) {
-      unsigned DestReg = cast<RegisterSDNode>(User->getOperand(1))->getReg();
-      if (TargetRegisterInfo::isVirtualRegister(DestReg)) {
-        VRBase = DestReg;
-        Match = false;
-      } else if (DestReg != SrcReg)
-        Match = false;
-    } else {
-      for (unsigned i = 0, e = User->getNumOperands(); i != e; ++i) {
-        SDValue Op = User->getOperand(i);
-        if (Op.getNode() != Node || Op.getResNo() != ResNo)
-          continue;
-        MVT VT = Node->getValueType(Op.getResNo());
-        if (VT == MVT::Other || VT == MVT::Flag)
-          continue;
-        Match = false;
-        if (User->isMachineOpcode()) {
-          const TargetInstrDesc &II = TII->get(User->getMachineOpcode());
-          const TargetRegisterClass *RC =
-            getInstrOperandRegClass(TRI,TII,II,i+II.getNumDefs());
-          if (!UseRC)
-            UseRC = RC;
-          else if (RC)
-            assert(UseRC == RC &&
-                   "Multiple uses expecting different register classes!");
+  if (!IsClone && !IsCloned)
+    for (SDNode::use_iterator UI = Node->use_begin(), E = Node->use_end();
+         UI != E; ++UI) {
+      SDNode *User = *UI;
+      bool Match = true;
+      if (User->getOpcode() == ISD::CopyToReg && 
+          User->getOperand(2).getNode() == Node &&
+          User->getOperand(2).getResNo() == ResNo) {
+        unsigned DestReg = cast<RegisterSDNode>(User->getOperand(1))->getReg();
+        if (TargetRegisterInfo::isVirtualRegister(DestReg)) {
+          VRBase = DestReg;
+          Match = false;
+        } else if (DestReg != SrcReg)
+          Match = false;
+      } else {
+        for (unsigned i = 0, e = User->getNumOperands(); i != e; ++i) {
+          SDValue Op = User->getOperand(i);
+          if (Op.getNode() != Node || Op.getResNo() != ResNo)
+            continue;
+          MVT VT = Node->getValueType(Op.getResNo());
+          if (VT == MVT::Other || VT == MVT::Flag)
+            continue;
+          Match = false;
+          if (User->isMachineOpcode()) {
+            const TargetInstrDesc &II = TII->get(User->getMachineOpcode());
+            const TargetRegisterClass *RC =
+              getInstrOperandRegClass(TRI,TII,II,i+II.getNumDefs());
+            if (!UseRC)
+              UseRC = RC;
+            else if (RC)
+              assert(UseRC == RC &&
+                     "Multiple uses expecting different register classes!");
+          }
         }
       }
+      MatchReg &= Match;
+      if (VRBase)
+        break;
     }
-    MatchReg &= Match;
-    if (VRBase)
-      break;
-  }
 
   MVT VT = Node->getValueType(ResNo);
   const TargetRegisterClass *SrcRC = 0, *DstRC = 0;
@@ -157,7 +159,8 @@
 }
 
 void ScheduleDAGSDNodes::CreateVirtualRegisters(SDNode *Node, MachineInstr *MI,
-                                       const TargetInstrDesc &II, bool IsClone,
+                                       const TargetInstrDesc &II,
+                                       bool IsClone, bool IsCloned,
                                        DenseMap<SDValue, unsigned> &VRBaseMap) {
   assert(Node->getMachineOpcode() != TargetInstrInfo::IMPLICIT_DEF &&
          "IMPLICIT_DEF should have been handled as a special case elsewhere!");
@@ -167,20 +170,22 @@
     // is a vreg, use the CopyToReg'd destination register instead of creating
     // a new vreg.
     unsigned VRBase = 0;
-    for (SDNode::use_iterator UI = Node->use_begin(), E = Node->use_end();
-         UI != E; ++UI) {
-      SDNode *User = *UI;
-      if (User->getOpcode() == ISD::CopyToReg && 
-          User->getOperand(2).getNode() == Node &&
-          User->getOperand(2).getResNo() == i) {
-        unsigned Reg = cast<RegisterSDNode>(User->getOperand(1))->getReg();
-        if (TargetRegisterInfo::isVirtualRegister(Reg)) {
-          VRBase = Reg;
-          MI->addOperand(MachineOperand::CreateReg(Reg, true));
-          break;
+
+    if (!IsClone && !IsCloned)
+      for (SDNode::use_iterator UI = Node->use_begin(), E = Node->use_end();
+           UI != E; ++UI) {
+        SDNode *User = *UI;
+        if (User->getOpcode() == ISD::CopyToReg && 
+            User->getOperand(2).getNode() == Node &&
+            User->getOperand(2).getResNo() == i) {
+          unsigned Reg = cast<RegisterSDNode>(User->getOperand(1))->getReg();
+          if (TargetRegisterInfo::isVirtualRegister(Reg)) {
+            VRBase = Reg;
+            MI->addOperand(MachineOperand::CreateReg(Reg, true));
+            break;
+          }
         }
       }
-    }
 
     // Create the result registers for this node and add the result regs to
     // the machine instruction.
@@ -452,7 +457,7 @@
 
 /// EmitNode - Generate machine code for an node and needed dependencies.
 ///
-void ScheduleDAGSDNodes::EmitNode(SDNode *Node, bool IsClone,
+void ScheduleDAGSDNodes::EmitNode(SDNode *Node, bool IsClone, bool IsCloned,
                                   DenseMap<SDValue, unsigned> &VRBaseMap) {
   // If machine instruction
   if (Node->isMachineOpcode()) {
@@ -489,7 +494,7 @@
     // Add result register values for things that are defined by this
     // instruction.
     if (NumResults)
-      CreateVirtualRegisters(Node, MI, II, IsClone, VRBaseMap);
+      CreateVirtualRegisters(Node, MI, II, IsClone, IsCloned, VRBaseMap);
     
     // Emit all of the actual operands of this instruction, adding them to the
     // instruction as appropriate.
@@ -512,7 +517,7 @@
       for (unsigned i = II.getNumDefs(); i < NumResults; ++i) {
         unsigned Reg = II.getImplicitDefs()[i - II.getNumDefs()];
         if (Node->hasAnyUseOfValue(i))
-          EmitCopyFromReg(Node, i, IsClone, Reg, VRBaseMap);
+          EmitCopyFromReg(Node, i, IsClone, IsCloned, Reg, VRBaseMap);
       }
     }
     return;
@@ -559,7 +564,7 @@
   }
   case ISD::CopyFromReg: {
     unsigned SrcReg = cast<RegisterSDNode>(Node->getOperand(1))->getReg();
-    EmitCopyFromReg(Node, 0, IsClone, SrcReg, VRBaseMap);
+    EmitCopyFromReg(Node, 0, IsClone, IsCloned, SrcReg, VRBaseMap);
     break;
   }
   case ISD::INLINEASM: {
@@ -636,13 +641,14 @@
     }
 
     SmallVector<SDNode *, 4> FlaggedNodes;
-    for (SDNode *N = SU->getNode()->getFlaggedNode(); N; N = N->getFlaggedNode())
+    for (SDNode *N = SU->getNode()->getFlaggedNode(); N;
+         N = N->getFlaggedNode())
       FlaggedNodes.push_back(N);
     while (!FlaggedNodes.empty()) {
-      EmitNode(FlaggedNodes.back(), SU->OrigNode != SU, VRBaseMap);
+      EmitNode(FlaggedNodes.back(), SU->OrigNode != SU, SU->isCloned,VRBaseMap);
       FlaggedNodes.pop_back();
     }
-    EmitNode(SU->getNode(), SU->OrigNode != SU, VRBaseMap);
+    EmitNode(SU->getNode(), SU->OrigNode != SU, SU->isCloned, VRBaseMap);
   }
 
   return BB;

Added: llvm/trunk/test/CodeGen/X86/2009-01-16-SchedulerBug.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/2009-01-16-SchedulerBug.ll?rev=62356&view=auto

==============================================================================
--- llvm/trunk/test/CodeGen/X86/2009-01-16-SchedulerBug.ll (added)
+++ llvm/trunk/test/CodeGen/X86/2009-01-16-SchedulerBug.ll Fri Jan 16 14:57:18 2009
@@ -0,0 +1,50 @@
+; RUN: llvm-as < %s | llc -mtriple=i386-apple-darwin
+; rdar://6501631
+
+	%CF = type { %Register }
+	%XXV = type { i32 (...)** }
+	%Register = type { %"struct.XXC::BCFs", i32 }
+	%"struct.XXC::BCFs" = type { i32 }
+
+declare { i32, i1 } @llvm.sadd.with.overflow.i32(i32, i32) nounwind
+
+define fastcc %XXV* @bar(%CF* %call_frame, %XXV** %exception) nounwind {
+prologue:
+	%param_x = load %XXV** null		; <%XXV*> [#uses=1]
+	%unique_1.i = ptrtoint %XXV* %param_x to i1		; <i1> [#uses=1]
+	br i1 %unique_1.i, label %NextVerify42, label %FailedVerify
+
+NextVerify42:		; preds = %prologue
+	%param_y = load %XXV** null		; <%XXV*> [#uses=1]
+	%unique_1.i58 = ptrtoint %XXV* %param_y to i1		; <i1> [#uses=1]
+	br i1 %unique_1.i58, label %function_setup.cont, label %FailedVerify
+
+function_setup.cont:		; preds = %NextVerify42
+	br i1 false, label %label13, label %label
+
+label:		; preds = %function_setup.cont
+	%has_exn = icmp eq %XXV* null, null		; <i1> [#uses=1]
+	br i1 %has_exn, label %kjsNumberLiteral.exit, label %handle_exception
+
+kjsNumberLiteral.exit:		; preds = %label
+	%0 = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 0, i32 0)		; <{ i32, i1 }> [#uses=2]
+	%intAdd = extractvalue { i32, i1 } %0, 0		; <i32> [#uses=2]
+	%intAddOverflow = extractvalue { i32, i1 } %0, 1		; <i1> [#uses=1]
+	%toint56 = ashr i32 %intAdd, 1		; <i32> [#uses=1]
+	%toFP57 = sitofp i32 %toint56 to double		; <double> [#uses=1]
+	br i1 %intAddOverflow, label %rematerializeAdd, label %label13
+
+label13:		; preds = %kjsNumberLiteral.exit, %function_setup.cont
+	%var_lr1.0 = phi double [ %toFP57, %kjsNumberLiteral.exit ], [ 0.000000e+00, %function_setup.cont ]		; <double> [#uses=0]
+	unreachable
+
+FailedVerify:		; preds = %NextVerify42, %prologue
+	ret %XXV* null
+
+rematerializeAdd:		; preds = %kjsNumberLiteral.exit
+	%rematerializedInt = sub i32 %intAdd, 0		; <i32> [#uses=0]
+	ret %XXV* null
+
+handle_exception:		; preds = %label
+	ret %XXV* undef
+}





More information about the llvm-commits mailing list