summaryrefslogtreecommitdiffstats
path: root/llvm/test/Transforms/LoopInterchange
diff options
context:
space:
mode:
authorFlorian Hahn <flo@fhahn.com>2019-12-04 17:26:29 +0000
committerFlorian Hahn <flo@fhahn.com>2019-12-04 17:46:01 +0000
commite8a5c17211339a747d2bf5b0df708c8392121e6d (patch)
treeda014a5c59fe8a6b106a1b01b05284e67d5869ae /llvm/test/Transforms/LoopInterchange
parenta249551bb232414b68525d40cd7bae617293c67b (diff)
downloadbcm5719-llvm-e8a5c17211339a747d2bf5b0df708c8392121e6d.tar.gz
bcm5719-llvm-e8a5c17211339a747d2bf5b0df708c8392121e6d.zip
[LoopInterchange] Improve inner exit loop safety checks.
The PHI node checks for inner loop exits are too permissive currently. As indicated by an existing comment, we should only allow LCSSA PHI nodes that are part of reductions or are only used outside of the loop nest. We ensure this by checking the users of the LCSSA PHIs. Specifically, it is not safe to use an exiting value from the inner loop in the latch of the outer loop. It also moves the inner loop exit check before the outer loop exit check. Fixes PR43473. Reviewers: efriedma, mcrosier Reviewed By: efriedma Differential Revision: https://reviews.llvm.org/D68144
Diffstat (limited to 'llvm/test/Transforms/LoopInterchange')
-rw-r--r--llvm/test/Transforms/LoopInterchange/pr43473-invalid-lcssa-phis-in-inner-exit.ll108
1 files changed, 108 insertions, 0 deletions
diff --git a/llvm/test/Transforms/LoopInterchange/pr43473-invalid-lcssa-phis-in-inner-exit.ll b/llvm/test/Transforms/LoopInterchange/pr43473-invalid-lcssa-phis-in-inner-exit.ll
new file mode 100644
index 00000000000..9ae5f42e1ae
--- /dev/null
+++ b/llvm/test/Transforms/LoopInterchange/pr43473-invalid-lcssa-phis-in-inner-exit.ll
@@ -0,0 +1,108 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -loop-interchange -S < %s | FileCheck %s
+
+; Test cases for PR43473.
+
+; In the 2 test cases below, we have a LCSSA PHI in the inner loop exit, which
+; is used in the outer loop latch. This is not supported.
+
+define void @test1() {
+; CHECK-LABEL: @test1(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br label [[OUTER_HEADER:%.*]]
+; CHECK: outer.header:
+; CHECK-NEXT: [[OUTER_IV:%.*]] = phi i64 [ undef, [[ENTRY:%.*]] ], [ [[OUTER_IV_NEXT:%.*]], [[OUTER_LATCH:%.*]] ]
+; CHECK-NEXT: [[IDX:%.*]] = getelementptr inbounds double, double* undef, i64 [[OUTER_IV]]
+; CHECK-NEXT: br label [[INNER:%.*]]
+; CHECK: inner:
+; CHECK-NEXT: [[INNER_IV:%.*]] = phi i64 [ 0, [[OUTER_HEADER]] ], [ [[INNER_IV_NEXT:%.*]], [[INNER]] ]
+; CHECK-NEXT: [[TMP0:%.*]] = load double, double* [[IDX]], align 8
+; CHECK-NEXT: store double undef, double* [[IDX]], align 8
+; CHECK-NEXT: [[INNER_IV_NEXT]] = add nuw nsw i64 [[INNER_IV]], 1
+; CHECK-NEXT: br i1 false, label [[INNER]], label [[OUTER_LATCH]]
+; CHECK: outer.latch:
+; CHECK-NEXT: [[INC43_LCSSA_WIDE_US:%.*]] = phi i64 [ [[INNER_IV_NEXT]], [[INNER]] ]
+; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[INC43_LCSSA_WIDE_US]] to i32
+; CHECK-NEXT: [[OUTER_IV_NEXT]] = add nsw i64 [[OUTER_IV]], 1
+; CHECK-NEXT: br i1 false, label [[OUTER_HEADER]], label [[OUTER_EXIT:%.*]]
+; CHECK: outer.exit:
+; CHECK-NEXT: ret void
+;
+entry:
+ br label %outer.header
+
+outer.header: ; preds = %for.cond26.for.end44_crit_edge.us, %entry
+ %outer.iv = phi i64 [ undef, %entry ], [ %outer.iv.next, %outer.latch ]
+ %idx = getelementptr inbounds double, double* undef, i64 %outer.iv
+ br label %inner
+
+inner: ; preds = %for.body28.us, %for.body25.us
+ %inner.iv = phi i64 [ 0, %outer.header ], [ %inner.iv.next, %inner ]
+ %0 = load double, double* %idx, align 8
+ store double undef, double* %idx, align 8
+ %inner.iv.next = add nuw nsw i64 %inner.iv, 1
+ br i1 undef, label %inner, label %outer.latch
+
+outer.latch: ; preds = %inner
+ %inc43.lcssa.wide.us = phi i64 [ %inner.iv.next, %inner ]
+ %1 = trunc i64 %inc43.lcssa.wide.us to i32
+ %outer.iv.next = add nsw i64 %outer.iv, 1
+ br i1 undef, label %outer.header, label %outer.exit
+
+outer.exit: ; preds = %for.cond26.for.end44_crit_edge.us
+ ret void
+}
+
+; Same as @test1, but with a dedicated inner loop exit block.
+define void @test2() {
+; CHECK-LABEL: @test2(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br label [[OUTER_HEADER:%.*]]
+; CHECK: outer.header:
+; CHECK-NEXT: [[OUTER_IV:%.*]] = phi i64 [ undef, [[ENTRY:%.*]] ], [ [[OUTER_IV_NEXT:%.*]], [[OUTER_LATCH:%.*]] ]
+; CHECK-NEXT: [[IDX:%.*]] = getelementptr inbounds double, double* undef, i64 [[OUTER_IV]]
+; CHECK-NEXT: br label [[INNER:%.*]]
+; CHECK: inner:
+; CHECK-NEXT: [[INNER_IV:%.*]] = phi i64 [ 0, [[OUTER_HEADER]] ], [ [[INNER_IV_NEXT:%.*]], [[INNER]] ]
+; CHECK-NEXT: [[TMP0:%.*]] = load double, double* [[IDX]], align 8
+; CHECK-NEXT: store double undef, double* [[IDX]], align 8
+; CHECK-NEXT: [[INNER_IV_NEXT]] = add nuw nsw i64 [[INNER_IV]], 1
+; CHECK-NEXT: br i1 false, label [[INNER]], label [[INNER_EXIT:%.*]]
+; CHECK: inner.exit:
+; CHECK-NEXT: [[INC43_LCSSA_WIDE_US:%.*]] = phi i64 [ [[INNER_IV_NEXT]], [[INNER]] ]
+; CHECK-NEXT: br label [[OUTER_LATCH]]
+; CHECK: outer.latch:
+; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[INC43_LCSSA_WIDE_US]] to i32
+; CHECK-NEXT: [[OUTER_IV_NEXT]] = add nsw i64 [[OUTER_IV]], 1
+; CHECK-NEXT: br i1 false, label [[OUTER_HEADER]], label [[OUTER_EXIT:%.*]]
+; CHECK: outer.exit:
+; CHECK-NEXT: ret void
+;
+entry:
+ br label %outer.header
+
+outer.header: ; preds = %for.cond26.for.end44_crit_edge.us, %entry
+ %outer.iv = phi i64 [ undef, %entry ], [ %outer.iv.next, %outer.latch ]
+ %idx = getelementptr inbounds double, double* undef, i64 %outer.iv
+ br label %inner
+
+inner: ; preds = %for.body28.us, %for.body25.us
+ %inner.iv = phi i64 [ 0, %outer.header ], [ %inner.iv.next, %inner ]
+ %0 = load double, double* %idx, align 8
+ store double undef, double* %idx, align 8
+ %inner.iv.next = add nuw nsw i64 %inner.iv, 1
+ br i1 undef, label %inner, label %inner.exit
+
+inner.exit:
+ %inc43.lcssa.wide.us = phi i64 [ %inner.iv.next, %inner ]
+ br label %outer.latch
+
+outer.latch: ; preds = %inner
+ %1 = trunc i64 %inc43.lcssa.wide.us to i32
+ %outer.iv.next = add nsw i64 %outer.iv, 1
+ br i1 undef, label %outer.header, label %outer.exit
+
+outer.exit: ; preds = %for.cond26.for.end44_crit_edge.us
+ ret void
+}
+
OpenPOWER on IntegriCloud