From 308a7c7ed441fe5637891345dc3c2a80c56dd217 Mon Sep 17 00:00:00 2001 From: Silviu Baranga Date: Tue, 3 Nov 2015 16:27:04 +0000 Subject: [PATCH] Fix PR25372 - teach replaceCongruentPHIs to handle cases where SE evaluates a PHI to a SCEVConstant Summary: Since now Scalar Evolution can create non-add rec expressions for PHI nodes, it can also create SCEVConstant expressions. This will confuse replaceCongruentPHIs, which previously relied on the fact that SCEV could not produce constants in this case. We will now replace the node with a constant in these cases - or avoid processing the Phi in case of a type mismatch. Reviewers: sanjoy Subscribers: llvm-commits, majnemer Differential Revision: http://reviews.llvm.org/D14230 llvm-svn: 251938 --- llvm/lib/Analysis/ScalarEvolutionExpander.cpp | 15 ++++++++- .../Transforms/IndVarSimplify/const_phi.ll | 33 +++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 llvm/test/Transforms/IndVarSimplify/const_phi.ll diff --git a/llvm/lib/Analysis/ScalarEvolutionExpander.cpp b/llvm/lib/Analysis/ScalarEvolutionExpander.cpp index 2c2e5828003a..b3b04ad148fd 100644 --- a/llvm/lib/Analysis/ScalarEvolutionExpander.cpp +++ b/llvm/lib/Analysis/ScalarEvolutionExpander.cpp @@ -1735,9 +1735,22 @@ unsigned SCEVExpander::replaceCongruentIVs(Loop *L, const DominatorTree *DT, PEnd = Phis.end(); PIter != PEnd; ++PIter) { PHINode *Phi = *PIter; + auto SimplifyPHINode = [&](PHINode *PN) -> Value * { + if (Value *V = SimplifyInstruction(PN, DL, &SE.TLI, &SE.DT, &SE.AC)) + return V; + if (!SE.isSCEVable(PN->getType())) + return nullptr; + auto *Const = dyn_cast(SE.getSCEV(PN)); + if (!Const) + return nullptr; + return Const->getValue(); + }; + // Fold constant phis. They may be congruent to other constant phis and // would confuse the logic below that expects proper IVs. - if (Value *V = SimplifyInstruction(Phi, DL, &SE.TLI, &SE.DT, &SE.AC)) { + if (Value *V = SimplifyPHINode(Phi)) { + if (V->getType() != Phi->getType()) + continue; Phi->replaceAllUsesWith(V); DeadInsts.emplace_back(Phi); ++NumElim; diff --git a/llvm/test/Transforms/IndVarSimplify/const_phi.ll b/llvm/test/Transforms/IndVarSimplify/const_phi.ll new file mode 100644 index 000000000000..33dc5514d3cc --- /dev/null +++ b/llvm/test/Transforms/IndVarSimplify/const_phi.ll @@ -0,0 +1,33 @@ +; RUN: opt < %s -indvars -S | FileCheck %s + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" + +; PR25372 +; We can compute the expression of %phi0 and that is a SCEV +; constant. However, instcombine can't deduce this, so we can +; potentially end up trying to handle a constant when replacing +; congruent IVs. + +; CHECK-LABEL: crash +define void @crash() { +entry: + br i1 false, label %not_taken, label %pre + +not_taken: + br label %pre + +pre: +; %phi0.pre and %phi1.pre are evaluated by SCEV to constant 0. + %phi0.pre = phi i32 [ 0, %entry ], [ 2, %not_taken ] + %phi1.pre = phi i32 [ 0, %entry ], [ 1, %not_taken ] + br label %loop + +loop: +; %phi0 and %phi1 are evaluated by SCEV to constant 0. + %phi0 = phi i32 [ 0, %loop ], [ %phi0.pre, %pre ] + %phi1 = phi i32 [ 0, %loop ], [ %phi1.pre, %pre ] + br i1 undef, label %exit, label %loop + +exit: + ret void +}