xref: /llvm-project/llvm/test/Transforms/LICM/infinite_loops.ll (revision 80e8f2beeb954f8c241897099bb01b24da400e8a)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -S -passes=licm < %s | FileCheck %s
3; RUN: opt -aa-pipeline=basic-aa -passes='require<opt-remark-emit>,loop-mssa(licm)' -S %s | FileCheck %s
4
5; Make sure we don't hoist the unsafe division to some executable block.
6define void @test_impossible_exit_in_untaken_block(i32 %a, i32 %b, ptr %p) {
7; CHECK-LABEL: @test_impossible_exit_in_untaken_block(
8; CHECK-NEXT:  entry:
9; CHECK-NEXT:    br label [[LOOP:%.*]]
10; CHECK:       loop:
11; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
12; CHECK-NEXT:    br i1 false, label [[NEVER_TAKEN:%.*]], label [[BACKEDGE]]
13; CHECK:       never_taken:
14; CHECK-NEXT:    [[DIV:%.*]] = sdiv i32 [[A:%.*]], [[B:%.*]]
15; CHECK-NEXT:    store i32 [[DIV]], ptr [[P:%.*]]
16; CHECK-NEXT:    br i1 true, label [[BACKEDGE]], label [[EXIT:%.*]]
17; CHECK:       backedge:
18; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
19; CHECK-NEXT:    br label [[LOOP]]
20; CHECK:       exit:
21; CHECK-NEXT:    ret void
22;
23entry:
24  br label %loop
25
26loop:
27  %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
28  br i1 false, label %never_taken, label %backedge
29
30never_taken:
31  %div = sdiv i32 %a, %b
32  store i32 %div, ptr %p
33  br i1 true, label %backedge, label %exit
34
35backedge:
36  %iv.next = add i32 %iv, 1
37  br label %loop
38
39exit:
40  ret void
41}
42
43; The test above is UB in C++, because there is a requirement that any
44; thead should eventually terminate, execute volatile access operation, call IO
45; or synchronize. In spite of that, the behavior in the test above *might* be
46; correct. This one is equivalent to the test above, but it has a volatile
47; memory access in the loop's mustexec block, so the compiler no longer has a
48; right to assume that it must terminate. Show that the same problem persists,
49; and that it was a bug and not a cool optimization based on loop infinity.
50; By the moment when this test was added, it was accidentally correct due to
51; reasons not directly related to this piece of logic. Make sure that it keeps
52; correct in the future.
53define void @test_impossible_exit_in_untaken_block_no_ub(i32 %a, i32 %b, ptr noalias %p, ptr noalias %vp) {
54; CHECK-LABEL: @test_impossible_exit_in_untaken_block_no_ub(
55; CHECK-NEXT:  entry:
56; CHECK-NEXT:    br label [[LOOP:%.*]]
57; CHECK:       loop:
58; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
59; CHECK-NEXT:    [[TMP0:%.*]] = load volatile i32, ptr [[VP:%.*]]
60; CHECK-NEXT:    br i1 false, label [[NEVER_TAKEN:%.*]], label [[BACKEDGE]]
61; CHECK:       never_taken:
62; CHECK-NEXT:    [[DIV:%.*]] = sdiv i32 [[A:%.*]], [[B:%.*]]
63; CHECK-NEXT:    store i32 [[DIV]], ptr [[P:%.*]]
64; CHECK-NEXT:    br i1 true, label [[BACKEDGE]], label [[EXIT:%.*]]
65; CHECK:       backedge:
66; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
67; CHECK-NEXT:    br label [[LOOP]]
68; CHECK:       exit:
69; CHECK-NEXT:    ret void
70;
71entry:
72  br label %loop
73
74loop:
75  %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
76  load volatile i32, ptr %vp
77  br i1 false, label %never_taken, label %backedge
78
79never_taken:
80  %div = sdiv i32 %a, %b
81  store i32 %div, ptr %p
82  br i1 true, label %backedge, label %exit
83
84backedge:
85  %iv.next = add i32 %iv, 1
86  br label %loop
87
88exit:
89  ret void
90}
91
92; Same as above, but the volatile access is in mustexecute backedge block. The
93; loop is no longer "finite by specification", make sure we don't hoist sdiv
94; from it no matter how general the MustThrow analysis is.
95define void @test_impossible_exit_in_untaken_block_no_ub_2(i32 %a, i32 %b, ptr noalias %p, ptr noalias %vp) {
96; CHECK-LABEL: @test_impossible_exit_in_untaken_block_no_ub_2(
97; CHECK-NEXT:  entry:
98; CHECK-NEXT:    br label [[LOOP:%.*]]
99; CHECK:       loop:
100; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
101; CHECK-NEXT:    br i1 false, label [[NEVER_TAKEN:%.*]], label [[BACKEDGE]]
102; CHECK:       never_taken:
103; CHECK-NEXT:    [[DIV:%.*]] = sdiv i32 [[A:%.*]], [[B:%.*]]
104; CHECK-NEXT:    store i32 [[DIV]], ptr [[P:%.*]]
105; CHECK-NEXT:    br i1 true, label [[BACKEDGE]], label [[EXIT:%.*]]
106; CHECK:       backedge:
107; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
108; CHECK-NEXT:    [[TMP0:%.*]] = load volatile i32, ptr [[VP:%.*]]
109; CHECK-NEXT:    br label [[LOOP]]
110; CHECK:       exit:
111; CHECK-NEXT:    ret void
112;
113entry:
114  br label %loop
115
116loop:
117  %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
118  br i1 false, label %never_taken, label %backedge
119
120never_taken:
121  %div = sdiv i32 %a, %b
122  store i32 %div, ptr %p
123  br i1 true, label %backedge, label %exit
124
125backedge:
126  %iv.next = add i32 %iv, 1
127  load volatile i32, ptr %vp
128  br label %loop
129
130exit:
131  ret void
132}
133