1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals 2; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,TUNIT 3; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,CGSCC 4 5target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" 6 7; Test 0 8; 9; Make sure we propagate information from the caller to the callback callee but 10; only for arguments that are mapped through the callback metadata. Here, the 11; first two arguments of the call and the callback callee do not correspond to 12; each other but argument 3-5 of the transitive call site in the caller match 13; arguments 2-4 of the callback callee. Here we should see information and value 14; transfer in both directions. 15 16define void @t0_caller(ptr %a) { 17; TUNIT-LABEL: define {{[^@]+}}@t0_caller 18; TUNIT-SAME: (ptr align 256 [[A:%.*]]) { 19; TUNIT-NEXT: entry: 20; TUNIT-NEXT: [[B:%.*]] = alloca i32, align 32 21; TUNIT-NEXT: [[C:%.*]] = alloca ptr, align 64 22; TUNIT-NEXT: [[PTR:%.*]] = alloca i32, align 128 23; TUNIT-NEXT: store i32 42, ptr [[B]], align 32 24; TUNIT-NEXT: store ptr [[B]], ptr [[C]], align 64 25; TUNIT-NEXT: call void (ptr, ptr, ptr, ...) @t0_callback_broker(ptr noundef align 4294967296 null, ptr noundef nonnull align 128 dereferenceable(4) [[PTR]], ptr noundef nonnull @t0_callback_callee, ptr align 256 [[A]], i64 undef, ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(8) [[C]]) 26; TUNIT-NEXT: ret void 27; 28; CGSCC-LABEL: define {{[^@]+}}@t0_caller 29; CGSCC-SAME: (ptr align 256 [[A:%.*]]) { 30; CGSCC-NEXT: entry: 31; CGSCC-NEXT: [[B:%.*]] = alloca i32, align 32 32; CGSCC-NEXT: [[C:%.*]] = alloca ptr, align 64 33; CGSCC-NEXT: [[PTR:%.*]] = alloca i32, align 128 34; CGSCC-NEXT: store i32 42, ptr [[B]], align 32 35; CGSCC-NEXT: store ptr [[B]], ptr [[C]], align 64 36; CGSCC-NEXT: call void (ptr, ptr, ptr, ...) @t0_callback_broker(ptr noundef align 4294967296 null, ptr noundef nonnull align 128 dereferenceable(4) [[PTR]], ptr noundef nonnull @t0_callback_callee, ptr align 256 [[A]], i64 noundef 99, ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(8) [[C]]) 37; CGSCC-NEXT: ret void 38; 39entry: 40 %b = alloca i32, align 32 41 %c = alloca ptr, align 64 42 %ptr = alloca i32, align 128 43 store i32 42, ptr %b, align 4 44 store ptr %b, ptr %c, align 8 45 call void (ptr, ptr, ptr, ...) @t0_callback_broker(ptr null, ptr %ptr, ptr @t0_callback_callee, ptr %a, i64 99, ptr %c) 46 ret void 47} 48 49; Note that the first two arguments are provided by the callback_broker according to the callback in !1 below! 50; The others are annotated with alignment information, amongst others, or even replaced by the constants passed to the call. 51define internal void @t0_callback_callee(ptr %is_not_null, ptr %ptr, ptr %a, i64 %b, ptr %c) { 52; 53; TUNIT-LABEL: define {{[^@]+}}@t0_callback_callee 54; TUNIT-SAME: (ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[IS_NOT_NULL:%.*]], ptr nofree noundef nonnull readonly align 8 captures(none) dereferenceable(4) [[PTR:%.*]], ptr align 256 [[A:%.*]], i64 [[B:%.*]], ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(8) [[C:%.*]]) { 55; TUNIT-NEXT: entry: 56; TUNIT-NEXT: [[PTR_VAL:%.*]] = load i32, ptr [[PTR]], align 8 57; TUNIT-NEXT: store i32 [[PTR_VAL]], ptr [[IS_NOT_NULL]], align 4 58; TUNIT-NEXT: [[TMP0:%.*]] = load ptr, ptr [[C]], align 64 59; TUNIT-NEXT: tail call void @t0_check(ptr align 256 [[A]], i64 noundef 99, ptr align 32 [[TMP0]]) 60; TUNIT-NEXT: ret void 61; 62; CGSCC-LABEL: define {{[^@]+}}@t0_callback_callee 63; CGSCC-SAME: (ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[IS_NOT_NULL:%.*]], ptr nofree noundef nonnull readonly align 8 captures(none) dereferenceable(4) [[PTR:%.*]], ptr align 256 [[A:%.*]], i64 [[B:%.*]], ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(8) [[C:%.*]]) { 64; CGSCC-NEXT: entry: 65; CGSCC-NEXT: [[PTR_VAL:%.*]] = load i32, ptr [[PTR]], align 8 66; CGSCC-NEXT: store i32 [[PTR_VAL]], ptr [[IS_NOT_NULL]], align 4 67; CGSCC-NEXT: [[TMP0:%.*]] = load ptr, ptr [[C]], align 64 68; CGSCC-NEXT: tail call void @t0_check(ptr align 256 [[A]], i64 noundef 99, ptr [[TMP0]]) 69; CGSCC-NEXT: ret void 70; 71entry: 72 %ptr_val = load i32, ptr %ptr, align 8 73 store i32 %ptr_val, ptr %is_not_null 74 %0 = load ptr, ptr %c, align 8 75 tail call void @t0_check(ptr %a, i64 %b, ptr %0) 76 ret void 77} 78 79declare void @t0_check(ptr align 256, i64, ptr) 80 81declare !callback !0 void @t0_callback_broker(ptr, ptr, ptr, ...) 82 83; Test 1 84; 85; Similar to test 0 but with some additional annotations (noalias/nocapute) to make sure 86; we deduce and propagate noalias and others properly. 87 88define void @t1_caller(ptr noalias %a) { 89; 90; TUNIT-LABEL: define {{[^@]+}}@t1_caller 91; TUNIT-SAME: (ptr noalias align 256 captures(none) [[A:%.*]]) { 92; TUNIT-NEXT: entry: 93; TUNIT-NEXT: [[B:%.*]] = alloca i32, align 32 94; TUNIT-NEXT: [[C:%.*]] = alloca ptr, align 64 95; TUNIT-NEXT: [[PTR:%.*]] = alloca i32, align 128 96; TUNIT-NEXT: store i32 42, ptr [[B]], align 32 97; TUNIT-NEXT: store ptr [[B]], ptr [[C]], align 64 98; TUNIT-NEXT: call void (ptr, ptr, ptr, ...) @t1_callback_broker(ptr noundef align 4294967296 null, ptr noalias noundef nonnull align 128 captures(none) dereferenceable(4) [[PTR]], ptr noundef nonnull captures(none) @t1_callback_callee, ptr align 256 captures(none) [[A]], i64 undef, ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(8) [[C]]) 99; TUNIT-NEXT: ret void 100; 101; CGSCC-LABEL: define {{[^@]+}}@t1_caller 102; CGSCC-SAME: (ptr noalias align 256 captures(none) [[A:%.*]]) { 103; CGSCC-NEXT: entry: 104; CGSCC-NEXT: [[B:%.*]] = alloca i32, align 32 105; CGSCC-NEXT: [[C:%.*]] = alloca ptr, align 64 106; CGSCC-NEXT: [[PTR:%.*]] = alloca i32, align 128 107; CGSCC-NEXT: store i32 42, ptr [[B]], align 32 108; CGSCC-NEXT: store ptr [[B]], ptr [[C]], align 64 109; CGSCC-NEXT: call void (ptr, ptr, ptr, ...) @t1_callback_broker(ptr noundef align 4294967296 null, ptr noalias noundef nonnull align 128 captures(none) dereferenceable(4) [[PTR]], ptr noundef nonnull captures(none) @t1_callback_callee, ptr align 256 captures(none) [[A]], i64 noundef 99, ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(8) [[C]]) 110; CGSCC-NEXT: ret void 111; 112entry: 113 %b = alloca i32, align 32 114 %c = alloca ptr, align 64 115 %ptr = alloca i32, align 128 116 store i32 42, ptr %b, align 4 117 store ptr %b, ptr %c, align 8 118 call void (ptr, ptr, ptr, ...) @t1_callback_broker(ptr null, ptr %ptr, ptr @t1_callback_callee, ptr %a, i64 99, ptr %c) 119 ret void 120} 121 122; Note that the first two arguments are provided by the callback_broker according to the callback in !1 below! 123; The others are annotated with alignment information, amongst others, or even replaced by the constants passed to the call. 124define internal void @t1_callback_callee(ptr %is_not_null, ptr %ptr, ptr %a, i64 %b, ptr %c) { 125; 126; TUNIT: Function Attrs: nosync 127; TUNIT-LABEL: define {{[^@]+}}@t1_callback_callee 128; TUNIT-SAME: (ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[IS_NOT_NULL:%.*]], ptr nofree noundef nonnull readonly align 8 captures(none) dereferenceable(4) [[PTR:%.*]], ptr align 256 captures(none) [[A:%.*]], i64 [[B:%.*]], ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(8) [[C:%.*]]) #[[ATTR0:[0-9]+]] { 129; TUNIT-NEXT: entry: 130; TUNIT-NEXT: [[PTR_VAL:%.*]] = load i32, ptr [[PTR]], align 8 131; TUNIT-NEXT: store i32 [[PTR_VAL]], ptr [[IS_NOT_NULL]], align 4 132; TUNIT-NEXT: [[TMP0:%.*]] = load ptr, ptr [[C]], align 64 133; TUNIT-NEXT: tail call void @t1_check(ptr align 256 captures(none) [[A]], i64 noundef 99, ptr align 32 captures(none) [[TMP0]]) 134; TUNIT-NEXT: ret void 135; 136; CGSCC: Function Attrs: nosync 137; CGSCC-LABEL: define {{[^@]+}}@t1_callback_callee 138; CGSCC-SAME: (ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[IS_NOT_NULL:%.*]], ptr nofree noundef nonnull readonly align 8 captures(none) dereferenceable(4) [[PTR:%.*]], ptr align 256 captures(none) [[A:%.*]], i64 [[B:%.*]], ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(8) [[C:%.*]]) #[[ATTR0:[0-9]+]] { 139; CGSCC-NEXT: entry: 140; CGSCC-NEXT: [[PTR_VAL:%.*]] = load i32, ptr [[PTR]], align 8 141; CGSCC-NEXT: store i32 [[PTR_VAL]], ptr [[IS_NOT_NULL]], align 4 142; CGSCC-NEXT: [[TMP0:%.*]] = load ptr, ptr [[C]], align 64 143; CGSCC-NEXT: tail call void @t1_check(ptr align 256 captures(none) [[A]], i64 noundef 99, ptr captures(none) [[TMP0]]) 144; CGSCC-NEXT: ret void 145; 146entry: 147 %ptr_val = load i32, ptr %ptr, align 8 148 store i32 %ptr_val, ptr %is_not_null 149 %0 = load ptr, ptr %c, align 8 150 tail call void @t1_check(ptr %a, i64 %b, ptr %0) 151 ret void 152} 153 154declare void @t1_check(ptr nocapture align 256, i64, ptr nocapture) nosync 155 156declare !callback !0 void @t1_callback_broker(ptr nocapture , ptr nocapture , ptr nocapture, ...) 157 158; Test 2 159; 160; Similar to test 1 but checking that the noalias is only placed if potential synchronization through @t2_check is preserved. 161 162define void @t2_caller(ptr noalias %a) { 163; TUNIT-LABEL: define {{[^@]+}}@t2_caller 164; TUNIT-SAME: (ptr noalias align 256 captures(none) [[A:%.*]]) { 165; TUNIT-NEXT: entry: 166; TUNIT-NEXT: [[B:%.*]] = alloca i32, align 32 167; TUNIT-NEXT: [[C:%.*]] = alloca ptr, align 64 168; TUNIT-NEXT: [[PTR:%.*]] = alloca i32, align 128 169; TUNIT-NEXT: store i32 42, ptr [[B]], align 32 170; TUNIT-NEXT: store ptr [[B]], ptr [[C]], align 64 171; TUNIT-NEXT: call void (ptr, ptr, ptr, ...) @t2_callback_broker(ptr noundef align 4294967296 null, ptr noalias noundef nonnull align 128 captures(none) dereferenceable(4) [[PTR]], ptr noundef nonnull captures(none) @t2_callback_callee, ptr align 256 captures(none) [[A]], i64 undef, ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(8) [[C]]) 172; TUNIT-NEXT: ret void 173; 174; CGSCC-LABEL: define {{[^@]+}}@t2_caller 175; CGSCC-SAME: (ptr noalias align 256 captures(none) [[A:%.*]]) { 176; CGSCC-NEXT: entry: 177; CGSCC-NEXT: [[B:%.*]] = alloca i32, align 32 178; CGSCC-NEXT: [[C:%.*]] = alloca ptr, align 64 179; CGSCC-NEXT: [[PTR:%.*]] = alloca i32, align 128 180; CGSCC-NEXT: store i32 42, ptr [[B]], align 32 181; CGSCC-NEXT: store ptr [[B]], ptr [[C]], align 64 182; CGSCC-NEXT: call void (ptr, ptr, ptr, ...) @t2_callback_broker(ptr noundef align 4294967296 null, ptr noalias noundef nonnull align 128 captures(none) dereferenceable(4) [[PTR]], ptr noundef nonnull captures(none) @t2_callback_callee, ptr align 256 captures(none) [[A]], i64 noundef 99, ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(8) [[C]]) 183; CGSCC-NEXT: ret void 184; 185entry: 186 %b = alloca i32, align 32 187 %c = alloca ptr, align 64 188 %ptr = alloca i32, align 128 189 store i32 42, ptr %b, align 4 190 store ptr %b, ptr %c, align 8 191 call void (ptr, ptr, ptr, ...) @t2_callback_broker(ptr null, ptr %ptr, ptr @t2_callback_callee, ptr %a, i64 99, ptr %c) 192 ret void 193} 194 195; Note that the first two arguments are provided by the callback_broker according to the callback in !1 below! 196; The others are annotated with alignment information, amongst others, or even replaced by the constants passed to the call. 197; 198; FIXME: We should derive noalias for %a and add a "fake use" of %a in all potentially synchronizing calls. 199define internal void @t2_callback_callee(ptr %is_not_null, ptr %ptr, ptr %a, i64 %b, ptr %c) { 200; 201; TUNIT-LABEL: define {{[^@]+}}@t2_callback_callee 202; TUNIT-SAME: (ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[IS_NOT_NULL:%.*]], ptr nofree noundef nonnull readonly align 8 captures(none) dereferenceable(4) [[PTR:%.*]], ptr align 256 captures(none) [[A:%.*]], i64 [[B:%.*]], ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(8) [[C:%.*]]) { 203; TUNIT-NEXT: entry: 204; TUNIT-NEXT: [[PTR_VAL:%.*]] = load i32, ptr [[PTR]], align 8 205; TUNIT-NEXT: store i32 [[PTR_VAL]], ptr [[IS_NOT_NULL]], align 4 206; TUNIT-NEXT: [[TMP0:%.*]] = load ptr, ptr [[C]], align 64 207; TUNIT-NEXT: tail call void @t2_check(ptr align 256 captures(none) [[A]], i64 noundef 99, ptr align 32 captures(none) [[TMP0]]) 208; TUNIT-NEXT: ret void 209; 210; CGSCC-LABEL: define {{[^@]+}}@t2_callback_callee 211; CGSCC-SAME: (ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[IS_NOT_NULL:%.*]], ptr nofree noundef nonnull readonly align 8 captures(none) dereferenceable(4) [[PTR:%.*]], ptr align 256 captures(none) [[A:%.*]], i64 [[B:%.*]], ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(8) [[C:%.*]]) { 212; CGSCC-NEXT: entry: 213; CGSCC-NEXT: [[PTR_VAL:%.*]] = load i32, ptr [[PTR]], align 8 214; CGSCC-NEXT: store i32 [[PTR_VAL]], ptr [[IS_NOT_NULL]], align 4 215; CGSCC-NEXT: [[TMP0:%.*]] = load ptr, ptr [[C]], align 64 216; CGSCC-NEXT: tail call void @t2_check(ptr align 256 captures(none) [[A]], i64 noundef 99, ptr captures(none) [[TMP0]]) 217; CGSCC-NEXT: ret void 218; 219entry: 220 %ptr_val = load i32, ptr %ptr, align 8 221 store i32 %ptr_val, ptr %is_not_null 222 %0 = load ptr, ptr %c, align 8 223 tail call void @t2_check(ptr %a, i64 %b, ptr %0) 224 ret void 225} 226 227declare void @t2_check(ptr nocapture align 256, i64, ptr nocapture) 228 229declare !callback !0 void @t2_callback_broker(ptr nocapture , ptr nocapture , ptr nocapture, ...) 230 231; Test 3 232; 233; Basically test 2 with the casted callback callee used twice. 234 235define void @t3_caller(ptr noalias %a) { 236; TUNIT-LABEL: define {{[^@]+}}@t3_caller 237; TUNIT-SAME: (ptr noalias align 256 captures(none) [[A:%.*]]) { 238; TUNIT-NEXT: entry: 239; TUNIT-NEXT: [[B:%.*]] = alloca i32, align 32 240; TUNIT-NEXT: [[C:%.*]] = alloca ptr, align 64 241; TUNIT-NEXT: [[PTR:%.*]] = alloca i32, align 128 242; TUNIT-NEXT: store i32 42, ptr [[B]], align 32 243; TUNIT-NEXT: store ptr [[B]], ptr [[C]], align 64 244; TUNIT-NEXT: call void (ptr, ptr, ptr, ...) @t3_callback_broker(ptr noundef align 4294967296 null, ptr noalias noundef nonnull align 128 captures(none) dereferenceable(4) [[PTR]], ptr noundef nonnull captures(none) @t3_callback_callee, ptr align 256 captures(none) [[A]], i64 undef, ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(8) [[C]]) 245; TUNIT-NEXT: call void (ptr, ptr, ptr, ...) @t3_callback_broker(ptr noundef align 4294967296 null, ptr noalias noundef nonnull align 128 captures(none) dereferenceable(4) [[PTR]], ptr noundef nonnull captures(none) @t3_callback_callee, ptr align 256 captures(none) [[A]], i64 undef, ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(8) [[C]]) 246; TUNIT-NEXT: ret void 247; 248; CGSCC-LABEL: define {{[^@]+}}@t3_caller 249; CGSCC-SAME: (ptr noalias align 256 captures(none) [[A:%.*]]) { 250; CGSCC-NEXT: entry: 251; CGSCC-NEXT: [[B:%.*]] = alloca i32, align 32 252; CGSCC-NEXT: [[C:%.*]] = alloca ptr, align 64 253; CGSCC-NEXT: [[PTR:%.*]] = alloca i32, align 128 254; CGSCC-NEXT: store i32 42, ptr [[B]], align 32 255; CGSCC-NEXT: store ptr [[B]], ptr [[C]], align 64 256; CGSCC-NEXT: call void (ptr, ptr, ptr, ...) @t3_callback_broker(ptr noundef align 4294967296 null, ptr noalias noundef nonnull align 128 captures(none) dereferenceable(4) [[PTR]], ptr noundef nonnull captures(none) @t3_callback_callee, ptr align 256 captures(none) [[A]], i64 noundef 99, ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(8) [[C]]) 257; CGSCC-NEXT: call void (ptr, ptr, ptr, ...) @t3_callback_broker(ptr noundef align 4294967296 null, ptr noalias noundef nonnull align 128 captures(none) dereferenceable(4) [[PTR]], ptr noundef nonnull captures(none) @t3_callback_callee, ptr align 256 captures(none) [[A]], i64 noundef 99, ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(8) [[C]]) 258; CGSCC-NEXT: ret void 259; 260entry: 261 %b = alloca i32, align 32 262 %c = alloca ptr, align 64 263 %ptr = alloca i32, align 128 264 store i32 42, ptr %b, align 4 265 store ptr %b, ptr %c, align 8 266 call void (ptr, ptr, ptr, ...) @t3_callback_broker(ptr null, ptr %ptr, ptr @t3_callback_callee, ptr %a, i64 99, ptr %c) 267 call void (ptr, ptr, ptr, ...) @t3_callback_broker(ptr null, ptr %ptr, ptr @t3_callback_callee, ptr %a, i64 99, ptr %c) 268 ret void 269} 270 271; Note that the first two arguments are provided by the callback_broker according to the callback in !1 below! 272; The others are annotated with alignment information, amongst others, or even replaced by the constants passed to the call. 273; 274; FIXME: We should derive noalias for %a and add a "fake use" of %a in all potentially synchronizing calls. 275define internal void @t3_callback_callee(ptr %is_not_null, ptr %ptr, ptr %a, i64 %b, ptr %c) { 276; 277; TUNIT-LABEL: define {{[^@]+}}@t3_callback_callee 278; TUNIT-SAME: (ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[IS_NOT_NULL:%.*]], ptr nofree noundef nonnull readonly align 8 captures(none) dereferenceable(4) [[PTR:%.*]], ptr align 256 captures(none) [[A:%.*]], i64 [[B:%.*]], ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(8) [[C:%.*]]) { 279; TUNIT-NEXT: entry: 280; TUNIT-NEXT: [[PTR_VAL:%.*]] = load i32, ptr [[PTR]], align 8 281; TUNIT-NEXT: store i32 [[PTR_VAL]], ptr [[IS_NOT_NULL]], align 4 282; TUNIT-NEXT: [[TMP0:%.*]] = load ptr, ptr [[C]], align 64 283; TUNIT-NEXT: tail call void @t3_check(ptr align 256 captures(none) [[A]], i64 noundef 99, ptr align 32 captures(none) [[TMP0]]) 284; TUNIT-NEXT: ret void 285; 286; CGSCC-LABEL: define {{[^@]+}}@t3_callback_callee 287; CGSCC-SAME: (ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[IS_NOT_NULL:%.*]], ptr nofree noundef nonnull readonly align 8 captures(none) dereferenceable(4) [[PTR:%.*]], ptr align 256 captures(none) [[A:%.*]], i64 [[B:%.*]], ptr noalias nofree noundef nonnull readonly align 64 captures(none) dereferenceable(8) [[C:%.*]]) { 288; CGSCC-NEXT: entry: 289; CGSCC-NEXT: [[PTR_VAL:%.*]] = load i32, ptr [[PTR]], align 8 290; CGSCC-NEXT: store i32 [[PTR_VAL]], ptr [[IS_NOT_NULL]], align 4 291; CGSCC-NEXT: [[TMP0:%.*]] = load ptr, ptr [[C]], align 64 292; CGSCC-NEXT: tail call void @t3_check(ptr align 256 captures(none) [[A]], i64 noundef 99, ptr captures(none) [[TMP0]]) 293; CGSCC-NEXT: ret void 294; 295entry: 296 %ptr_val = load i32, ptr %ptr, align 8 297 store i32 %ptr_val, ptr %is_not_null 298 %0 = load ptr, ptr %c, align 8 299 tail call void @t3_check(ptr %a, i64 %b, ptr %0) 300 ret void 301} 302 303declare void @t3_check(ptr nocapture align 256, i64, ptr nocapture) 304 305declare !callback !0 void @t3_callback_broker(ptr nocapture , ptr nocapture , ptr nocapture, ...) 306 307!0 = !{!1} 308!1 = !{i64 2, i64 -1, i64 -1, i1 true} 309;. 310; TUNIT: attributes #[[ATTR0]] = { nosync } 311;. 312; CGSCC: attributes #[[ATTR0]] = { nosync } 313;. 314; TUNIT: [[META0:![0-9]+]] = !{[[META1:![0-9]+]]} 315; TUNIT: [[META1]] = !{i64 2, i64 -1, i64 -1, i1 true} 316;. 317; CGSCC: [[META0:![0-9]+]] = !{[[META1:![0-9]+]]} 318; CGSCC: [[META1]] = !{i64 2, i64 -1, i64 -1, i1 true} 319;. 320;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: 321; CHECK: {{.*}} 322