summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp10
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp5
-rw-r--r--llvm/test/CodeGen/PowerPC/combine-to-pre-index-store-crash.ll25
3 files changed, 34 insertions, 6 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index be306c09650..bba223ec200 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -9593,6 +9593,10 @@ bool DAGCombiner::CombineToPreIndexedLoadStore(SDNode *N) {
return false;
}
+ // Caches for hasPredecessorHelper.
+ SmallPtrSet<const SDNode *, 32> Visited;
+ SmallVector<const SDNode *, 16> Worklist;
+
// If the offset is a constant, there may be other adds of constants that
// can be folded with this one. We should do this to avoid having to keep
// a copy of the original base pointer.
@@ -9607,7 +9611,7 @@ bool DAGCombiner::CombineToPreIndexedLoadStore(SDNode *N) {
if (Use.getUser() == Ptr.getNode() || Use != BasePtr)
continue;
- if (Use.getUser()->isPredecessorOf(N))
+ if (N->hasPredecessorHelper(Use.getUser(), Visited, Worklist))
continue;
if (Use.getUser()->getOpcode() != ISD::ADD &&
@@ -9637,10 +9641,6 @@ bool DAGCombiner::CombineToPreIndexedLoadStore(SDNode *N) {
// Now check for #3 and #4.
bool RealUse = false;
- // Caches for hasPredecessorHelper
- SmallPtrSet<const SDNode *, 32> Visited;
- SmallVector<const SDNode *, 16> Worklist;
-
for (SDNode *Use : Ptr.getNode()->uses()) {
if (Use == N)
continue;
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 66f47ac46e1..0b9522e94d4 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -6949,13 +6949,16 @@ SDNode::hasPredecessorHelper(const SDNode *N,
// Haven't visited N yet. Continue the search.
while (!Worklist.empty()) {
const SDNode *M = Worklist.pop_back_val();
+ bool Found = false;
for (const SDValue &OpV : M->op_values()) {
SDNode *Op = OpV.getNode();
if (Visited.insert(Op).second)
Worklist.push_back(Op);
if (Op == N)
- return true;
+ Found = true;
}
+ if (Found)
+ return true;
}
return false;
diff --git a/llvm/test/CodeGen/PowerPC/combine-to-pre-index-store-crash.ll b/llvm/test/CodeGen/PowerPC/combine-to-pre-index-store-crash.ll
new file mode 100644
index 00000000000..9bd0dd874b4
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/combine-to-pre-index-store-crash.ll
@@ -0,0 +1,25 @@
+; RUN: llc -mtriple=powerpc64le-unknown-linux-gnu < %s | FileCheck %s
+
+; CHECK-LABEL: TestFoo:
+; CHECK: std
+; CHECK: bl TestBar
+; CHECK: stbu
+; CHECK: std
+; CHECK: blr
+
+%StructA = type <{ i64, { i64, i64 }, { i64, i64 } }>
+
+define void @TestFoo(%StructA* %this) {
+ %tmp = getelementptr inbounds %StructA, %StructA* %this, i64 0, i32 1
+ %tmp11 = getelementptr inbounds %StructA, %StructA* %this, i64 0, i32 1, i32 1
+ %tmp12 = bitcast { i64, i64 }* %tmp to i64**
+ store i64* %tmp11, i64** %tmp12
+ call void @TestBar()
+ %tmp13 = getelementptr inbounds %StructA, %StructA* %this, i64 0, i32 2, i32 1
+ store i64* %tmp13, i64** undef
+ %.cast.i.i.i = bitcast i64* %tmp13 to i8*
+ store i8 0, i8* %.cast.i.i.i
+ ret void
+}
+
+declare void @TestBar()
OpenPOWER on IntegriCloud