1 ; Make sure that even without some external devirtualization iteration tool,
2 ; the CGSCC pass manager correctly observes and re-visits SCCs that change
3 ; structure due to devirtualization. We trigger devirtualization here with GVN
4 ; which forwards a store through a load and to an indirect call.
6 ; RUN: opt -aa-pipeline=basic-aa -passes='cgscc(function-attrs)' -S < %s | FileCheck %s --check-prefix=BEFORE
7 ; RUN: opt -aa-pipeline=basic-aa -passes='cgscc(function-attrs,function(gvn))' -S < %s | FileCheck %s --check-prefix=AFTER
9 ; Also check that adding an extra CGSCC pass after the function update but
10 ; without requiring the outer manager to iterate doesn't break any invariant.
11 ; RUN: opt -aa-pipeline=basic-aa -passes='cgscc(function-attrs,function(gvn),function-attrs)' -S < %s | FileCheck %s --check-prefix=AFTER
13 declare void @readnone() nofree nosync readnone
14 declare void @unknown()
16 ; The @test1_* checks that if we refine an indirect call to a direct call and
17 ; in the process change the very structure of the call graph we also revisit
18 ; that component of the graph and do so in an up-to-date fashion.
20 ; BEFORE: define void @test1_a1() {
21 ; AFTER: define void @test1_a1() {
22 define void @test1_a1() {
24 store ptr @test1_b2, ptr %fptr
25 store ptr @test1_b1, ptr %fptr
26 %f = load ptr, ptr %fptr
31 ; BEFORE: define void @test1_b1() {
32 ; AFTER: define void @test1_b1() {
33 define void @test1_b1() {
39 ; BEFORE: define void @test1_a2() {
40 ; AFTER: define void @test1_a2() #0 {
41 define void @test1_a2() {
43 store ptr @test1_b1, ptr %fptr
44 store ptr @test1_b2, ptr %fptr
45 %f = load ptr, ptr %fptr
50 ; BEFORE: define void @test1_b2() {
51 ; AFTER: define void @test1_b2() #0 {
52 define void @test1_b2() {
59 ; The @test2_* set of functions exercise a case where running function passes
60 ; introduces a new post-order relationship that was not present originally and
61 ; makes sure we walk across the SCCs in that order.
63 ; CHECK: define void @test2_a() {
64 define void @test2_a() {
72 ; CHECK: define void @test2_b1() #0 {
73 define void @test2_b1() {
75 store ptr @test2_a, ptr %fptr
76 store ptr @readnone, ptr %fptr
77 %f = load ptr, ptr %fptr
82 ; CHECK: define void @test2_b2() #0 {
83 define void @test2_b2() {
85 store ptr @test2_a, ptr %fptr
86 store ptr @test2_b2, ptr %fptr
87 store ptr @test2_b3, ptr %fptr
88 store ptr @test2_b1, ptr %fptr
89 %f = load ptr, ptr %fptr
94 ; CHECK: define void @test2_b3() #0 {
95 define void @test2_b3() {
97 store ptr @test2_a, ptr %fptr
98 store ptr @test2_b2, ptr %fptr
99 store ptr @test2_b3, ptr %fptr
100 store ptr @test2_b1, ptr %fptr
101 %f = load ptr, ptr %fptr
106 ; CHECK: attributes #0 = { nofree nosync readnone }