brintos

brintos / llvm-project-archived public Read only

0
0
Text · 18.9 KiB · 80a0b2b Raw
322 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals2; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal  -attributor-annotate-decl-cs  -S < %s | FileCheck %s --check-prefixes=CHECK,TUNIT3; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal  -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,CGSCC4 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 08;9; Make sure we propagate information from the caller to the callback callee but10; only for arguments that are mapped through the callback metadata. Here, the11; first two arguments of the call and the callback callee do not correspond to12; each other but argument 3-5 of the transitive call site in the caller match13; arguments 2-4 of the callback callee. Here we should see information and value14; transfer in both directions.15 16define void @t0_caller(ptr %a) {17; TUNIT-LABEL: define {{[^@]+}}@t0_caller18; TUNIT-SAME: (ptr align 256 [[A:%.*]]) {19; TUNIT-NEXT:  entry:20; TUNIT-NEXT:    [[B:%.*]] = alloca i32, align 3221; TUNIT-NEXT:    [[C:%.*]] = alloca ptr, align 6422; TUNIT-NEXT:    [[PTR:%.*]] = alloca i32, align 12823; TUNIT-NEXT:    store i32 42, ptr [[B]], align 3224; TUNIT-NEXT:    store ptr [[B]], ptr [[C]], align 6425; TUNIT-NEXT:    call void (ptr, ptr, ptr, ...) @t0_callback_broker(ptr noundef 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 void27;28; CGSCC-LABEL: define {{[^@]+}}@t0_caller29; CGSCC-SAME: (ptr align 256 [[A:%.*]]) {30; CGSCC-NEXT:  entry:31; CGSCC-NEXT:    [[B:%.*]] = alloca i32, align 3232; CGSCC-NEXT:    [[C:%.*]] = alloca ptr, align 6433; CGSCC-NEXT:    [[PTR:%.*]] = alloca i32, align 12834; CGSCC-NEXT:    store i32 42, ptr [[B]], align 3235; CGSCC-NEXT:    store ptr [[B]], ptr [[C]], align 6436; CGSCC-NEXT:    call void (ptr, ptr, ptr, ...) @t0_callback_broker(ptr noundef 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 void38;39entry:40  %b = alloca i32, align 3241  %c = alloca ptr, align 6442  %ptr = alloca i32, align 12843  store i32 42, ptr %b, align 444  store ptr %b, ptr %c, align 845  call void (ptr, ptr, ptr, ...) @t0_callback_broker(ptr null, ptr %ptr, ptr @t0_callback_callee, ptr %a, i64 99, ptr %c)46  ret void47}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_callee54; 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 857; TUNIT-NEXT:    store i32 [[PTR_VAL]], ptr [[IS_NOT_NULL]], align 458; TUNIT-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[C]], align 6459; TUNIT-NEXT:    tail call void @t0_check(ptr align 256 [[A]], i64 noundef 99, ptr align 32 [[TMP0]])60; TUNIT-NEXT:    ret void61;62; CGSCC-LABEL: define {{[^@]+}}@t0_callback_callee63; 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 866; CGSCC-NEXT:    store i32 [[PTR_VAL]], ptr [[IS_NOT_NULL]], align 467; CGSCC-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[C]], align 6468; CGSCC-NEXT:    tail call void @t0_check(ptr align 256 [[A]], i64 noundef 99, ptr [[TMP0]])69; CGSCC-NEXT:    ret void70;71entry:72  %ptr_val = load i32, ptr %ptr, align 873  store i32 %ptr_val, ptr %is_not_null74  %0 = load ptr, ptr %c, align 875  tail call void @t0_check(ptr %a, i64 %b, ptr %0)76  ret void77}78 79declare void @t0_check(ptr align 256, i64, ptr)80 81declare !callback !0 void @t0_callback_broker(ptr, ptr, ptr, ...)82 83; Test 184;85; Similar to test 0 but with some additional annotations (noalias/nocapute) to make sure86; we deduce and propagate noalias and others properly.87 88define void @t1_caller(ptr noalias %a) {89;90; TUNIT-LABEL: define {{[^@]+}}@t1_caller91; TUNIT-SAME: (ptr noalias align 256 captures(none) [[A:%.*]]) {92; TUNIT-NEXT:  entry:93; TUNIT-NEXT:    [[B:%.*]] = alloca i32, align 3294; TUNIT-NEXT:    [[C:%.*]] = alloca ptr, align 6495; TUNIT-NEXT:    [[PTR:%.*]] = alloca i32, align 12896; TUNIT-NEXT:    store i32 42, ptr [[B]], align 3297; TUNIT-NEXT:    store ptr [[B]], ptr [[C]], align 6498; TUNIT-NEXT:    call void (ptr, ptr, ptr, ...) @t1_callback_broker(ptr noundef 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 void100;101; CGSCC-LABEL: define {{[^@]+}}@t1_caller102; CGSCC-SAME: (ptr noalias align 256 captures(none) [[A:%.*]]) {103; CGSCC-NEXT:  entry:104; CGSCC-NEXT:    [[B:%.*]] = alloca i32, align 32105; CGSCC-NEXT:    [[C:%.*]] = alloca ptr, align 64106; CGSCC-NEXT:    [[PTR:%.*]] = alloca i32, align 128107; CGSCC-NEXT:    store i32 42, ptr [[B]], align 32108; CGSCC-NEXT:    store ptr [[B]], ptr [[C]], align 64109; CGSCC-NEXT:    call void (ptr, ptr, ptr, ...) @t1_callback_broker(ptr noundef 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 void111;112entry:113  %b = alloca i32, align 32114  %c = alloca ptr, align 64115  %ptr = alloca i32, align 128116  store i32 42, ptr %b, align 4117  store ptr %b, ptr %c, align 8118  call void (ptr, ptr, ptr, ...) @t1_callback_broker(ptr null, ptr %ptr, ptr @t1_callback_callee, ptr %a, i64 99, ptr %c)119  ret void120}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: nosync127; TUNIT-LABEL: define {{[^@]+}}@t1_callback_callee128; 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 8131; TUNIT-NEXT:    store i32 [[PTR_VAL]], ptr [[IS_NOT_NULL]], align 4132; TUNIT-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[C]], align 64133; 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 void135;136; CGSCC: Function Attrs: nosync137; CGSCC-LABEL: define {{[^@]+}}@t1_callback_callee138; 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 8141; CGSCC-NEXT:    store i32 [[PTR_VAL]], ptr [[IS_NOT_NULL]], align 4142; CGSCC-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[C]], align 64143; CGSCC-NEXT:    tail call void @t1_check(ptr align 256 captures(none) [[A]], i64 noundef 99, ptr captures(none) [[TMP0]])144; CGSCC-NEXT:    ret void145;146entry:147  %ptr_val = load i32, ptr %ptr, align 8148  store i32 %ptr_val, ptr %is_not_null149  %0 = load ptr, ptr %c, align 8150  tail call void @t1_check(ptr %a, i64 %b, ptr %0)151  ret void152}153 154declare void @t1_check(ptr nocapture align 256, i64, ptr nocapture) nosync155 156declare !callback !0 void @t1_callback_broker(ptr nocapture , ptr nocapture , ptr nocapture, ...)157 158; Test 2159;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_caller164; TUNIT-SAME: (ptr noalias align 256 captures(none) [[A:%.*]]) {165; TUNIT-NEXT:  entry:166; TUNIT-NEXT:    [[B:%.*]] = alloca i32, align 32167; TUNIT-NEXT:    [[C:%.*]] = alloca ptr, align 64168; TUNIT-NEXT:    [[PTR:%.*]] = alloca i32, align 128169; TUNIT-NEXT:    store i32 42, ptr [[B]], align 32170; TUNIT-NEXT:    store ptr [[B]], ptr [[C]], align 64171; TUNIT-NEXT:    call void (ptr, ptr, ptr, ...) @t2_callback_broker(ptr noundef 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 void173;174; CGSCC-LABEL: define {{[^@]+}}@t2_caller175; CGSCC-SAME: (ptr noalias align 256 captures(none) [[A:%.*]]) {176; CGSCC-NEXT:  entry:177; CGSCC-NEXT:    [[B:%.*]] = alloca i32, align 32178; CGSCC-NEXT:    [[C:%.*]] = alloca ptr, align 64179; CGSCC-NEXT:    [[PTR:%.*]] = alloca i32, align 128180; CGSCC-NEXT:    store i32 42, ptr [[B]], align 32181; CGSCC-NEXT:    store ptr [[B]], ptr [[C]], align 64182; CGSCC-NEXT:    call void (ptr, ptr, ptr, ...) @t2_callback_broker(ptr noundef 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 void184;185entry:186  %b = alloca i32, align 32187  %c = alloca ptr, align 64188  %ptr = alloca i32, align 128189  store i32 42, ptr %b, align 4190  store ptr %b, ptr %c, align 8191  call void (ptr, ptr, ptr, ...) @t2_callback_broker(ptr null, ptr %ptr, ptr @t2_callback_callee, ptr %a, i64 99, ptr %c)192  ret void193}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_callee202; 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 8205; TUNIT-NEXT:    store i32 [[PTR_VAL]], ptr [[IS_NOT_NULL]], align 4206; TUNIT-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[C]], align 64207; 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 void209;210; CGSCC-LABEL: define {{[^@]+}}@t2_callback_callee211; 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 8214; CGSCC-NEXT:    store i32 [[PTR_VAL]], ptr [[IS_NOT_NULL]], align 4215; CGSCC-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[C]], align 64216; CGSCC-NEXT:    tail call void @t2_check(ptr align 256 captures(none) [[A]], i64 noundef 99, ptr captures(none) [[TMP0]])217; CGSCC-NEXT:    ret void218;219entry:220  %ptr_val = load i32, ptr %ptr, align 8221  store i32 %ptr_val, ptr %is_not_null222  %0 = load ptr, ptr %c, align 8223  tail call void @t2_check(ptr %a, i64 %b, ptr %0)224  ret void225}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 3232;233; Basically test 2 with the casted callback callee used twice.234 235define void @t3_caller(ptr noalias %a) {236; TUNIT-LABEL: define {{[^@]+}}@t3_caller237; TUNIT-SAME: (ptr noalias align 256 captures(none) [[A:%.*]]) {238; TUNIT-NEXT:  entry:239; TUNIT-NEXT:    [[B:%.*]] = alloca i32, align 32240; TUNIT-NEXT:    [[C:%.*]] = alloca ptr, align 64241; TUNIT-NEXT:    [[PTR:%.*]] = alloca i32, align 128242; TUNIT-NEXT:    store i32 42, ptr [[B]], align 32243; TUNIT-NEXT:    store ptr [[B]], ptr [[C]], align 64244; TUNIT-NEXT:    call void (ptr, ptr, ptr, ...) @t3_callback_broker(ptr noundef 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 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 void247;248; CGSCC-LABEL: define {{[^@]+}}@t3_caller249; CGSCC-SAME: (ptr noalias align 256 captures(none) [[A:%.*]]) {250; CGSCC-NEXT:  entry:251; CGSCC-NEXT:    [[B:%.*]] = alloca i32, align 32252; CGSCC-NEXT:    [[C:%.*]] = alloca ptr, align 64253; CGSCC-NEXT:    [[PTR:%.*]] = alloca i32, align 128254; CGSCC-NEXT:    store i32 42, ptr [[B]], align 32255; CGSCC-NEXT:    store ptr [[B]], ptr [[C]], align 64256; CGSCC-NEXT:    call void (ptr, ptr, ptr, ...) @t3_callback_broker(ptr noundef 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 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 void259;260entry:261  %b = alloca i32, align 32262  %c = alloca ptr, align 64263  %ptr = alloca i32, align 128264  store i32 42, ptr %b, align 4265  store ptr %b, ptr %c, align 8266  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 void269}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_callee278; 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 8281; TUNIT-NEXT:    store i32 [[PTR_VAL]], ptr [[IS_NOT_NULL]], align 4282; TUNIT-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[C]], align 64283; 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 void285;286; CGSCC-LABEL: define {{[^@]+}}@t3_callback_callee287; 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 8290; CGSCC-NEXT:    store i32 [[PTR_VAL]], ptr [[IS_NOT_NULL]], align 4291; CGSCC-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[C]], align 64292; CGSCC-NEXT:    tail call void @t3_check(ptr align 256 captures(none) [[A]], i64 noundef 99, ptr captures(none) [[TMP0]])293; CGSCC-NEXT:    ret void294;295entry:296  %ptr_val = load i32, ptr %ptr, align 8297  store i32 %ptr_val, ptr %is_not_null298  %0 = load ptr, ptr %c, align 8299  tail call void @t3_check(ptr %a, i64 %b, ptr %0)300  ret void301}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