[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / Attributor / callbacks.ll
blobd698f6f6ab1de42964e396bb0db804af33cb53b4
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=2 -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=2 -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 target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
9 ; Test 0
11 ; Make sure we propagate information from the caller to the callback callee but
12 ; only for arguments that are mapped through the callback metadata. Here, the
13 ; first two arguments of the call and the callback callee do not correspond to
14 ; each other but argument 3-5 of the transitive call site in the caller match
15 ; arguments 2-4 of the callback callee. Here we should see information and value
16 ; transfer in both directions.
18 define void @t0_caller(i32* %a) {
19 ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@t0_caller
20 ; IS__TUNIT_OPM-SAME: (i32* align 256 [[A:%.*]]) {
21 ; IS__TUNIT_OPM-NEXT:  entry:
22 ; IS__TUNIT_OPM-NEXT:    [[B:%.*]] = alloca i32, align 32
23 ; IS__TUNIT_OPM-NEXT:    [[C:%.*]] = alloca i32*, align 64
24 ; IS__TUNIT_OPM-NEXT:    [[PTR:%.*]] = alloca i32, align 128
25 ; IS__TUNIT_OPM-NEXT:    [[TMP0:%.*]] = bitcast i32* [[B]] to i8*
26 ; IS__TUNIT_OPM-NEXT:    store i32 42, i32* [[B]], align 32
27 ; IS__TUNIT_OPM-NEXT:    store i32* [[B]], i32** [[C]], align 64
28 ; IS__TUNIT_OPM-NEXT:    call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t0_callback_broker(i32* noalias nocapture noundef align 536870912 null, i32* noundef nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* noundef bitcast (void (i32*, i32*, i32*, i64, i32**)* @t0_callback_callee to void (i32*, i32*, ...)*), i32* align 256 [[A]], i64 undef, i32** nocapture nofree noundef nonnull readonly align 64 dereferenceable(8) [[C]])
29 ; IS__TUNIT_OPM-NEXT:    ret void
31 ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@t0_caller
32 ; IS__TUNIT_NPM-SAME: (i32* align 256 [[A:%.*]]) {
33 ; IS__TUNIT_NPM-NEXT:  entry:
34 ; IS__TUNIT_NPM-NEXT:    [[B:%.*]] = alloca i32, align 32
35 ; IS__TUNIT_NPM-NEXT:    [[C:%.*]] = alloca i32*, align 64
36 ; IS__TUNIT_NPM-NEXT:    [[PTR:%.*]] = alloca i32, align 128
37 ; IS__TUNIT_NPM-NEXT:    [[TMP0:%.*]] = bitcast i32* [[B]] to i8*
38 ; IS__TUNIT_NPM-NEXT:    store i32 42, i32* [[B]], align 32
39 ; IS__TUNIT_NPM-NEXT:    store i32* [[B]], i32** [[C]], align 64
40 ; IS__TUNIT_NPM-NEXT:    call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t0_callback_broker(i32* noalias nocapture noundef align 536870912 null, i32* noundef nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* noundef bitcast (void (i32*, i32*, i32*, i64, i32**)* @t0_callback_callee to void (i32*, i32*, ...)*), i32* align 256 [[A]], i64 undef, i32** noalias nocapture nofree noundef nonnull readonly align 64 dereferenceable(8) [[C]])
41 ; IS__TUNIT_NPM-NEXT:    ret void
43 ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@t0_caller
44 ; IS__CGSCC_OPM-SAME: (i32* align 256 [[A:%.*]]) {
45 ; IS__CGSCC_OPM-NEXT:  entry:
46 ; IS__CGSCC_OPM-NEXT:    [[B:%.*]] = alloca i32, align 32
47 ; IS__CGSCC_OPM-NEXT:    [[C:%.*]] = alloca i32*, align 64
48 ; IS__CGSCC_OPM-NEXT:    [[PTR:%.*]] = alloca i32, align 128
49 ; IS__CGSCC_OPM-NEXT:    [[TMP0:%.*]] = bitcast i32* [[B]] to i8*
50 ; IS__CGSCC_OPM-NEXT:    store i32 42, i32* [[B]], align 32
51 ; IS__CGSCC_OPM-NEXT:    store i32* [[B]], i32** [[C]], align 64
52 ; IS__CGSCC_OPM-NEXT:    call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t0_callback_broker(i32* noalias nocapture noundef align 536870912 null, i32* noundef nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* noundef bitcast (void (i32*, i32*, i32*, i64, i32**)* @t0_callback_callee to void (i32*, i32*, ...)*), i32* align 256 [[A]], i64 noundef 99, i32** nocapture nofree noundef nonnull readonly align 64 dereferenceable(8) [[C]])
53 ; IS__CGSCC_OPM-NEXT:    ret void
55 ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@t0_caller
56 ; IS__CGSCC_NPM-SAME: (i32* align 256 [[A:%.*]]) {
57 ; IS__CGSCC_NPM-NEXT:  entry:
58 ; IS__CGSCC_NPM-NEXT:    [[B:%.*]] = alloca i32, align 32
59 ; IS__CGSCC_NPM-NEXT:    [[C:%.*]] = alloca i32*, align 64
60 ; IS__CGSCC_NPM-NEXT:    [[PTR:%.*]] = alloca i32, align 128
61 ; IS__CGSCC_NPM-NEXT:    [[TMP0:%.*]] = bitcast i32* [[B]] to i8*
62 ; IS__CGSCC_NPM-NEXT:    store i32 42, i32* [[B]], align 32
63 ; IS__CGSCC_NPM-NEXT:    store i32* [[B]], i32** [[C]], align 64
64 ; IS__CGSCC_NPM-NEXT:    call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t0_callback_broker(i32* noalias nocapture noundef align 536870912 null, i32* noundef nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* noundef bitcast (void (i32*, i32*, i32*, i64, i32**)* @t0_callback_callee to void (i32*, i32*, ...)*), i32* align 256 [[A]], i64 noundef 99, i32** noalias nocapture nofree noundef nonnull readonly align 64 dereferenceable(8) [[C]])
65 ; IS__CGSCC_NPM-NEXT:    ret void
67 entry:
68   %b = alloca i32, align 32
69   %c = alloca i32*, align 64
70   %ptr = alloca i32, align 128
71   %0 = bitcast i32* %b to i8*
72   store i32 42, i32* %b, align 4
73   store i32* %b, i32** %c, align 8
74   call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t0_callback_broker(i32* null, i32* %ptr, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*, i64, i32**)* @t0_callback_callee to void (i32*, i32*, ...)*), i32* %a, i64 99, i32** %c)
75   ret void
78 ; Note that the first two arguments are provided by the callback_broker according to the callback in !1 below!
79 ; The others are annotated with alignment information, amongst others, or even replaced by the constants passed to the call.
80 define internal void @t0_callback_callee(i32* %is_not_null, i32* %ptr, i32* %a, i64 %b, i32** %c) {
82 ; IS________OPM-LABEL: define {{[^@]+}}@t0_callback_callee
83 ; IS________OPM-SAME: (i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[IS_NOT_NULL:%.*]], i32* nocapture nofree noundef nonnull readonly align 8 dereferenceable(4) [[PTR:%.*]], i32* align 256 [[A:%.*]], i64 [[B:%.*]], i32** nocapture nofree noundef nonnull readonly align 64 dereferenceable(8) [[C:%.*]]) {
84 ; IS________OPM-NEXT:  entry:
85 ; IS________OPM-NEXT:    [[PTR_VAL:%.*]] = load i32, i32* [[PTR]], align 8
86 ; IS________OPM-NEXT:    store i32 [[PTR_VAL]], i32* [[IS_NOT_NULL]], align 4
87 ; IS________OPM-NEXT:    [[TMP0:%.*]] = load i32*, i32** [[C]], align 64
88 ; IS________OPM-NEXT:    tail call void @t0_check(i32* align 256 [[A]], i64 noundef 99, i32* [[TMP0]])
89 ; IS________OPM-NEXT:    ret void
91 ; IS________NPM-LABEL: define {{[^@]+}}@t0_callback_callee
92 ; IS________NPM-SAME: (i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[IS_NOT_NULL:%.*]], i32* nocapture nofree noundef nonnull readonly align 8 dereferenceable(4) [[PTR:%.*]], i32* align 256 [[A:%.*]], i64 [[B:%.*]], i32** noalias nocapture nofree noundef nonnull readonly align 64 dereferenceable(8) [[C:%.*]]) {
93 ; IS________NPM-NEXT:  entry:
94 ; IS________NPM-NEXT:    [[PTR_VAL:%.*]] = load i32, i32* [[PTR]], align 8
95 ; IS________NPM-NEXT:    store i32 [[PTR_VAL]], i32* [[IS_NOT_NULL]], align 4
96 ; IS________NPM-NEXT:    [[TMP0:%.*]] = load i32*, i32** [[C]], align 64
97 ; IS________NPM-NEXT:    tail call void @t0_check(i32* align 256 [[A]], i64 noundef 99, i32* [[TMP0]])
98 ; IS________NPM-NEXT:    ret void
100 entry:
101   %ptr_val = load i32, i32* %ptr, align 8
102   store i32 %ptr_val, i32* %is_not_null
103   %0 = load i32*, i32** %c, align 8
104   tail call void @t0_check(i32* %a, i64 %b, i32* %0)
105   ret void
108 declare void @t0_check(i32* align 256, i64, i32*)
110 declare !callback !0 void @t0_callback_broker(i32*, i32*, void (i32*, i32*, ...)*, ...)
112 ; Test 1
114 ; Similar to test 0 but with some additional annotations (noalias/nocapute) to make sure
115 ; we deduce and propagate noalias and others properly.
117 define void @t1_caller(i32* noalias %a) {
119 ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@t1_caller
120 ; IS__TUNIT_OPM-SAME: (i32* noalias nocapture align 256 [[A:%.*]]) {
121 ; IS__TUNIT_OPM-NEXT:  entry:
122 ; IS__TUNIT_OPM-NEXT:    [[B:%.*]] = alloca i32, align 32
123 ; IS__TUNIT_OPM-NEXT:    [[C:%.*]] = alloca i32*, align 64
124 ; IS__TUNIT_OPM-NEXT:    [[PTR:%.*]] = alloca i32, align 128
125 ; IS__TUNIT_OPM-NEXT:    [[TMP0:%.*]] = bitcast i32* [[B]] to i8*
126 ; IS__TUNIT_OPM-NEXT:    store i32 42, i32* [[B]], align 32
127 ; IS__TUNIT_OPM-NEXT:    store i32* [[B]], i32** [[C]], align 64
128 ; IS__TUNIT_OPM-NEXT:    call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t1_callback_broker(i32* noalias nocapture noundef align 536870912 null, i32* nocapture noundef nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nocapture noundef bitcast (void (i32*, i32*, i32*, i64, i32**)* @t1_callback_callee to void (i32*, i32*, ...)*), i32* nocapture align 256 [[A]], i64 undef, i32** nocapture nofree noundef nonnull readonly align 64 dereferenceable(8) [[C]])
129 ; IS__TUNIT_OPM-NEXT:    ret void
131 ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@t1_caller
132 ; IS__TUNIT_NPM-SAME: (i32* noalias nocapture align 256 [[A:%.*]]) {
133 ; IS__TUNIT_NPM-NEXT:  entry:
134 ; IS__TUNIT_NPM-NEXT:    [[B:%.*]] = alloca i32, align 32
135 ; IS__TUNIT_NPM-NEXT:    [[C:%.*]] = alloca i32*, align 64
136 ; IS__TUNIT_NPM-NEXT:    [[PTR:%.*]] = alloca i32, align 128
137 ; IS__TUNIT_NPM-NEXT:    [[TMP0:%.*]] = bitcast i32* [[B]] to i8*
138 ; IS__TUNIT_NPM-NEXT:    store i32 42, i32* [[B]], align 32
139 ; IS__TUNIT_NPM-NEXT:    store i32* [[B]], i32** [[C]], align 64
140 ; IS__TUNIT_NPM-NEXT:    call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t1_callback_broker(i32* noalias nocapture noundef align 536870912 null, i32* noalias nocapture noundef nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nocapture noundef bitcast (void (i32*, i32*, i32*, i64, i32**)* @t1_callback_callee to void (i32*, i32*, ...)*), i32* nocapture align 256 [[A]], i64 undef, i32** noalias nocapture nofree noundef nonnull readonly align 64 dereferenceable(8) [[C]])
141 ; IS__TUNIT_NPM-NEXT:    ret void
143 ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@t1_caller
144 ; IS__CGSCC_OPM-SAME: (i32* noalias nocapture align 256 [[A:%.*]]) {
145 ; IS__CGSCC_OPM-NEXT:  entry:
146 ; IS__CGSCC_OPM-NEXT:    [[B:%.*]] = alloca i32, align 32
147 ; IS__CGSCC_OPM-NEXT:    [[C:%.*]] = alloca i32*, align 64
148 ; IS__CGSCC_OPM-NEXT:    [[PTR:%.*]] = alloca i32, align 128
149 ; IS__CGSCC_OPM-NEXT:    [[TMP0:%.*]] = bitcast i32* [[B]] to i8*
150 ; IS__CGSCC_OPM-NEXT:    store i32 42, i32* [[B]], align 32
151 ; IS__CGSCC_OPM-NEXT:    store i32* [[B]], i32** [[C]], align 64
152 ; IS__CGSCC_OPM-NEXT:    call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t1_callback_broker(i32* noalias nocapture noundef align 536870912 null, i32* nocapture noundef nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nocapture noundef bitcast (void (i32*, i32*, i32*, i64, i32**)* @t1_callback_callee to void (i32*, i32*, ...)*), i32* nocapture align 256 [[A]], i64 noundef 99, i32** nocapture nofree noundef nonnull readonly align 64 dereferenceable(8) [[C]])
153 ; IS__CGSCC_OPM-NEXT:    ret void
155 ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@t1_caller
156 ; IS__CGSCC_NPM-SAME: (i32* noalias nocapture align 256 [[A:%.*]]) {
157 ; IS__CGSCC_NPM-NEXT:  entry:
158 ; IS__CGSCC_NPM-NEXT:    [[B:%.*]] = alloca i32, align 32
159 ; IS__CGSCC_NPM-NEXT:    [[C:%.*]] = alloca i32*, align 64
160 ; IS__CGSCC_NPM-NEXT:    [[PTR:%.*]] = alloca i32, align 128
161 ; IS__CGSCC_NPM-NEXT:    [[TMP0:%.*]] = bitcast i32* [[B]] to i8*
162 ; IS__CGSCC_NPM-NEXT:    store i32 42, i32* [[B]], align 32
163 ; IS__CGSCC_NPM-NEXT:    store i32* [[B]], i32** [[C]], align 64
164 ; IS__CGSCC_NPM-NEXT:    call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t1_callback_broker(i32* noalias nocapture noundef align 536870912 null, i32* noalias nocapture noundef nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nocapture noundef bitcast (void (i32*, i32*, i32*, i64, i32**)* @t1_callback_callee to void (i32*, i32*, ...)*), i32* nocapture align 256 [[A]], i64 noundef 99, i32** noalias nocapture nofree noundef nonnull readonly align 64 dereferenceable(8) [[C]])
165 ; IS__CGSCC_NPM-NEXT:    ret void
167 entry:
168   %b = alloca i32, align 32
169   %c = alloca i32*, align 64
170   %ptr = alloca i32, align 128
171   %0 = bitcast i32* %b to i8*
172   store i32 42, i32* %b, align 4
173   store i32* %b, i32** %c, align 8
174   call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t1_callback_broker(i32* null, i32* %ptr, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*, i64, i32**)* @t1_callback_callee to void (i32*, i32*, ...)*), i32* %a, i64 99, i32** %c)
175   ret void
178 ; Note that the first two arguments are provided by the callback_broker according to the callback in !1 below!
179 ; The others are annotated with alignment information, amongst others, or even replaced by the constants passed to the call.
180 define internal void @t1_callback_callee(i32* %is_not_null, i32* %ptr, i32* %a, i64 %b, i32** %c) {
182 ; IS________OPM: Function Attrs: nosync
183 ; IS________OPM-LABEL: define {{[^@]+}}@t1_callback_callee
184 ; IS________OPM-SAME: (i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[IS_NOT_NULL:%.*]], i32* nocapture nofree noundef nonnull readonly align 8 dereferenceable(4) [[PTR:%.*]], i32* nocapture align 256 [[A:%.*]], i64 [[B:%.*]], i32** nocapture nofree noundef nonnull readonly align 64 dereferenceable(8) [[C:%.*]]) #[[ATTR0:[0-9]+]] {
185 ; IS________OPM-NEXT:  entry:
186 ; IS________OPM-NEXT:    [[PTR_VAL:%.*]] = load i32, i32* [[PTR]], align 8
187 ; IS________OPM-NEXT:    store i32 [[PTR_VAL]], i32* [[IS_NOT_NULL]], align 4
188 ; IS________OPM-NEXT:    [[TMP0:%.*]] = load i32*, i32** [[C]], align 64
189 ; IS________OPM-NEXT:    tail call void @t1_check(i32* nocapture align 256 [[A]], i64 noundef 99, i32* nocapture [[TMP0]])
190 ; IS________OPM-NEXT:    ret void
192 ; IS________NPM: Function Attrs: nosync
193 ; IS________NPM-LABEL: define {{[^@]+}}@t1_callback_callee
194 ; IS________NPM-SAME: (i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[IS_NOT_NULL:%.*]], i32* nocapture nofree noundef nonnull readonly align 8 dereferenceable(4) [[PTR:%.*]], i32* nocapture align 256 [[A:%.*]], i64 [[B:%.*]], i32** noalias nocapture nofree noundef nonnull readonly align 64 dereferenceable(8) [[C:%.*]]) #[[ATTR0:[0-9]+]] {
195 ; IS________NPM-NEXT:  entry:
196 ; IS________NPM-NEXT:    [[PTR_VAL:%.*]] = load i32, i32* [[PTR]], align 8
197 ; IS________NPM-NEXT:    store i32 [[PTR_VAL]], i32* [[IS_NOT_NULL]], align 4
198 ; IS________NPM-NEXT:    [[TMP0:%.*]] = load i32*, i32** [[C]], align 64
199 ; IS________NPM-NEXT:    tail call void @t1_check(i32* nocapture align 256 [[A]], i64 noundef 99, i32* nocapture [[TMP0]])
200 ; IS________NPM-NEXT:    ret void
202 entry:
203   %ptr_val = load i32, i32* %ptr, align 8
204   store i32 %ptr_val, i32* %is_not_null
205   %0 = load i32*, i32** %c, align 8
206   tail call void @t1_check(i32* %a, i64 %b, i32* %0)
207   ret void
210 declare void @t1_check(i32* nocapture align 256, i64, i32* nocapture) nosync
212 declare !callback !0 void @t1_callback_broker(i32* nocapture , i32* nocapture , void (i32*, i32*, ...)* nocapture, ...)
214 ; Test 2
216 ; Similar to test 1 but checking that the noalias is only placed if potential synchronization through @t2_check is preserved.
218 define void @t2_caller(i32* noalias %a) {
219 ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@t2_caller
220 ; IS__TUNIT_OPM-SAME: (i32* noalias nocapture align 256 [[A:%.*]]) {
221 ; IS__TUNIT_OPM-NEXT:  entry:
222 ; IS__TUNIT_OPM-NEXT:    [[B:%.*]] = alloca i32, align 32
223 ; IS__TUNIT_OPM-NEXT:    [[C:%.*]] = alloca i32*, align 64
224 ; IS__TUNIT_OPM-NEXT:    [[PTR:%.*]] = alloca i32, align 128
225 ; IS__TUNIT_OPM-NEXT:    [[TMP0:%.*]] = bitcast i32* [[B]] to i8*
226 ; IS__TUNIT_OPM-NEXT:    store i32 42, i32* [[B]], align 32
227 ; IS__TUNIT_OPM-NEXT:    store i32* [[B]], i32** [[C]], align 64
228 ; IS__TUNIT_OPM-NEXT:    call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t2_callback_broker(i32* noalias nocapture noundef align 536870912 null, i32* nocapture noundef nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nocapture noundef bitcast (void (i32*, i32*, i32*, i64, i32**)* @t2_callback_callee to void (i32*, i32*, ...)*), i32* nocapture align 256 [[A]], i64 undef, i32** nocapture nofree noundef nonnull readonly align 64 dereferenceable(8) [[C]])
229 ; IS__TUNIT_OPM-NEXT:    ret void
231 ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@t2_caller
232 ; IS__TUNIT_NPM-SAME: (i32* noalias nocapture align 256 [[A:%.*]]) {
233 ; IS__TUNIT_NPM-NEXT:  entry:
234 ; IS__TUNIT_NPM-NEXT:    [[B:%.*]] = alloca i32, align 32
235 ; IS__TUNIT_NPM-NEXT:    [[C:%.*]] = alloca i32*, align 64
236 ; IS__TUNIT_NPM-NEXT:    [[PTR:%.*]] = alloca i32, align 128
237 ; IS__TUNIT_NPM-NEXT:    [[TMP0:%.*]] = bitcast i32* [[B]] to i8*
238 ; IS__TUNIT_NPM-NEXT:    store i32 42, i32* [[B]], align 32
239 ; IS__TUNIT_NPM-NEXT:    store i32* [[B]], i32** [[C]], align 64
240 ; IS__TUNIT_NPM-NEXT:    call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t2_callback_broker(i32* noalias nocapture noundef align 536870912 null, i32* noalias nocapture noundef nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nocapture noundef bitcast (void (i32*, i32*, i32*, i64, i32**)* @t2_callback_callee to void (i32*, i32*, ...)*), i32* nocapture align 256 [[A]], i64 undef, i32** noalias nocapture nofree noundef nonnull readonly align 64 dereferenceable(8) [[C]])
241 ; IS__TUNIT_NPM-NEXT:    ret void
243 ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@t2_caller
244 ; IS__CGSCC_OPM-SAME: (i32* noalias nocapture align 256 [[A:%.*]]) {
245 ; IS__CGSCC_OPM-NEXT:  entry:
246 ; IS__CGSCC_OPM-NEXT:    [[B:%.*]] = alloca i32, align 32
247 ; IS__CGSCC_OPM-NEXT:    [[C:%.*]] = alloca i32*, align 64
248 ; IS__CGSCC_OPM-NEXT:    [[PTR:%.*]] = alloca i32, align 128
249 ; IS__CGSCC_OPM-NEXT:    [[TMP0:%.*]] = bitcast i32* [[B]] to i8*
250 ; IS__CGSCC_OPM-NEXT:    store i32 42, i32* [[B]], align 32
251 ; IS__CGSCC_OPM-NEXT:    store i32* [[B]], i32** [[C]], align 64
252 ; IS__CGSCC_OPM-NEXT:    call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t2_callback_broker(i32* noalias nocapture noundef align 536870912 null, i32* nocapture noundef nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nocapture noundef bitcast (void (i32*, i32*, i32*, i64, i32**)* @t2_callback_callee to void (i32*, i32*, ...)*), i32* nocapture align 256 [[A]], i64 noundef 99, i32** nocapture nofree noundef nonnull readonly align 64 dereferenceable(8) [[C]])
253 ; IS__CGSCC_OPM-NEXT:    ret void
255 ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@t2_caller
256 ; IS__CGSCC_NPM-SAME: (i32* noalias nocapture align 256 [[A:%.*]]) {
257 ; IS__CGSCC_NPM-NEXT:  entry:
258 ; IS__CGSCC_NPM-NEXT:    [[B:%.*]] = alloca i32, align 32
259 ; IS__CGSCC_NPM-NEXT:    [[C:%.*]] = alloca i32*, align 64
260 ; IS__CGSCC_NPM-NEXT:    [[PTR:%.*]] = alloca i32, align 128
261 ; IS__CGSCC_NPM-NEXT:    [[TMP0:%.*]] = bitcast i32* [[B]] to i8*
262 ; IS__CGSCC_NPM-NEXT:    store i32 42, i32* [[B]], align 32
263 ; IS__CGSCC_NPM-NEXT:    store i32* [[B]], i32** [[C]], align 64
264 ; IS__CGSCC_NPM-NEXT:    call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t2_callback_broker(i32* noalias nocapture noundef align 536870912 null, i32* noalias nocapture noundef nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nocapture noundef bitcast (void (i32*, i32*, i32*, i64, i32**)* @t2_callback_callee to void (i32*, i32*, ...)*), i32* nocapture align 256 [[A]], i64 noundef 99, i32** noalias nocapture nofree noundef nonnull readonly align 64 dereferenceable(8) [[C]])
265 ; IS__CGSCC_NPM-NEXT:    ret void
267 entry:
268   %b = alloca i32, align 32
269   %c = alloca i32*, align 64
270   %ptr = alloca i32, align 128
271   %0 = bitcast i32* %b to i8*
272   store i32 42, i32* %b, align 4
273   store i32* %b, i32** %c, align 8
274   call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t2_callback_broker(i32* null, i32* %ptr, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*, i64, i32**)* @t2_callback_callee to void (i32*, i32*, ...)*), i32* %a, i64 99, i32** %c)
275   ret void
278 ; Note that the first two arguments are provided by the callback_broker according to the callback in !1 below!
279 ; The others are annotated with alignment information, amongst others, or even replaced by the constants passed to the call.
281 ; FIXME: We should derive noalias for %a and add a "fake use" of %a in all potentially synchronizing calls.
282 define internal void @t2_callback_callee(i32* %is_not_null, i32* %ptr, i32* %a, i64 %b, i32** %c) {
284 ; IS________OPM-LABEL: define {{[^@]+}}@t2_callback_callee
285 ; IS________OPM-SAME: (i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[IS_NOT_NULL:%.*]], i32* nocapture nofree noundef nonnull readonly align 8 dereferenceable(4) [[PTR:%.*]], i32* nocapture align 256 [[A:%.*]], i64 [[B:%.*]], i32** nocapture nofree noundef nonnull readonly align 64 dereferenceable(8) [[C:%.*]]) {
286 ; IS________OPM-NEXT:  entry:
287 ; IS________OPM-NEXT:    [[PTR_VAL:%.*]] = load i32, i32* [[PTR]], align 8
288 ; IS________OPM-NEXT:    store i32 [[PTR_VAL]], i32* [[IS_NOT_NULL]], align 4
289 ; IS________OPM-NEXT:    [[TMP0:%.*]] = load i32*, i32** [[C]], align 64
290 ; IS________OPM-NEXT:    tail call void @t2_check(i32* nocapture align 256 [[A]], i64 noundef 99, i32* nocapture [[TMP0]])
291 ; IS________OPM-NEXT:    ret void
293 ; IS________NPM-LABEL: define {{[^@]+}}@t2_callback_callee
294 ; IS________NPM-SAME: (i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[IS_NOT_NULL:%.*]], i32* nocapture nofree noundef nonnull readonly align 8 dereferenceable(4) [[PTR:%.*]], i32* nocapture align 256 [[A:%.*]], i64 [[B:%.*]], i32** noalias nocapture nofree noundef nonnull readonly align 64 dereferenceable(8) [[C:%.*]]) {
295 ; IS________NPM-NEXT:  entry:
296 ; IS________NPM-NEXT:    [[PTR_VAL:%.*]] = load i32, i32* [[PTR]], align 8
297 ; IS________NPM-NEXT:    store i32 [[PTR_VAL]], i32* [[IS_NOT_NULL]], align 4
298 ; IS________NPM-NEXT:    [[TMP0:%.*]] = load i32*, i32** [[C]], align 64
299 ; IS________NPM-NEXT:    tail call void @t2_check(i32* nocapture align 256 [[A]], i64 noundef 99, i32* nocapture [[TMP0]])
300 ; IS________NPM-NEXT:    ret void
302 entry:
303   %ptr_val = load i32, i32* %ptr, align 8
304   store i32 %ptr_val, i32* %is_not_null
305   %0 = load i32*, i32** %c, align 8
306   tail call void @t2_check(i32* %a, i64 %b, i32* %0)
307   ret void
310 declare void @t2_check(i32* nocapture align 256, i64, i32* nocapture)
312 declare !callback !0 void @t2_callback_broker(i32* nocapture , i32* nocapture , void (i32*, i32*, ...)* nocapture, ...)
314 ; Test 3
316 ; Basically test 2 with the casted callback callee used twice.
318 define void @t3_caller(i32* noalias %a) {
319 ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@t3_caller
320 ; IS__TUNIT_OPM-SAME: (i32* noalias nocapture align 256 [[A:%.*]]) {
321 ; IS__TUNIT_OPM-NEXT:  entry:
322 ; IS__TUNIT_OPM-NEXT:    [[B:%.*]] = alloca i32, align 32
323 ; IS__TUNIT_OPM-NEXT:    [[C:%.*]] = alloca i32*, align 64
324 ; IS__TUNIT_OPM-NEXT:    [[PTR:%.*]] = alloca i32, align 128
325 ; IS__TUNIT_OPM-NEXT:    [[TMP0:%.*]] = bitcast i32* [[B]] to i8*
326 ; IS__TUNIT_OPM-NEXT:    store i32 42, i32* [[B]], align 32
327 ; IS__TUNIT_OPM-NEXT:    store i32* [[B]], i32** [[C]], align 64
328 ; IS__TUNIT_OPM-NEXT:    call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t3_callback_broker(i32* noalias nocapture noundef align 536870912 null, i32* nocapture noundef nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nocapture noundef bitcast (void (i32*, i32*, i32*, i64, i32**)* @t3_callback_callee to void (i32*, i32*, ...)*), i32* nocapture align 256 [[A]], i64 undef, i32** nocapture nofree noundef nonnull readonly align 64 dereferenceable(8) [[C]])
329 ; IS__TUNIT_OPM-NEXT:    call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t3_callback_broker(i32* noalias nocapture noundef align 536870912 null, i32* nocapture noundef nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nocapture noundef bitcast (void (i32*, i32*, i32*, i64, i32**)* @t3_callback_callee to void (i32*, i32*, ...)*), i32* nocapture align 256 [[A]], i64 undef, i32** nocapture nofree noundef nonnull readonly align 64 dereferenceable(8) [[C]])
330 ; IS__TUNIT_OPM-NEXT:    ret void
332 ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@t3_caller
333 ; IS__TUNIT_NPM-SAME: (i32* noalias nocapture align 256 [[A:%.*]]) {
334 ; IS__TUNIT_NPM-NEXT:  entry:
335 ; IS__TUNIT_NPM-NEXT:    [[B:%.*]] = alloca i32, align 32
336 ; IS__TUNIT_NPM-NEXT:    [[C:%.*]] = alloca i32*, align 64
337 ; IS__TUNIT_NPM-NEXT:    [[PTR:%.*]] = alloca i32, align 128
338 ; IS__TUNIT_NPM-NEXT:    [[TMP0:%.*]] = bitcast i32* [[B]] to i8*
339 ; IS__TUNIT_NPM-NEXT:    store i32 42, i32* [[B]], align 32
340 ; IS__TUNIT_NPM-NEXT:    store i32* [[B]], i32** [[C]], align 64
341 ; IS__TUNIT_NPM-NEXT:    call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t3_callback_broker(i32* noalias nocapture noundef align 536870912 null, i32* noalias nocapture noundef nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nocapture noundef bitcast (void (i32*, i32*, i32*, i64, i32**)* @t3_callback_callee to void (i32*, i32*, ...)*), i32* nocapture align 256 [[A]], i64 undef, i32** noalias nocapture nofree noundef nonnull readonly align 64 dereferenceable(8) [[C]])
342 ; IS__TUNIT_NPM-NEXT:    call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t3_callback_broker(i32* noalias nocapture noundef align 536870912 null, i32* noalias nocapture noundef nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nocapture noundef bitcast (void (i32*, i32*, i32*, i64, i32**)* @t3_callback_callee to void (i32*, i32*, ...)*), i32* nocapture align 256 [[A]], i64 undef, i32** noalias nocapture nofree noundef nonnull readonly align 64 dereferenceable(8) [[C]])
343 ; IS__TUNIT_NPM-NEXT:    ret void
345 ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@t3_caller
346 ; IS__CGSCC_OPM-SAME: (i32* noalias nocapture align 256 [[A:%.*]]) {
347 ; IS__CGSCC_OPM-NEXT:  entry:
348 ; IS__CGSCC_OPM-NEXT:    [[B:%.*]] = alloca i32, align 32
349 ; IS__CGSCC_OPM-NEXT:    [[C:%.*]] = alloca i32*, align 64
350 ; IS__CGSCC_OPM-NEXT:    [[PTR:%.*]] = alloca i32, align 128
351 ; IS__CGSCC_OPM-NEXT:    [[TMP0:%.*]] = bitcast i32* [[B]] to i8*
352 ; IS__CGSCC_OPM-NEXT:    store i32 42, i32* [[B]], align 32
353 ; IS__CGSCC_OPM-NEXT:    store i32* [[B]], i32** [[C]], align 64
354 ; IS__CGSCC_OPM-NEXT:    call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t3_callback_broker(i32* noalias nocapture noundef align 536870912 null, i32* nocapture noundef nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nocapture noundef bitcast (void (i32*, i32*, i32*, i64, i32**)* @t3_callback_callee to void (i32*, i32*, ...)*), i32* nocapture align 256 [[A]], i64 noundef 99, i32** nocapture nofree noundef nonnull readonly align 64 dereferenceable(8) [[C]])
355 ; IS__CGSCC_OPM-NEXT:    call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t3_callback_broker(i32* noalias nocapture noundef align 536870912 null, i32* nocapture noundef nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nocapture noundef bitcast (void (i32*, i32*, i32*, i64, i32**)* @t3_callback_callee to void (i32*, i32*, ...)*), i32* nocapture align 256 [[A]], i64 noundef 99, i32** nocapture nofree noundef nonnull readonly align 64 dereferenceable(8) [[C]])
356 ; IS__CGSCC_OPM-NEXT:    ret void
358 ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@t3_caller
359 ; IS__CGSCC_NPM-SAME: (i32* noalias nocapture align 256 [[A:%.*]]) {
360 ; IS__CGSCC_NPM-NEXT:  entry:
361 ; IS__CGSCC_NPM-NEXT:    [[B:%.*]] = alloca i32, align 32
362 ; IS__CGSCC_NPM-NEXT:    [[C:%.*]] = alloca i32*, align 64
363 ; IS__CGSCC_NPM-NEXT:    [[PTR:%.*]] = alloca i32, align 128
364 ; IS__CGSCC_NPM-NEXT:    [[TMP0:%.*]] = bitcast i32* [[B]] to i8*
365 ; IS__CGSCC_NPM-NEXT:    store i32 42, i32* [[B]], align 32
366 ; IS__CGSCC_NPM-NEXT:    store i32* [[B]], i32** [[C]], align 64
367 ; IS__CGSCC_NPM-NEXT:    call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t3_callback_broker(i32* noalias nocapture noundef align 536870912 null, i32* noalias nocapture noundef nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nocapture noundef bitcast (void (i32*, i32*, i32*, i64, i32**)* @t3_callback_callee to void (i32*, i32*, ...)*), i32* nocapture align 256 [[A]], i64 noundef 99, i32** noalias nocapture nofree noundef nonnull readonly align 64 dereferenceable(8) [[C]])
368 ; IS__CGSCC_NPM-NEXT:    call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t3_callback_broker(i32* noalias nocapture noundef align 536870912 null, i32* noalias nocapture noundef nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nocapture noundef bitcast (void (i32*, i32*, i32*, i64, i32**)* @t3_callback_callee to void (i32*, i32*, ...)*), i32* nocapture align 256 [[A]], i64 noundef 99, i32** noalias nocapture nofree noundef nonnull readonly align 64 dereferenceable(8) [[C]])
369 ; IS__CGSCC_NPM-NEXT:    ret void
371 entry:
372   %b = alloca i32, align 32
373   %c = alloca i32*, align 64
374   %ptr = alloca i32, align 128
375   %0 = bitcast i32* %b to i8*
376   store i32 42, i32* %b, align 4
377   store i32* %b, i32** %c, align 8
378   call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t3_callback_broker(i32* null, i32* %ptr, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*, i64, i32**)* @t3_callback_callee to void (i32*, i32*, ...)*), i32* %a, i64 99, i32** %c)
379   call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t3_callback_broker(i32* null, i32* %ptr, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*, i64, i32**)* @t3_callback_callee to void (i32*, i32*, ...)*), i32* %a, i64 99, i32** %c)
380   ret void
383 ; Note that the first two arguments are provided by the callback_broker according to the callback in !1 below!
384 ; The others are annotated with alignment information, amongst others, or even replaced by the constants passed to the call.
386 ; FIXME: We should derive noalias for %a and add a "fake use" of %a in all potentially synchronizing calls.
387 define internal void @t3_callback_callee(i32* %is_not_null, i32* %ptr, i32* %a, i64 %b, i32** %c) {
389 ; IS________OPM-LABEL: define {{[^@]+}}@t3_callback_callee
390 ; IS________OPM-SAME: (i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[IS_NOT_NULL:%.*]], i32* nocapture nofree noundef nonnull readonly align 8 dereferenceable(4) [[PTR:%.*]], i32* nocapture align 256 [[A:%.*]], i64 [[B:%.*]], i32** nocapture nofree noundef nonnull readonly align 64 dereferenceable(8) [[C:%.*]]) {
391 ; IS________OPM-NEXT:  entry:
392 ; IS________OPM-NEXT:    [[PTR_VAL:%.*]] = load i32, i32* [[PTR]], align 8
393 ; IS________OPM-NEXT:    store i32 [[PTR_VAL]], i32* [[IS_NOT_NULL]], align 4
394 ; IS________OPM-NEXT:    [[TMP0:%.*]] = load i32*, i32** [[C]], align 64
395 ; IS________OPM-NEXT:    tail call void @t3_check(i32* nocapture align 256 [[A]], i64 noundef 99, i32* nocapture [[TMP0]])
396 ; IS________OPM-NEXT:    ret void
398 ; IS________NPM-LABEL: define {{[^@]+}}@t3_callback_callee
399 ; IS________NPM-SAME: (i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[IS_NOT_NULL:%.*]], i32* nocapture nofree noundef nonnull readonly align 8 dereferenceable(4) [[PTR:%.*]], i32* nocapture align 256 [[A:%.*]], i64 [[B:%.*]], i32** noalias nocapture nofree noundef nonnull readonly align 64 dereferenceable(8) [[C:%.*]]) {
400 ; IS________NPM-NEXT:  entry:
401 ; IS________NPM-NEXT:    [[PTR_VAL:%.*]] = load i32, i32* [[PTR]], align 8
402 ; IS________NPM-NEXT:    store i32 [[PTR_VAL]], i32* [[IS_NOT_NULL]], align 4
403 ; IS________NPM-NEXT:    [[TMP0:%.*]] = load i32*, i32** [[C]], align 64
404 ; IS________NPM-NEXT:    tail call void @t3_check(i32* nocapture align 256 [[A]], i64 noundef 99, i32* nocapture [[TMP0]])
405 ; IS________NPM-NEXT:    ret void
407 entry:
408   %ptr_val = load i32, i32* %ptr, align 8
409   store i32 %ptr_val, i32* %is_not_null
410   %0 = load i32*, i32** %c, align 8
411   tail call void @t3_check(i32* %a, i64 %b, i32* %0)
412   ret void
415 declare void @t3_check(i32* nocapture align 256, i64, i32* nocapture)
417 declare !callback !0 void @t3_callback_broker(i32* nocapture , i32* nocapture , void (i32*, i32*, ...)* nocapture, ...)
419 !0 = !{!1}
420 !1 = !{i64 2, i64 -1, i64 -1, i1 true}
422 ; CHECK: attributes #[[ATTR0:[0-9]+]] = { nosync }
424 ; CHECK: [[META0:![0-9]+]] = !{!1}
425 ; CHECK: [[META1:![0-9]+]] = !{i64 2, i64 -1, i64 -1, i1 true}