Index: llvm/lib/Transforms/Utils/LoopUtils.cpp =================================================================== --- llvm/lib/Transforms/Utils/LoopUtils.cpp +++ llvm/lib/Transforms/Utils/LoopUtils.cpp @@ -1246,6 +1246,22 @@ return true; } +/// Checks if it is safe to call InductionDescriptor::isInductionPHI for \p Phi, +/// and returns true if this Phi is an induction phi in the loop. When +/// isInductionPHI returns true, \p ID will be also be set by isInductionPHI. +bool checkIsIndPhi(PHINode *Phi, Loop *L, ScalarEvolution *SE, + InductionDescriptor &ID) { + if (!Phi) + return false; + if (!L->getLoopPreheader()) + return false; + if (Phi->getParent() != L->getHeader()) + return false; + if (!InductionDescriptor::isInductionPHI(Phi, L, SE, ID)) + return false; + return true; +} + int llvm::rewriteLoopExitValues(Loop *L, LoopInfo *LI, TargetLibraryInfo *TLI, ScalarEvolution *SE, const TargetTransformInfo *TTI, @@ -1306,10 +1322,7 @@ InductionDescriptor ID; PHINode *IndPhi = dyn_cast(Inst); if (IndPhi) { - if (IndPhi->getParent() != L->getHeader()) - continue; - // Do not consider non induction phis. - if (!InductionDescriptor::isInductionPHI(IndPhi, L, SE, ID)) + if (!checkIsIndPhi(IndPhi, L, SE, ID)) continue; // This is an induction PHI. Check that the only users are PHI // nodes, and induction variable update binary operators. @@ -1330,12 +1343,8 @@ continue; if (llvm::any_of(Inst->users(), [&](User *U) { PHINode *Phi = dyn_cast(U); - if (!Phi) + if (Phi != PN && !checkIsIndPhi(Phi, L, SE, ID)) return true; - if (Phi->getParent() == L->getHeader()) { - if (!InductionDescriptor::isInductionPHI(Phi, L, SE, ID)) - return true; - } return false; })) continue; Index: llvm/test/Transforms/LoopStrengthReduce/remove_scev_indvars.ll =================================================================== --- llvm/test/Transforms/LoopStrengthReduce/remove_scev_indvars.ll +++ llvm/test/Transforms/LoopStrengthReduce/remove_scev_indvars.ll @@ -91,3 +91,33 @@ dead: ; No predecessors! br label %for.cond6403 } + + +; Check that this doesn't crash +%struct.kernfs_node = type { %struct.kernfs_node* } + +@kernfs_path_from_node_locked_kn_to = dso_local local_unnamed_addr global %struct.kernfs_node zeroinitializer, align 8 +@kernfs_path_from_node_locked___trans_tmp_1 = dso_local local_unnamed_addr global i32 0, align 4 + +define dso_local void @kernfs_path_from_node() { +entry: + callbr void asm sideeffect "", "i"(i8* blockaddress(@kernfs_path_from_node, %while.body)) + to label %asm.fallthrough [label %while.body] + +asm.fallthrough: ; preds = %entry + br label %while.body + +while.body: ; preds = %entry, %asm.fallthrough, %while.body + %depth.04 = phi i32 [ %inc, %while.body ], [ undef, %asm.fallthrough ], [ undef, %entry ] + %to.03 = phi %struct.kernfs_node* [ %0, %while.body ], [ @kernfs_path_from_node_locked_kn_to, %asm.fallthrough ], [ @kernfs_path_from_node_locked_kn_to, %entry ] + %inc = add i32 %depth.04, 1 + %parent = getelementptr inbounds %struct.kernfs_node, %struct.kernfs_node* %to.03, i64 0, i32 0 + %0 = load %struct.kernfs_node*, %struct.kernfs_node** %parent, align 8 + %tobool.not = icmp eq %struct.kernfs_node* %0, null + br i1 %tobool.not, label %while.end, label %while.body + +while.end: ; preds = %while.body + %inc.lcssa = phi i32 [ %inc, %while.body ] + store i32 %inc.lcssa, i32* @kernfs_path_from_node_locked___trans_tmp_1, align 4 + ret void +}