summaryrefslogtreecommitdiffstats
path: root/llvm/test/Transforms/LoopInterchange/pr43473-invalid-lcssa-phis-in-inner-exit.ll
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/test/Transforms/LoopInterchange/pr43473-invalid-lcssa-phis-in-inner-exit.ll')
-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