Index: lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -9593,6 +9593,10 @@ return false; } + // Caches for hasPredecessorHelper. + SmallPtrSet Visited; + SmallVector 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 @@ 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 @@ // Now check for #3 and #4. bool RealUse = false; - // Caches for hasPredecessorHelper - SmallPtrSet Visited; - SmallVector Worklist; - for (SDNode *Use : Ptr.getNode()->uses()) { if (Use == N) continue; Index: lib/CodeGen/SelectionDAG/SelectionDAG.cpp =================================================================== --- lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -6949,13 +6949,16 @@ // 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; Index: test/CodeGen/PowerPC/combine-to-pre-index-store-crash.ll =================================================================== --- /dev/null +++ test/CodeGen/PowerPC/combine-to-pre-index-store-crash.ll @@ -0,0 +1,20 @@ +; RUN: llc < %s +target datalayout = "e-m:e-i64:64-n32:64" +target triple = "powerpc64le-grtev4-linux-gnu" + +%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()