Index: llvm/test/Transforms/Attributor/nocapture-2.ll =================================================================== --- llvm/test/Transforms/Attributor/nocapture-2.ll +++ llvm/test/Transforms/Attributor/nocapture-2.ll @@ -1,12 +1,12 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-attributes --check-globals --version 2 -; RUN: opt -opaque-pointers=0 -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,TUNIT -; RUN: opt -opaque-pointers=0 -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,CGSCC +; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,TUNIT +; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,CGSCC ; ; Test cases specifically designed for the "no-capture" argument attribute. ; We use FIXME's to indicate problems and missing attributes. ; target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" -declare i32* @unknown() +declare ptr @unknown() ; TEST comparison against NULL ; @@ -15,17 +15,17 @@ ; } ; ; no-capture is missing on %p because it is not dereferenceable -define i32 @is_null_return(i32* %p) #0 { +define i32 @is_null_return(ptr %p) #0 { ; CHECK: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable ; CHECK-LABEL: define i32 @is_null_return -; CHECK-SAME: (i32* nofree readnone [[P:%.*]]) #[[ATTR0:[0-9]+]] { +; CHECK-SAME: (ptr nofree readnone [[P:%.*]]) #[[ATTR0:[0-9]+]] { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32* [[P]], null +; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[P]], null ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] ; entry: - %cmp = icmp eq i32* %p, null + %cmp = icmp eq ptr %p, null %conv = zext i1 %cmp to i32 ret i32 %conv } @@ -41,53 +41,53 @@ ; } ; ; no-capture is missing on %p because it is not dereferenceable -define i32 @is_null_control(i32* %p) #0 { +define i32 @is_null_control(ptr %p) #0 { ; CHECK: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable ; CHECK-LABEL: define i32 @is_null_control -; CHECK-SAME: (i32* nofree [[P:%.*]]) #[[ATTR0]] { +; CHECK-SAME: (ptr nofree [[P:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32* [[P]], null +; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[P]], null ; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] ; CHECK: if.then: -; CHECK-NEXT: store i32 1, i32* [[RETVAL]], align 4 +; CHECK-NEXT: store i32 1, ptr [[RETVAL]], align 4 ; CHECK-NEXT: br label [[RETURN:%.*]] ; CHECK: if.end: -; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32* null, [[P]] +; CHECK-NEXT: [[CMP1:%.*]] = icmp eq ptr null, [[P]] ; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN2:%.*]], label [[IF_END3:%.*]] ; CHECK: if.then2: -; CHECK-NEXT: store i32 1, i32* [[RETVAL]], align 4 +; CHECK-NEXT: store i32 1, ptr [[RETVAL]], align 4 ; CHECK-NEXT: br label [[RETURN]] ; CHECK: if.end3: -; CHECK-NEXT: store i32 0, i32* [[RETVAL]], align 4 +; CHECK-NEXT: store i32 0, ptr [[RETVAL]], align 4 ; CHECK-NEXT: br label [[RETURN]] ; CHECK: return: -; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[RETVAL]], align 4 +; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[RETVAL]], align 4 ; CHECK-NEXT: ret i32 [[TMP0]] ; entry: %retval = alloca i32, align 4 - %cmp = icmp eq i32* %p, null + %cmp = icmp eq ptr %p, null br i1 %cmp, label %if.then, label %if.end if.then: ; preds = %entry - store i32 1, i32* %retval, align 4 + store i32 1, ptr %retval, align 4 br label %return if.end: ; preds = %entry - %cmp1 = icmp eq i32* null, %p + %cmp1 = icmp eq ptr null, %p br i1 %cmp1, label %if.then2, label %if.end3 if.then2: ; preds = %if.end - store i32 1, i32* %retval, align 4 + store i32 1, ptr %retval, align 4 br label %return if.end3: ; preds = %if.end - store i32 0, i32* %retval, align 4 + store i32 0, ptr %retval, align 4 br label %return return: ; preds = %if.end3, %if.then2, %if.then - %0 = load i32, i32* %retval, align 4 + %0 = load i32, ptr %retval, align 4 ret i32 %0 } @@ -98,16 +98,16 @@ ; return 0; ; } ; -define double* @srec0(double* %a) #0 { +define ptr @srec0(ptr %a) #0 { ; CHECK: Function Attrs: mustprogress nofree noinline nosync nounwind willreturn memory(none) uwtable -; CHECK-LABEL: define noalias noundef align 4294967296 double* @srec0 -; CHECK-SAME: (double* nocapture nofree readnone [[A:%.*]]) #[[ATTR1:[0-9]+]] { +; CHECK-LABEL: define noalias noundef align 4294967296 ptr @srec0 +; CHECK-SAME: (ptr nocapture nofree readnone [[A:%.*]]) #[[ATTR1:[0-9]+]] { ; CHECK-NEXT: entry: -; CHECK-NEXT: ret double* null +; CHECK-NEXT: ret ptr null ; entry: - %call = call double* @srec0(double* %a) - ret double* null + %call = call ptr @srec0(ptr %a) + ret ptr null } ; TEST singleton SCC with lots of nested recursive calls @@ -123,31 +123,31 @@ ; ; Other arguments are possible here due to the no-return behavior. ; -define i32* @srec16(i32* %a) #0 { +define ptr @srec16(ptr %a) #0 { ; CHECK: Function Attrs: mustprogress nofree noinline nosync nounwind willreturn memory(none) uwtable -; CHECK-LABEL: define noalias nonnull align 4294967296 dereferenceable(4294967295) i32* @srec16 -; CHECK-SAME: (i32* nocapture nofree readnone [[A:%.*]]) #[[ATTR1]] { +; CHECK-LABEL: define noalias nonnull align 4294967296 dereferenceable(4294967295) ptr @srec16 +; CHECK-SAME: (ptr nocapture nofree readnone [[A:%.*]]) #[[ATTR1]] { ; CHECK-NEXT: entry: -; CHECK-NEXT: ret i32* undef +; CHECK-NEXT: ret ptr undef ; entry: - %call = call i32* @srec16(i32* %a) - %call1 = call i32* @srec16(i32* %call) - %call2 = call i32* @srec16(i32* %call1) - %call3 = call i32* @srec16(i32* %call2) - %call4 = call i32* @srec16(i32* %call3) - %call5 = call i32* @srec16(i32* %call4) - %call6 = call i32* @srec16(i32* %call5) - %call7 = call i32* @srec16(i32* %call6) - %call8 = call i32* @srec16(i32* %call7) - %call9 = call i32* @srec16(i32* %call8) - %call10 = call i32* @srec16(i32* %call9) - %call11 = call i32* @srec16(i32* %call10) - %call12 = call i32* @srec16(i32* %call11) - %call13 = call i32* @srec16(i32* %call12) - %call14 = call i32* @srec16(i32* %call13) - %call15 = call i32* @srec16(i32* %call14) - ret i32* %call15 + %call = call ptr @srec16(ptr %a) + %call1 = call ptr @srec16(ptr %call) + %call2 = call ptr @srec16(ptr %call1) + %call3 = call ptr @srec16(ptr %call2) + %call4 = call ptr @srec16(ptr %call3) + %call5 = call ptr @srec16(ptr %call4) + %call6 = call ptr @srec16(ptr %call5) + %call7 = call ptr @srec16(ptr %call6) + %call8 = call ptr @srec16(ptr %call7) + %call9 = call ptr @srec16(ptr %call8) + %call10 = call ptr @srec16(ptr %call9) + %call11 = call ptr @srec16(ptr %call10) + %call12 = call ptr @srec16(ptr %call11) + %call13 = call ptr @srec16(ptr %call12) + %call14 = call ptr @srec16(ptr %call13) + %call15 = call ptr @srec16(ptr %call14) + ret ptr %call15 } ; TEST SCC with various calls, casts, and comparisons agains NULL @@ -163,193 +163,150 @@ ; void *scc_C(short *a) { ; return scc_A((int*)(scc_A(a) ? scc_B((double*)a) : scc_C(a))); ; } -define float* @scc_A(i32* dereferenceable_or_null(4) %a) { +define ptr @scc_A(ptr dereferenceable_or_null(4) %a) { ; TUNIT: Function Attrs: nofree nosync nounwind memory(none) -; TUNIT-LABEL: define dereferenceable_or_null(4) float* @scc_A -; TUNIT-SAME: (i32* nofree noundef readnone dereferenceable_or_null(4) "no-capture-maybe-returned" [[A:%.*]]) #[[ATTR2:[0-9]+]] { +; TUNIT-LABEL: define noundef dereferenceable_or_null(4) ptr @scc_A +; TUNIT-SAME: (ptr nofree noundef readnone returned dereferenceable_or_null(4) "no-capture-maybe-returned" [[A:%.*]]) #[[ATTR2:[0-9]+]] { ; TUNIT-NEXT: entry: -; TUNIT-NEXT: [[TOBOOL:%.*]] = icmp ne i32* [[A]], null +; TUNIT-NEXT: [[TOBOOL:%.*]] = icmp ne ptr [[A]], null ; TUNIT-NEXT: br i1 [[TOBOOL]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] ; TUNIT: cond.true: -; TUNIT-NEXT: [[TMP0:%.*]] = bitcast i32* [[A]] to i16* -; TUNIT-NEXT: [[CALL:%.*]] = call dereferenceable_or_null(4) i8* @scc_C(i16* noalias nofree noundef nonnull readnone dereferenceable(4) "no-capture-maybe-returned" [[TMP0]]) #[[ATTR9:[0-9]+]] -; TUNIT-NEXT: [[TMP1:%.*]] = bitcast i8* [[CALL]] to double* -; TUNIT-NEXT: [[CALL1:%.*]] = call dereferenceable_or_null(4) i64* @scc_B(double* noalias nofree readnone dereferenceable_or_null(8) "no-capture-maybe-returned" [[TMP1]]) #[[ATTR9]] -; TUNIT-NEXT: [[TMP2:%.*]] = bitcast i64* [[CALL1]] to i32* -; TUNIT-NEXT: [[CALL2:%.*]] = call dereferenceable_or_null(4) float* @scc_A(i32* noalias nofree readnone dereferenceable_or_null(4) "no-capture-maybe-returned" [[TMP2]]) #[[ATTR9]] -; TUNIT-NEXT: [[TMP3:%.*]] = bitcast float* [[CALL2]] to i32* +; TUNIT-NEXT: [[CALL:%.*]] = call noundef dereferenceable_or_null(4) ptr @scc_C(ptr noalias nofree noundef readnone dereferenceable_or_null(4) "no-capture-maybe-returned" [[A]]) #[[ATTR9:[0-9]+]] +; TUNIT-NEXT: [[CALL1:%.*]] = call noundef dereferenceable_or_null(8) ptr @scc_B(ptr noalias nofree noundef readnone dereferenceable_or_null(8) "no-capture-maybe-returned" [[A]]) #[[ATTR9]] +; TUNIT-NEXT: [[CALL2:%.*]] = call ptr @scc_A(ptr noalias nofree noundef readnone dereferenceable_or_null(8) "no-capture-maybe-returned" [[A]]) #[[ATTR9]] ; TUNIT-NEXT: br label [[COND_END:%.*]] ; TUNIT: cond.false: ; TUNIT-NEXT: br label [[COND_END]] ; TUNIT: cond.end: -; TUNIT-NEXT: [[COND:%.*]] = phi i32* [ [[TMP3]], [[COND_TRUE]] ], [ [[A]], [[COND_FALSE]] ] -; TUNIT-NEXT: [[TMP4:%.*]] = bitcast i32* [[COND]] to float* -; TUNIT-NEXT: ret float* [[TMP4]] +; TUNIT-NEXT: [[COND:%.*]] = phi ptr [ [[A]], [[COND_TRUE]] ], [ [[A]], [[COND_FALSE]] ] +; TUNIT-NEXT: ret ptr [[A]] ; ; CGSCC: Function Attrs: nofree nosync nounwind memory(none) -; CGSCC-LABEL: define dereferenceable_or_null(4) float* @scc_A -; CGSCC-SAME: (i32* nofree noundef readnone dereferenceable_or_null(4) "no-capture-maybe-returned" [[A:%.*]]) #[[ATTR2:[0-9]+]] { +; CGSCC-LABEL: define noundef dereferenceable_or_null(4) ptr @scc_A +; CGSCC-SAME: (ptr nofree noundef readnone returned dereferenceable_or_null(4) "no-capture-maybe-returned" [[A:%.*]]) #[[ATTR2:[0-9]+]] { ; CGSCC-NEXT: entry: -; CGSCC-NEXT: [[TOBOOL:%.*]] = icmp ne i32* [[A]], null +; CGSCC-NEXT: [[TOBOOL:%.*]] = icmp ne ptr [[A]], null ; CGSCC-NEXT: br i1 [[TOBOOL]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] ; CGSCC: cond.true: -; CGSCC-NEXT: [[TMP0:%.*]] = bitcast i32* [[A]] to i16* -; CGSCC-NEXT: [[CALL:%.*]] = call dereferenceable_or_null(4) i8* @scc_C(i16* noalias nofree noundef nonnull readnone dereferenceable(4) "no-capture-maybe-returned" [[TMP0]]) #[[ATTR10:[0-9]+]] -; CGSCC-NEXT: [[TMP1:%.*]] = bitcast i8* [[CALL]] to double* -; CGSCC-NEXT: [[CALL1:%.*]] = call dereferenceable_or_null(4) i64* @scc_B(double* noalias nofree readnone dereferenceable_or_null(8) "no-capture-maybe-returned" [[TMP1]]) #[[ATTR10]] -; CGSCC-NEXT: [[TMP2:%.*]] = bitcast i64* [[CALL1]] to i32* -; CGSCC-NEXT: [[CALL2:%.*]] = call dereferenceable_or_null(4) float* @scc_A(i32* noalias nofree readnone dereferenceable_or_null(4) "no-capture-maybe-returned" [[TMP2]]) #[[ATTR10]] -; CGSCC-NEXT: [[TMP3:%.*]] = bitcast float* [[CALL2]] to i32* +; CGSCC-NEXT: [[CALL:%.*]] = call noundef dereferenceable_or_null(4) ptr @scc_C(ptr noalias nofree noundef readnone dereferenceable_or_null(4) "no-capture-maybe-returned" [[A]]) #[[ATTR10:[0-9]+]] +; CGSCC-NEXT: [[CALL1:%.*]] = call noundef dereferenceable_or_null(8) ptr @scc_B(ptr noalias nofree noundef readnone dereferenceable_or_null(8) "no-capture-maybe-returned" [[A]]) #[[ATTR10]] +; CGSCC-NEXT: [[CALL2:%.*]] = call ptr @scc_A(ptr noalias nofree noundef readnone dereferenceable_or_null(8) "no-capture-maybe-returned" [[A]]) #[[ATTR10]] ; CGSCC-NEXT: br label [[COND_END:%.*]] ; CGSCC: cond.false: ; CGSCC-NEXT: br label [[COND_END]] ; CGSCC: cond.end: -; CGSCC-NEXT: [[COND:%.*]] = phi i32* [ [[TMP3]], [[COND_TRUE]] ], [ [[A]], [[COND_FALSE]] ] -; CGSCC-NEXT: [[TMP4:%.*]] = bitcast i32* [[COND]] to float* -; CGSCC-NEXT: ret float* [[TMP4]] +; CGSCC-NEXT: [[COND:%.*]] = phi ptr [ [[A]], [[COND_TRUE]] ], [ [[A]], [[COND_FALSE]] ] +; CGSCC-NEXT: ret ptr [[A]] ; entry: - %tobool = icmp ne i32* %a, null + %tobool = icmp ne ptr %a, null br i1 %tobool, label %cond.true, label %cond.false cond.true: ; preds = %entry - %0 = bitcast i32* %a to i16* - %call = call i8* @scc_C(i16* %0) - %1 = bitcast i8* %call to double* - %call1 = call i64* @scc_B(double* %1) - %2 = bitcast i64* %call1 to i32* - %call2 = call float* @scc_A(i32* %2) - %3 = bitcast float* %call2 to i32* + %call = call ptr @scc_C(ptr %a) + %call1 = call ptr @scc_B(ptr %call) + %call2 = call ptr @scc_A(ptr %call1) br label %cond.end cond.false: ; preds = %entry br label %cond.end cond.end: ; preds = %cond.false, %cond.true - %cond = phi i32* [ %3, %cond.true ], [ %a, %cond.false ] - %4 = bitcast i32* %cond to float* - ret float* %4 + %cond = phi ptr [ %call2, %cond.true ], [ %a, %cond.false ] + ret ptr %cond } ; FIXME: the call1 below to scc_B should return dereferenceable_or_null(8) (as the callee does). Something prevented that deduction and needs to be investigated. -define i64* @scc_B(double* dereferenceable_or_null(8) %a) { +define ptr @scc_B(ptr dereferenceable_or_null(8) %a) { ; CHECK: Function Attrs: nofree nosync nounwind memory(none) -; CHECK-LABEL: define dereferenceable_or_null(4) i64* @scc_B -; CHECK-SAME: (double* nofree noundef readnone dereferenceable_or_null(8) "no-capture-maybe-returned" [[A:%.*]]) #[[ATTR2:[0-9]+]] { +; CHECK-LABEL: define noundef dereferenceable_or_null(8) ptr @scc_B +; CHECK-SAME: (ptr nofree noundef readnone returned dereferenceable_or_null(8) "no-capture-maybe-returned" [[A:%.*]]) #[[ATTR2:[0-9]+]] { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne double* [[A]], null +; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne ptr [[A]], null ; CHECK-NEXT: br i1 [[TOBOOL]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] ; CHECK: cond.true: -; CHECK-NEXT: [[TMP0:%.*]] = bitcast double* [[A]] to i32* -; CHECK-NEXT: [[CALL:%.*]] = call dereferenceable_or_null(4) float* @scc_A(i32* noalias nofree noundef nonnull readnone dereferenceable(8) "no-capture-maybe-returned" [[TMP0]]) #[[ATTR2]] -; CHECK-NEXT: [[TMP1:%.*]] = bitcast float* [[CALL]] to double* -; CHECK-NEXT: [[CALL1:%.*]] = call dereferenceable_or_null(4) i64* @scc_B(double* noalias nofree readnone dereferenceable_or_null(8) "no-capture-maybe-returned" [[TMP1]]) #[[ATTR2]] -; CHECK-NEXT: [[TMP2:%.*]] = bitcast i64* [[CALL1]] to i16* -; CHECK-NEXT: [[CALL2:%.*]] = call dereferenceable_or_null(4) i8* @scc_C(i16* noalias nofree readnone dereferenceable_or_null(4) "no-capture-maybe-returned" [[TMP2]]) #[[ATTR2]] +; CHECK-NEXT: [[CALL:%.*]] = call noundef dereferenceable_or_null(4) ptr @scc_A(ptr noalias nofree noundef readnone dereferenceable_or_null(8) "no-capture-maybe-returned" [[A]]) #[[ATTR2]] +; CHECK-NEXT: [[CALL1:%.*]] = call noundef dereferenceable_or_null(8) ptr @scc_B(ptr noalias nofree noundef readnone dereferenceable_or_null(8) "no-capture-maybe-returned" [[A]]) #[[ATTR2]] +; CHECK-NEXT: [[CALL2:%.*]] = call ptr @scc_C(ptr noalias nofree noundef readnone dereferenceable_or_null(8) "no-capture-maybe-returned" [[A]]) #[[ATTR2]] ; CHECK-NEXT: br label [[COND_END:%.*]] ; CHECK: cond.false: -; CHECK-NEXT: [[TMP3:%.*]] = bitcast double* [[A]] to i8* ; CHECK-NEXT: br label [[COND_END]] ; CHECK: cond.end: -; CHECK-NEXT: [[COND:%.*]] = phi i8* [ [[CALL2]], [[COND_TRUE]] ], [ [[TMP3]], [[COND_FALSE]] ] -; CHECK-NEXT: [[TMP4:%.*]] = bitcast i8* [[COND]] to i64* -; CHECK-NEXT: ret i64* [[TMP4]] +; CHECK-NEXT: [[COND:%.*]] = phi ptr [ [[A]], [[COND_TRUE]] ], [ [[A]], [[COND_FALSE]] ] +; CHECK-NEXT: ret ptr [[A]] ; entry: - %tobool = icmp ne double* %a, null + %tobool = icmp ne ptr %a, null br i1 %tobool, label %cond.true, label %cond.false cond.true: ; preds = %entry - %0 = bitcast double* %a to i32* - %call = call float* @scc_A(i32* %0) - %1 = bitcast float* %call to double* - %call1 = call i64* @scc_B(double* %1) - %2 = bitcast i64* %call1 to i16* - %call2 = call i8* @scc_C(i16* %2) + %call = call ptr @scc_A(ptr %a) + %call1 = call ptr @scc_B(ptr %call) + %call2 = call ptr @scc_C(ptr %call1) br label %cond.end cond.false: ; preds = %entry - %3 = bitcast double* %a to i8* br label %cond.end cond.end: ; preds = %cond.false, %cond.true - %cond = phi i8* [ %call2, %cond.true ], [ %3, %cond.false ] - %4 = bitcast i8* %cond to i64* - ret i64* %4 + %cond = phi ptr [ %call2, %cond.true ], [ %a, %cond.false ] + ret ptr %cond } -define i8* @scc_C(i16* dereferenceable_or_null(2) %a) { +define ptr @scc_C(ptr dereferenceable_or_null(2) %a) { ; TUNIT: Function Attrs: nofree nosync nounwind memory(none) -; TUNIT-LABEL: define dereferenceable_or_null(4) i8* @scc_C -; TUNIT-SAME: (i16* nofree noundef readnone dereferenceable_or_null(4) "no-capture-maybe-returned" [[A:%.*]]) #[[ATTR2]] { +; TUNIT-LABEL: define noundef dereferenceable_or_null(4) ptr @scc_C +; TUNIT-SAME: (ptr nofree noundef readnone returned dereferenceable_or_null(4) "no-capture-maybe-returned" [[A:%.*]]) #[[ATTR2]] { ; TUNIT-NEXT: entry: -; TUNIT-NEXT: [[BC:%.*]] = bitcast i16* [[A]] to i32* -; TUNIT-NEXT: [[CALL:%.*]] = call dereferenceable_or_null(4) float* @scc_A(i32* noalias nofree noundef readnone dereferenceable_or_null(4) "no-capture-maybe-returned" [[BC]]) #[[ATTR9]] -; TUNIT-NEXT: [[BC2:%.*]] = bitcast float* [[CALL]] to i8* -; TUNIT-NEXT: [[TOBOOL:%.*]] = icmp ne i8* [[BC2]], null +; TUNIT-NEXT: [[CALL:%.*]] = call dereferenceable_or_null(4) ptr @scc_A(ptr noalias nofree noundef readnone dereferenceable_or_null(4) "no-capture-maybe-returned" [[A]]) #[[ATTR9]] +; TUNIT-NEXT: [[TOBOOL:%.*]] = icmp ne ptr [[A]], null ; TUNIT-NEXT: br i1 [[TOBOOL]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] ; TUNIT: cond.true: -; TUNIT-NEXT: [[TMP0:%.*]] = bitcast i16* [[A]] to double* -; TUNIT-NEXT: [[CALL1:%.*]] = call dereferenceable_or_null(4) i64* @scc_B(double* noalias nofree noundef readnone dereferenceable_or_null(8) "no-capture-maybe-returned" [[TMP0]]) #[[ATTR9]] -; TUNIT-NEXT: [[TMP1:%.*]] = bitcast i64* [[CALL1]] to i8* +; TUNIT-NEXT: [[CALL1:%.*]] = call ptr @scc_B(ptr noalias nofree noundef readnone dereferenceable_or_null(8) "no-capture-maybe-returned" [[A]]) #[[ATTR9]] ; TUNIT-NEXT: br label [[COND_END:%.*]] ; TUNIT: cond.false: -; TUNIT-NEXT: [[CALL2:%.*]] = call dereferenceable_or_null(4) i8* @scc_C(i16* noalias nofree noundef readnone dereferenceable_or_null(4) "no-capture-maybe-returned" [[A]]) #[[ATTR9]] +; TUNIT-NEXT: [[CALL2:%.*]] = call ptr @scc_C(ptr noalias nofree noundef readnone dereferenceable_or_null(4) "no-capture-maybe-returned" [[A]]) #[[ATTR9]] ; TUNIT-NEXT: br label [[COND_END]] ; TUNIT: cond.end: -; TUNIT-NEXT: [[COND:%.*]] = phi i8* [ [[TMP1]], [[COND_TRUE]] ], [ [[CALL2]], [[COND_FALSE]] ] -; TUNIT-NEXT: [[TMP2:%.*]] = bitcast i8* [[COND]] to i32* -; TUNIT-NEXT: [[CALL3:%.*]] = call dereferenceable_or_null(4) float* @scc_A(i32* noalias nofree readnone dereferenceable_or_null(4) "no-capture-maybe-returned" [[TMP2]]) #[[ATTR9]] -; TUNIT-NEXT: [[TMP3:%.*]] = bitcast float* [[CALL3]] to i8* -; TUNIT-NEXT: ret i8* [[TMP3]] +; TUNIT-NEXT: [[COND:%.*]] = phi ptr [ [[A]], [[COND_TRUE]] ], [ [[A]], [[COND_FALSE]] ] +; TUNIT-NEXT: [[CALL3:%.*]] = call ptr @scc_A(ptr noalias nofree noundef readnone dereferenceable_or_null(4) "no-capture-maybe-returned" [[A]]) #[[ATTR9]] +; TUNIT-NEXT: ret ptr [[A]] ; ; CGSCC: Function Attrs: nofree nosync nounwind memory(none) -; CGSCC-LABEL: define dereferenceable_or_null(4) i8* @scc_C -; CGSCC-SAME: (i16* nofree noundef readnone dereferenceable_or_null(4) "no-capture-maybe-returned" [[A:%.*]]) #[[ATTR2]] { +; CGSCC-LABEL: define noundef dereferenceable_or_null(4) ptr @scc_C +; CGSCC-SAME: (ptr nofree noundef readnone returned dereferenceable_or_null(4) "no-capture-maybe-returned" [[A:%.*]]) #[[ATTR2]] { ; CGSCC-NEXT: entry: -; CGSCC-NEXT: [[BC:%.*]] = bitcast i16* [[A]] to i32* -; CGSCC-NEXT: [[CALL:%.*]] = call dereferenceable_or_null(4) float* @scc_A(i32* noalias nofree noundef readnone dereferenceable_or_null(4) "no-capture-maybe-returned" [[BC]]) #[[ATTR10]] -; CGSCC-NEXT: [[BC2:%.*]] = bitcast float* [[CALL]] to i8* -; CGSCC-NEXT: [[TOBOOL:%.*]] = icmp ne i8* [[BC2]], null +; CGSCC-NEXT: [[CALL:%.*]] = call dereferenceable_or_null(4) ptr @scc_A(ptr noalias nofree noundef readnone dereferenceable_or_null(4) "no-capture-maybe-returned" [[A]]) #[[ATTR10]] +; CGSCC-NEXT: [[TOBOOL:%.*]] = icmp ne ptr [[A]], null ; CGSCC-NEXT: br i1 [[TOBOOL]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] ; CGSCC: cond.true: -; CGSCC-NEXT: [[TMP0:%.*]] = bitcast i16* [[A]] to double* -; CGSCC-NEXT: [[CALL1:%.*]] = call dereferenceable_or_null(4) i64* @scc_B(double* noalias nofree noundef readnone dereferenceable_or_null(8) "no-capture-maybe-returned" [[TMP0]]) #[[ATTR10]] -; CGSCC-NEXT: [[TMP1:%.*]] = bitcast i64* [[CALL1]] to i8* +; CGSCC-NEXT: [[CALL1:%.*]] = call ptr @scc_B(ptr noalias nofree noundef readnone dereferenceable_or_null(8) "no-capture-maybe-returned" [[A]]) #[[ATTR10]] ; CGSCC-NEXT: br label [[COND_END:%.*]] ; CGSCC: cond.false: -; CGSCC-NEXT: [[CALL2:%.*]] = call dereferenceable_or_null(4) i8* @scc_C(i16* noalias nofree noundef readnone dereferenceable_or_null(4) "no-capture-maybe-returned" [[A]]) #[[ATTR10]] +; CGSCC-NEXT: [[CALL2:%.*]] = call ptr @scc_C(ptr noalias nofree noundef readnone dereferenceable_or_null(4) "no-capture-maybe-returned" [[A]]) #[[ATTR10]] ; CGSCC-NEXT: br label [[COND_END]] ; CGSCC: cond.end: -; CGSCC-NEXT: [[COND:%.*]] = phi i8* [ [[TMP1]], [[COND_TRUE]] ], [ [[CALL2]], [[COND_FALSE]] ] -; CGSCC-NEXT: [[TMP2:%.*]] = bitcast i8* [[COND]] to i32* -; CGSCC-NEXT: [[CALL3:%.*]] = call dereferenceable_or_null(4) float* @scc_A(i32* noalias nofree readnone dereferenceable_or_null(4) "no-capture-maybe-returned" [[TMP2]]) #[[ATTR10]] -; CGSCC-NEXT: [[TMP3:%.*]] = bitcast float* [[CALL3]] to i8* -; CGSCC-NEXT: ret i8* [[TMP3]] +; CGSCC-NEXT: [[COND:%.*]] = phi ptr [ [[A]], [[COND_TRUE]] ], [ [[A]], [[COND_FALSE]] ] +; CGSCC-NEXT: [[CALL3:%.*]] = call ptr @scc_A(ptr noalias nofree noundef readnone dereferenceable_or_null(4) "no-capture-maybe-returned" [[A]]) #[[ATTR10]] +; CGSCC-NEXT: ret ptr [[A]] ; entry: - %bc = bitcast i16* %a to i32* - %call = call float* @scc_A(i32* %bc) - %bc2 = bitcast float* %call to i8* - %tobool = icmp ne i8* %bc2, null + %call = call ptr @scc_A(ptr %a) + %tobool = icmp ne ptr %call, null br i1 %tobool, label %cond.true, label %cond.false cond.true: ; preds = %entry - %0 = bitcast i16* %a to double* - %call1 = call i64* @scc_B(double* %0) - %1 = bitcast i64* %call1 to i8* + %call1 = call ptr @scc_B(ptr %a) br label %cond.end cond.false: ; preds = %entry - %call2 = call i8* @scc_C(i16* %a) + %call2 = call ptr @scc_C(ptr %a) br label %cond.end cond.end: ; preds = %cond.false, %cond.true - %cond = phi i8* [ %1, %cond.true ], [ %call2, %cond.false ] - %2 = bitcast i8* %cond to i32* - %call3 = call float* @scc_A(i32* %2) - %3 = bitcast float* %call3 to i8* - ret i8* %3 + %cond = phi ptr [ %call1, %cond.true ], [ %call2, %cond.false ] + %call3 = call ptr @scc_A(ptr %cond) + ret ptr %call3 } @@ -360,18 +317,18 @@ ; external_no_capture(p); ; } ; -declare void @external_no_capture(i32* nocapture) +declare void @external_no_capture(ptr nocapture) -define void @test_external_no_capture(i32* %p) #0 { +define void @test_external_no_capture(ptr %p) #0 { ; CHECK: Function Attrs: noinline nounwind uwtable ; CHECK-LABEL: define void @test_external_no_capture -; CHECK-SAME: (i32* nocapture [[P:%.*]]) #[[ATTR3:[0-9]+]] { +; CHECK-SAME: (ptr nocapture [[P:%.*]]) #[[ATTR3:[0-9]+]] { ; CHECK-NEXT: entry: -; CHECK-NEXT: call void @external_no_capture(i32* nocapture [[P]]) +; CHECK-NEXT: call void @external_no_capture(ptr nocapture [[P]]) ; CHECK-NEXT: ret void ; entry: - call void @external_no_capture(i32* %p) + call void @external_no_capture(ptr %p) ret void } @@ -381,20 +338,20 @@ ; printf(p, a); ; } ; -define void @test_var_arg_call(i8* %p, i32 %a) #0 { +define void @test_var_arg_call(ptr %p, i32 %a) #0 { ; CHECK: Function Attrs: noinline nounwind uwtable ; CHECK-LABEL: define void @test_var_arg_call -; CHECK-SAME: (i8* nocapture [[P:%.*]], i32 [[A:%.*]]) #[[ATTR3]] { +; CHECK-SAME: (ptr nocapture [[P:%.*]], i32 [[A:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CALL:%.*]] = call i32 (i8*, ...) @printf(i8* nocapture [[P]], i32 [[A]]) +; CHECK-NEXT: [[CALL:%.*]] = call i32 (ptr, ...) @printf(ptr nocapture [[P]], i32 [[A]]) ; CHECK-NEXT: ret void ; entry: - %call = call i32 (i8*, ...) @printf(i8* %p, i32 %a) + %call = call i32 (ptr, ...) @printf(ptr %p, i32 %a) ret void } -declare i32 @printf(i8* nocapture, ...) +declare i32 @printf(ptr nocapture, ...) ; TEST "captured" only through return @@ -405,17 +362,17 @@ ; } ; ; There should *not* be a no-capture attribute on %a -define i64* @not_captured_but_returned_0(i64* %a) #0 { +define ptr @not_captured_but_returned_0(ptr %a) #0 { ; CHECK: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(argmem: write) uwtable -; CHECK-LABEL: define noundef nonnull align 8 dereferenceable(8) i64* @not_captured_but_returned_0 -; CHECK-SAME: (i64* nofree noundef nonnull returned writeonly align 8 dereferenceable(8) "no-capture-maybe-returned" [[A:%.*]]) #[[ATTR4:[0-9]+]] { +; CHECK-LABEL: define noundef nonnull align 8 dereferenceable(8) ptr @not_captured_but_returned_0 +; CHECK-SAME: (ptr nofree noundef nonnull returned writeonly align 8 dereferenceable(8) "no-capture-maybe-returned" [[A:%.*]]) #[[ATTR4:[0-9]+]] { ; CHECK-NEXT: entry: -; CHECK-NEXT: store i64 0, i64* [[A]], align 8 -; CHECK-NEXT: ret i64* [[A]] +; CHECK-NEXT: store i64 0, ptr [[A]], align 8 +; CHECK-NEXT: ret ptr [[A]] ; entry: - store i64 0, i64* %a, align 8 - ret i64* %a + store i64 0, ptr %a, align 8 + ret ptr %a } ; TEST "captured" only through return @@ -426,19 +383,19 @@ ; } ; ; There should *not* be a no-capture attribute on %a -define i64* @not_captured_but_returned_1(i64* %a) #0 { +define ptr @not_captured_but_returned_1(ptr %a) #0 { ; CHECK: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(argmem: write) uwtable -; CHECK-LABEL: define noundef nonnull align 8 dereferenceable(8) i64* @not_captured_but_returned_1 -; CHECK-SAME: (i64* nofree nonnull writeonly align 8 dereferenceable(16) "no-capture-maybe-returned" [[A:%.*]]) #[[ATTR4]] { +; CHECK-LABEL: define noundef nonnull align 8 dereferenceable(8) ptr @not_captured_but_returned_1 +; CHECK-SAME: (ptr nofree nonnull writeonly align 8 dereferenceable(16) "no-capture-maybe-returned" [[A:%.*]]) #[[ATTR4]] { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i64, i64* [[A]], i64 1 -; CHECK-NEXT: store i64 1, i64* [[ADD_PTR]], align 8 -; CHECK-NEXT: ret i64* [[ADD_PTR]] +; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i64, ptr [[A]], i64 1 +; CHECK-NEXT: store i64 1, ptr [[ADD_PTR]], align 8 +; CHECK-NEXT: ret ptr [[ADD_PTR]] ; entry: - %add.ptr = getelementptr inbounds i64, i64* %a, i64 1 - store i64 1, i64* %add.ptr, align 8 - ret i64* %add.ptr + %add.ptr = getelementptr inbounds i64, ptr %a, i64 1 + store i64 1, ptr %add.ptr, align 8 + ret ptr %add.ptr } ; TEST calls to "captured" only through return functions @@ -448,26 +405,26 @@ ; not_captured_but_returned_1(a); ; } ; -define void @test_not_captured_but_returned_calls(i64* %a) #0 { +define void @test_not_captured_but_returned_calls(ptr %a) #0 { ; TUNIT: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(argmem: write) uwtable ; TUNIT-LABEL: define void @test_not_captured_but_returned_calls -; TUNIT-SAME: (i64* nocapture nofree writeonly align 8 [[A:%.*]]) #[[ATTR4]] { +; TUNIT-SAME: (ptr nocapture nofree writeonly align 8 [[A:%.*]]) #[[ATTR4]] { ; TUNIT-NEXT: entry: -; TUNIT-NEXT: [[CALL:%.*]] = call i64* @not_captured_but_returned_0(i64* nofree writeonly align 8 "no-capture-maybe-returned" [[A]]) #[[ATTR10:[0-9]+]] -; TUNIT-NEXT: [[CALL1:%.*]] = call i64* @not_captured_but_returned_1(i64* nofree writeonly align 8 "no-capture-maybe-returned" [[A]]) #[[ATTR10]] +; TUNIT-NEXT: [[CALL:%.*]] = call ptr @not_captured_but_returned_0(ptr nofree writeonly align 8 "no-capture-maybe-returned" [[A]]) #[[ATTR10:[0-9]+]] +; TUNIT-NEXT: [[CALL1:%.*]] = call ptr @not_captured_but_returned_1(ptr nofree writeonly align 8 "no-capture-maybe-returned" [[A]]) #[[ATTR10]] ; TUNIT-NEXT: ret void ; ; CGSCC: Function Attrs: mustprogress nofree noinline nosync nounwind willreturn memory(argmem: write) uwtable ; CGSCC-LABEL: define void @test_not_captured_but_returned_calls -; CGSCC-SAME: (i64* nofree noundef nonnull writeonly align 8 dereferenceable(16) [[A:%.*]]) #[[ATTR5:[0-9]+]] { +; CGSCC-SAME: (ptr nofree noundef nonnull writeonly align 8 dereferenceable(16) [[A:%.*]]) #[[ATTR5:[0-9]+]] { ; CGSCC-NEXT: entry: -; CGSCC-NEXT: [[CALL:%.*]] = call i64* @not_captured_but_returned_0(i64* nofree noundef nonnull writeonly align 8 dereferenceable(16) [[A]]) #[[ATTR11:[0-9]+]] -; CGSCC-NEXT: [[CALL1:%.*]] = call i64* @not_captured_but_returned_1(i64* nofree noundef nonnull writeonly align 8 dereferenceable(16) [[A]]) #[[ATTR11]] +; CGSCC-NEXT: [[CALL:%.*]] = call ptr @not_captured_but_returned_0(ptr nofree noundef nonnull writeonly align 8 dereferenceable(16) [[A]]) #[[ATTR11:[0-9]+]] +; CGSCC-NEXT: [[CALL1:%.*]] = call ptr @not_captured_but_returned_1(ptr nofree noundef nonnull writeonly align 8 dereferenceable(16) [[A]]) #[[ATTR11]] ; CGSCC-NEXT: ret void ; entry: - %call = call i64* @not_captured_but_returned_0(i64* %a) - %call1 = call i64* @not_captured_but_returned_1(i64* %a) + %call = call ptr @not_captured_but_returned_0(ptr %a) + %call1 = call ptr @not_captured_but_returned_1(ptr %a) ret void } @@ -478,24 +435,24 @@ ; } ; ; There should *not* be a no-capture attribute on %a -define i64* @negative_test_not_captured_but_returned_call_0a(i64* %a) #0 { +define ptr @negative_test_not_captured_but_returned_call_0a(ptr %a) #0 { ; TUNIT: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(argmem: write) uwtable -; TUNIT-LABEL: define align 8 i64* @negative_test_not_captured_but_returned_call_0a -; TUNIT-SAME: (i64* nofree returned writeonly align 8 "no-capture-maybe-returned" [[A:%.*]]) #[[ATTR4]] { +; TUNIT-LABEL: define align 8 ptr @negative_test_not_captured_but_returned_call_0a +; TUNIT-SAME: (ptr nofree returned writeonly align 8 "no-capture-maybe-returned" [[A:%.*]]) #[[ATTR4]] { ; TUNIT-NEXT: entry: -; TUNIT-NEXT: [[CALL:%.*]] = call i64* @not_captured_but_returned_0(i64* nofree writeonly align 8 "no-capture-maybe-returned" [[A]]) #[[ATTR10]] -; TUNIT-NEXT: ret i64* [[A]] +; TUNIT-NEXT: [[CALL:%.*]] = call ptr @not_captured_but_returned_0(ptr nofree writeonly align 8 "no-capture-maybe-returned" [[A]]) #[[ATTR10]] +; TUNIT-NEXT: ret ptr [[A]] ; ; CGSCC: Function Attrs: mustprogress nofree noinline nosync nounwind willreturn memory(argmem: write) uwtable -; CGSCC-LABEL: define noundef nonnull align 8 dereferenceable(8) i64* @negative_test_not_captured_but_returned_call_0a -; CGSCC-SAME: (i64* nofree noundef nonnull writeonly align 8 dereferenceable(8) [[A:%.*]]) #[[ATTR5]] { +; CGSCC-LABEL: define noundef nonnull align 8 dereferenceable(8) ptr @negative_test_not_captured_but_returned_call_0a +; CGSCC-SAME: (ptr nofree noundef nonnull writeonly align 8 dereferenceable(8) [[A:%.*]]) #[[ATTR5]] { ; CGSCC-NEXT: entry: -; CGSCC-NEXT: [[CALL:%.*]] = call noundef nonnull align 8 dereferenceable(8) i64* @not_captured_but_returned_0(i64* nofree noundef nonnull writeonly align 8 dereferenceable(8) [[A]]) #[[ATTR11]] -; CGSCC-NEXT: ret i64* [[CALL]] +; CGSCC-NEXT: [[CALL:%.*]] = call noundef nonnull align 8 dereferenceable(8) ptr @not_captured_but_returned_0(ptr nofree noundef nonnull writeonly align 8 dereferenceable(8) [[A]]) #[[ATTR11]] +; CGSCC-NEXT: ret ptr [[CALL]] ; entry: - %call = call i64* @not_captured_but_returned_0(i64* %a) - ret i64* %call + %call = call ptr @not_captured_but_returned_0(ptr %a) + ret ptr %call } ; TEST captured through write @@ -505,29 +462,29 @@ ; } ; ; There should *not* be a no-capture attribute on %a -define void @negative_test_not_captured_but_returned_call_0b(i64* %a) #0 { +define void @negative_test_not_captured_but_returned_call_0b(ptr %a) #0 { ; TUNIT: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(argmem: write) uwtable ; TUNIT-LABEL: define void @negative_test_not_captured_but_returned_call_0b -; TUNIT-SAME: (i64* nofree writeonly align 8 [[A:%.*]]) #[[ATTR4]] { +; TUNIT-SAME: (ptr nofree writeonly align 8 [[A:%.*]]) #[[ATTR4]] { ; TUNIT-NEXT: entry: -; TUNIT-NEXT: [[CALL:%.*]] = call i64* @not_captured_but_returned_0(i64* nofree writeonly align 8 "no-capture-maybe-returned" [[A]]) #[[ATTR10]] -; TUNIT-NEXT: [[TMP0:%.*]] = ptrtoint i64* [[A]] to i64 -; TUNIT-NEXT: store i64 [[TMP0]], i64* [[A]], align 8 +; TUNIT-NEXT: [[CALL:%.*]] = call ptr @not_captured_but_returned_0(ptr nofree writeonly align 8 "no-capture-maybe-returned" [[A]]) #[[ATTR10]] +; TUNIT-NEXT: [[TMP0:%.*]] = ptrtoint ptr [[A]] to i64 +; TUNIT-NEXT: store i64 [[TMP0]], ptr [[A]], align 8 ; TUNIT-NEXT: ret void ; ; CGSCC: Function Attrs: mustprogress nofree noinline nosync nounwind willreturn memory(argmem: write) uwtable ; CGSCC-LABEL: define void @negative_test_not_captured_but_returned_call_0b -; CGSCC-SAME: (i64* nofree noundef nonnull writeonly align 8 dereferenceable(8) [[A:%.*]]) #[[ATTR5]] { +; CGSCC-SAME: (ptr nofree noundef nonnull writeonly align 8 dereferenceable(8) [[A:%.*]]) #[[ATTR5]] { ; CGSCC-NEXT: entry: -; CGSCC-NEXT: [[CALL:%.*]] = call i64* @not_captured_but_returned_0(i64* nofree noundef nonnull writeonly align 8 dereferenceable(8) [[A]]) #[[ATTR11]] -; CGSCC-NEXT: [[TMP0:%.*]] = ptrtoint i64* [[CALL]] to i64 -; CGSCC-NEXT: store i64 [[TMP0]], i64* [[A]], align 8 +; CGSCC-NEXT: [[CALL:%.*]] = call ptr @not_captured_but_returned_0(ptr nofree noundef nonnull writeonly align 8 dereferenceable(8) [[A]]) #[[ATTR11]] +; CGSCC-NEXT: [[TMP0:%.*]] = ptrtoint ptr [[CALL]] to i64 +; CGSCC-NEXT: store i64 [[TMP0]], ptr [[A]], align 8 ; CGSCC-NEXT: ret void ; entry: - %call = call i64* @not_captured_but_returned_0(i64* %a) - %0 = ptrtoint i64* %call to i64 - store i64 %0, i64* %a, align 8 + %call = call ptr @not_captured_but_returned_0(ptr %a) + %0 = ptrtoint ptr %call to i64 + store i64 %0, ptr %a, align 8 ret void } @@ -538,24 +495,24 @@ ; } ; ; There should *not* be a no-capture attribute on %a -define i64* @negative_test_not_captured_but_returned_call_1a(i64* %a) #0 { +define ptr @negative_test_not_captured_but_returned_call_1a(ptr %a) #0 { ; TUNIT: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(argmem: write) uwtable -; TUNIT-LABEL: define noundef nonnull align 8 dereferenceable(8) i64* @negative_test_not_captured_but_returned_call_1a -; TUNIT-SAME: (i64* nofree writeonly align 8 "no-capture-maybe-returned" [[A:%.*]]) #[[ATTR4]] { +; TUNIT-LABEL: define noundef nonnull align 8 dereferenceable(8) ptr @negative_test_not_captured_but_returned_call_1a +; TUNIT-SAME: (ptr nofree writeonly align 8 "no-capture-maybe-returned" [[A:%.*]]) #[[ATTR4]] { ; TUNIT-NEXT: entry: -; TUNIT-NEXT: [[CALL:%.*]] = call noundef nonnull align 8 dereferenceable(8) i64* @not_captured_but_returned_1(i64* nofree writeonly align 8 "no-capture-maybe-returned" [[A]]) #[[ATTR10]] -; TUNIT-NEXT: ret i64* [[CALL]] +; TUNIT-NEXT: [[CALL:%.*]] = call noundef nonnull align 8 dereferenceable(8) ptr @not_captured_but_returned_1(ptr nofree writeonly align 8 "no-capture-maybe-returned" [[A]]) #[[ATTR10]] +; TUNIT-NEXT: ret ptr [[CALL]] ; ; CGSCC: Function Attrs: mustprogress nofree noinline nosync nounwind willreturn memory(argmem: write) uwtable -; CGSCC-LABEL: define noundef nonnull align 8 dereferenceable(8) i64* @negative_test_not_captured_but_returned_call_1a -; CGSCC-SAME: (i64* nofree noundef nonnull writeonly align 8 dereferenceable(16) [[A:%.*]]) #[[ATTR5]] { +; CGSCC-LABEL: define noundef nonnull align 8 dereferenceable(8) ptr @negative_test_not_captured_but_returned_call_1a +; CGSCC-SAME: (ptr nofree noundef nonnull writeonly align 8 dereferenceable(16) [[A:%.*]]) #[[ATTR5]] { ; CGSCC-NEXT: entry: -; CGSCC-NEXT: [[CALL:%.*]] = call noundef nonnull align 8 dereferenceable(8) i64* @not_captured_but_returned_1(i64* nofree noundef nonnull writeonly align 8 dereferenceable(16) [[A]]) #[[ATTR11]] -; CGSCC-NEXT: ret i64* [[CALL]] +; CGSCC-NEXT: [[CALL:%.*]] = call noundef nonnull align 8 dereferenceable(8) ptr @not_captured_but_returned_1(ptr nofree noundef nonnull writeonly align 8 dereferenceable(16) [[A]]) #[[ATTR11]] +; CGSCC-NEXT: ret ptr [[CALL]] ; entry: - %call = call i64* @not_captured_but_returned_1(i64* %a) - ret i64* %call + %call = call ptr @not_captured_but_returned_1(ptr %a) + ret ptr %call } ; TEST captured through write @@ -565,29 +522,29 @@ ; } ; ; There should *not* be a no-capture attribute on %a -define void @negative_test_not_captured_but_returned_call_1b(i64* %a) #0 { +define void @negative_test_not_captured_but_returned_call_1b(ptr %a) #0 { ; TUNIT: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(write) uwtable ; TUNIT-LABEL: define void @negative_test_not_captured_but_returned_call_1b -; TUNIT-SAME: (i64* nofree writeonly align 8 [[A:%.*]]) #[[ATTR5:[0-9]+]] { +; TUNIT-SAME: (ptr nofree writeonly align 8 [[A:%.*]]) #[[ATTR5:[0-9]+]] { ; TUNIT-NEXT: entry: -; TUNIT-NEXT: [[CALL:%.*]] = call align 8 i64* @not_captured_but_returned_1(i64* nofree writeonly align 8 "no-capture-maybe-returned" [[A]]) #[[ATTR10]] -; TUNIT-NEXT: [[TMP0:%.*]] = ptrtoint i64* [[CALL]] to i64 -; TUNIT-NEXT: store i64 [[TMP0]], i64* [[CALL]], align 8 +; TUNIT-NEXT: [[CALL:%.*]] = call align 8 ptr @not_captured_but_returned_1(ptr nofree writeonly align 8 "no-capture-maybe-returned" [[A]]) #[[ATTR10]] +; TUNIT-NEXT: [[TMP0:%.*]] = ptrtoint ptr [[CALL]] to i64 +; TUNIT-NEXT: store i64 [[TMP0]], ptr [[CALL]], align 8 ; TUNIT-NEXT: ret void ; ; CGSCC: Function Attrs: mustprogress nofree noinline nosync nounwind willreturn memory(write) uwtable ; CGSCC-LABEL: define void @negative_test_not_captured_but_returned_call_1b -; CGSCC-SAME: (i64* nofree noundef nonnull writeonly align 8 dereferenceable(16) [[A:%.*]]) #[[ATTR6:[0-9]+]] { +; CGSCC-SAME: (ptr nofree noundef nonnull writeonly align 8 dereferenceable(16) [[A:%.*]]) #[[ATTR6:[0-9]+]] { ; CGSCC-NEXT: entry: -; CGSCC-NEXT: [[CALL:%.*]] = call align 8 i64* @not_captured_but_returned_1(i64* nofree noundef nonnull writeonly align 8 dereferenceable(16) [[A]]) #[[ATTR11]] -; CGSCC-NEXT: [[TMP0:%.*]] = ptrtoint i64* [[CALL]] to i64 -; CGSCC-NEXT: store i64 [[TMP0]], i64* [[CALL]], align 8 +; CGSCC-NEXT: [[CALL:%.*]] = call align 8 ptr @not_captured_but_returned_1(ptr nofree noundef nonnull writeonly align 8 dereferenceable(16) [[A]]) #[[ATTR11]] +; CGSCC-NEXT: [[TMP0:%.*]] = ptrtoint ptr [[CALL]] to i64 +; CGSCC-NEXT: store i64 [[TMP0]], ptr [[CALL]], align 8 ; CGSCC-NEXT: ret void ; entry: - %call = call i64* @not_captured_but_returned_1(i64* %a) - %0 = ptrtoint i64* %call to i64 - store i64 %0, i64* %call, align 8 + %call = call ptr @not_captured_but_returned_1(ptr %a) + %0 = ptrtoint ptr %call to i64 + store i64 %0, ptr %call, align 8 ret void } @@ -602,85 +559,85 @@ ; Verify we do *not* assume b is returned or not captured. ; -define i32* @ret_arg_or_unknown(i32* %b) #0 { +define ptr @ret_arg_or_unknown(ptr %b) #0 { ; CHECK: Function Attrs: noinline nounwind uwtable -; CHECK-LABEL: define i32* @ret_arg_or_unknown -; CHECK-SAME: (i32* [[B:%.*]]) #[[ATTR3]] { +; CHECK-LABEL: define ptr @ret_arg_or_unknown +; CHECK-SAME: (ptr [[B:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32* [[B]], null +; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[B]], null ; CHECK-NEXT: br i1 [[CMP]], label [[RET_ARG:%.*]], label [[RET_UNKNOWN:%.*]] ; CHECK: ret_arg: -; CHECK-NEXT: ret i32* [[B]] +; CHECK-NEXT: ret ptr [[B]] ; CHECK: ret_unknown: -; CHECK-NEXT: [[CALL:%.*]] = call i32* @unknown() -; CHECK-NEXT: ret i32* [[CALL]] +; CHECK-NEXT: [[CALL:%.*]] = call ptr @unknown() +; CHECK-NEXT: ret ptr [[CALL]] ; entry: - %cmp = icmp eq i32* %b, null + %cmp = icmp eq ptr %b, null br i1 %cmp, label %ret_arg, label %ret_unknown ret_arg: - ret i32* %b + ret ptr %b ret_unknown: - %call = call i32* @unknown() - ret i32* %call + %call = call ptr @unknown() + ret ptr %call } -define i32* @ret_arg_or_unknown_through_phi(i32* %b) #0 { +define ptr @ret_arg_or_unknown_through_phi(ptr %b) #0 { ; CHECK: Function Attrs: noinline nounwind uwtable -; CHECK-LABEL: define i32* @ret_arg_or_unknown_through_phi -; CHECK-SAME: (i32* [[B:%.*]]) #[[ATTR3]] { +; CHECK-LABEL: define ptr @ret_arg_or_unknown_through_phi +; CHECK-SAME: (ptr [[B:%.*]]) #[[ATTR3]] { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32* [[B]], null +; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[B]], null ; CHECK-NEXT: br i1 [[CMP]], label [[RET_ARG:%.*]], label [[RET_UNKNOWN:%.*]] ; CHECK: ret_arg: ; CHECK-NEXT: br label [[R:%.*]] ; CHECK: ret_unknown: -; CHECK-NEXT: [[CALL:%.*]] = call i32* @unknown() +; CHECK-NEXT: [[CALL:%.*]] = call ptr @unknown() ; CHECK-NEXT: br label [[R]] ; CHECK: r: -; CHECK-NEXT: [[PHI:%.*]] = phi i32* [ [[B]], [[RET_ARG]] ], [ [[CALL]], [[RET_UNKNOWN]] ] -; CHECK-NEXT: ret i32* [[PHI]] +; CHECK-NEXT: [[PHI:%.*]] = phi ptr [ [[B]], [[RET_ARG]] ], [ [[CALL]], [[RET_UNKNOWN]] ] +; CHECK-NEXT: ret ptr [[PHI]] ; entry: - %cmp = icmp eq i32* %b, null + %cmp = icmp eq ptr %b, null br i1 %cmp, label %ret_arg, label %ret_unknown ret_arg: br label %r ret_unknown: - %call = call i32* @unknown() + %call = call ptr @unknown() br label %r r: - %phi = phi i32* [ %b, %ret_arg ], [ %call, %ret_unknown ] - ret i32* %phi + %phi = phi ptr [ %b, %ret_arg ], [ %call, %ret_unknown ] + ret ptr %phi } ; TEST not captured by readonly external function ; -declare i32* @readonly_unknown(i32*, i32*) readonly +declare ptr @readonly_unknown(ptr, ptr) readonly -define void @not_captured_by_readonly_call(i32* %b) #0 { +define void @not_captured_by_readonly_call(ptr %b) #0 { ; TUNIT: Function Attrs: noinline nounwind memory(read) uwtable ; TUNIT-LABEL: define void @not_captured_by_readonly_call -; TUNIT-SAME: (i32* nocapture readonly [[B:%.*]]) #[[ATTR7:[0-9]+]] { +; TUNIT-SAME: (ptr nocapture readonly [[B:%.*]]) #[[ATTR7:[0-9]+]] { ; TUNIT-NEXT: entry: -; TUNIT-NEXT: [[CALL:%.*]] = call i32* @readonly_unknown(i32* readonly [[B]], i32* readonly [[B]]) +; TUNIT-NEXT: [[CALL:%.*]] = call ptr @readonly_unknown(ptr readonly [[B]], ptr readonly [[B]]) ; TUNIT-NEXT: ret void ; ; CGSCC: Function Attrs: noinline nounwind memory(read) uwtable ; CGSCC-LABEL: define void @not_captured_by_readonly_call -; CGSCC-SAME: (i32* nocapture readonly [[B:%.*]]) #[[ATTR8:[0-9]+]] { +; CGSCC-SAME: (ptr nocapture readonly [[B:%.*]]) #[[ATTR8:[0-9]+]] { ; CGSCC-NEXT: entry: -; CGSCC-NEXT: [[CALL:%.*]] = call i32* @readonly_unknown(i32* readonly [[B]], i32* readonly [[B]]) +; CGSCC-NEXT: [[CALL:%.*]] = call ptr @readonly_unknown(ptr readonly [[B]], ptr readonly [[B]]) ; CGSCC-NEXT: ret void ; entry: - %call = call i32* @readonly_unknown(i32* %b, i32* %b) + %call = call ptr @readonly_unknown(ptr %b, ptr %b) ret void } @@ -689,116 +646,116 @@ ; ; Make sure the returned flag on %r is strong enough to justify nocapture on %b but **not** on %r. ; -define i32* @not_captured_by_readonly_call_not_returned_either1(i32* %b, i32* returned %r) { +define ptr @not_captured_by_readonly_call_not_returned_either1(ptr %b, ptr returned %r) { ; TUNIT: Function Attrs: nounwind memory(read) -; TUNIT-LABEL: define i32* @not_captured_by_readonly_call_not_returned_either1 -; TUNIT-SAME: (i32* nocapture readonly [[B:%.*]], i32* readonly returned [[R:%.*]]) #[[ATTR8:[0-9]+]] { +; TUNIT-LABEL: define ptr @not_captured_by_readonly_call_not_returned_either1 +; TUNIT-SAME: (ptr nocapture readonly [[B:%.*]], ptr readonly returned [[R:%.*]]) #[[ATTR8:[0-9]+]] { ; TUNIT-NEXT: entry: -; TUNIT-NEXT: [[CALL:%.*]] = call i32* @readonly_unknown(i32* readonly [[B]], i32* readonly [[R]]) #[[ATTR11:[0-9]+]] -; TUNIT-NEXT: ret i32* [[CALL]] +; TUNIT-NEXT: [[CALL:%.*]] = call ptr @readonly_unknown(ptr readonly [[B]], ptr readonly [[R]]) #[[ATTR11:[0-9]+]] +; TUNIT-NEXT: ret ptr [[CALL]] ; ; CGSCC: Function Attrs: nounwind memory(read) -; CGSCC-LABEL: define i32* @not_captured_by_readonly_call_not_returned_either1 -; CGSCC-SAME: (i32* nocapture readonly [[B:%.*]], i32* readonly returned [[R:%.*]]) #[[ATTR9:[0-9]+]] { +; CGSCC-LABEL: define ptr @not_captured_by_readonly_call_not_returned_either1 +; CGSCC-SAME: (ptr nocapture readonly [[B:%.*]], ptr readonly returned [[R:%.*]]) #[[ATTR9:[0-9]+]] { ; CGSCC-NEXT: entry: -; CGSCC-NEXT: [[CALL:%.*]] = call i32* @readonly_unknown(i32* readonly [[B]], i32* readonly [[R]]) #[[ATTR11]] -; CGSCC-NEXT: ret i32* [[CALL]] +; CGSCC-NEXT: [[CALL:%.*]] = call ptr @readonly_unknown(ptr readonly [[B]], ptr readonly [[R]]) #[[ATTR11]] +; CGSCC-NEXT: ret ptr [[CALL]] ; entry: - %call = call i32* @readonly_unknown(i32* %b, i32* %r) nounwind - ret i32* %call + %call = call ptr @readonly_unknown(ptr %b, ptr %r) nounwind + ret ptr %call } -declare i32* @readonly_unknown_r1a(i32*, i32* returned) readonly -define i32* @not_captured_by_readonly_call_not_returned_either2(i32* %b, i32* %r) { +declare ptr @readonly_unknown_r1a(ptr, ptr returned) readonly +define ptr @not_captured_by_readonly_call_not_returned_either2(ptr %b, ptr %r) { ; TUNIT: Function Attrs: nounwind memory(read) -; TUNIT-LABEL: define i32* @not_captured_by_readonly_call_not_returned_either2 -; TUNIT-SAME: (i32* readonly [[B:%.*]], i32* readonly [[R:%.*]]) #[[ATTR8]] { +; TUNIT-LABEL: define ptr @not_captured_by_readonly_call_not_returned_either2 +; TUNIT-SAME: (ptr readonly [[B:%.*]], ptr readonly [[R:%.*]]) #[[ATTR8]] { ; TUNIT-NEXT: entry: -; TUNIT-NEXT: [[CALL:%.*]] = call i32* @readonly_unknown_r1a(i32* readonly [[B]], i32* readonly [[R]]) #[[ATTR11]] -; TUNIT-NEXT: ret i32* [[CALL]] +; TUNIT-NEXT: [[CALL:%.*]] = call ptr @readonly_unknown_r1a(ptr readonly [[B]], ptr readonly [[R]]) #[[ATTR11]] +; TUNIT-NEXT: ret ptr [[CALL]] ; ; CGSCC: Function Attrs: nounwind memory(read) -; CGSCC-LABEL: define i32* @not_captured_by_readonly_call_not_returned_either2 -; CGSCC-SAME: (i32* readonly [[B:%.*]], i32* readonly [[R:%.*]]) #[[ATTR9]] { +; CGSCC-LABEL: define ptr @not_captured_by_readonly_call_not_returned_either2 +; CGSCC-SAME: (ptr readonly [[B:%.*]], ptr readonly [[R:%.*]]) #[[ATTR9]] { ; CGSCC-NEXT: entry: -; CGSCC-NEXT: [[CALL:%.*]] = call i32* @readonly_unknown_r1a(i32* readonly [[B]], i32* readonly [[R]]) #[[ATTR11]] -; CGSCC-NEXT: ret i32* [[CALL]] +; CGSCC-NEXT: [[CALL:%.*]] = call ptr @readonly_unknown_r1a(ptr readonly [[B]], ptr readonly [[R]]) #[[ATTR11]] +; CGSCC-NEXT: ret ptr [[CALL]] ; entry: - %call = call i32* @readonly_unknown_r1a(i32* %b, i32* %r) nounwind - ret i32* %call + %call = call ptr @readonly_unknown_r1a(ptr %b, ptr %r) nounwind + ret ptr %call } -declare i32* @readonly_unknown_r1b(i32*, i32* returned) readonly nounwind -define i32* @not_captured_by_readonly_call_not_returned_either3(i32* %b, i32* %r) { +declare ptr @readonly_unknown_r1b(ptr, ptr returned) readonly nounwind +define ptr @not_captured_by_readonly_call_not_returned_either3(ptr %b, ptr %r) { ; TUNIT: Function Attrs: nounwind memory(read) -; TUNIT-LABEL: define i32* @not_captured_by_readonly_call_not_returned_either3 -; TUNIT-SAME: (i32* nocapture readonly [[B:%.*]], i32* readonly [[R:%.*]]) #[[ATTR8]] { +; TUNIT-LABEL: define ptr @not_captured_by_readonly_call_not_returned_either3 +; TUNIT-SAME: (ptr nocapture readonly [[B:%.*]], ptr readonly [[R:%.*]]) #[[ATTR8]] { ; TUNIT-NEXT: entry: -; TUNIT-NEXT: [[CALL:%.*]] = call i32* @readonly_unknown_r1b(i32* nocapture readonly [[B]], i32* readonly [[R]]) #[[ATTR11]] -; TUNIT-NEXT: ret i32* [[CALL]] +; TUNIT-NEXT: [[CALL:%.*]] = call ptr @readonly_unknown_r1b(ptr nocapture readonly [[B]], ptr readonly [[R]]) #[[ATTR11]] +; TUNIT-NEXT: ret ptr [[CALL]] ; ; CGSCC: Function Attrs: nounwind memory(read) -; CGSCC-LABEL: define i32* @not_captured_by_readonly_call_not_returned_either3 -; CGSCC-SAME: (i32* nocapture readonly [[B:%.*]], i32* readonly [[R:%.*]]) #[[ATTR9]] { +; CGSCC-LABEL: define ptr @not_captured_by_readonly_call_not_returned_either3 +; CGSCC-SAME: (ptr nocapture readonly [[B:%.*]], ptr readonly [[R:%.*]]) #[[ATTR9]] { ; CGSCC-NEXT: entry: -; CGSCC-NEXT: [[CALL:%.*]] = call i32* @readonly_unknown_r1b(i32* nocapture readonly [[B]], i32* readonly [[R]]) #[[ATTR11]] -; CGSCC-NEXT: ret i32* [[CALL]] +; CGSCC-NEXT: [[CALL:%.*]] = call ptr @readonly_unknown_r1b(ptr nocapture readonly [[B]], ptr readonly [[R]]) #[[ATTR11]] +; CGSCC-NEXT: ret ptr [[CALL]] ; entry: - %call = call i32* @readonly_unknown_r1b(i32* %b, i32* %r) - ret i32* %call + %call = call ptr @readonly_unknown_r1b(ptr %b, ptr %r) + ret ptr %call } -define i32* @not_captured_by_readonly_call_not_returned_either4(i32* %b, i32* %r) nounwind { +define ptr @not_captured_by_readonly_call_not_returned_either4(ptr %b, ptr %r) nounwind { ; TUNIT: Function Attrs: nounwind memory(read) -; TUNIT-LABEL: define i32* @not_captured_by_readonly_call_not_returned_either4 -; TUNIT-SAME: (i32* readonly [[B:%.*]], i32* readonly [[R:%.*]]) #[[ATTR8]] { +; TUNIT-LABEL: define ptr @not_captured_by_readonly_call_not_returned_either4 +; TUNIT-SAME: (ptr readonly [[B:%.*]], ptr readonly [[R:%.*]]) #[[ATTR8]] { ; TUNIT-NEXT: entry: -; TUNIT-NEXT: [[CALL:%.*]] = call i32* @readonly_unknown_r1a(i32* readonly [[B]], i32* readonly [[R]]) -; TUNIT-NEXT: ret i32* [[CALL]] +; TUNIT-NEXT: [[CALL:%.*]] = call ptr @readonly_unknown_r1a(ptr readonly [[B]], ptr readonly [[R]]) +; TUNIT-NEXT: ret ptr [[CALL]] ; ; CGSCC: Function Attrs: nounwind memory(read) -; CGSCC-LABEL: define i32* @not_captured_by_readonly_call_not_returned_either4 -; CGSCC-SAME: (i32* readonly [[B:%.*]], i32* readonly [[R:%.*]]) #[[ATTR9]] { +; CGSCC-LABEL: define ptr @not_captured_by_readonly_call_not_returned_either4 +; CGSCC-SAME: (ptr readonly [[B:%.*]], ptr readonly [[R:%.*]]) #[[ATTR9]] { ; CGSCC-NEXT: entry: -; CGSCC-NEXT: [[CALL:%.*]] = call i32* @readonly_unknown_r1a(i32* readonly [[B]], i32* readonly [[R]]) -; CGSCC-NEXT: ret i32* [[CALL]] +; CGSCC-NEXT: [[CALL:%.*]] = call ptr @readonly_unknown_r1a(ptr readonly [[B]], ptr readonly [[R]]) +; CGSCC-NEXT: ret ptr [[CALL]] ; entry: - %call = call i32* @readonly_unknown_r1a(i32* %b, i32* %r) - ret i32* %call + %call = call ptr @readonly_unknown_r1a(ptr %b, ptr %r) + ret ptr %call } -declare i32* @unknown_i32p(i32*) -define void @nocapture_is_not_subsumed_1(i32* nocapture %b) { +declare ptr @unknown_i32p(ptr) +define void @nocapture_is_not_subsumed_1(ptr nocapture %b) { ; CHECK-LABEL: define void @nocapture_is_not_subsumed_1 -; CHECK-SAME: (i32* nocapture [[B:%.*]]) { +; CHECK-SAME: (ptr nocapture [[B:%.*]]) { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CALL:%.*]] = call i32* @unknown_i32p(i32* [[B]]) -; CHECK-NEXT: store i32 0, i32* [[CALL]], align 4 +; CHECK-NEXT: [[CALL:%.*]] = call ptr @unknown_i32p(ptr [[B]]) +; CHECK-NEXT: store i32 0, ptr [[CALL]], align 4 ; CHECK-NEXT: ret void ; entry: - %call = call i32* @unknown_i32p(i32* %b) - store i32 0, i32* %call + %call = call ptr @unknown_i32p(ptr %b) + store i32 0, ptr %call ret void } -declare i32* @readonly_i32p(i32*) readonly -define void @nocapture_is_not_subsumed_2(i32* nocapture %b) { +declare ptr @readonly_i32p(ptr) readonly +define void @nocapture_is_not_subsumed_2(ptr nocapture %b) { ; CHECK-LABEL: define void @nocapture_is_not_subsumed_2 -; CHECK-SAME: (i32* nocapture [[B:%.*]]) { +; CHECK-SAME: (ptr nocapture [[B:%.*]]) { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CALL:%.*]] = call i32* @readonly_i32p(i32* readonly [[B]]) -; CHECK-NEXT: store i32 0, i32* [[CALL]], align 4 +; CHECK-NEXT: [[CALL:%.*]] = call ptr @readonly_i32p(ptr readonly [[B]]) +; CHECK-NEXT: store i32 0, ptr [[CALL]], align 4 ; CHECK-NEXT: ret void ; entry: - %call = call i32* @readonly_i32p(i32* %b) - store i32 0, i32* %call + %call = call ptr @readonly_i32p(ptr %b) + store i32 0, ptr %call ret void }