xref: /llvm-project/llvm/test/Transforms/LoopUnroll/complete_unroll_profitability_with_assume.ll (revision ef992b60798b6cd2c50b25351bfc392e319896b7)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -S < %s -passes=loop-unroll -unroll-threshold=42 | FileCheck %s --check-prefix=ANALYZE-FULL
3
4; This test is supposed to check that calls to @llvm.assume builtin are not
5; prohibiting the analysis of full unroll profitability in case the cost of the
6; unrolled loop (not acounting to any simplifications done by such unrolling) is
7; higher than some threshold.
8;
9; Ensure that we indeed are testing this code path by verifying that the loop is
10; not unrolled without such analysis:
11
12; RUN: opt -S < %s -passes=loop-unroll -unroll-threshold=42 -unroll-max-iteration-count-to-analyze=2 \
13; RUN:   -unroll-peel-max-count=0  | FileCheck %s --check-prefix=DONT-ANALYZE-FULL
14
15; Function Attrs: nounwind
16declare void @llvm.assume(i1) #1
17
18define i32 @foo(ptr %a) {
19; ANALYZE-FULL-LABEL: @foo(
20; ANALYZE-FULL-NEXT:  entry:
21; ANALYZE-FULL-NEXT:    br label [[FOR_BODY:%.*]]
22; ANALYZE-FULL:       for.body:
23; ANALYZE-FULL-NEXT:    br i1 true, label [[DO_STORE:%.*]], label [[FOR_NEXT:%.*]]
24; ANALYZE-FULL:       do_store:
25; ANALYZE-FULL-NEXT:    store i32 0, ptr [[A:%.*]], align 4
26; ANALYZE-FULL-NEXT:    br label [[FOR_NEXT]]
27; ANALYZE-FULL:       for.next:
28; ANALYZE-FULL-NEXT:    br i1 true, label [[DO_STORE_1:%.*]], label [[FOR_NEXT_1:%.*]]
29; ANALYZE-FULL:       do_store.1:
30; ANALYZE-FULL-NEXT:    [[GEP_1:%.*]] = getelementptr i32, ptr [[A]], i32 1
31; ANALYZE-FULL-NEXT:    store i32 1, ptr [[GEP_1]], align 4
32; ANALYZE-FULL-NEXT:    br label [[FOR_NEXT_1]]
33; ANALYZE-FULL:       for.next.1:
34; ANALYZE-FULL-NEXT:    br i1 true, label [[DO_STORE_2:%.*]], label [[FOR_NEXT_2:%.*]]
35; ANALYZE-FULL:       do_store.2:
36; ANALYZE-FULL-NEXT:    [[GEP_2:%.*]] = getelementptr i32, ptr [[A]], i32 2
37; ANALYZE-FULL-NEXT:    store i32 2, ptr [[GEP_2]], align 4
38; ANALYZE-FULL-NEXT:    br label [[FOR_NEXT_2]]
39; ANALYZE-FULL:       for.next.2:
40; ANALYZE-FULL-NEXT:    br i1 true, label [[DO_STORE_3:%.*]], label [[FOR_NEXT_3:%.*]]
41; ANALYZE-FULL:       do_store.3:
42; ANALYZE-FULL-NEXT:    [[GEP_3:%.*]] = getelementptr i32, ptr [[A]], i32 3
43; ANALYZE-FULL-NEXT:    store i32 3, ptr [[GEP_3]], align 4
44; ANALYZE-FULL-NEXT:    br label [[FOR_NEXT_3]]
45; ANALYZE-FULL:       for.next.3:
46; ANALYZE-FULL-NEXT:    br i1 false, label [[DO_STORE_4:%.*]], label [[FOR_NEXT_4:%.*]]
47; ANALYZE-FULL:       do_store.4:
48; ANALYZE-FULL-NEXT:    [[GEP_4:%.*]] = getelementptr i32, ptr [[A]], i32 4
49; ANALYZE-FULL-NEXT:    store i32 4, ptr [[GEP_4]], align 4
50; ANALYZE-FULL-NEXT:    br label [[FOR_NEXT_4]]
51; ANALYZE-FULL:       for.next.4:
52; ANALYZE-FULL-NEXT:    br i1 false, label [[DO_STORE_5:%.*]], label [[FOR_NEXT_5:%.*]]
53; ANALYZE-FULL:       do_store.5:
54; ANALYZE-FULL-NEXT:    [[GEP_5:%.*]] = getelementptr i32, ptr [[A]], i32 5
55; ANALYZE-FULL-NEXT:    store i32 5, ptr [[GEP_5]], align 4
56; ANALYZE-FULL-NEXT:    br label [[FOR_NEXT_5]]
57; ANALYZE-FULL:       for.next.5:
58; ANALYZE-FULL-NEXT:    br i1 false, label [[DO_STORE_6:%.*]], label [[FOR_NEXT_6:%.*]]
59; ANALYZE-FULL:       do_store.6:
60; ANALYZE-FULL-NEXT:    [[GEP_6:%.*]] = getelementptr i32, ptr [[A]], i32 6
61; ANALYZE-FULL-NEXT:    store i32 6, ptr [[GEP_6]], align 4
62; ANALYZE-FULL-NEXT:    br label [[FOR_NEXT_6]]
63; ANALYZE-FULL:       for.next.6:
64; ANALYZE-FULL-NEXT:    br i1 false, label [[DO_STORE_7:%.*]], label [[FOR_NEXT_7:%.*]]
65; ANALYZE-FULL:       do_store.7:
66; ANALYZE-FULL-NEXT:    [[GEP_7:%.*]] = getelementptr i32, ptr [[A]], i32 7
67; ANALYZE-FULL-NEXT:    store i32 7, ptr [[GEP_7]], align 4
68; ANALYZE-FULL-NEXT:    br label [[FOR_NEXT_7]]
69; ANALYZE-FULL:       for.next.7:
70; ANALYZE-FULL-NEXT:    br i1 false, label [[DO_STORE_8:%.*]], label [[FOR_NEXT_8:%.*]]
71; ANALYZE-FULL:       do_store.8:
72; ANALYZE-FULL-NEXT:    [[GEP_8:%.*]] = getelementptr i32, ptr [[A]], i32 8
73; ANALYZE-FULL-NEXT:    store i32 8, ptr [[GEP_8]], align 4
74; ANALYZE-FULL-NEXT:    br label [[FOR_NEXT_8]]
75; ANALYZE-FULL:       for.next.8:
76; ANALYZE-FULL-NEXT:    ret i32 9
77;
78; DONT-ANALYZE-FULL-LABEL: @foo(
79; DONT-ANALYZE-FULL-NEXT:  entry:
80; DONT-ANALYZE-FULL-NEXT:    br label [[FOR_BODY:%.*]]
81; DONT-ANALYZE-FULL:       for.body:
82; DONT-ANALYZE-FULL-NEXT:    [[INDVAR:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INDVAR_NEXT:%.*]], [[FOR_NEXT:%.*]] ]
83; DONT-ANALYZE-FULL-NEXT:    [[INDVAR_NEXT]] = add i32 [[INDVAR]], 1
84; DONT-ANALYZE-FULL-NEXT:    [[CMP:%.*]] = icmp ule i32 [[INDVAR]], 20
85; DONT-ANALYZE-FULL-NEXT:    tail call void @llvm.assume(i1 [[CMP]])
86; DONT-ANALYZE-FULL-NEXT:    [[CMP2:%.*]] = icmp ule i32 [[INDVAR]], 3
87; DONT-ANALYZE-FULL-NEXT:    br i1 [[CMP2]], label [[DO_STORE:%.*]], label [[FOR_NEXT]]
88; DONT-ANALYZE-FULL:       do_store:
89; DONT-ANALYZE-FULL-NEXT:    [[GEP:%.*]] = getelementptr i32, ptr [[A:%.*]], i32 [[INDVAR]]
90; DONT-ANALYZE-FULL-NEXT:    store i32 [[INDVAR]], ptr [[GEP]], align 4
91; DONT-ANALYZE-FULL-NEXT:    br label [[FOR_NEXT]]
92; DONT-ANALYZE-FULL:       for.next:
93; DONT-ANALYZE-FULL-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[INDVAR_NEXT]], 9
94; DONT-ANALYZE-FULL-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[LOOPEXIT:%.*]]
95; DONT-ANALYZE-FULL:       loopexit:
96; DONT-ANALYZE-FULL-NEXT:    [[INDVAR_NEXT_LCSSA:%.*]] = phi i32 [ [[INDVAR_NEXT]], [[FOR_NEXT]] ]
97; DONT-ANALYZE-FULL-NEXT:    ret i32 [[INDVAR_NEXT_LCSSA]]
98;
99entry:
100  br label %for.body
101for.body:
102  %indvar = phi i32 [ 0, %entry ], [ %indvar.next, %for.next ]
103  %indvar.next = add i32 %indvar, 1
104  %cmp = icmp ule i32 %indvar, 20
105  tail call void @llvm.assume(i1 %cmp)
106  %cmp2 = icmp ule i32 %indvar, 3
107  br i1 %cmp2, label %do_store, label %for.next
108
109do_store:
110  %gep = getelementptr i32, ptr %a, i32 %indvar
111  store i32 %indvar, ptr %gep
112  br label %for.next
113
114for.next:
115  %exitcond = icmp ne i32 %indvar.next, 9
116  br i1 %exitcond, label %for.body, label %loopexit
117loopexit:
118  ret i32 %indvar.next
119}
120