xref: /llvm-project/llvm/test/Transforms/LoopUnroll/full-unroll-one-unpredictable-exit.ll (revision ef992b60798b6cd2c50b25351bfc392e319896b7)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -S -passes=loop-unroll %s | FileCheck %s
3
4; In both cases, we have one unpredictable exit and one IV-based exit with
5; known trip count. We can fully unroll against the latter. In one of the
6; examples the IV-based exit is the latch exit, in the other the non-latch
7; exit. After full unrolling, the functions fold to ret i1 true.
8
9define i1 @test_latch() {
10; CHECK-LABEL: @test_latch(
11; CHECK-NEXT:  start:
12; CHECK-NEXT:    [[A1:%.*]] = alloca [2 x i64], align 8
13; CHECK-NEXT:    [[A2:%.*]] = alloca [2 x i64], align 8
14; CHECK-NEXT:    store i64 -5015437470765251660, ptr [[A1]], align 8
15; CHECK-NEXT:    [[A1_1:%.*]] = getelementptr inbounds [2 x i64], ptr [[A1]], i64 0, i64 1
16; CHECK-NEXT:    store i64 -8661621401413125213, ptr [[A1_1]], align 8
17; CHECK-NEXT:    store i64 -5015437470765251660, ptr [[A2]], align 8
18; CHECK-NEXT:    [[A2_1:%.*]] = getelementptr inbounds [2 x i64], ptr [[A2]], i64 0, i64 1
19; CHECK-NEXT:    store i64 -8661621401413125213, ptr [[A2_1]], align 8
20; CHECK-NEXT:    br label [[LOOP:%.*]]
21; CHECK:       loop:
22; CHECK-NEXT:    [[LOAD1:%.*]] = load i64, ptr [[A1]], align 8
23; CHECK-NEXT:    [[LOAD2:%.*]] = load i64, ptr [[A2]], align 8
24; CHECK-NEXT:    [[EXITCOND2:%.*]] = icmp eq i64 [[LOAD1]], [[LOAD2]]
25; CHECK-NEXT:    br i1 [[EXITCOND2]], label [[LATCH:%.*]], label [[EXIT:%.*]]
26; CHECK:       latch:
27; CHECK-NEXT:    [[GEP1_1:%.*]] = getelementptr inbounds [2 x i64], ptr [[A1]], i64 0, i64 1
28; CHECK-NEXT:    [[GEP2_1:%.*]] = getelementptr inbounds [2 x i64], ptr [[A2]], i64 0, i64 1
29; CHECK-NEXT:    [[LOAD1_1:%.*]] = load i64, ptr [[GEP1_1]], align 8
30; CHECK-NEXT:    [[LOAD2_1:%.*]] = load i64, ptr [[GEP2_1]], align 8
31; CHECK-NEXT:    [[EXITCOND2_1:%.*]] = icmp eq i64 [[LOAD1_1]], [[LOAD2_1]]
32; CHECK-NEXT:    br i1 [[EXITCOND2_1]], label [[LATCH_1:%.*]], label [[EXIT]]
33; CHECK:       latch.1:
34; CHECK-NEXT:    br label [[EXIT]]
35; CHECK:       exit:
36; CHECK-NEXT:    [[EXIT_VAL:%.*]] = phi i1 [ false, [[LOOP]] ], [ false, [[LATCH]] ], [ true, [[LATCH_1]] ]
37; CHECK-NEXT:    ret i1 [[EXIT_VAL]]
38;
39start:
40  %a1 = alloca [2 x i64], align 8
41  %a2 = alloca [2 x i64], align 8
42  store i64 -5015437470765251660, ptr %a1, align 8
43  %a1.1 = getelementptr inbounds [2 x i64], ptr %a1, i64 0, i64 1
44  store i64 -8661621401413125213, ptr %a1.1, align 8
45  store i64 -5015437470765251660, ptr %a2, align 8
46  %a2.1 = getelementptr inbounds [2 x i64], ptr %a2, i64 0, i64 1
47  store i64 -8661621401413125213, ptr %a2.1, align 8
48  br label %loop
49
50loop:
51  %iv = phi i64 [ 0, %start ], [ %iv.next, %latch ]
52  %gep1 = getelementptr inbounds [2 x i64], ptr %a1, i64 0, i64 %iv
53  %gep2 = getelementptr inbounds [2 x i64], ptr %a2, i64 0, i64 %iv
54  %load1 = load i64, ptr %gep1, align 8
55  %load2 = load i64, ptr %gep2, align 8
56  %exitcond2 = icmp eq i64 %load1, %load2
57  br i1 %exitcond2, label %latch, label %exit
58
59latch:
60  %iv.next = add nuw nsw i64 %iv, 1
61  %exitcond = icmp eq i64 %iv.next, 2
62  br i1 %exitcond, label %exit, label %loop
63
64exit:
65  %exit.val = phi i1 [ true, %latch ], [ false, %loop ]
66  ret i1 %exit.val
67}
68
69define i1 @test_non_latch() {
70; CHECK-LABEL: @test_non_latch(
71; CHECK-NEXT:  start:
72; CHECK-NEXT:    [[A1:%.*]] = alloca [2 x i64], align 8
73; CHECK-NEXT:    [[A2:%.*]] = alloca [2 x i64], align 8
74; CHECK-NEXT:    store i64 -5015437470765251660, ptr [[A1]], align 8
75; CHECK-NEXT:    [[A1_1:%.*]] = getelementptr inbounds [2 x i64], ptr [[A1]], i64 0, i64 1
76; CHECK-NEXT:    store i64 -8661621401413125213, ptr [[A1_1]], align 8
77; CHECK-NEXT:    store i64 -5015437470765251660, ptr [[A2]], align 8
78; CHECK-NEXT:    [[A2_1:%.*]] = getelementptr inbounds [2 x i64], ptr [[A2]], i64 0, i64 1
79; CHECK-NEXT:    store i64 -8661621401413125213, ptr [[A2_1]], align 8
80; CHECK-NEXT:    br label [[LOOP:%.*]]
81; CHECK:       loop:
82; CHECK-NEXT:    br label [[LATCH:%.*]]
83; CHECK:       latch:
84; CHECK-NEXT:    [[LOAD1:%.*]] = load i64, ptr [[A1]], align 8
85; CHECK-NEXT:    [[LOAD2:%.*]] = load i64, ptr [[A2]], align 8
86; CHECK-NEXT:    [[EXITCOND2:%.*]] = icmp eq i64 [[LOAD1]], [[LOAD2]]
87; CHECK-NEXT:    br i1 [[EXITCOND2]], label [[LOOP_1:%.*]], label [[EXIT:%.*]]
88; CHECK:       loop.1:
89; CHECK-NEXT:    br label [[LATCH_1:%.*]]
90; CHECK:       latch.1:
91; CHECK-NEXT:    [[GEP1_1:%.*]] = getelementptr inbounds [2 x i64], ptr [[A1]], i64 0, i64 1
92; CHECK-NEXT:    [[GEP2_1:%.*]] = getelementptr inbounds [2 x i64], ptr [[A2]], i64 0, i64 1
93; CHECK-NEXT:    [[LOAD1_1:%.*]] = load i64, ptr [[GEP1_1]], align 8
94; CHECK-NEXT:    [[LOAD2_1:%.*]] = load i64, ptr [[GEP2_1]], align 8
95; CHECK-NEXT:    [[EXITCOND2_1:%.*]] = icmp eq i64 [[LOAD1_1]], [[LOAD2_1]]
96; CHECK-NEXT:    br i1 [[EXITCOND2_1]], label [[LOOP_2:%.*]], label [[EXIT]]
97; CHECK:       loop.2:
98; CHECK-NEXT:    br i1 true, label [[EXIT]], label [[LATCH_2:%.*]]
99; CHECK:       latch.2:
100; CHECK-NEXT:    br label [[EXIT]]
101; CHECK:       exit:
102; CHECK-NEXT:    [[EXIT_VAL:%.*]] = phi i1 [ false, [[LATCH]] ], [ false, [[LATCH_1]] ], [ true, [[LOOP_2]] ], [ false, [[LATCH_2]] ]
103; CHECK-NEXT:    ret i1 [[EXIT_VAL]]
104;
105start:
106  %a1 = alloca [2 x i64], align 8
107  %a2 = alloca [2 x i64], align 8
108  store i64 -5015437470765251660, ptr %a1, align 8
109  %a1.1 = getelementptr inbounds [2 x i64], ptr %a1, i64 0, i64 1
110  store i64 -8661621401413125213, ptr %a1.1, align 8
111  store i64 -5015437470765251660, ptr %a2, align 8
112  %a2.1 = getelementptr inbounds [2 x i64], ptr %a2, i64 0, i64 1
113  store i64 -8661621401413125213, ptr %a2.1, align 8
114  br label %loop
115
116loop:
117  %iv = phi i64 [ 0, %start ], [ %iv.next, %latch ]
118  %exitcond = icmp eq i64 %iv, 2
119  br i1 %exitcond, label %exit, label %latch
120
121latch:
122  %iv.next = add nuw nsw i64 %iv, 1
123  %gep1 = getelementptr inbounds [2 x i64], ptr %a1, i64 0, i64 %iv
124  %gep2 = getelementptr inbounds [2 x i64], ptr %a2, i64 0, i64 %iv
125  %load1 = load i64, ptr %gep1, align 8
126  %load2 = load i64, ptr %gep2, align 8
127  %exitcond2 = icmp eq i64 %load1, %load2
128  br i1 %exitcond2, label %loop, label %exit
129
130exit:
131  %exit.val = phi i1 [ false, %latch ], [ true, %loop ]
132  ret i1 %exit.val
133}
134