1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals
2 ; RUN: opt -attributor -enable-new-pm=0 -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=6 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM
3 ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=6 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM
4 ; RUN: opt -attributor-cgscc -enable-new-pm=0 -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM
5 ; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_OPM,IS__CGSCC____,IS________NPM,IS__CGSCC_NPM
7 ; musttail call result can't be replaced with a constant, unless the call can be removed
9 declare i32 @external()
11 define i8* @start(i8 %v) {
13 ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@start
14 ; IS__TUNIT_OPM-SAME: (i8 [[V:%.*]]) {
15 ; IS__TUNIT_OPM-NEXT: [[C1:%.*]] = icmp eq i8 [[V]], 0
16 ; IS__TUNIT_OPM-NEXT: br i1 [[C1]], label [[TRUE:%.*]], label [[FALSE:%.*]]
17 ; IS__TUNIT_OPM: true:
18 ; IS__TUNIT_OPM-NEXT: [[CA:%.*]] = musttail call i8* @side_effects(i8 [[V]])
19 ; IS__TUNIT_OPM-NEXT: ret i8* [[CA]]
20 ; IS__TUNIT_OPM: false:
21 ; IS__TUNIT_OPM-NEXT: [[C2:%.*]] = icmp eq i8 [[V]], 1
22 ; IS__TUNIT_OPM-NEXT: br i1 [[C2]], label [[C2_TRUE:%.*]], label [[C2_FALSE:%.*]]
23 ; IS__TUNIT_OPM: c2_true:
24 ; IS__TUNIT_OPM-NEXT: ret i8* null
25 ; IS__TUNIT_OPM: c2_false:
26 ; IS__TUNIT_OPM-NEXT: [[CA2:%.*]] = musttail call i8* @dont_zap_me(i8 undef)
27 ; IS__TUNIT_OPM-NEXT: ret i8* [[CA2]]
29 ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@start
30 ; IS__TUNIT_NPM-SAME: (i8 [[V:%.*]]) {
31 ; IS__TUNIT_NPM-NEXT: [[C1:%.*]] = icmp eq i8 [[V]], 0
32 ; IS__TUNIT_NPM-NEXT: br i1 [[C1]], label [[TRUE:%.*]], label [[FALSE:%.*]]
33 ; IS__TUNIT_NPM: true:
34 ; IS__TUNIT_NPM-NEXT: [[CA:%.*]] = musttail call i8* @side_effects(i8 undef)
35 ; IS__TUNIT_NPM-NEXT: ret i8* [[CA]]
36 ; IS__TUNIT_NPM: false:
37 ; IS__TUNIT_NPM-NEXT: [[C2:%.*]] = icmp eq i8 [[V]], 1
38 ; IS__TUNIT_NPM-NEXT: br i1 [[C2]], label [[C2_TRUE:%.*]], label [[C2_FALSE:%.*]]
39 ; IS__TUNIT_NPM: c2_true:
40 ; IS__TUNIT_NPM-NEXT: ret i8* null
41 ; IS__TUNIT_NPM: c2_false:
42 ; IS__TUNIT_NPM-NEXT: [[CA2:%.*]] = musttail call i8* @dont_zap_me(i8 undef)
43 ; IS__TUNIT_NPM-NEXT: ret i8* [[CA2]]
45 ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@start
46 ; IS__CGSCC_OPM-SAME: (i8 [[V:%.*]]) {
47 ; IS__CGSCC_OPM-NEXT: [[C1:%.*]] = icmp eq i8 [[V]], 0
48 ; IS__CGSCC_OPM-NEXT: br i1 [[C1]], label [[TRUE:%.*]], label [[FALSE:%.*]]
49 ; IS__CGSCC_OPM: true:
50 ; IS__CGSCC_OPM-NEXT: [[CA:%.*]] = musttail call i8* @side_effects(i8 [[V]])
51 ; IS__CGSCC_OPM-NEXT: ret i8* [[CA]]
52 ; IS__CGSCC_OPM: false:
53 ; IS__CGSCC_OPM-NEXT: [[C2:%.*]] = icmp eq i8 [[V]], 1
54 ; IS__CGSCC_OPM-NEXT: br i1 [[C2]], label [[C2_TRUE:%.*]], label [[C2_FALSE:%.*]]
55 ; IS__CGSCC_OPM: c2_true:
56 ; IS__CGSCC_OPM-NEXT: ret i8* undef
57 ; IS__CGSCC_OPM: c2_false:
58 ; IS__CGSCC_OPM-NEXT: [[CA2:%.*]] = musttail call i8* @dont_zap_me(i8 undef)
59 ; IS__CGSCC_OPM-NEXT: ret i8* [[CA2]]
61 ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@start
62 ; IS__CGSCC_NPM-SAME: (i8 [[V:%.*]]) {
63 ; IS__CGSCC_NPM-NEXT: [[C1:%.*]] = icmp eq i8 [[V]], 0
64 ; IS__CGSCC_NPM-NEXT: br i1 [[C1]], label [[TRUE:%.*]], label [[FALSE:%.*]]
65 ; IS__CGSCC_NPM: true:
66 ; IS__CGSCC_NPM-NEXT: [[CA:%.*]] = musttail call i8* @side_effects(i8 undef)
67 ; IS__CGSCC_NPM-NEXT: ret i8* [[CA]]
68 ; IS__CGSCC_NPM: false:
69 ; IS__CGSCC_NPM-NEXT: [[C2:%.*]] = icmp eq i8 [[V]], 1
70 ; IS__CGSCC_NPM-NEXT: br i1 [[C2]], label [[C2_TRUE:%.*]], label [[C2_FALSE:%.*]]
71 ; IS__CGSCC_NPM: c2_true:
72 ; IS__CGSCC_NPM-NEXT: ret i8* undef
73 ; IS__CGSCC_NPM: c2_false:
74 ; IS__CGSCC_NPM-NEXT: [[CA2:%.*]] = musttail call i8* @dont_zap_me(i8 undef)
75 ; IS__CGSCC_NPM-NEXT: ret i8* [[CA2]]
77 %c1 = icmp eq i8 %v, 0
78 br i1 %c1, label %true, label %false
80 ; FIXME: propagate the value information for %v
81 %ca = musttail call i8* @side_effects(i8 %v)
84 %c2 = icmp eq i8 %v, 1
85 br i1 %c2, label %c2_true, label %c2_false
87 %ca1 = musttail call i8* @no_side_effects(i8 %v)
90 %ca2 = musttail call i8* @dont_zap_me(i8 %v)
94 define internal i8* @side_effects(i8 %v) {
95 ; IS________OPM-LABEL: define {{[^@]+}}@side_effects
96 ; IS________OPM-SAME: (i8 [[V:%.*]]) {
97 ; IS________OPM-NEXT: [[I1:%.*]] = call i32 @external()
98 ; IS________OPM-NEXT: [[CA:%.*]] = musttail call i8* @start(i8 [[V]])
99 ; IS________OPM-NEXT: ret i8* [[CA]]
101 ; IS________NPM-LABEL: define {{[^@]+}}@side_effects
102 ; IS________NPM-SAME: (i8 [[V:%.*]]) {
103 ; IS________NPM-NEXT: [[I1:%.*]] = call i32 @external()
104 ; IS________NPM-NEXT: [[CA:%.*]] = musttail call i8* @start(i8 noundef 0)
105 ; IS________NPM-NEXT: ret i8* [[CA]]
107 %i1 = call i32 @external()
109 ; since this goes back to `start` the SCPP should be see that the return value
111 ; The call can't be removed due to `external` call above, though.
113 %ca = musttail call i8* @start(i8 %v)
115 ; Thus the result must be returned anyway
119 define internal i8* @no_side_effects(i8 %v) readonly nounwind {
120 ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
121 ; IS__CGSCC____-LABEL: define {{[^@]+}}@no_side_effects
122 ; IS__CGSCC____-SAME: (i8 [[V:%.*]]) #[[ATTR0:[0-9]+]] {
123 ; IS__CGSCC____-NEXT: ret i8* undef
128 define internal i8* @dont_zap_me(i8 %v) {
129 ; CHECK-LABEL: define {{[^@]+}}@dont_zap_me
130 ; CHECK-SAME: (i8 [[V:%.*]]) {
131 ; CHECK-NEXT: [[I1:%.*]] = call i32 @external()
132 ; CHECK-NEXT: ret i8* undef
134 %i1 = call i32 @external()
138 ; IS__CGSCC____: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn }