From: Sanjoy Das <sanjoy@playingwithpointers.com>
Date: Sat, 31 Oct 2015 23:21:40 +0000 (+0000)
Subject: [SCEV] Don't create SCEV expressions that break LCSSA
X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=2b19a081101fb6af3ee2ae3726e4dec6b3a04cda;p=oota-llvm.git

[SCEV] Don't create SCEV expressions that break LCSSA

Prevent `createNodeFromSelectLikePHI` from creating SCEV expressions
that break LCSSA.

A better fix for the same issue is to teach SCEVExpander to not break
LCSSA by inserting PHI nodes at appropriate places.  That's planned for
the future.

Fixes PR25360.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@251756 91177308-0d34-0410-b5e6-96231b3b80d8
---

diff --git a/lib/Analysis/ScalarEvolution.cpp b/lib/Analysis/ScalarEvolution.cpp
index a24b154ab96..e7380682d9f 100644
--- a/lib/Analysis/ScalarEvolution.cpp
+++ b/lib/Analysis/ScalarEvolution.cpp
@@ -3943,6 +3943,11 @@ const SCEV *ScalarEvolution::createNodeFromSelectLikePHI(PHINode *PN) {
   if (PN->getNumIncomingValues() == 2) {
     const Loop *L = LI.getLoopFor(PN->getParent());
 
+    // We don't want to break LCSSA, even in a SCEV expression tree.
+    for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i)
+      if (LI.getLoopFor(PN->getIncomingBlock(i)) != L)
+        return nullptr;
+
     // Try to match
     //
     //  br %cond, label %left, label %right
diff --git a/test/Analysis/ScalarEvolution/smax-br-phi-idioms.ll b/test/Analysis/ScalarEvolution/smax-br-phi-idioms.ll
index 2657982979d..500f3e16c8f 100644
--- a/test/Analysis/ScalarEvolution/smax-br-phi-idioms.ll
+++ b/test/Analysis/ScalarEvolution/smax-br-phi-idioms.ll
@@ -102,3 +102,27 @@ define i32 @f4(i32 %x, i32 %init, i32 %lim) {
 ; CHECK-NEXT:  -->  %v U: full-set S: full-set
   ret i32 %v
 }
+
+define i32 @f5(i32* %val) {
+; CHECK-LABEL: Classifying expressions for: @f5
+entry:
+  br label %for.end
+
+for.condt:
+  br i1 true, label %for.cond.0, label %for.end
+
+for.end:
+  %inc = load i32, i32* %val
+  br i1 false, label %for.condt, label %for.cond.0
+
+for.cond.0:
+  %init = phi i32 [ 0, %for.condt ], [ %inc, %for.end ]
+
+; CHECK:  %init = phi i32 [ 0, %for.condt ], [ %inc, %for.end ]
+; CHECK-NEXT:  -->  %init U: full-set S: full-set
+
+; Matching "through" %init will break LCSSA at the SCEV expression
+; level.
+
+  ret i32 %init
+}
diff --git a/test/Transforms/IndVarSimplify/pr25360.ll b/test/Transforms/IndVarSimplify/pr25360.ll
new file mode 100644
index 00000000000..9f6df7051ea
--- /dev/null
+++ b/test/Transforms/IndVarSimplify/pr25360.ll
@@ -0,0 +1,33 @@
+; RUN: opt -indvars -S < %s | FileCheck %s
+
+
+; Ensure that does not crash
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @f() {
+; CHECK-LABEL: @f(
+entry:
+  br label %for.end
+
+for.condt:                         ; preds = %for.end
+  br i1 true, label %for.cond.0, label %for.end
+
+for.end:                                          ; preds = %for.body.3
+  %inc = select i1 undef, i32 2, i32 1
+  br i1 false, label %for.condt, label %for.cond.0
+
+for.cond.0:                       ; preds = %for.end, %for.condt
+  %init = phi i32 [ 0, %for.condt ], [ %inc, %for.end ]
+  br i1 true, label %for.end.13, label %for.body.9
+
+for.body.9:                                       ; preds = %for.body.9, %for.cond.0
+  %p1.addr.22 = phi i32 [ %inc10, %for.body.9 ], [ %init, %for.cond.0 ]
+  %inc10 = add i32 %p1.addr.22, 1
+  br i1 true, label %for.end.13, label %for.body.9
+
+for.end.13:                                       ; preds = %for.cond.7.for.end.13_crit_edge, %for.cond.0
+  %p1.addr.2.lcssa = phi i32 [ %inc10, %for.body.9 ], [ %init, %for.cond.0 ]
+  ret void
+}