blob: 164f7a66a6f3c33b5f764aee760598a14c419809 [file] [log] [blame]
Chandler Carruthb698d592017-01-22 10:34:01 +00001; Test for a subtle bug when computing analyses during inlining and mutating
2; the SCC structure. Without care, this can fail to invalidate analyses.
3;
4; RUN: opt < %s -passes='cgscc(inline,function(verify<domtree>))' -debug-pass-manager -S 2>&1 | FileCheck %s
5
6; First we check that the passes run in the way we expect. Otherwise this test
7; may stop testing anything.
8;
9; CHECK-LABEL: Starting llvm::Module pass manager run.
Chandler Carruth20e588e2017-03-09 11:35:40 +000010; CHECK: Running pass: InlinerPass on (test1_f, test1_g, test1_h)
11; CHECK: Running analysis: FunctionAnalysisManagerCGSCCProxy on (test1_f, test1_g, test1_h)
Chandler Carruthb698d592017-01-22 10:34:01 +000012; CHECK: Running analysis: DominatorTreeAnalysis on test1_f
13; CHECK: Running analysis: DominatorTreeAnalysis on test1_g
Chandler Carruthbd9c2902017-07-09 03:59:31 +000014; CHECK: Invalidating all non-preserved analyses for: (test1_f)
Chandler Carruthb698d592017-01-22 10:34:01 +000015; CHECK: Invalidating all non-preserved analyses for: test1_f
16; CHECK: Invalidating analysis: DominatorTreeAnalysis on test1_f
Chandler Carruthbd9c2902017-07-09 03:59:31 +000017; CHECK: Invalidating analysis: LoopAnalysis on test1_f
18; CHECK: Invalidating analysis: BranchProbabilityAnalysis on test1_f
19; CHECK: Invalidating analysis: BlockFrequencyAnalysis on test1_f
20; CHECK: Invalidating all non-preserved analyses for: (test1_g, test1_h)
Chandler Carruth20e588e2017-03-09 11:35:40 +000021; CHECK: Invalidating all non-preserved analyses for: test1_g
22; CHECK: Invalidating analysis: DominatorTreeAnalysis on test1_g
Chandler Carruthbd9c2902017-07-09 03:59:31 +000023; CHECK: Invalidating analysis: LoopAnalysis on test1_g
24; CHECK: Invalidating analysis: BranchProbabilityAnalysis on test1_g
25; CHECK: Invalidating analysis: BlockFrequencyAnalysis on test1_g
Chandler Carruthb698d592017-01-22 10:34:01 +000026; CHECK: Invalidating all non-preserved analyses for: test1_h
27; CHECK: Invalidating analysis: DominatorTreeAnalysis on test1_h
Chandler Carruthbd9c2902017-07-09 03:59:31 +000028; CHECK: Invalidating analysis: LoopAnalysis on test1_h
29; CHECK: Invalidating analysis: BranchProbabilityAnalysis on test1_h
30; CHECK: Invalidating analysis: BlockFrequencyAnalysis on test1_h
31; CHECK-NOT: Invalidating analysis:
32; CHECK: Starting llvm::Function pass manager run.
33; CHECK-NEXT: Running pass: DominatorTreeVerifierPass on test1_g
34; CHECK-NEXT: Running analysis: DominatorTreeAnalysis on test1_g
35; CHECK-NEXT: Finished llvm::Function pass manager run.
36; CHECK-NEXT: Starting llvm::Function pass manager run.
37; CHECK-NEXT: Running pass: DominatorTreeVerifierPass on test1_h
38; CHECK-NEXT: Running analysis: DominatorTreeAnalysis on test1_h
39; CHECK-NEXT: Finished llvm::Function pass manager run.
40; CHECK-NOT: Invalidating analysis:
41; CHECK: Running pass: DominatorTreeVerifierPass on test1_f
42; CHECK-NEXT: Running analysis: DominatorTreeAnalysis on test1_f
Chandler Carruthb698d592017-01-22 10:34:01 +000043
44; An external function used to control branches.
45declare i1 @flag()
46; CHECK-LABEL: declare i1 @flag()
47
48; The utility function with interesting control flow that gets inlined below to
49; perturb the dominator tree.
50define internal void @callee() {
51entry:
52 %ptr = alloca i8
53 %flag = call i1 @flag()
54 br i1 %flag, label %then, label %else
55
56then:
57 store volatile i8 42, i8* %ptr
58 br label %return
59
60else:
61 store volatile i8 -42, i8* %ptr
62 br label %return
63
64return:
65 ret void
66}
67
68; The 'test1_' prefixed functions work to carefully test that incrementally
69; reducing an SCC in the inliner cannot accidentially leave stale function
70; analysis results due to failing to invalidate them for all the functions.
71
Chandler Carruth20e588e2017-03-09 11:35:40 +000072; The inliner visits this last function. It can't actually break any cycles
73; here, but because we visit this function we compute fresh analyses for it.
74; These analyses are then invalidated when we inline callee disrupting the
75; CFG, and it is important that they be freed.
76define void @test1_h() {
77; CHECK-LABEL: define void @test1_h()
Chandler Carruthb698d592017-01-22 10:34:01 +000078entry:
Chandler Carruth20e588e2017-03-09 11:35:40 +000079 call void @test1_g()
Chandler Carruthb698d592017-01-22 10:34:01 +000080; CHECK: call void @test1_g()
81
82 ; Pull interesting CFG into this function.
83 call void @callee()
84; CHECK-NOT: call void @callee()
85
86 ret void
87; CHECK: ret void
88}
89
Chandler Carruth20e588e2017-03-09 11:35:40 +000090; We visit this function second and here we inline the edge to 'test1_f'
Chandler Carruthb698d592017-01-22 10:34:01 +000091; separating it into its own SCC. The current SCC is now just 'test1_g' and
92; 'test1_h'.
93define void @test1_g() {
94; CHECK-LABEL: define void @test1_g()
95entry:
96 ; This edge gets inlined away.
97 call void @test1_f()
98; CHECK-NOT: call void @test1_f()
99; CHECK: call void @test1_g()
100
101 ; We force this edge to survive inlining.
102 call void @test1_h() noinline
103; CHECK: call void @test1_h()
104
105 ; Pull interesting CFG into this function.
106 call void @callee()
107; CHECK-NOT: call void @callee()
108
109 ret void
110; CHECK: ret void
111}
112
Chandler Carruth20e588e2017-03-09 11:35:40 +0000113; We visit this function first in the inliner, and while we inline callee
114; perturbing the CFG, we don't inline anything else and the SCC structure
115; remains in tact.
116define void @test1_f() {
117; CHECK-LABEL: define void @test1_f()
Chandler Carruthb698d592017-01-22 10:34:01 +0000118entry:
Chandler Carruth20e588e2017-03-09 11:35:40 +0000119 ; We force this edge to survive inlining.
120 call void @test1_g() noinline
Chandler Carruthb698d592017-01-22 10:34:01 +0000121; CHECK: call void @test1_g()
122
123 ; Pull interesting CFG into this function.
124 call void @callee()
125; CHECK-NOT: call void @callee()
126
127 ret void
128; CHECK: ret void
129}
Chandler Carruthc213c672017-07-09 13:45:11 +0000130
131; The 'test2_' prefixed code works to carefully trigger forming an SCC with
132; a dominator tree for one of the functions but not the other and without even
133; a function analysis manager proxy for the SCC that things get merged into.
134; Without proper handling when updating the call graph this will find a stale
135; dominator tree.
136
137@test2_global = external global i32, align 4
138
139define void @test2_hoge(i1 (i32*)* %arg) {
140; CHECK-LABEL: define void @test2_hoge(
141bb:
142 %tmp2 = call zeroext i1 %arg(i32* @test2_global)
143; CHECK: call zeroext i1 %arg(
144 br label %bb3
145
146bb3:
147 %tmp5 = call zeroext i1 %arg(i32* @test2_global)
148; CHECK: call zeroext i1 %arg(
149 br i1 %tmp5, label %bb3, label %bb6
150
151bb6:
152 ret void
153}
154
155define zeroext i1 @test2_widget(i32* %arg) {
156; CHECK-LABEL: define zeroext i1 @test2_widget(
157bb:
158 %tmp1 = alloca i8, align 1
159 %tmp2 = alloca i32, align 4
160 call void @test2_quux()
161; CHECK-NOT: call
162;
163; CHECK: call zeroext i1 @test2_widget(i32* @test2_global)
164; CHECK-NEXT: br label %[[NEW_BB:.*]]
165;
166; CHECK: [[NEW_BB]]:
167; CHECK-NEXT: call zeroext i1 @test2_widget(i32* @test2_global)
168;
169; CHECK: {{.*}}:
170
171 call void @test2_hoge.1(i32* %arg)
172; CHECK-NEXT: call void @test2_hoge.1(
173
174 %tmp4 = call zeroext i1 @test2_barney(i32* %tmp2)
175 %tmp5 = zext i1 %tmp4 to i32
176 store i32 %tmp5, i32* %tmp2, align 4
177 %tmp6 = call zeroext i1 @test2_barney(i32* null)
178 call void @test2_ham(i8* %tmp1)
179; CHECK: call void @test2_ham(
180
181 call void @test2_quux()
182; CHECK-NOT: call
183;
184; CHECK: call zeroext i1 @test2_widget(i32* @test2_global)
185; CHECK-NEXT: br label %[[NEW_BB:.*]]
186;
187; CHECK: [[NEW_BB]]:
188; CHECK-NEXT: call zeroext i1 @test2_widget(i32* @test2_global)
189;
190; CHECK: {{.*}}:
191 ret i1 true
192; CHECK-NEXT: ret i1 true
193}
194
195define internal void @test2_quux() {
196; CHECK-NOT: @test2_quux
197bb:
198 call void @test2_hoge(i1 (i32*)* @test2_widget)
199 ret void
200}
201
202declare void @test2_hoge.1(i32*)
203
204declare zeroext i1 @test2_barney(i32*)
205
206declare void @test2_ham(i8*)