IndVarSimplify: check if loop invariant expansion can trap
authorDavid Majnemer <david.majnemer@gmail.com>
Tue, 4 Jun 2013 17:51:58 +0000 (17:51 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Tue, 4 Jun 2013 17:51:58 +0000 (17:51 +0000)
IndVarSimplify is willing to move divide instructions outside of their
loop bodies if they are invariant of the loop.  However, it may not be
safe to expand them if we do not know if they can trap.

Instead, check to see if it is not safe to expand the instruction and
skip the expansion.

This fixes PR16041.

Testcase by Rafael Ávila de Espíndola.

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

lib/Transforms/Scalar/IndVarSimplify.cpp
test/Transforms/IndVarSimplify/udiv-invariant-but-traps.ll [new file with mode: 0644]

index 8e76c78f5ac334212d551440b1ea21033cbeff9a..df11e92c9ed7cd6420753e6ad468f7d8fdc2f509 100644 (file)
@@ -532,7 +532,7 @@ void IndVarSimplify::RewriteLoopExitValues(Loop *L, SCEVExpander &Rewriter) {
         // and varies predictably *inside* the loop.  Evaluate the value it
         // contains when the loop exits, if possible.
         const SCEV *ExitValue = SE->getSCEVAtScope(Inst, L->getParentLoop());
-        if (!SE->isLoopInvariant(ExitValue, L))
+        if (!SE->isLoopInvariant(ExitValue, L) || !isSafeToExpand(ExitValue))
           continue;
 
         // Computing the value outside of the loop brings no benefit if :
diff --git a/test/Transforms/IndVarSimplify/udiv-invariant-but-traps.ll b/test/Transforms/IndVarSimplify/udiv-invariant-but-traps.ll
new file mode 100644 (file)
index 0000000..b2d2629
--- /dev/null
@@ -0,0 +1,32 @@
+; RUN: opt -indvars -S < %s | FileCheck %s
+
+@b = common global i32 0, align 4
+
+define i32 @foo(i32 %x, i1 %y) {
+bb0:
+  br label %bb1
+
+bb1:
+  br i1 %y, label %bb14, label %bb8
+
+bb8:
+  %i = phi i64 [ %i.next, %bb8 ], [ 0, %bb1 ]
+  %i.next = add i64 %i, 1
+  %div = udiv i32 1, %x
+  %c = icmp eq i64 %i.next, 6
+  br i1 %c, label %bb11, label %bb8
+
+bb11:
+  br i1 %y, label %bb1, label %bb13
+
+bb13:
+  store i32 %div, i32* @b, align 4
+  br label %bb14
+
+bb14:
+  ret i32 0
+}
+
+; CHECK: @foo
+; CHECK: bb8:
+; CHECK: udiv