summaryrefslogtreecommitdiffstats
path: root/llvm/test/Transforms/Inline/cgscc-incremental-invalidate.ll
blob: 82d321ccf225c2e1b2993b37e32198273d3bfc54 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
; Test for a subtle bug when computing analyses during inlining and mutating
; the SCC structure. Without care, this can fail to invalidate analyses.
;
; RUN: opt < %s -passes='cgscc(inline,function(verify<domtree>))' -debug-pass-manager -S 2>&1 | FileCheck %s

; First we check that the passes run in the way we expect. Otherwise this test
; may stop testing anything.
;
; CHECK-LABEL: Starting llvm::Module pass manager run.
; CHECK: Running pass: InlinerPass on (test1_f, test1_g, test1_h)
; CHECK: Running analysis: FunctionAnalysisManagerCGSCCProxy on (test1_f, test1_g, test1_h)
; CHECK: Running analysis: DominatorTreeAnalysis on test1_f
; CHECK: Running analysis: DominatorTreeAnalysis on test1_g
; CHECK: Invalidating all non-preserved analyses for: (test1_f, test1_g, test1_h)
; CHECK: Invalidating all non-preserved analyses for: test1_f
; CHECK: Invalidating analysis: DominatorTreeAnalysis on test1_f
; CHECK: Invalidating all non-preserved analyses for: test1_g
; CHECK: Invalidating analysis: DominatorTreeAnalysis on test1_g
; CHECK: Invalidating all non-preserved analyses for: test1_h
; CHECK-NOT: Invalidating anaylsis:
; CHECK: Running analysis: DominatorTreeAnalysis on test1_h
; CHECK: Invalidating all non-preserved analyses for: (test1_g, test1_h)
; CHECK: Invalidating all non-preserved analyses for: test1_h
; CHECK: Invalidating analysis: DominatorTreeAnalysis on test1_h

; An external function used to control branches.
declare i1 @flag()
; CHECK-LABEL: declare i1 @flag()

; The utility function with interesting control flow that gets inlined below to
; perturb the dominator tree.
define internal void @callee() {
entry:
  %ptr = alloca i8
  %flag = call i1 @flag()
  br i1 %flag, label %then, label %else

then:
  store volatile i8 42, i8* %ptr
  br label %return

else:
  store volatile i8 -42, i8* %ptr
  br label %return

return:
  ret void
}

; The 'test1_' prefixed functions work to carefully test that incrementally
; reducing an SCC in the inliner cannot accidentially leave stale function
; analysis results due to failing to invalidate them for all the functions.

; The inliner visits this last function. It can't actually break any cycles
; here, but because we visit this function we compute fresh analyses for it.
; These analyses are then invalidated when we inline callee disrupting the
; CFG, and it is important that they be freed.
define void @test1_h() {
; CHECK-LABEL: define void @test1_h()
entry:
  call void @test1_g()
; CHECK: call void @test1_g()

  ; Pull interesting CFG into this function.
  call void @callee()
; CHECK-NOT: call void @callee()

  ret void
; CHECK: ret void
}

; We visit this function second and here we inline the edge to 'test1_f'
; separating it into its own SCC. The current SCC is now just 'test1_g' and
; 'test1_h'.
define void @test1_g() {
; CHECK-LABEL: define void @test1_g()
entry:
  ; This edge gets inlined away.
  call void @test1_f()
; CHECK-NOT: call void @test1_f()
; CHECK: call void @test1_g()

  ; We force this edge to survive inlining.
  call void @test1_h() noinline
; CHECK: call void @test1_h()

  ; Pull interesting CFG into this function.
  call void @callee()
; CHECK-NOT: call void @callee()

  ret void
; CHECK: ret void
}

; We visit this function first in the inliner, and while we inline callee
; perturbing the CFG, we don't inline anything else and the SCC structure
; remains in tact.
define void @test1_f() {
; CHECK-LABEL: define void @test1_f()
entry:
  ; We force this edge to survive inlining.
  call void @test1_g() noinline
; CHECK: call void @test1_g()

  ; Pull interesting CFG into this function.
  call void @callee()
; CHECK-NOT: call void @callee()

  ret void
; CHECK: ret void
}
OpenPOWER on IntegriCloud