[llvm-commits] [llvm] r46099 - in /llvm/trunk: lib/CodeGen/SelectionDAG/DAGCombiner.cpp test/CodeGen/X86/2008-01-16-InvalidDAGCombineXform.ll

Evan Cheng evan.cheng at apple.com
Wed Jan 16 15:11:55 PST 2008


Author: evancheng
Date: Wed Jan 16 17:11:54 2008
New Revision: 46099

URL: http://llvm.org/viewvc/llvm-project?rev=46099&view=rev
Log:
Fixes a nasty dag combiner bug that causes a bunch of tests to fail at -O0.

It's not safe to use the two value CombineTo variant to combine away a dead load.
e.g. 
v1, chain2 = load chain1, loc
v2, chain3 = load chain2, loc
v3         = add v2, c 
Now we replace use of v1 with undef, use of chain2 with chain1.
ReplaceAllUsesWith() will iterate through uses of the first load and update operands:
v1, chain2 = load chain1, loc
v2, chain3 = load chain1, loc
v3         = add v2, c 
Now the second load is the same as the first load, SelectionDAG cse will ensure
the use of second load is replaced with the first load.
v1, chain2 = load chain1, loc
v3         = add v1, c
Then v1 is replaced with undef and bad things happen.

Added:
    llvm/trunk/test/CodeGen/X86/2008-01-16-InvalidDAGCombineXform.ll
Modified:
    llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp

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

==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Wed Jan 16 17:11:54 2008
@@ -4055,16 +4055,54 @@
   if (!LD->isVolatile()) {
     if (N->getValueType(1) == MVT::Other) {
       // Unindexed loads.
-      if (N->hasNUsesOfValue(0, 0))
-        return CombineTo(N, DAG.getNode(ISD::UNDEF, N->getValueType(0)), Chain);
+      if (N->hasNUsesOfValue(0, 0)) {
+        // It's not safe to use the two value CombineTo variant here. e.g.
+        // v1, chain2 = load chain1, loc
+        // v2, chain3 = load chain2, loc
+        // v3         = add v2, c
+        // Now we replace use of v1 with undef, use of chain2 with chain1.
+        // ReplaceAllUsesWith() will iterate through uses of the first load and
+        // update operands:
+        // v1, chain2 = load chain1, loc
+        // v2, chain3 = load chain1, loc
+        // v3         = add v2, c
+        // Now the second load is the same as the first load, SelectionDAG cse
+        // will ensure the use of second load is replaced with the first load.
+        // v1, chain2 = load chain1, loc
+        // v3         = add v1, c
+        // Then v1 is replaced with undef and bad things happen.
+        std::vector<SDNode*> NowDead;
+        SDOperand Undef = DAG.getNode(ISD::UNDEF, N->getValueType(0));
+        DOUT << "\nReplacing.6 "; DEBUG(N->dump(&DAG));
+        DOUT << "\nWith: "; DEBUG(Undef.Val->dump(&DAG));
+        DOUT << " and 1 other value\n";
+        DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 0), Undef, &NowDead);
+        DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 1), Chain, &NowDead);
+        removeFromWorkList(N);
+        for (unsigned i = 0, e = NowDead.size(); i != e; ++i)
+          removeFromWorkList(NowDead[i]);
+        DAG.DeleteNode(N);
+        return SDOperand(N, 0);   // Return N so it doesn't get rechecked!
+      }
     } else {
       // Indexed loads.
       assert(N->getValueType(2) == MVT::Other && "Malformed indexed loads?");
       if (N->hasNUsesOfValue(0, 0) && N->hasNUsesOfValue(0, 1)) {
-        SDOperand Undef0 = DAG.getNode(ISD::UNDEF, N->getValueType(0));
-        SDOperand Undef1 = DAG.getNode(ISD::UNDEF, N->getValueType(1));
-        SDOperand To[] = { Undef0, Undef1, Chain };
-        return CombineTo(N, To, 3);
+        std::vector<SDNode*> NowDead;
+        SDOperand Undef = DAG.getNode(ISD::UNDEF, N->getValueType(0));
+        DOUT << "\nReplacing.6 "; DEBUG(N->dump(&DAG));
+        DOUT << "\nWith: "; DEBUG(Undef.Val->dump(&DAG));
+        DOUT << " and 2 other values\n";
+        DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 0), Undef, &NowDead);
+        DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 1),
+                                      DAG.getNode(ISD::UNDEF, N->getValueType(1)),
+                                      &NowDead);
+        DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 2), Chain, &NowDead);
+        removeFromWorkList(N);
+        for (unsigned i = 0, e = NowDead.size(); i != e; ++i)
+          removeFromWorkList(NowDead[i]);
+        DAG.DeleteNode(N);
+        return SDOperand(N, 0);   // Return N so it doesn't get rechecked!
       }
     }
   }

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

==============================================================================
--- llvm/trunk/test/CodeGen/X86/2008-01-16-InvalidDAGCombineXform.ll (added)
+++ llvm/trunk/test/CodeGen/X86/2008-01-16-InvalidDAGCombineXform.ll Wed Jan 16 17:11:54 2008
@@ -0,0 +1,30 @@
+; RUN: llvm-as < %s | llc -march=x86 | not grep IMPLICIT_DEF
+
+	%struct.node_t = type { double*, %struct.node_t*, %struct.node_t**, double**, double*, i32, i32 }
+
+define void @localize_local_bb19_bb(%struct.node_t** %cur_node) {
+newFuncRoot:
+	%tmp1 = load %struct.node_t** %cur_node, align 4		; <%struct.node_t*> [#uses=1]
+	%tmp2 = getelementptr %struct.node_t* %tmp1, i32 0, i32 4		; <double**> [#uses=1]
+	%tmp3 = load double** %tmp2, align 4		; <double*> [#uses=1]
+	%tmp4 = load %struct.node_t** %cur_node, align 4		; <%struct.node_t*> [#uses=1]
+	%tmp5 = getelementptr %struct.node_t* %tmp4, i32 0, i32 4		; <double**> [#uses=1]
+	store double* %tmp3, double** %tmp5, align 4
+	%tmp6 = load %struct.node_t** %cur_node, align 4		; <%struct.node_t*> [#uses=1]
+	%tmp7 = getelementptr %struct.node_t* %tmp6, i32 0, i32 3		; <double***> [#uses=1]
+	%tmp8 = load double*** %tmp7, align 4		; <double**> [#uses=1]
+	%tmp9 = load %struct.node_t** %cur_node, align 4		; <%struct.node_t*> [#uses=1]
+	%tmp10 = getelementptr %struct.node_t* %tmp9, i32 0, i32 3		; <double***> [#uses=1]
+	store double** %tmp8, double*** %tmp10, align 4
+	%tmp11 = load %struct.node_t** %cur_node, align 4		; <%struct.node_t*> [#uses=1]
+	%tmp12 = getelementptr %struct.node_t* %tmp11, i32 0, i32 0		; <double**> [#uses=1]
+	%tmp13 = load double** %tmp12, align 4		; <double*> [#uses=1]
+	%tmp14 = load %struct.node_t** %cur_node, align 4		; <%struct.node_t*> [#uses=1]
+	%tmp15 = getelementptr %struct.node_t* %tmp14, i32 0, i32 0		; <double**> [#uses=1]
+	store double* %tmp13, double** %tmp15, align 4
+	%tmp16 = load %struct.node_t** %cur_node, align 4		; <%struct.node_t*> [#uses=1]
+	%tmp17 = getelementptr %struct.node_t* %tmp16, i32 0, i32 1		; <%struct.node_t**> [#uses=1]
+	%tmp18 = load %struct.node_t** %tmp17, align 4		; <%struct.node_t*> [#uses=1]
+	store %struct.node_t* %tmp18, %struct.node_t** %cur_node, align 4
+	ret void
+}





More information about the llvm-commits mailing list