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
6
7target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
8
9; Test 0
10;
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.
17
18define 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 noundef nonnull readonly align 64 dereferenceable(8) [[C]])
29; IS__TUNIT_OPM-NEXT:    ret void
30;
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 noundef nonnull readonly align 64 dereferenceable(8) [[C]])
41; IS__TUNIT_NPM-NEXT:    ret void
42;
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 noundef nonnull readonly align 64 dereferenceable(8) [[C]])
53; IS__CGSCC_OPM-NEXT:    ret void
54;
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 noundef nonnull readonly align 64 dereferenceable(8) [[C]])
65; IS__CGSCC_NPM-NEXT:    ret void
66;
67entry:
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
76}
77
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.
80define internal void @t0_callback_callee(i32* %is_not_null, i32* %ptr, i32* %a, i64 %b, i32** %c) {
81;
82; IS________OPM-LABEL: define {{[^@]+}}@t0_callback_callee
83; IS________OPM-SAME: (i32* nocapture noundef nonnull writeonly align 4 dereferenceable(4) [[IS_NOT_NULL:%.*]], i32* nocapture noundef nonnull readonly align 8 dereferenceable(4) [[PTR:%.*]], i32* align 256 [[A:%.*]], i64 [[B:%.*]], i32** nocapture 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
90;
91; IS________NPM-LABEL: define {{[^@]+}}@t0_callback_callee
92; IS________NPM-SAME: (i32* nocapture noundef nonnull writeonly align 4 dereferenceable(4) [[IS_NOT_NULL:%.*]], i32* nocapture noundef nonnull readonly align 8 dereferenceable(4) [[PTR:%.*]], i32* align 256 [[A:%.*]], i64 [[B:%.*]], i32** noalias nocapture 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
99;
100entry:
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
106}
107
108declare void @t0_check(i32* align 256, i64, i32*)
109
110declare !callback !0 void @t0_callback_broker(i32*, i32*, void (i32*, i32*, ...)*, ...)
111
112; Test 1
113;
114; Similar to test 0 but with some additional annotations (noalias/nocapute) to make sure
115; we deduce and propagate noalias and others properly.
116
117define void @t1_caller(i32* noalias %a) {
118;
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 noundef nonnull readonly align 64 dereferenceable(8) [[C]])
129; IS__TUNIT_OPM-NEXT:    ret void
130;
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 noundef nonnull readonly align 64 dereferenceable(8) [[C]])
141; IS__TUNIT_NPM-NEXT:    ret void
142;
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 noundef nonnull readonly align 64 dereferenceable(8) [[C]])
153; IS__CGSCC_OPM-NEXT:    ret void
154;
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 noundef nonnull readonly align 64 dereferenceable(8) [[C]])
165; IS__CGSCC_NPM-NEXT:    ret void
166;
167entry:
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
176}
177
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.
180define internal void @t1_callback_callee(i32* %is_not_null, i32* %ptr, i32* %a, i64 %b, i32** %c) {
181;
182; IS________OPM: Function Attrs: nosync
183; IS________OPM-LABEL: define {{[^@]+}}@t1_callback_callee
184; IS________OPM-SAME: (i32* nocapture noundef nonnull writeonly align 4 dereferenceable(4) [[IS_NOT_NULL:%.*]], i32* nocapture noundef nonnull readonly align 8 dereferenceable(4) [[PTR:%.*]], i32* nocapture align 256 [[A:%.*]], i64 [[B:%.*]], i32** nocapture 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
191;
192; IS________NPM: Function Attrs: nosync
193; IS________NPM-LABEL: define {{[^@]+}}@t1_callback_callee
194; IS________NPM-SAME: (i32* nocapture noundef nonnull writeonly align 4 dereferenceable(4) [[IS_NOT_NULL:%.*]], i32* nocapture noundef nonnull readonly align 8 dereferenceable(4) [[PTR:%.*]], i32* nocapture align 256 [[A:%.*]], i64 [[B:%.*]], i32** noalias nocapture 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
201;
202entry:
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
208}
209
210declare void @t1_check(i32* nocapture align 256, i64, i32* nocapture) nosync
211
212declare !callback !0 void @t1_callback_broker(i32* nocapture , i32* nocapture , void (i32*, i32*, ...)* nocapture, ...)
213
214; Test 2
215;
216; Similar to test 1 but checking that the noalias is only placed if potential synchronization through @t2_check is preserved.
217
218define 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 noundef nonnull readonly align 64 dereferenceable(8) [[C]])
229; IS__TUNIT_OPM-NEXT:    ret void
230;
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 noundef nonnull readonly align 64 dereferenceable(8) [[C]])
241; IS__TUNIT_NPM-NEXT:    ret void
242;
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 noundef nonnull readonly align 64 dereferenceable(8) [[C]])
253; IS__CGSCC_OPM-NEXT:    ret void
254;
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 noundef nonnull readonly align 64 dereferenceable(8) [[C]])
265; IS__CGSCC_NPM-NEXT:    ret void
266;
267entry:
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
276}
277
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.
280;
281; FIXME: We should derive noalias for %a and add a "fake use" of %a in all potentially synchronizing calls.
282define internal void @t2_callback_callee(i32* %is_not_null, i32* %ptr, i32* %a, i64 %b, i32** %c) {
283;
284; IS________OPM-LABEL: define {{[^@]+}}@t2_callback_callee
285; IS________OPM-SAME: (i32* nocapture noundef nonnull writeonly align 4 dereferenceable(4) [[IS_NOT_NULL:%.*]], i32* nocapture noundef nonnull readonly align 8 dereferenceable(4) [[PTR:%.*]], i32* nocapture align 256 [[A:%.*]], i64 [[B:%.*]], i32** nocapture 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
292;
293; IS________NPM-LABEL: define {{[^@]+}}@t2_callback_callee
294; IS________NPM-SAME: (i32* nocapture noundef nonnull writeonly align 4 dereferenceable(4) [[IS_NOT_NULL:%.*]], i32* nocapture noundef nonnull readonly align 8 dereferenceable(4) [[PTR:%.*]], i32* nocapture align 256 [[A:%.*]], i64 [[B:%.*]], i32** noalias nocapture 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
301;
302entry:
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
308}
309
310declare void @t2_check(i32* nocapture align 256, i64, i32* nocapture)
311
312declare !callback !0 void @t2_callback_broker(i32* nocapture , i32* nocapture , void (i32*, i32*, ...)* nocapture, ...)
313
314; Test 3
315;
316; Basically test 2 with the casted callback callee used twice.
317
318define 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 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 noundef nonnull readonly align 64 dereferenceable(8) [[C]])
330; IS__TUNIT_OPM-NEXT:    ret void
331;
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 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 noundef nonnull readonly align 64 dereferenceable(8) [[C]])
343; IS__TUNIT_NPM-NEXT:    ret void
344;
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 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 noundef nonnull readonly align 64 dereferenceable(8) [[C]])
356; IS__CGSCC_OPM-NEXT:    ret void
357;
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 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 noundef nonnull readonly align 64 dereferenceable(8) [[C]])
369; IS__CGSCC_NPM-NEXT:    ret void
370;
371entry:
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
381}
382
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.
385;
386; FIXME: We should derive noalias for %a and add a "fake use" of %a in all potentially synchronizing calls.
387define internal void @t3_callback_callee(i32* %is_not_null, i32* %ptr, i32* %a, i64 %b, i32** %c) {
388;
389; IS________OPM-LABEL: define {{[^@]+}}@t3_callback_callee
390; IS________OPM-SAME: (i32* nocapture noundef nonnull writeonly align 4 dereferenceable(4) [[IS_NOT_NULL:%.*]], i32* nocapture noundef nonnull readonly align 8 dereferenceable(4) [[PTR:%.*]], i32* nocapture align 256 [[A:%.*]], i64 [[B:%.*]], i32** nocapture 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
397;
398; IS________NPM-LABEL: define {{[^@]+}}@t3_callback_callee
399; IS________NPM-SAME: (i32* nocapture noundef nonnull writeonly align 4 dereferenceable(4) [[IS_NOT_NULL:%.*]], i32* nocapture noundef nonnull readonly align 8 dereferenceable(4) [[PTR:%.*]], i32* nocapture align 256 [[A:%.*]], i64 [[B:%.*]], i32** noalias nocapture 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
406;
407entry:
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
413}
414
415declare void @t3_check(i32* nocapture align 256, i64, i32* nocapture)
416
417declare !callback !0 void @t3_callback_broker(i32* nocapture , i32* nocapture , void (i32*, i32*, ...)* nocapture, ...)
418
419!0 = !{!1}
420!1 = !{i64 2, i64 -1, i64 -1, i1 true}
421;.
422; CHECK: attributes #[[ATTR0:[0-9]+]] = { nosync }
423;.
424; CHECK: [[META0:![0-9]+]] = !{!1}
425; CHECK: [[META1:![0-9]+]] = !{i64 2, i64 -1, i64 -1, i1 true}
426;.
427