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 4294967296 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
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 4294967296 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
42;
43; IS__CGSCC____-LABEL: define {{[^@]+}}@t0_caller
44; IS__CGSCC____-SAME: (i32* align 256 [[A:%.*]]) {
45; IS__CGSCC____-NEXT:  entry:
46; IS__CGSCC____-NEXT:    [[B:%.*]] = alloca i32, align 32
47; IS__CGSCC____-NEXT:    [[C:%.*]] = alloca i32*, align 64
48; IS__CGSCC____-NEXT:    [[PTR:%.*]] = alloca i32, align 128
49; IS__CGSCC____-NEXT:    [[TMP0:%.*]] = bitcast i32* [[B]] to i8*
50; IS__CGSCC____-NEXT:    store i32 42, i32* [[B]], align 32
51; IS__CGSCC____-NEXT:    store i32* [[B]], i32** [[C]], align 64
52; IS__CGSCC____-NEXT:    call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t0_callback_broker(i32* noalias nocapture noundef align 4294967296 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** nofree noundef nonnull readonly align 64 dereferenceable(8) [[C]])
53; IS__CGSCC____-NEXT:    ret void
54;
55entry:
56  %b = alloca i32, align 32
57  %c = alloca i32*, align 64
58  %ptr = alloca i32, align 128
59  %0 = bitcast i32* %b to i8*
60  store i32 42, i32* %b, align 4
61  store i32* %b, i32** %c, align 8
62  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)
63  ret void
64}
65
66; Note that the first two arguments are provided by the callback_broker according to the callback in !1 below!
67; The others are annotated with alignment information, amongst others, or even replaced by the constants passed to the call.
68define internal void @t0_callback_callee(i32* %is_not_null, i32* %ptr, i32* %a, i64 %b, i32** %c) {
69;
70; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@t0_callback_callee
71; IS__TUNIT_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:%.*]]) {
72; IS__TUNIT_OPM-NEXT:  entry:
73; IS__TUNIT_OPM-NEXT:    [[PTR_VAL:%.*]] = load i32, i32* [[PTR]], align 8
74; IS__TUNIT_OPM-NEXT:    store i32 [[PTR_VAL]], i32* [[IS_NOT_NULL]], align 4
75; IS__TUNIT_OPM-NEXT:    [[TMP0:%.*]] = load i32*, i32** [[C]], align 64
76; IS__TUNIT_OPM-NEXT:    tail call void @t0_check(i32* align 256 [[A]], i64 noundef 99, i32* nonnull align 32 [[TMP0]])
77; IS__TUNIT_OPM-NEXT:    ret void
78;
79; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@t0_callback_callee
80; IS__TUNIT_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:%.*]]) {
81; IS__TUNIT_NPM-NEXT:  entry:
82; IS__TUNIT_NPM-NEXT:    [[PTR_VAL:%.*]] = load i32, i32* [[PTR]], align 8
83; IS__TUNIT_NPM-NEXT:    store i32 [[PTR_VAL]], i32* [[IS_NOT_NULL]], align 4
84; IS__TUNIT_NPM-NEXT:    [[TMP0:%.*]] = load i32*, i32** [[C]], align 64
85; IS__TUNIT_NPM-NEXT:    tail call void @t0_check(i32* align 256 [[A]], i64 noundef 99, i32* nonnull align 32 [[TMP0]])
86; IS__TUNIT_NPM-NEXT:    ret void
87;
88; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@t0_callback_callee
89; IS__CGSCC_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:%.*]]) {
90; IS__CGSCC_OPM-NEXT:  entry:
91; IS__CGSCC_OPM-NEXT:    [[PTR_VAL:%.*]] = load i32, i32* [[PTR]], align 8
92; IS__CGSCC_OPM-NEXT:    store i32 [[PTR_VAL]], i32* [[IS_NOT_NULL]], align 4
93; IS__CGSCC_OPM-NEXT:    [[TMP0:%.*]] = load i32*, i32** [[C]], align 64
94; IS__CGSCC_OPM-NEXT:    tail call void @t0_check(i32* align 256 [[A]], i64 noundef 99, i32* [[TMP0]])
95; IS__CGSCC_OPM-NEXT:    ret void
96;
97; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@t0_callback_callee
98; IS__CGSCC_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:%.*]]) {
99; IS__CGSCC_NPM-NEXT:  entry:
100; IS__CGSCC_NPM-NEXT:    [[PTR_VAL:%.*]] = load i32, i32* [[PTR]], align 8
101; IS__CGSCC_NPM-NEXT:    store i32 [[PTR_VAL]], i32* [[IS_NOT_NULL]], align 4
102; IS__CGSCC_NPM-NEXT:    [[TMP0:%.*]] = load i32*, i32** [[C]], align 64
103; IS__CGSCC_NPM-NEXT:    tail call void @t0_check(i32* align 256 [[A]], i64 noundef 99, i32* [[TMP0]])
104; IS__CGSCC_NPM-NEXT:    ret void
105;
106entry:
107  %ptr_val = load i32, i32* %ptr, align 8
108  store i32 %ptr_val, i32* %is_not_null
109  %0 = load i32*, i32** %c, align 8
110  tail call void @t0_check(i32* %a, i64 %b, i32* %0)
111  ret void
112}
113
114declare void @t0_check(i32* align 256, i64, i32*)
115
116declare !callback !0 void @t0_callback_broker(i32*, i32*, void (i32*, i32*, ...)*, ...)
117
118; Test 1
119;
120; Similar to test 0 but with some additional annotations (noalias/nocapute) to make sure
121; we deduce and propagate noalias and others properly.
122
123define void @t1_caller(i32* noalias %a) {
124;
125; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@t1_caller
126; IS__TUNIT_OPM-SAME: (i32* noalias nocapture align 256 [[A:%.*]]) {
127; IS__TUNIT_OPM-NEXT:  entry:
128; IS__TUNIT_OPM-NEXT:    [[B:%.*]] = alloca i32, align 32
129; IS__TUNIT_OPM-NEXT:    [[C:%.*]] = alloca i32*, align 64
130; IS__TUNIT_OPM-NEXT:    [[PTR:%.*]] = alloca i32, align 128
131; IS__TUNIT_OPM-NEXT:    [[TMP0:%.*]] = bitcast i32* [[B]] to i8*
132; IS__TUNIT_OPM-NEXT:    store i32 42, i32* [[B]], align 32
133; IS__TUNIT_OPM-NEXT:    store i32* [[B]], i32** [[C]], align 64
134; IS__TUNIT_OPM-NEXT:    call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t1_callback_broker(i32* noalias nocapture noundef align 4294967296 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]])
135; IS__TUNIT_OPM-NEXT:    ret void
136;
137; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@t1_caller
138; IS__TUNIT_NPM-SAME: (i32* noalias nocapture align 256 [[A:%.*]]) {
139; IS__TUNIT_NPM-NEXT:  entry:
140; IS__TUNIT_NPM-NEXT:    [[B:%.*]] = alloca i32, align 32
141; IS__TUNIT_NPM-NEXT:    [[C:%.*]] = alloca i32*, align 64
142; IS__TUNIT_NPM-NEXT:    [[PTR:%.*]] = alloca i32, align 128
143; IS__TUNIT_NPM-NEXT:    [[TMP0:%.*]] = bitcast i32* [[B]] to i8*
144; IS__TUNIT_NPM-NEXT:    store i32 42, i32* [[B]], align 32
145; IS__TUNIT_NPM-NEXT:    store i32* [[B]], i32** [[C]], align 64
146; IS__TUNIT_NPM-NEXT:    call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t1_callback_broker(i32* noalias nocapture noundef align 4294967296 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]])
147; IS__TUNIT_NPM-NEXT:    ret void
148;
149; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@t1_caller
150; IS__CGSCC_OPM-SAME: (i32* noalias align 256 [[A:%.*]]) {
151; IS__CGSCC_OPM-NEXT:  entry:
152; IS__CGSCC_OPM-NEXT:    [[B:%.*]] = alloca i32, align 32
153; IS__CGSCC_OPM-NEXT:    [[C:%.*]] = alloca i32*, align 64
154; IS__CGSCC_OPM-NEXT:    [[PTR:%.*]] = alloca i32, align 128
155; IS__CGSCC_OPM-NEXT:    [[TMP0:%.*]] = bitcast i32* [[B]] to i8*
156; IS__CGSCC_OPM-NEXT:    store i32 42, i32* [[B]], align 32
157; IS__CGSCC_OPM-NEXT:    store i32* [[B]], i32** [[C]], align 64
158; IS__CGSCC_OPM-NEXT:    call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t1_callback_broker(i32* noalias nocapture noundef align 4294967296 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* align 256 [[A]], i64 noundef 99, i32** nofree noundef nonnull readonly align 64 dereferenceable(8) [[C]])
159; IS__CGSCC_OPM-NEXT:    ret void
160;
161; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@t1_caller
162; IS__CGSCC_NPM-SAME: (i32* noalias align 256 [[A:%.*]]) {
163; IS__CGSCC_NPM-NEXT:  entry:
164; IS__CGSCC_NPM-NEXT:    [[B:%.*]] = alloca i32, align 32
165; IS__CGSCC_NPM-NEXT:    [[C:%.*]] = alloca i32*, align 64
166; IS__CGSCC_NPM-NEXT:    [[PTR:%.*]] = alloca i32, align 128
167; IS__CGSCC_NPM-NEXT:    [[TMP0:%.*]] = bitcast i32* [[B]] to i8*
168; IS__CGSCC_NPM-NEXT:    store i32 42, i32* [[B]], align 32
169; IS__CGSCC_NPM-NEXT:    store i32* [[B]], i32** [[C]], align 64
170; IS__CGSCC_NPM-NEXT:    call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t1_callback_broker(i32* noalias nocapture noundef align 4294967296 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* align 256 [[A]], i64 noundef 99, i32** nofree noundef nonnull readonly align 64 dereferenceable(8) [[C]])
171; IS__CGSCC_NPM-NEXT:    ret void
172;
173entry:
174  %b = alloca i32, align 32
175  %c = alloca i32*, align 64
176  %ptr = alloca i32, align 128
177  %0 = bitcast i32* %b to i8*
178  store i32 42, i32* %b, align 4
179  store i32* %b, i32** %c, align 8
180  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)
181  ret void
182}
183
184; Note that the first two arguments are provided by the callback_broker according to the callback in !1 below!
185; The others are annotated with alignment information, amongst others, or even replaced by the constants passed to the call.
186define internal void @t1_callback_callee(i32* %is_not_null, i32* %ptr, i32* %a, i64 %b, i32** %c) {
187;
188; IS__TUNIT_OPM: Function Attrs: nosync
189; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@t1_callback_callee
190; IS__TUNIT_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]+]] {
191; IS__TUNIT_OPM-NEXT:  entry:
192; IS__TUNIT_OPM-NEXT:    [[PTR_VAL:%.*]] = load i32, i32* [[PTR]], align 8
193; IS__TUNIT_OPM-NEXT:    store i32 [[PTR_VAL]], i32* [[IS_NOT_NULL]], align 4
194; IS__TUNIT_OPM-NEXT:    [[TMP0:%.*]] = load i32*, i32** [[C]], align 64
195; IS__TUNIT_OPM-NEXT:    tail call void @t1_check(i32* nocapture align 256 [[A]], i64 noundef 99, i32* nocapture nonnull align 32 [[TMP0]])
196; IS__TUNIT_OPM-NEXT:    ret void
197;
198; IS__TUNIT_NPM: Function Attrs: nosync
199; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@t1_callback_callee
200; IS__TUNIT_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]+]] {
201; IS__TUNIT_NPM-NEXT:  entry:
202; IS__TUNIT_NPM-NEXT:    [[PTR_VAL:%.*]] = load i32, i32* [[PTR]], align 8
203; IS__TUNIT_NPM-NEXT:    store i32 [[PTR_VAL]], i32* [[IS_NOT_NULL]], align 4
204; IS__TUNIT_NPM-NEXT:    [[TMP0:%.*]] = load i32*, i32** [[C]], align 64
205; IS__TUNIT_NPM-NEXT:    tail call void @t1_check(i32* nocapture align 256 [[A]], i64 noundef 99, i32* nocapture nonnull align 32 [[TMP0]])
206; IS__TUNIT_NPM-NEXT:    ret void
207;
208; IS__CGSCC_OPM: Function Attrs: nosync
209; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@t1_callback_callee
210; IS__CGSCC_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]+]] {
211; IS__CGSCC_OPM-NEXT:  entry:
212; IS__CGSCC_OPM-NEXT:    [[PTR_VAL:%.*]] = load i32, i32* [[PTR]], align 8
213; IS__CGSCC_OPM-NEXT:    store i32 [[PTR_VAL]], i32* [[IS_NOT_NULL]], align 4
214; IS__CGSCC_OPM-NEXT:    [[TMP0:%.*]] = load i32*, i32** [[C]], align 64
215; IS__CGSCC_OPM-NEXT:    tail call void @t1_check(i32* nocapture align 256 [[A]], i64 noundef 99, i32* nocapture [[TMP0]])
216; IS__CGSCC_OPM-NEXT:    ret void
217;
218; IS__CGSCC_NPM: Function Attrs: nosync
219; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@t1_callback_callee
220; IS__CGSCC_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]+]] {
221; IS__CGSCC_NPM-NEXT:  entry:
222; IS__CGSCC_NPM-NEXT:    [[PTR_VAL:%.*]] = load i32, i32* [[PTR]], align 8
223; IS__CGSCC_NPM-NEXT:    store i32 [[PTR_VAL]], i32* [[IS_NOT_NULL]], align 4
224; IS__CGSCC_NPM-NEXT:    [[TMP0:%.*]] = load i32*, i32** [[C]], align 64
225; IS__CGSCC_NPM-NEXT:    tail call void @t1_check(i32* nocapture align 256 [[A]], i64 noundef 99, i32* nocapture [[TMP0]])
226; IS__CGSCC_NPM-NEXT:    ret void
227;
228entry:
229  %ptr_val = load i32, i32* %ptr, align 8
230  store i32 %ptr_val, i32* %is_not_null
231  %0 = load i32*, i32** %c, align 8
232  tail call void @t1_check(i32* %a, i64 %b, i32* %0)
233  ret void
234}
235
236declare void @t1_check(i32* nocapture align 256, i64, i32* nocapture) nosync
237
238declare !callback !0 void @t1_callback_broker(i32* nocapture , i32* nocapture , void (i32*, i32*, ...)* nocapture, ...)
239
240; Test 2
241;
242; Similar to test 1 but checking that the noalias is only placed if potential synchronization through @t2_check is preserved.
243
244define void @t2_caller(i32* noalias %a) {
245; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@t2_caller
246; IS__TUNIT_OPM-SAME: (i32* noalias nocapture align 256 [[A:%.*]]) {
247; IS__TUNIT_OPM-NEXT:  entry:
248; IS__TUNIT_OPM-NEXT:    [[B:%.*]] = alloca i32, align 32
249; IS__TUNIT_OPM-NEXT:    [[C:%.*]] = alloca i32*, align 64
250; IS__TUNIT_OPM-NEXT:    [[PTR:%.*]] = alloca i32, align 128
251; IS__TUNIT_OPM-NEXT:    [[TMP0:%.*]] = bitcast i32* [[B]] to i8*
252; IS__TUNIT_OPM-NEXT:    store i32 42, i32* [[B]], align 32
253; IS__TUNIT_OPM-NEXT:    store i32* [[B]], i32** [[C]], align 64
254; IS__TUNIT_OPM-NEXT:    call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t2_callback_broker(i32* noalias nocapture noundef align 4294967296 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]])
255; IS__TUNIT_OPM-NEXT:    ret void
256;
257; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@t2_caller
258; IS__TUNIT_NPM-SAME: (i32* noalias nocapture align 256 [[A:%.*]]) {
259; IS__TUNIT_NPM-NEXT:  entry:
260; IS__TUNIT_NPM-NEXT:    [[B:%.*]] = alloca i32, align 32
261; IS__TUNIT_NPM-NEXT:    [[C:%.*]] = alloca i32*, align 64
262; IS__TUNIT_NPM-NEXT:    [[PTR:%.*]] = alloca i32, align 128
263; IS__TUNIT_NPM-NEXT:    [[TMP0:%.*]] = bitcast i32* [[B]] to i8*
264; IS__TUNIT_NPM-NEXT:    store i32 42, i32* [[B]], align 32
265; IS__TUNIT_NPM-NEXT:    store i32* [[B]], i32** [[C]], align 64
266; IS__TUNIT_NPM-NEXT:    call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t2_callback_broker(i32* noalias nocapture noundef align 4294967296 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]])
267; IS__TUNIT_NPM-NEXT:    ret void
268;
269; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@t2_caller
270; IS__CGSCC_OPM-SAME: (i32* noalias align 256 [[A:%.*]]) {
271; IS__CGSCC_OPM-NEXT:  entry:
272; IS__CGSCC_OPM-NEXT:    [[B:%.*]] = alloca i32, align 32
273; IS__CGSCC_OPM-NEXT:    [[C:%.*]] = alloca i32*, align 64
274; IS__CGSCC_OPM-NEXT:    [[PTR:%.*]] = alloca i32, align 128
275; IS__CGSCC_OPM-NEXT:    [[TMP0:%.*]] = bitcast i32* [[B]] to i8*
276; IS__CGSCC_OPM-NEXT:    store i32 42, i32* [[B]], align 32
277; IS__CGSCC_OPM-NEXT:    store i32* [[B]], i32** [[C]], align 64
278; IS__CGSCC_OPM-NEXT:    call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t2_callback_broker(i32* noalias nocapture noundef align 4294967296 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* align 256 [[A]], i64 noundef 99, i32** nofree noundef nonnull readonly align 64 dereferenceable(8) [[C]])
279; IS__CGSCC_OPM-NEXT:    ret void
280;
281; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@t2_caller
282; IS__CGSCC_NPM-SAME: (i32* noalias align 256 [[A:%.*]]) {
283; IS__CGSCC_NPM-NEXT:  entry:
284; IS__CGSCC_NPM-NEXT:    [[B:%.*]] = alloca i32, align 32
285; IS__CGSCC_NPM-NEXT:    [[C:%.*]] = alloca i32*, align 64
286; IS__CGSCC_NPM-NEXT:    [[PTR:%.*]] = alloca i32, align 128
287; IS__CGSCC_NPM-NEXT:    [[TMP0:%.*]] = bitcast i32* [[B]] to i8*
288; IS__CGSCC_NPM-NEXT:    store i32 42, i32* [[B]], align 32
289; IS__CGSCC_NPM-NEXT:    store i32* [[B]], i32** [[C]], align 64
290; IS__CGSCC_NPM-NEXT:    call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t2_callback_broker(i32* noalias nocapture noundef align 4294967296 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* align 256 [[A]], i64 noundef 99, i32** nofree noundef nonnull readonly align 64 dereferenceable(8) [[C]])
291; IS__CGSCC_NPM-NEXT:    ret void
292;
293entry:
294  %b = alloca i32, align 32
295  %c = alloca i32*, align 64
296  %ptr = alloca i32, align 128
297  %0 = bitcast i32* %b to i8*
298  store i32 42, i32* %b, align 4
299  store i32* %b, i32** %c, align 8
300  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)
301  ret void
302}
303
304; Note that the first two arguments are provided by the callback_broker according to the callback in !1 below!
305; The others are annotated with alignment information, amongst others, or even replaced by the constants passed to the call.
306;
307; FIXME: We should derive noalias for %a and add a "fake use" of %a in all potentially synchronizing calls.
308define internal void @t2_callback_callee(i32* %is_not_null, i32* %ptr, i32* %a, i64 %b, i32** %c) {
309;
310; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@t2_callback_callee
311; IS__TUNIT_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:%.*]]) {
312; IS__TUNIT_OPM-NEXT:  entry:
313; IS__TUNIT_OPM-NEXT:    [[PTR_VAL:%.*]] = load i32, i32* [[PTR]], align 8
314; IS__TUNIT_OPM-NEXT:    store i32 [[PTR_VAL]], i32* [[IS_NOT_NULL]], align 4
315; IS__TUNIT_OPM-NEXT:    [[TMP0:%.*]] = load i32*, i32** [[C]], align 64
316; IS__TUNIT_OPM-NEXT:    tail call void @t2_check(i32* nocapture align 256 [[A]], i64 noundef 99, i32* nocapture nonnull align 32 [[TMP0]])
317; IS__TUNIT_OPM-NEXT:    ret void
318;
319; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@t2_callback_callee
320; IS__TUNIT_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:%.*]]) {
321; IS__TUNIT_NPM-NEXT:  entry:
322; IS__TUNIT_NPM-NEXT:    [[PTR_VAL:%.*]] = load i32, i32* [[PTR]], align 8
323; IS__TUNIT_NPM-NEXT:    store i32 [[PTR_VAL]], i32* [[IS_NOT_NULL]], align 4
324; IS__TUNIT_NPM-NEXT:    [[TMP0:%.*]] = load i32*, i32** [[C]], align 64
325; IS__TUNIT_NPM-NEXT:    tail call void @t2_check(i32* nocapture align 256 [[A]], i64 noundef 99, i32* nocapture nonnull align 32 [[TMP0]])
326; IS__TUNIT_NPM-NEXT:    ret void
327;
328; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@t2_callback_callee
329; IS__CGSCC_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:%.*]]) {
330; IS__CGSCC_OPM-NEXT:  entry:
331; IS__CGSCC_OPM-NEXT:    [[PTR_VAL:%.*]] = load i32, i32* [[PTR]], align 8
332; IS__CGSCC_OPM-NEXT:    store i32 [[PTR_VAL]], i32* [[IS_NOT_NULL]], align 4
333; IS__CGSCC_OPM-NEXT:    [[TMP0:%.*]] = load i32*, i32** [[C]], align 64
334; IS__CGSCC_OPM-NEXT:    tail call void @t2_check(i32* nocapture align 256 [[A]], i64 noundef 99, i32* nocapture [[TMP0]])
335; IS__CGSCC_OPM-NEXT:    ret void
336;
337; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@t2_callback_callee
338; IS__CGSCC_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:%.*]]) {
339; IS__CGSCC_NPM-NEXT:  entry:
340; IS__CGSCC_NPM-NEXT:    [[PTR_VAL:%.*]] = load i32, i32* [[PTR]], align 8
341; IS__CGSCC_NPM-NEXT:    store i32 [[PTR_VAL]], i32* [[IS_NOT_NULL]], align 4
342; IS__CGSCC_NPM-NEXT:    [[TMP0:%.*]] = load i32*, i32** [[C]], align 64
343; IS__CGSCC_NPM-NEXT:    tail call void @t2_check(i32* nocapture align 256 [[A]], i64 noundef 99, i32* nocapture [[TMP0]])
344; IS__CGSCC_NPM-NEXT:    ret void
345;
346entry:
347  %ptr_val = load i32, i32* %ptr, align 8
348  store i32 %ptr_val, i32* %is_not_null
349  %0 = load i32*, i32** %c, align 8
350  tail call void @t2_check(i32* %a, i64 %b, i32* %0)
351  ret void
352}
353
354declare void @t2_check(i32* nocapture align 256, i64, i32* nocapture)
355
356declare !callback !0 void @t2_callback_broker(i32* nocapture , i32* nocapture , void (i32*, i32*, ...)* nocapture, ...)
357
358; Test 3
359;
360; Basically test 2 with the casted callback callee used twice.
361
362define void @t3_caller(i32* noalias %a) {
363; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@t3_caller
364; IS__TUNIT_OPM-SAME: (i32* noalias nocapture align 256 [[A:%.*]]) {
365; IS__TUNIT_OPM-NEXT:  entry:
366; IS__TUNIT_OPM-NEXT:    [[B:%.*]] = alloca i32, align 32
367; IS__TUNIT_OPM-NEXT:    [[C:%.*]] = alloca i32*, align 64
368; IS__TUNIT_OPM-NEXT:    [[PTR:%.*]] = alloca i32, align 128
369; IS__TUNIT_OPM-NEXT:    [[TMP0:%.*]] = bitcast i32* [[B]] to i8*
370; IS__TUNIT_OPM-NEXT:    store i32 42, i32* [[B]], align 32
371; IS__TUNIT_OPM-NEXT:    store i32* [[B]], i32** [[C]], align 64
372; IS__TUNIT_OPM-NEXT:    call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t3_callback_broker(i32* noalias nocapture noundef align 4294967296 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]])
373; IS__TUNIT_OPM-NEXT:    call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t3_callback_broker(i32* noalias nocapture noundef align 4294967296 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]])
374; IS__TUNIT_OPM-NEXT:    ret void
375;
376; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@t3_caller
377; IS__TUNIT_NPM-SAME: (i32* noalias nocapture align 256 [[A:%.*]]) {
378; IS__TUNIT_NPM-NEXT:  entry:
379; IS__TUNIT_NPM-NEXT:    [[B:%.*]] = alloca i32, align 32
380; IS__TUNIT_NPM-NEXT:    [[C:%.*]] = alloca i32*, align 64
381; IS__TUNIT_NPM-NEXT:    [[PTR:%.*]] = alloca i32, align 128
382; IS__TUNIT_NPM-NEXT:    [[TMP0:%.*]] = bitcast i32* [[B]] to i8*
383; IS__TUNIT_NPM-NEXT:    store i32 42, i32* [[B]], align 32
384; IS__TUNIT_NPM-NEXT:    store i32* [[B]], i32** [[C]], align 64
385; IS__TUNIT_NPM-NEXT:    call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t3_callback_broker(i32* noalias nocapture noundef align 4294967296 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]])
386; IS__TUNIT_NPM-NEXT:    call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t3_callback_broker(i32* noalias nocapture noundef align 4294967296 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]])
387; IS__TUNIT_NPM-NEXT:    ret void
388;
389; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@t3_caller
390; IS__CGSCC_OPM-SAME: (i32* noalias align 256 [[A:%.*]]) {
391; IS__CGSCC_OPM-NEXT:  entry:
392; IS__CGSCC_OPM-NEXT:    [[B:%.*]] = alloca i32, align 32
393; IS__CGSCC_OPM-NEXT:    [[C:%.*]] = alloca i32*, align 64
394; IS__CGSCC_OPM-NEXT:    [[PTR:%.*]] = alloca i32, align 128
395; IS__CGSCC_OPM-NEXT:    [[TMP0:%.*]] = bitcast i32* [[B]] to i8*
396; IS__CGSCC_OPM-NEXT:    store i32 42, i32* [[B]], align 32
397; IS__CGSCC_OPM-NEXT:    store i32* [[B]], i32** [[C]], align 64
398; IS__CGSCC_OPM-NEXT:    call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t3_callback_broker(i32* noalias nocapture noundef align 4294967296 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* align 256 [[A]], i64 noundef 99, i32** nofree noundef nonnull readonly align 64 dereferenceable(8) [[C]])
399; IS__CGSCC_OPM-NEXT:    call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t3_callback_broker(i32* noalias nocapture noundef align 4294967296 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* align 256 [[A]], i64 noundef 99, i32** nofree noundef nonnull readonly align 64 dereferenceable(8) [[C]])
400; IS__CGSCC_OPM-NEXT:    ret void
401;
402; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@t3_caller
403; IS__CGSCC_NPM-SAME: (i32* noalias align 256 [[A:%.*]]) {
404; IS__CGSCC_NPM-NEXT:  entry:
405; IS__CGSCC_NPM-NEXT:    [[B:%.*]] = alloca i32, align 32
406; IS__CGSCC_NPM-NEXT:    [[C:%.*]] = alloca i32*, align 64
407; IS__CGSCC_NPM-NEXT:    [[PTR:%.*]] = alloca i32, align 128
408; IS__CGSCC_NPM-NEXT:    [[TMP0:%.*]] = bitcast i32* [[B]] to i8*
409; IS__CGSCC_NPM-NEXT:    store i32 42, i32* [[B]], align 32
410; IS__CGSCC_NPM-NEXT:    store i32* [[B]], i32** [[C]], align 64
411; IS__CGSCC_NPM-NEXT:    call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t3_callback_broker(i32* noalias nocapture noundef align 4294967296 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* align 256 [[A]], i64 noundef 99, i32** nofree noundef nonnull readonly align 64 dereferenceable(8) [[C]])
412; IS__CGSCC_NPM-NEXT:    call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t3_callback_broker(i32* noalias nocapture noundef align 4294967296 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* align 256 [[A]], i64 noundef 99, i32** nofree noundef nonnull readonly align 64 dereferenceable(8) [[C]])
413; IS__CGSCC_NPM-NEXT:    ret void
414;
415entry:
416  %b = alloca i32, align 32
417  %c = alloca i32*, align 64
418  %ptr = alloca i32, align 128
419  %0 = bitcast i32* %b to i8*
420  store i32 42, i32* %b, align 4
421  store i32* %b, i32** %c, align 8
422  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)
423  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)
424  ret void
425}
426
427; Note that the first two arguments are provided by the callback_broker according to the callback in !1 below!
428; The others are annotated with alignment information, amongst others, or even replaced by the constants passed to the call.
429;
430; FIXME: We should derive noalias for %a and add a "fake use" of %a in all potentially synchronizing calls.
431define internal void @t3_callback_callee(i32* %is_not_null, i32* %ptr, i32* %a, i64 %b, i32** %c) {
432;
433; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@t3_callback_callee
434; IS__TUNIT_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:%.*]]) {
435; IS__TUNIT_OPM-NEXT:  entry:
436; IS__TUNIT_OPM-NEXT:    [[PTR_VAL:%.*]] = load i32, i32* [[PTR]], align 8
437; IS__TUNIT_OPM-NEXT:    store i32 [[PTR_VAL]], i32* [[IS_NOT_NULL]], align 4
438; IS__TUNIT_OPM-NEXT:    [[TMP0:%.*]] = load i32*, i32** [[C]], align 64
439; IS__TUNIT_OPM-NEXT:    tail call void @t3_check(i32* nocapture align 256 [[A]], i64 noundef 99, i32* nocapture nonnull align 32 [[TMP0]])
440; IS__TUNIT_OPM-NEXT:    ret void
441;
442; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@t3_callback_callee
443; IS__TUNIT_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:%.*]]) {
444; IS__TUNIT_NPM-NEXT:  entry:
445; IS__TUNIT_NPM-NEXT:    [[PTR_VAL:%.*]] = load i32, i32* [[PTR]], align 8
446; IS__TUNIT_NPM-NEXT:    store i32 [[PTR_VAL]], i32* [[IS_NOT_NULL]], align 4
447; IS__TUNIT_NPM-NEXT:    [[TMP0:%.*]] = load i32*, i32** [[C]], align 64
448; IS__TUNIT_NPM-NEXT:    tail call void @t3_check(i32* nocapture align 256 [[A]], i64 noundef 99, i32* nocapture nonnull align 32 [[TMP0]])
449; IS__TUNIT_NPM-NEXT:    ret void
450;
451; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@t3_callback_callee
452; IS__CGSCC_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:%.*]]) {
453; IS__CGSCC_OPM-NEXT:  entry:
454; IS__CGSCC_OPM-NEXT:    [[PTR_VAL:%.*]] = load i32, i32* [[PTR]], align 8
455; IS__CGSCC_OPM-NEXT:    store i32 [[PTR_VAL]], i32* [[IS_NOT_NULL]], align 4
456; IS__CGSCC_OPM-NEXT:    [[TMP0:%.*]] = load i32*, i32** [[C]], align 64
457; IS__CGSCC_OPM-NEXT:    tail call void @t3_check(i32* nocapture align 256 [[A]], i64 noundef 99, i32* nocapture [[TMP0]])
458; IS__CGSCC_OPM-NEXT:    ret void
459;
460; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@t3_callback_callee
461; IS__CGSCC_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:%.*]]) {
462; IS__CGSCC_NPM-NEXT:  entry:
463; IS__CGSCC_NPM-NEXT:    [[PTR_VAL:%.*]] = load i32, i32* [[PTR]], align 8
464; IS__CGSCC_NPM-NEXT:    store i32 [[PTR_VAL]], i32* [[IS_NOT_NULL]], align 4
465; IS__CGSCC_NPM-NEXT:    [[TMP0:%.*]] = load i32*, i32** [[C]], align 64
466; IS__CGSCC_NPM-NEXT:    tail call void @t3_check(i32* nocapture align 256 [[A]], i64 noundef 99, i32* nocapture [[TMP0]])
467; IS__CGSCC_NPM-NEXT:    ret void
468;
469entry:
470  %ptr_val = load i32, i32* %ptr, align 8
471  store i32 %ptr_val, i32* %is_not_null
472  %0 = load i32*, i32** %c, align 8
473  tail call void @t3_check(i32* %a, i64 %b, i32* %0)
474  ret void
475}
476
477declare void @t3_check(i32* nocapture align 256, i64, i32* nocapture)
478
479declare !callback !0 void @t3_callback_broker(i32* nocapture , i32* nocapture , void (i32*, i32*, ...)* nocapture, ...)
480
481!0 = !{!1}
482!1 = !{i64 2, i64 -1, i64 -1, i1 true}
483;.
484; CHECK: attributes #[[ATTR0:[0-9]+]] = { nosync }
485;.
486; CHECK: [[META0:![0-9]+]] = !{!1}
487; CHECK: [[META1:![0-9]+]] = !{i64 2, i64 -1, i64 -1, i1 true}
488;.
489