[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / Inline / cgscc-incremental-invalidate.ll
blob0b548f74e32c5f7445c116925525d865e7d2f547
1 ; Test for a subtle bug when computing analyses during inlining and mutating
2 ; the SCC structure. Without care, this can fail to invalidate analyses.
4 ; RUN: opt < %s -aa-pipeline= -passes='cgscc(inline,function(verify<domtree>))' -debug-pass-manager -S 2>&1 | FileCheck %s
6 ; First we check that the passes run in the way we expect. Otherwise this test
7 ; may stop testing anything.
9 ; CHECK: Running pass: InlinerPass on (test1_f, test1_g, test1_h)
10 ; CHECK: Running analysis: DominatorTreeAnalysis on test1_f
11 ; CHECK: Running analysis: DominatorTreeAnalysis on test1_g
12 ; CHECK: Invalidating analysis: DominatorTreeAnalysis on test1_f
13 ; CHECK: Invalidating analysis: LoopAnalysis on test1_f
14 ; CHECK: Invalidating analysis: BranchProbabilityAnalysis on test1_f
15 ; CHECK: Invalidating analysis: BlockFrequencyAnalysis on test1_f
16 ; CHECK: Invalidating analysis: DominatorTreeAnalysis on test1_g
17 ; CHECK: Invalidating analysis: LoopAnalysis on test1_g
18 ; CHECK: Invalidating analysis: BranchProbabilityAnalysis on test1_g
19 ; CHECK: Invalidating analysis: BlockFrequencyAnalysis on test1_g
20 ; CHECK: Invalidating analysis: DominatorTreeAnalysis on test1_h
21 ; CHECK: Invalidating analysis: LoopAnalysis on test1_h
22 ; CHECK: Invalidating analysis: BranchProbabilityAnalysis on test1_h
23 ; CHECK: Invalidating analysis: BlockFrequencyAnalysis on test1_h
24 ; CHECK-NOT: Invalidating analysis:
25 ; CHECK: Running pass: DominatorTreeVerifierPass on test1_g
26 ; CHECK-NEXT: Running analysis: DominatorTreeAnalysis on test1_g
27 ; CHECK-NOT: Invalidating analysis:
28 ; CHECK: Running pass: DominatorTreeVerifierPass on test1_h
29 ; CHECK-NEXT: Running analysis: DominatorTreeAnalysis on test1_h
30 ; CHECK-NOT: Invalidating analysis:
31 ; CHECK: Running pass: DominatorTreeVerifierPass on test1_f
32 ; CHECK-NEXT: Running analysis: DominatorTreeAnalysis on test1_f
34 ; An external function used to control branches.
35 declare i1 @flag()
36 ; CHECK-LABEL: declare i1 @flag()
38 ; The utility function with interesting control flow that gets inlined below to
39 ; perturb the dominator tree.
40 define internal void @callee() {
41 entry:
42   %ptr = alloca i8
43   %flag = call i1 @flag()
44   br i1 %flag, label %then, label %else
46 then:
47   store volatile i8 42, i8* %ptr
48   br label %return
50 else:
51   store volatile i8 -42, i8* %ptr
52   br label %return
54 return:
55   ret void
58 ; The 'test1_' prefixed functions work to carefully test that incrementally
59 ; reducing an SCC in the inliner cannot accidentially leave stale function
60 ; analysis results due to failing to invalidate them for all the functions.
62 ; We visit this function first in the inliner, and while we inline callee
63 ; perturbing the CFG, we don't inline anything else and the SCC structure
64 ; remains in tact.
65 define void @test1_f() {
66 ; CHECK-LABEL: define void @test1_f()
67 entry:
68   ; We force this edge to survive inlining.
69   call void @test1_g() noinline
70 ; CHECK: call void @test1_g()
72   ; Pull interesting CFG into this function.
73   call void @callee()
74 ; CHECK-NOT: call void @callee()
76   ret void
77 ; CHECK: ret void
80 ; We visit this function second and here we inline the edge to 'test1_f'
81 ; separating it into its own SCC. The current SCC is now just 'test1_g' and
82 ; 'test1_h'.
83 define void @test1_g() {
84 ; CHECK-LABEL: define void @test1_g()
85 entry:
86   ; This edge gets inlined away.
87   call void @test1_f()
88 ; CHECK-NOT: call void @test1_f()
89 ; CHECK: call void @test1_g()
91   ; We force this edge to survive inlining.
92   call void @test1_h() noinline
93 ; CHECK: call void @test1_h()
95   ; Pull interesting CFG into this function.
96   call void @callee()
97 ; CHECK-NOT: call void @callee()
99   ret void
100 ; CHECK: ret void
103 ; The inliner visits this last function. It can't actually break any cycles
104 ; here, but because we visit this function we compute fresh analyses for it.
105 ; These analyses are then invalidated when we inline callee disrupting the
106 ; CFG, and it is important that they be freed.
107 define void @test1_h() {
108 ; CHECK-LABEL: define void @test1_h()
109 entry:
110   call void @test1_g()
111 ; CHECK: call void @test1_g()
113   ; Pull interesting CFG into this function.
114   call void @callee()
115 ; CHECK-NOT: call void @callee()
117   ret void
118 ; CHECK: ret void
121 ; The 'test2_' prefixed code works to carefully trigger forming an SCC with
122 ; a dominator tree for one of the functions but not the other and without even
123 ; a function analysis manager proxy for the SCC that things get merged into.
124 ; Without proper handling when updating the call graph this will find a stale
125 ; dominator tree.
127 @test2_global = external global i32, align 4
129 define void @test2_hoge(i1 (i32*)* %arg) {
130 ; CHECK-LABEL: define void @test2_hoge(
132   %tmp2 = call zeroext i1 %arg(i32* @test2_global)
133 ; CHECK: call zeroext i1 %arg(
134   br label %bb3
136 bb3:
137   %tmp5 = call zeroext i1 %arg(i32* @test2_global)
138 ; CHECK: call zeroext i1 %arg(
139   br i1 %tmp5, label %bb3, label %bb6
141 bb6:
142   ret void
145 define zeroext i1 @test2_widget(i32* %arg) {
146 ; CHECK-LABEL: define zeroext i1 @test2_widget(
148   %tmp1 = alloca i8, align 1
149   %tmp2 = alloca i32, align 4
150   call void @test2_quux()
151 ; CHECK-NOT:     call
153 ; CHECK:         call zeroext i1 @test2_widget(i32* @test2_global)
154 ; CHECK-NEXT:    br label %[[NEW_BB:.*]]
156 ; CHECK:       [[NEW_BB]]:
157 ; CHECK-NEXT:    call zeroext i1 @test2_widget(i32* @test2_global)
159 ; CHECK:       {{.*}}:
161   call void @test2_hoge.1(i32* %arg)
162 ; CHECK-NEXT:    call void @test2_hoge.1(
164   %tmp4 = call zeroext i1 @test2_barney(i32* %tmp2)
165   %tmp5 = zext i1 %tmp4 to i32
166   store i32 %tmp5, i32* %tmp2, align 4
167   %tmp6 = call zeroext i1 @test2_barney(i32* null)
168   call void @test2_ham(i8* %tmp1)
169 ; CHECK:         call void @test2_ham(
171   call void @test2_quux()
172 ; CHECK-NOT:     call
174 ; CHECK:         call zeroext i1 @test2_widget(i32* @test2_global)
175 ; CHECK-NEXT:    br label %[[NEW_BB:.*]]
177 ; CHECK:       [[NEW_BB]]:
178 ; CHECK-NEXT:    call zeroext i1 @test2_widget(i32* @test2_global)
180 ; CHECK:       {{.*}}:
181   ret i1 true
182 ; CHECK-NEXT:    ret i1 true
185 define internal void @test2_quux() {
186 ; CHECK-NOT: @test2_quux
188   call void @test2_hoge(i1 (i32*)* @test2_widget)
189   ret void
192 declare void @test2_hoge.1(i32*)
194 declare zeroext i1 @test2_barney(i32*)
196 declare void @test2_ham(i8*)