[llvm] r269272 - [PowerPC] Fix a DAG replacement bug in PPCTargetLowering::DAGCombineExtBoolTrunc

Hal Finkel via llvm-commits llvm-commits at lists.llvm.org
Wed May 11 21:00:56 PDT 2016


Author: hfinkel
Date: Wed May 11 23:00:56 2016
New Revision: 269272

URL: http://llvm.org/viewvc/llvm-project?rev=269272&view=rev
Log:
[PowerPC] Fix a DAG replacement bug in PPCTargetLowering::DAGCombineExtBoolTrunc

While promoting nodes in PPCTargetLowering::DAGCombineExtBoolTrunc, it is
possible for one of the nodes to be replaced by another. To make sure we do not
visit the deleted nodes, and to make sure we visit the replacement nodes, use a
list of HandleSDNodes to track the to-be-promoted nodes during the promotion
process.

The same fix has been applied to the analogous code in
PPCTargetLowering::DAGCombineTruncBoolExt.

Fixes PR26985.

Added:
    llvm/trunk/test/CodeGen/PowerPC/ext-bool-trunc-repl.ll
Modified:
    llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp

Modified: llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp?rev=269272&r1=269271&r2=269272&view=diff
==============================================================================
--- llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp Wed May 11 23:00:56 2016
@@ -42,6 +42,7 @@
 #include "llvm/Support/MathExtras.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Target/TargetOptions.h"
+#include <list>
 
 using namespace llvm;
 
@@ -9914,14 +9915,18 @@ SDValue PPCTargetLowering::DAGCombineTru
       DAG.ReplaceAllUsesOfValueWith(Inputs[i], Inputs[i].getOperand(0));
   }
 
+  std::list<HandleSDNode> PromOpHandles;
+  for (auto &PromOp : PromOps)
+    PromOpHandles.emplace_back(PromOp); 
+
   // Replace all operations (these are all the same, but have a different
   // (i1) return type). DAG.getNode will validate that the types of
   // a binary operator match, so go through the list in reverse so that
   // we've likely promoted both operands first. Any intermediate truncations or
   // extensions disappear.
-  while (!PromOps.empty()) {
-    SDValue PromOp = PromOps.back();
-    PromOps.pop_back();
+  while (!PromOpHandles.empty()) {
+    SDValue PromOp = PromOpHandles.back().getValue();
+    PromOpHandles.pop_back();
 
     if (PromOp.getOpcode() == ISD::TRUNCATE ||
         PromOp.getOpcode() == ISD::SIGN_EXTEND ||
@@ -9930,7 +9935,7 @@ SDValue PPCTargetLowering::DAGCombineTru
       if (!isa<ConstantSDNode>(PromOp.getOperand(0)) &&
           PromOp.getOperand(0).getValueType() != MVT::i1) {
         // The operand is not yet ready (see comment below).
-        PromOps.insert(PromOps.begin(), PromOp);
+        PromOpHandles.emplace_front(PromOp);
         continue;
       }
 
@@ -9957,7 +9962,7 @@ SDValue PPCTargetLowering::DAGCombineTru
       // promoted (this should be rare because we're going through the
       // list backward, but if one of the operands has several users in
       // this cluster of to-be-promoted nodes, it is possible).
-      PromOps.insert(PromOps.begin(), PromOp);
+      PromOpHandles.emplace_front(PromOp);
       continue;
     }
 
@@ -10164,13 +10169,17 @@ SDValue PPCTargetLowering::DAGCombineExt
         DAG.getAnyExtOrTrunc(InSrc, dl, N->getValueType(0)));
   }
 
+  std::list<HandleSDNode> PromOpHandles;
+  for (auto &PromOp : PromOps)
+    PromOpHandles.emplace_back(PromOp); 
+
   // Replace all operations (these are all the same, but have a different
   // (promoted) return type). DAG.getNode will validate that the types of
   // a binary operator match, so go through the list in reverse so that
   // we've likely promoted both operands first.
-  while (!PromOps.empty()) {
-    SDValue PromOp = PromOps.back();
-    PromOps.pop_back();
+  while (!PromOpHandles.empty()) {
+    SDValue PromOp = PromOpHandles.back().getValue();
+    PromOpHandles.pop_back();
 
     unsigned C;
     switch (PromOp.getOpcode()) {
@@ -10187,7 +10196,7 @@ SDValue PPCTargetLowering::DAGCombineExt
       // promoted (this should be rare because we're going through the
       // list backward, but if one of the operands has several users in
       // this cluster of to-be-promoted nodes, it is possible).
-      PromOps.insert(PromOps.begin(), PromOp);
+      PromOpHandles.emplace_front(PromOp);
       continue;
     }
 
@@ -10199,7 +10208,7 @@ SDValue PPCTargetLowering::DAGCombineExt
            PromOp.getOperand(0).getValueType() != N->getValueType(0)) ||
           (SelectTruncOp[1].count(PromOp.getNode()) &&
            PromOp.getOperand(1).getValueType() != N->getValueType(0))) {
-        PromOps.insert(PromOps.begin(), PromOp);
+        PromOpHandles.emplace_front(PromOp);
         continue;
       }
     }

Added: llvm/trunk/test/CodeGen/PowerPC/ext-bool-trunc-repl.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/PowerPC/ext-bool-trunc-repl.ll?rev=269272&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/PowerPC/ext-bool-trunc-repl.ll (added)
+++ llvm/trunk/test/CodeGen/PowerPC/ext-bool-trunc-repl.ll Wed May 11 23:00:56 2016
@@ -0,0 +1,38 @@
+; RUN: llc -O0 < %s | FileCheck %s
+target datalayout = "e-m:e-i64:64-n32:64"
+target triple = "powerpc64le-unknown-linux-gnu"
+
+ at c = external global i32, align 4
+ at d = external global [2 x i32], align 4
+
+; Function Attrs: norecurse nounwind
+define void @fn2() #0 {
+; CHECK-LABEL: @fn2
+
+  br i1 undef, label %1, label %10
+
+; <label>:1:                                      ; preds = %0
+  br i1 undef, label %3, label %2
+
+; <label>:2:                                      ; preds = %2, %1
+  br i1 undef, label %3, label %2
+
+; <label>:3:                                      ; preds = %2, %1
+  br i1 undef, label %8, label %4
+
+; <label>:4:                                      ; preds = %4, %3
+  %5 = phi i64 [ %6, %4 ], [ undef, %3 ]
+  %6 = and i64 %5, and (i64 and (i64 and (i64 and (i64 and (i64 and (i64 and (i64 sext (i32 select (i1 icmp slt (i16 zext (i1 icmp eq (i32* getelementptr inbounds ([2 x i32], [2 x i32]* @d, i64 0, i64 1), i32* @c) to i16), i16 0), i32 zext (i1 icmp eq (i32* getelementptr inbounds ([2 x i32], [2 x i32]* @d, i64 0, i64 1), i32* @c) to i32), i32 lshr (i32 zext (i1 icmp eq (i32* getelementptr inbounds ([2 x i32], [2 x i32]* @d, i64 0, i64 1), i32* @c) to i32), i32 6)) to i64), i64 sext (i32 select (i1 icmp slt (i16 zext (i1 icmp eq (i32* getelementptr inbounds ([2 x i32], [2 x i32]* @d, i64 0, i64 1), i32* @c) to i16), i16 0), i32 zext (i1 icmp eq (i32* getelementptr inbounds ([2 x i32], [2 x i32]* @d, i64 0, i64 1), i32* @c) to i32), i32 lshr (i32 zext (i1 icmp eq (i32* getelementptr inbounds ([2 x i32], [2 x i32]* @d, i64 0, i64 1), i32* @c) to i32), i32 6)) to i64)), i64 sext (i32 select (i1 icmp slt (i16 zext (i1 icmp eq (i32* getelementptr inbounds ([2 x i32], [2 x i32]* @d, i64 0,
  i64 1), i32* @c) to i16), i16 0), i32 zext (i1 icmp eq (i32* getelementptr inbounds ([2 x i32], [2 x i32]* @d, i64 0, i64 1), i32* @c) to i32), i32 lshr (i32 zext (i1 icmp eq (i32* getelementptr inbounds ([2 x i32], [2 x i32]* @d, i64 0, i64 1), i32* @c) to i32), i32 6)) to i64)), i64 sext (i32 select (i1 icmp slt (i16 zext (i1 icmp eq (i32* getelementptr inbounds ([2 x i32], [2 x i32]* @d, i64 0, i64 1), i32* @c) to i16), i16 0), i32 zext (i1 icmp eq (i32* getelementptr inbounds ([2 x i32], [2 x i32]* @d, i64 0, i64 1), i32* @c) to i32), i32 lshr (i32 zext (i1 icmp eq (i32* getelementptr inbounds ([2 x i32], [2 x i32]* @d, i64 0, i64 1), i32* @c) to i32), i32 6)) to i64)), i64 sext (i32 select (i1 icmp slt (i16 zext (i1 icmp eq (i32* getelementptr inbounds ([2 x i32], [2 x i32]* @d, i64 0, i64 1), i32* @c) to i16), i16 0), i32 zext (i1 icmp eq (i32* getelementptr inbounds ([2 x i32], [2 x i32]* @d, i64 0, i64 1), i32* @c) to i32), i32 lshr (i32 zext (i1 icmp eq (i32* getelementptr
  inbounds ([2 x i32], [2 x i32]* @d, i64 0, i64 1), i32* @c) to i32), i32 6)) to i64)), i64 sext (i32 select (i1 icmp slt (i16 zext (i1 icmp eq (i32* getelementptr inbounds ([2 x i32], [2 x i32]* @d, i64 0, i64 1), i32* @c) to i16), i16 0), i32 zext (i1 icmp eq (i32* getelementptr inbounds ([2 x i32], [2 x i32]* @d, i64 0, i64 1), i32* @c) to i32), i32 lshr (i32 zext (i1 icmp eq (i32* getelementptr inbounds ([2 x i32], [2 x i32]* @d, i64 0, i64 1), i32* @c) to i32), i32 6)) to i64)), i64 sext (i32 select (i1 icmp slt (i16 zext (i1 icmp eq (i32* getelementptr inbounds ([2 x i32], [2 x i32]* @d, i64 0, i64 1), i32* @c) to i16), i16 0), i32 zext (i1 icmp eq (i32* getelementptr inbounds ([2 x i32], [2 x i32]* @d, i64 0, i64 1), i32* @c) to i32), i32 lshr (i32 zext (i1 icmp eq (i32* getelementptr inbounds ([2 x i32], [2 x i32]* @d, i64 0, i64 1), i32* @c) to i32), i32 6)) to i64)), i64 sext (i32 select (i1 icmp slt (i16 zext (i1 icmp eq (i32* getelementptr inbounds ([2 x i32], [2 x i32]*
  @d, i64 0, i64 1), i32* @c) to i16), i16 0), i32 zext (i1 icmp eq (i32* getelementptr inbounds ([2 x i32], [2 x i32]* @d, i64 0, i64 1), i32* @c) to i32), i32 lshr (i32 zext (i1 icmp eq (i32* getelementptr inbounds ([2 x i32], [2 x i32]* @d, i64 0, i64 1), i32* @c) to i32), i32 6)) to i64))
+  %7 = icmp slt i32 undef, 6
+  br i1 %7, label %4, label %8
+
+; <label>:8:                                      ; preds = %4, %3
+  %9 = phi i64 [ undef, %3 ], [ %6, %4 ]
+  br label %10
+
+; <label>:10:                                     ; preds = %8, %0
+  ret void
+}
+
+attributes #0 = { norecurse nounwind "target-cpu"="ppc64le" }
+




More information about the llvm-commits mailing list