1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -loop-interchange -S < %s | FileCheck %s 3 4; Test cases for PR43473. 5 6; In the 2 test cases below, we have a LCSSA PHI in the inner loop exit, which 7; is used in the outer loop latch. This is not supported. 8 9define void @test1() { 10; CHECK-LABEL: @test1( 11; CHECK-NEXT: entry: 12; CHECK-NEXT: br label [[OUTER_HEADER:%.*]] 13; CHECK: outer.header: 14; CHECK-NEXT: [[OUTER_IV:%.*]] = phi i64 [ undef, [[ENTRY:%.*]] ], [ [[OUTER_IV_NEXT:%.*]], [[OUTER_LATCH:%.*]] ] 15; CHECK-NEXT: [[IDX:%.*]] = getelementptr inbounds double, double* undef, i64 [[OUTER_IV]] 16; CHECK-NEXT: br label [[INNER:%.*]] 17; CHECK: inner: 18; CHECK-NEXT: [[INNER_IV:%.*]] = phi i64 [ 0, [[OUTER_HEADER]] ], [ [[INNER_IV_NEXT:%.*]], [[INNER]] ] 19; CHECK-NEXT: [[TMP0:%.*]] = load double, double* [[IDX]], align 8 20; CHECK-NEXT: store double undef, double* [[IDX]], align 8 21; CHECK-NEXT: [[INNER_IV_NEXT]] = add nuw nsw i64 [[INNER_IV]], 1 22; CHECK-NEXT: br i1 false, label [[INNER]], label [[OUTER_LATCH]] 23; CHECK: outer.latch: 24; CHECK-NEXT: [[INC43_LCSSA_WIDE_US:%.*]] = phi i64 [ [[INNER_IV_NEXT]], [[INNER]] ] 25; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[INC43_LCSSA_WIDE_US]] to i32 26; CHECK-NEXT: [[OUTER_IV_NEXT]] = add nsw i64 [[OUTER_IV]], 1 27; CHECK-NEXT: br i1 false, label [[OUTER_HEADER]], label [[OUTER_EXIT:%.*]] 28; CHECK: outer.exit: 29; CHECK-NEXT: ret void 30; 31entry: 32 br label %outer.header 33 34outer.header: ; preds = %for.cond26.for.end44_crit_edge.us, %entry 35 %outer.iv = phi i64 [ undef, %entry ], [ %outer.iv.next, %outer.latch ] 36 %idx = getelementptr inbounds double, double* undef, i64 %outer.iv 37 br label %inner 38 39inner: ; preds = %for.body28.us, %for.body25.us 40 %inner.iv = phi i64 [ 0, %outer.header ], [ %inner.iv.next, %inner ] 41 %0 = load double, double* %idx, align 8 42 store double undef, double* %idx, align 8 43 %inner.iv.next = add nuw nsw i64 %inner.iv, 1 44 br i1 undef, label %inner, label %outer.latch 45 46outer.latch: ; preds = %inner 47 %inc43.lcssa.wide.us = phi i64 [ %inner.iv.next, %inner ] 48 %1 = trunc i64 %inc43.lcssa.wide.us to i32 49 %outer.iv.next = add nsw i64 %outer.iv, 1 50 br i1 undef, label %outer.header, label %outer.exit 51 52outer.exit: ; preds = %for.cond26.for.end44_crit_edge.us 53 ret void 54} 55 56; Same as @test1, but with a dedicated inner loop exit block. 57define void @test2() { 58; CHECK-LABEL: @test2( 59; CHECK-NEXT: entry: 60; CHECK-NEXT: br label [[OUTER_HEADER:%.*]] 61; CHECK: outer.header: 62; CHECK-NEXT: [[OUTER_IV:%.*]] = phi i64 [ undef, [[ENTRY:%.*]] ], [ [[OUTER_IV_NEXT:%.*]], [[OUTER_LATCH:%.*]] ] 63; CHECK-NEXT: [[IDX:%.*]] = getelementptr inbounds double, double* undef, i64 [[OUTER_IV]] 64; CHECK-NEXT: br label [[INNER:%.*]] 65; CHECK: inner: 66; CHECK-NEXT: [[INNER_IV:%.*]] = phi i64 [ 0, [[OUTER_HEADER]] ], [ [[INNER_IV_NEXT:%.*]], [[INNER]] ] 67; CHECK-NEXT: [[TMP0:%.*]] = load double, double* [[IDX]], align 8 68; CHECK-NEXT: store double undef, double* [[IDX]], align 8 69; CHECK-NEXT: [[INNER_IV_NEXT]] = add nuw nsw i64 [[INNER_IV]], 1 70; CHECK-NEXT: br i1 false, label [[INNER]], label [[INNER_EXIT:%.*]] 71; CHECK: inner.exit: 72; CHECK-NEXT: [[INC43_LCSSA_WIDE_US:%.*]] = phi i64 [ [[INNER_IV_NEXT]], [[INNER]] ] 73; CHECK-NEXT: br label [[OUTER_LATCH]] 74; CHECK: outer.latch: 75; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[INC43_LCSSA_WIDE_US]] to i32 76; CHECK-NEXT: [[OUTER_IV_NEXT]] = add nsw i64 [[OUTER_IV]], 1 77; CHECK-NEXT: br i1 false, label [[OUTER_HEADER]], label [[OUTER_EXIT:%.*]] 78; CHECK: outer.exit: 79; CHECK-NEXT: ret void 80; 81entry: 82 br label %outer.header 83 84outer.header: ; preds = %for.cond26.for.end44_crit_edge.us, %entry 85 %outer.iv = phi i64 [ undef, %entry ], [ %outer.iv.next, %outer.latch ] 86 %idx = getelementptr inbounds double, double* undef, i64 %outer.iv 87 br label %inner 88 89inner: ; preds = %for.body28.us, %for.body25.us 90 %inner.iv = phi i64 [ 0, %outer.header ], [ %inner.iv.next, %inner ] 91 %0 = load double, double* %idx, align 8 92 store double undef, double* %idx, align 8 93 %inner.iv.next = add nuw nsw i64 %inner.iv, 1 94 br i1 undef, label %inner, label %inner.exit 95 96inner.exit: 97 %inc43.lcssa.wide.us = phi i64 [ %inner.iv.next, %inner ] 98 br label %outer.latch 99 100outer.latch: ; preds = %inner 101 %1 = trunc i64 %inc43.lcssa.wide.us to i32 102 %outer.iv.next = add nsw i64 %outer.iv, 1 103 br i1 undef, label %outer.header, label %outer.exit 104 105outer.exit: ; preds = %for.cond26.for.end44_crit_edge.us 106 ret void 107} 108 109