xref: /llvm-project/llvm/test/Transforms/IRCE/pre_post_loops.ll (revision 483e92468e597b73c646182bd755a0d5ef67d327)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 3
2; RUN: opt -verify-loop-info -irce-print-changed-loops -passes=irce -S < %s 2>&1 | FileCheck %s
3; RUN: opt -verify-loop-info -irce-print-changed-loops -passes='require<branch-prob>,irce' -S < %s 2>&1 | FileCheck %s
4
5; CHECK: irce: in function test_01: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
6; CHECK: irce: in function test_02: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting>
7
8; Iterate from 0 to SINT_MAX, check that the post-loop is generated.
9define void @test_01(ptr %arr, ptr %a_len_ptr) {
10; CHECK-LABEL: define void @test_01
11; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
12; CHECK-NEXT:  entry:
13; CHECK-NEXT:    [[EXIT_MAINLOOP_AT:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0:![0-9]+]]
14; CHECK-NEXT:    [[TMP0:%.*]] = icmp slt i32 0, [[EXIT_MAINLOOP_AT]]
15; CHECK-NEXT:    br i1 [[TMP0]], label [[LOOP_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
16; CHECK:       loop.preheader:
17; CHECK-NEXT:    br label [[LOOP:%.*]]
18; CHECK:       loop:
19; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
20; CHECK-NEXT:    [[IDX_NEXT]] = add nsw i32 [[IDX]], 1
21; CHECK-NEXT:    [[ABC:%.*]] = icmp slt i32 [[IDX]], [[EXIT_MAINLOOP_AT]]
22; CHECK-NEXT:    br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT1:%.*]]
23; CHECK:       in.bounds:
24; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]]
25; CHECK-NEXT:    store i32 0, ptr [[ADDR]], align 4
26; CHECK-NEXT:    [[NEXT:%.*]] = icmp slt i32 [[IDX_NEXT]], 2147483647
27; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i32 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]]
28; CHECK-NEXT:    br i1 [[TMP1]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]]
29; CHECK:       main.exit.selector:
30; CHECK-NEXT:    [[IDX_NEXT_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT]], [[IN_BOUNDS]] ]
31; CHECK-NEXT:    [[TMP2:%.*]] = icmp slt i32 [[IDX_NEXT_LCSSA]], 2147483647
32; CHECK-NEXT:    br i1 [[TMP2]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT:%.*]]
33; CHECK:       main.pseudo.exit:
34; CHECK-NEXT:    [[IDX_COPY:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
35; CHECK-NEXT:    [[INDVAR_END:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
36; CHECK-NEXT:    br label [[POSTLOOP:%.*]]
37; CHECK:       out.of.bounds.loopexit:
38; CHECK-NEXT:    br label [[OUT_OF_BOUNDS:%.*]]
39; CHECK:       out.of.bounds.loopexit1:
40; CHECK-NEXT:    br label [[OUT_OF_BOUNDS]]
41; CHECK:       out.of.bounds:
42; CHECK-NEXT:    ret void
43; CHECK:       exit.loopexit:
44; CHECK-NEXT:    br label [[EXIT]]
45; CHECK:       exit:
46; CHECK-NEXT:    ret void
47; CHECK:       postloop:
48; CHECK-NEXT:    br label [[LOOP_POSTLOOP:%.*]]
49; CHECK:       loop.postloop:
50; CHECK-NEXT:    [[IDX_POSTLOOP:%.*]] = phi i32 [ [[IDX_COPY]], [[POSTLOOP]] ], [ [[IDX_NEXT_POSTLOOP:%.*]], [[IN_BOUNDS_POSTLOOP:%.*]] ]
51; CHECK-NEXT:    [[IDX_NEXT_POSTLOOP]] = add i32 [[IDX_POSTLOOP]], 1
52; CHECK-NEXT:    [[ABC_POSTLOOP:%.*]] = icmp slt i32 [[IDX_POSTLOOP]], [[EXIT_MAINLOOP_AT]]
53; CHECK-NEXT:    br i1 [[ABC_POSTLOOP]], label [[IN_BOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]]
54; CHECK:       in.bounds.postloop:
55; CHECK-NEXT:    [[ADDR_POSTLOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_POSTLOOP]]
56; CHECK-NEXT:    store i32 0, ptr [[ADDR_POSTLOOP]], align 4
57; CHECK-NEXT:    [[NEXT_POSTLOOP:%.*]] = icmp slt i32 [[IDX_NEXT_POSTLOOP]], 2147483647
58; CHECK-NEXT:    br i1 [[NEXT_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT:%.*]], !llvm.loop [[LOOP1:![0-9]+]], !loop_constrainer.loop.clone [[META6:![0-9]+]]
59;
60
61entry:
62  %len = load i32, ptr %a_len_ptr, !range !0
63  br label %loop
64
65loop:
66  %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ]
67  %idx.next = add i32 %idx, 1
68  %abc = icmp slt i32 %idx, %len
69  br i1 %abc, label %in.bounds, label %out.of.bounds
70
71in.bounds:
72  %addr = getelementptr i32, ptr %arr, i32 %idx
73  store i32 0, ptr %addr
74  %next = icmp slt i32 %idx.next, 2147483647
75  br i1 %next, label %loop, label %exit
76
77out.of.bounds:
78  ret void
79
80exit:
81  ret void
82}
83
84; Iterate from SINT_MAX to 0, check that the pre-loop is generated.
85define void @test_02(ptr %arr, ptr %a_len_ptr) {
86; CHECK-LABEL: define void @test_02
87; CHECK-SAME: (ptr [[ARR:%.*]], ptr [[A_LEN_PTR:%.*]]) {
88; CHECK-NEXT:  entry:
89; CHECK-NEXT:    [[LEN:%.*]] = load i32, ptr [[A_LEN_PTR]], align 4, !range [[RNG0]]
90; CHECK-NEXT:    br i1 true, label [[LOOP_PRELOOP_PREHEADER:%.*]], label [[PRELOOP_PSEUDO_EXIT:%.*]]
91; CHECK:       loop.preloop.preheader:
92; CHECK-NEXT:    br label [[LOOP_PRELOOP:%.*]]
93; CHECK:       mainloop:
94; CHECK-NEXT:    br label [[LOOP:%.*]]
95; CHECK:       loop:
96; CHECK-NEXT:    [[IDX:%.*]] = phi i32 [ [[IDX_PRELOOP_COPY:%.*]], [[MAINLOOP:%.*]] ], [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ]
97; CHECK-NEXT:    [[IDX_NEXT]] = add nsw i32 [[IDX]], -1
98; CHECK-NEXT:    [[ABC:%.*]] = icmp slt i32 [[IDX]], [[LEN]]
99; CHECK-NEXT:    br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT1:%.*]]
100; CHECK:       in.bounds:
101; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]]
102; CHECK-NEXT:    store i32 0, ptr [[ADDR]], align 4
103; CHECK-NEXT:    [[NEXT:%.*]] = icmp sgt i32 [[IDX_NEXT]], -1
104; CHECK-NEXT:    br i1 [[NEXT]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
105; CHECK:       out.of.bounds.loopexit:
106; CHECK-NEXT:    br label [[OUT_OF_BOUNDS:%.*]]
107; CHECK:       out.of.bounds.loopexit1:
108; CHECK-NEXT:    br label [[OUT_OF_BOUNDS]]
109; CHECK:       out.of.bounds:
110; CHECK-NEXT:    ret void
111; CHECK:       exit.loopexit:
112; CHECK-NEXT:    br label [[EXIT:%.*]]
113; CHECK:       exit:
114; CHECK-NEXT:    ret void
115; CHECK:       loop.preloop:
116; CHECK-NEXT:    [[IDX_PRELOOP:%.*]] = phi i32 [ [[IDX_NEXT_PRELOOP:%.*]], [[IN_BOUNDS_PRELOOP:%.*]] ], [ 2147483647, [[LOOP_PRELOOP_PREHEADER]] ]
117; CHECK-NEXT:    [[IDX_NEXT_PRELOOP]] = add i32 [[IDX_PRELOOP]], -1
118; CHECK-NEXT:    [[ABC_PRELOOP:%.*]] = icmp slt i32 [[IDX_PRELOOP]], [[LEN]]
119; CHECK-NEXT:    br i1 [[ABC_PRELOOP]], label [[IN_BOUNDS_PRELOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]]
120; CHECK:       in.bounds.preloop:
121; CHECK-NEXT:    [[ADDR_PRELOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_PRELOOP]]
122; CHECK-NEXT:    store i32 0, ptr [[ADDR_PRELOOP]], align 4
123; CHECK-NEXT:    [[NEXT_PRELOOP:%.*]] = icmp sgt i32 [[IDX_NEXT_PRELOOP]], -1
124; CHECK-NEXT:    [[TMP0:%.*]] = icmp sgt i32 [[IDX_NEXT_PRELOOP]], -1
125; CHECK-NEXT:    br i1 [[TMP0]], label [[LOOP_PRELOOP]], label [[PRELOOP_EXIT_SELECTOR:%.*]], !llvm.loop [[LOOP7:![0-9]+]], !loop_constrainer.loop.clone [[META6]]
126; CHECK:       preloop.exit.selector:
127; CHECK-NEXT:    [[IDX_NEXT_PRELOOP_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT_PRELOOP]], [[IN_BOUNDS_PRELOOP]] ]
128; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt i32 [[IDX_NEXT_PRELOOP_LCSSA]], -1
129; CHECK-NEXT:    br i1 [[TMP1]], label [[PRELOOP_PSEUDO_EXIT]], label [[EXIT]]
130; CHECK:       preloop.pseudo.exit:
131; CHECK-NEXT:    [[IDX_PRELOOP_COPY]] = phi i32 [ 2147483647, [[ENTRY:%.*]] ], [ [[IDX_NEXT_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ]
132; CHECK-NEXT:    [[INDVAR_END:%.*]] = phi i32 [ 2147483647, [[ENTRY]] ], [ [[IDX_NEXT_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ]
133; CHECK-NEXT:    br label [[MAINLOOP]]
134;
135
136entry:
137  %len = load i32, ptr %a_len_ptr, !range !0
138  br label %loop
139
140loop:
141  %idx = phi i32 [ 2147483647, %entry ], [ %idx.next, %in.bounds ]
142  %idx.next = add i32 %idx, -1
143  %abc = icmp slt i32 %idx, %len
144  br i1 %abc, label %in.bounds, label %out.of.bounds
145
146in.bounds:
147  %addr = getelementptr i32, ptr %arr, i32 %idx
148  store i32 0, ptr %addr
149  %next = icmp sgt i32 %idx.next, -1
150  br i1 %next, label %loop, label %exit
151
152out.of.bounds:
153  ret void
154
155exit:
156  ret void
157}
158
159!0 = !{i32 0, i32 50}
160;.
161; CHECK: [[RNG0]] = !{i32 0, i32 50}
162; CHECK: [[LOOP1]] = distinct !{[[LOOP1]], [[META2:![0-9]+]], [[META3:![0-9]+]], [[META4:![0-9]+]], [[META5:![0-9]+]]}
163; CHECK: [[META2]] = !{!"llvm.loop.unroll.disable"}
164; CHECK: [[META3]] = !{!"llvm.loop.vectorize.enable", i1 false}
165; CHECK: [[META4]] = !{!"llvm.loop.licm_versioning.disable"}
166; CHECK: [[META5]] = !{!"llvm.loop.distribute.enable", i1 false}
167; CHECK: [[META6]] = !{}
168; CHECK: [[LOOP7]] = distinct !{[[LOOP7]], [[META2]], [[META3]], [[META4]], [[META5]]}
169;.
170