[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / Inline / cgscc-update.ll
blob5558e9b535ab291cbcf2a0c80f95af72fcf19c45
1 ; RUN: opt < %s -aa-pipeline=basic-aa -passes='cgscc(function-attrs,inline)' -S | FileCheck %s
2 ; This test runs the inliner and the function attribute deduction. It ensures
3 ; that when the inliner mutates the call graph it correctly updates the CGSCC
4 ; iteration so that we can compute refined function attributes. In this way it
5 ; is leveraging function attribute computation to observe correct call graph
6 ; updates.
8 ; Boring unknown external function call.
9 ; CHECK: declare void @unknown()
10 declare void @unknown()
12 ; Sanity check: this should get annotated as readnone.
13 ; CHECK: Function Attrs: nounwind readnone
14 ; CHECK-NEXT: declare void @readnone()
15 declare void @readnone() readnone nounwind
17 ; The 'test1_' prefixed functions are designed to trigger forming a new direct
18 ; call in the inlined body of the function. After that, we form a new SCC and
19 ; using that can deduce precise function attrs.
21 ; This function should no longer exist.
22 ; CHECK-NOT: @test1_f()
23 define internal void @test1_f(void()* %p) {
24 entry:
25   call void %p()
26   ret void
29 ; This function should have had 'readnone' deduced for its SCC.
30 ; CHECK: Function Attrs: nofree noinline nosync nounwind readnone
31 ; CHECK-NEXT: define void @test1_g()
32 define void @test1_g() noinline {
33 entry:
34   call void @test1_f(void()* @test1_h)
35   ret void
38 ; This function should have had 'readnone' deduced for its SCC.
39 ; CHECK: Function Attrs: nofree noinline nosync nounwind readnone
40 ; CHECK-NEXT: define void @test1_h()
41 define void @test1_h() noinline {
42 entry:
43   call void @test1_g()
44   call void @readnone()
45   ret void
49 ; The 'test2_' prefixed functions are designed to trigger forming a new direct
50 ; call due to RAUW-ing the returned value of a called function into the caller.
51 ; This too should form a new SCC which can then be reasoned about to compute
52 ; precise function attrs.
54 ; This function should no longer exist.
55 ; CHECK-NOT: @test2_f()
56 define internal void()* @test2_f() {
57 entry:
58   ret void()* @test2_h
61 ; This function should have had 'readnone' deduced for its SCC.
62 ; CHECK: Function Attrs: nofree noinline nosync nounwind readnone
63 ; CHECK-NEXT: define void @test2_g()
64 define void @test2_g() noinline {
65 entry:
66   %p = call void()* @test2_f()
67   call void %p()
68   ret void
71 ; This function should have had 'readnone' deduced for its SCC.
72 ; CHECK: Function Attrs: nofree noinline nosync nounwind readnone
73 ; CHECK-NEXT: define void @test2_h()
74 define void @test2_h() noinline {
75 entry:
76   call void @test2_g()
77   call void @readnone()
78   ret void
82 ; The 'test3_' prefixed functions are designed to inline in a way that causes
83 ; call sites to become trivially dead during the middle of inlining callsites of
84 ; a single function to make sure that the inliner does not get confused by this
85 ; pattern.
87 ; CHECK-NOT: @test3_maybe_unknown(
88 define internal void @test3_maybe_unknown(i1 %b) {
89 entry:
90   br i1 %b, label %then, label %exit
92 then:
93   call void @unknown()
94   br label %exit
96 exit:
97   ret void
100 ; CHECK-NOT: @test3_f(
101 define internal i1 @test3_f() {
102 entry:
103   ret i1 false
106 ; CHECK-NOT: @test3_g(
107 define internal i1 @test3_g(i1 %b) {
108 entry:
109   br i1 %b, label %then1, label %if2
111 then1:
112   call void @test3_maybe_unknown(i1 true)
113   br label %if2
115 if2:
116   %f = call i1 @test3_f()
117   br i1 %f, label %then2, label %exit
119 then2:
120   call void @test3_maybe_unknown(i1 true)
121   br label %exit
123 exit:
124   ret i1 false
127 ; FIXME: Currently the inliner doesn't successfully mark this as readnone
128 ; because while it simplifies trivially dead CFGs when inlining callees it
129 ; doesn't simplify the caller's trivially dead CFG and so we end with a dead
130 ; block calling @unknown.
131 ; CHECK-NOT: Function Attrs: readnone
132 ; CHECK: define void @test3_h()
133 define void @test3_h() {
134 entry:
135   %g = call i1 @test3_g(i1 false)
136   br i1 %g, label %then, label %exit
138 then:
139   call void @test3_maybe_unknown(i1 true)
140   br label %exit
142 exit:
143   call void @test3_maybe_unknown(i1 false)
144   ret void
148 ; The 'test4_' prefixed functions are designed to trigger forming a new direct
149 ; call in the inlined body of the function similar to 'test1_'. However, after
150 ; that we continue to inline another edge of the graph forcing us to do a more
151 ; interesting call graph update for the new call edge. Eventually, we still
152 ; form a new SCC and should use that can deduce precise function attrs.
154 ; This function should have had 'readnone' deduced for its SCC.
155 ; CHECK: Function Attrs: nofree noinline nosync nounwind readnone
156 ; CHECK-NEXT: define void @test4_f1()
157 define void @test4_f1() noinline {
158 entry:
159   call void @test4_h()
160   ret void
163 ; CHECK-NOT: @test4_f2
164 define internal void @test4_f2() {
165 entry:
166   call void @test4_f1()
167   ret void
170 ; CHECK-NOT: @test4_g
171 define internal void @test4_g(void()* %p) {
172 entry:
173   call void %p()
174   ret void
177 ; This function should have had 'readnone' deduced for its SCC.
178 ; CHECK: Function Attrs: nofree noinline nosync nounwind readnone
179 ; CHECK-NEXT: define void @test4_h()
180 define void @test4_h() noinline {
181 entry:
182   call void @test4_g(void()* @test4_f2)
183   ret void