xref: /llvm-project/llvm/test/Transforms/LoopFusion/triple_loop_nest_inner_guard.ll (revision 055fb7795aa219a3d274d280ec9129784f169f56)
1; RUN: opt -S -passes=loop-fusion < %s 2>&1 | FileCheck %s
2
3; Verify that LoopFusion can fuse two triple-loop nests with guarded inner
4; loops. Loops are in canonical form.
5
6@a = common global [10 x [10 x [10 x i32]]] zeroinitializer
7@b = common global [10 x [10 x [10 x i32]]] zeroinitializer
8@c = common global [10 x [10 x [10 x i32]]] zeroinitializer
9
10; CHECK-LABEL: @triple_loop_nest_inner_guard
11; CHECK: br i1 %{{.*}}, label %[[OUTER_PH:outer1.ph]], label %[[FUNC_EXIT:func_exit]]
12
13; CHECK: [[OUTER_PH]]:
14; CHECK: br label %[[OUTER_BODY_MIDDLE_GUARD:outer1.body.middle1.guard]]
15
16; CHECK: [[OUTER_BODY_MIDDLE_GUARD]]:
17; CHECK: br i1 %{{.*}}, label %[[MIDDLE_PH:middle1.ph]], label %[[OUTER_LATCH:outer2.latch]]
18
19; CHECK: [[MIDDLE_PH]]:
20; CHECK-NEXT: br label %[[MIDDLE_BODY_INNER_GUARD:middle1.body.inner1.guard]]
21
22; CHECK: [[MIDDLE_BODY_INNER_GUARD]]:
23; CHECK: br i1 %{{.*}}, label %[[INNER_PH:inner1.ph]], label %[[MIDDLE_LATCH:middle2.latch]]
24
25; CHECK: [[INNER_PH]]:
26; CHECK-NEXT: br label %[[INNER_BODY:inner1.body]]
27
28; CHECK: [[INNER_BODY]]:
29; First loop body.
30; CHECK: load
31; CHECK: add
32; CHECK: store
33; Second loop body.
34; CHECK: load
35; CHECK: mul
36; CHECK: store
37; CHECK: br i1 %{{.*}}, label %[[INNER_EXIT:inner2.exit]], label %[[INNER_BODY:inner1.body]]
38
39; CHECK: [[INNER_EXIT]]:
40; CHECK-NEXT: br label %[[MIDDLE_LATCH:middle2.latch]]
41
42; CHECK: [[MIDDLE_LATCH]]:
43; CHECK: br i1 %{{.*}}, label %[[MIDDLE_EXIT:middle2.exit]], label %[[MIDDLE_BODY_INNER_GUARD]]
44
45; CHECK: [[MIDDLE_EXIT]]:
46; CHECK-NEXT: br label %[[OUTER_LATCH:outer2.latch]]
47
48; CHECK: [[OUTER_LATCH]]:
49; CHECK: br i1 %{{.*}}, label %[[OUTER_EXIT:outer2.exit]], label %[[OUTER_BODY_MIDDLE_GUARD]]
50
51; CHECK: [[OUTER_EXIT]]:
52; CHECK-NEXT: br label %[[FUNC_EXIT:func_exit]]
53
54; CHECK: [[FUNC_EXIT]]:
55; CHECK-NEXT: ret
56
57define i32 @triple_loop_nest_inner_guard(i32 %m, i32 %n, i32 %M, i32 %N) {
58entry:
59  %cmp101 = icmp sgt i32 %m, 0
60  br i1 %cmp101, label %outer1.ph, label %func_exit
61
62outer1.ph:
63  %cmp298 = icmp sgt i32 %n, 0
64  %cmp696 = icmp sgt i32 %M, 0
65  %wide.trip.count122 = zext i32 %m to i64
66  %wide.trip.count118 = zext i32 %n to i64
67  %wide.trip.count114 = zext i32 %M to i64
68  br label %outer1.body.middle1.guard
69
70outer1.body.middle1.guard:
71  %iv120 = phi i64 [ 0, %outer1.ph ], [ %iv.next121, %outer1.latch ]
72  br i1 %cmp298, label %middle1.ph, label %outer1.latch
73
74middle1.ph:
75  br label %middle1.body.inner1.guard
76
77middle1.body.inner1.guard:
78  %iv116 = phi i64 [ %iv.next117, %middle1.latch ], [ 0, %middle1.ph ]
79  br i1 %cmp696, label %inner1.ph, label %middle1.latch
80
81inner1.ph:
82  br label %inner1.body
83
84inner1.body:
85  %iv112 = phi i64 [ %iv.next113, %inner1.body ], [ 0, %inner1.ph ]
86  %idx12 = getelementptr inbounds [10 x [10 x [10 x i32]]], ptr @a, i64 0, i64 %iv120, i64 %iv116, i64 %iv112
87  %0 = load i32, ptr %idx12
88  %add = add nsw i32 %0, 2
89  %idx18 = getelementptr inbounds [10 x [10 x [10 x i32]]], ptr @b, i64 0, i64 %iv120, i64 %iv116, i64 %iv112
90  store i32 %add, ptr %idx18
91  %iv.next113 = add nuw nsw i64 %iv112, 1
92  %exitcond115 = icmp eq i64 %iv.next113, %wide.trip.count114
93  br i1 %exitcond115, label %inner1.exit, label %inner1.body
94
95inner1.exit:
96  br label %middle1.latch
97
98middle1.latch:
99  %iv.next117 = add nuw nsw i64 %iv116, 1
100  %exitcond119 = icmp eq i64 %iv.next117, %wide.trip.count118
101  br i1 %exitcond119, label %middle1.exit, label %middle1.body.inner1.guard
102
103middle1.exit:
104  br label %outer1.latch
105
106outer1.latch:
107  %iv.next121 = add nuw nsw i64 %iv120, 1
108  %exitcond123 = icmp eq i64 %iv.next121, %wide.trip.count122
109  br i1 %exitcond123, label %outer2.ph, label %outer1.body.middle1.guard
110
111outer2.ph:
112  br label %outer2.middle2.guard
113
114outer2.middle2.guard:
115  %iv108 = phi i64 [ %iv.next109, %outer2.latch ], [ 0, %outer2.ph ]
116  br i1 %cmp298, label %middle2.ph, label %outer2.latch
117
118middle2.ph:
119  br label %middle2.body.inner2.guard
120
121middle2.body.inner2.guard:
122  %iv104 = phi i64 [ %iv.next105, %middle2.latch ], [ 0, %middle2.ph ]
123  br i1 %cmp696, label %inner2.ph, label %middle2.latch
124
125inner2.ph:
126  br label %inner2.body
127
128inner2.body:
129  %iv = phi i64 [ %iv.next, %inner2.body ], [ 0, %inner2.ph ]
130  %idx45 = getelementptr inbounds [10 x [10 x [10 x i32]]], ptr @a, i64 0, i64 %iv108, i64 %iv104, i64 %iv
131  %1 = load i32, ptr %idx45
132  %mul = shl nsw i32 %1, 1
133  %idx51 = getelementptr inbounds [10 x [10 x [10 x i32]]], ptr @c, i64 0, i64 %iv108, i64 %iv104, i64 %iv
134  store i32 %mul, ptr %idx51
135  %iv.next = add nuw nsw i64 %iv, 1
136  %exitcond = icmp eq i64 %iv.next, %wide.trip.count114
137  br i1 %exitcond, label %inner2.exit, label %inner2.body
138
139inner2.exit:
140  br label %middle2.latch
141
142middle2.latch:
143  %iv.next105 = add nuw nsw i64 %iv104, 1
144  %exitcond107 = icmp eq i64 %iv.next105, %wide.trip.count118
145  br i1 %exitcond107, label %middle2.exit, label %middle2.body.inner2.guard
146
147middle2.exit:
148  br label %outer2.latch
149
150outer2.latch:
151  %iv.next109 = add nuw nsw i64 %iv108, 1
152  %exitcond111 = icmp eq i64 %iv.next109, %wide.trip.count122
153  br i1 %exitcond111, label %outer2.exit, label %outer2.middle2.guard
154
155outer2.exit:
156  br label %func_exit
157
158func_exit:
159  ret i32 undef
160}
161