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