diff options
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.ll | 108 |
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 +} + |