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. 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. 10; CHECK: Running pass: InlinerPass on (test1_f, test1_g, test1_h) 11; CHECK: Running analysis: FunctionAnalysisManagerCGSCCProxy on (test1_f, test1_g, test1_h) 12; CHECK: Running analysis: DominatorTreeAnalysis on test1_f 13; CHECK: Running analysis: DominatorTreeAnalysis on test1_g 14; CHECK: Invalidating all non-preserved analyses for: (test1_f) 15; CHECK: Invalidating all non-preserved analyses for: test1_f 16; CHECK: Invalidating analysis: DominatorTreeAnalysis on test1_f 17; 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) 21; CHECK: Invalidating all non-preserved analyses for: test1_g 22; CHECK: Invalidating analysis: DominatorTreeAnalysis on test1_g 23; CHECK: Invalidating analysis: LoopAnalysis on test1_g 24; CHECK: Invalidating analysis: BranchProbabilityAnalysis on test1_g 25; CHECK: Invalidating analysis: BlockFrequencyAnalysis on test1_g 26; CHECK: Invalidating all non-preserved analyses for: test1_h 27; CHECK: Invalidating analysis: DominatorTreeAnalysis on test1_h 28; 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 43 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 72; 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() 78entry: 79 call void @test1_g() 80; 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 90; We visit this function second and here we inline the edge to 'test1_f' 91; 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 113; 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() 118entry: 119 ; We force this edge to survive inlining. 120 call void @test1_g() noinline 121; 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} 130 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*) 207