[llvm] d1f4c6a - [Attributor] Generalize calloc handling in heap-to-stack for any init value [NFC]

Philip Reames via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 12 16:59:33 PST 2022


Author: Philip Reames
Date: 2022-01-12T16:58:39-08:00
New Revision: d1f4c6a6112a9868f178d3a4c666f04ac5dc7415

URL: https://github.com/llvm/llvm-project/commit/d1f4c6a6112a9868f178d3a4c666f04ac5dc7415
DIFF: https://github.com/llvm/llvm-project/commit/d1f4c6a6112a9868f178d3a4c666f04ac5dc7415.diff

LOG: [Attributor] Generalize calloc handling in heap-to-stack for any init value [NFC]

Rewrite the calloc specific handling in heap-to-stack to allow arbitrary init values.  The basic problem being solved is that if an allocation is initilized to anything other than zero, this must be explicitly done for the formed alloca as well.

This covers the calloc case today, but once a couple of earlier guards are removed in this code, downstream allocators with other init values could also be handled.

Inspired by discussion on D116971

Added: 
    

Modified: 
    llvm/lib/Transforms/IPO/AttributorAttributes.cpp
    llvm/test/Transforms/Attributor/heap_to_stack.ll
    llvm/test/Transforms/Attributor/lowerheap.ll
    llvm/test/Transforms/Attributor/value-simplify-pointer-info.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
index 26975f5e4a747..d0534ed0e6353 100644
--- a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
+++ b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
@@ -5974,6 +5974,11 @@ struct AAHeapToStackFunction final : public AAHeapToStack {
         Alloca = new BitCastInst(Alloca, AI.CB->getType(), "malloc_bc",
                                  Alloca->getNextNode());
 
+      auto *I8Ty = Type::getInt8Ty(F->getContext());
+      auto *InitVal = getInitialValueOfAllocation(AI.CB, TLI, I8Ty);
+      assert(InitVal &&
+             "Must be able to materialize initial memory state of allocation");
+
       A.changeValueAfterManifest(*AI.CB, *Alloca);
 
       if (auto *II = dyn_cast<InvokeInst>(AI.CB)) {
@@ -5984,18 +5989,13 @@ struct AAHeapToStackFunction final : public AAHeapToStack {
         A.deleteAfterManifest(*AI.CB);
       }
 
-      // Zero out the allocated memory if it was a calloc.
-      if (AI.Kind == AllocationInfo::AllocationKind::CALLOC) {
-        auto *BI = new BitCastInst(Alloca, AI.CB->getType(), "calloc_bc",
-                                   Alloca->getNextNode());
-        Value *Ops[] = {
-            BI, ConstantInt::get(F->getContext(), APInt(8, 0, false)), Size,
-            ConstantInt::get(Type::getInt1Ty(F->getContext()), false)};
-
-        Type *Tys[] = {BI->getType(), AI.CB->getOperand(0)->getType()};
-        Module *M = F->getParent();
-        Function *Fn = Intrinsic::getDeclaration(M, Intrinsic::memset, Tys);
-        CallInst::Create(Fn, Ops, "", BI->getNextNode());
+      // Initialize the alloca with the same value as used by the allocation
+      // function.  We can skip undef as the initial value of an alloc is
+      // undef, and the memset would simply end up being DSEd.
+      if (!isa<UndefValue>(InitVal)) {
+        IRBuilder<> Builder(Alloca->getNextNode());
+        // TODO: Use alignment above if align!=1
+        Builder.CreateMemSet(Alloca, InitVal, Size, None);
       }
       HasChanged = ChangeStatus::CHANGED;
     }

diff  --git a/llvm/test/Transforms/Attributor/heap_to_stack.ll b/llvm/test/Transforms/Attributor/heap_to_stack.ll
index 2f9e004bad3be..0c40c0fe79f51 100644
--- a/llvm/test/Transforms/Attributor/heap_to_stack.ll
+++ b/llvm/test/Transforms/Attributor/heap_to_stack.ll
@@ -229,8 +229,7 @@ define void @test0() {
 ;
 ; IS________NPM-LABEL: define {{[^@]+}}@test0() {
 ; IS________NPM-NEXT:    [[TMP1:%.*]] = alloca i8, i64 8, align 1
-; IS________NPM-NEXT:    [[CALLOC_BC:%.*]] = bitcast i8* [[TMP1]] to i8*
-; IS________NPM-NEXT:    call void @llvm.memset.p0i8.i64(i8* [[CALLOC_BC]], i8 0, i64 8, i1 false)
+; IS________NPM-NEXT:    call void @llvm.memset.p0i8.i64(i8* [[TMP1]], i8 0, i64 8, i1 false)
 ; IS________NPM-NEXT:    tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]])
 ; IS________NPM-NEXT:    ret void
 ;

diff  --git a/llvm/test/Transforms/Attributor/lowerheap.ll b/llvm/test/Transforms/Attributor/lowerheap.ll
index 3388adaf76d8a..9b86a42bb3d70 100644
--- a/llvm/test/Transforms/Attributor/lowerheap.ll
+++ b/llvm/test/Transforms/Attributor/lowerheap.ll
@@ -46,11 +46,10 @@ define i64 @g(i64 %len) {
 ; IS________NPM-LABEL: define {{[^@]+}}@g
 ; IS________NPM-SAME: (i64 [[LEN:%.*]]) {
 ; IS________NPM-NEXT:  entry:
-; IS________NPM-NEXT:    [[H2S_CALLOC_SIZE:%.*]] = mul i64 [[LEN]], 8
-; IS________NPM-NEXT:    [[TMP0:%.*]] = alloca i8, i64 [[H2S_CALLOC_SIZE]], align 1
-; IS________NPM-NEXT:    [[CALLOC_BC:%.*]] = bitcast i8* [[TMP0]] to i8*
-; IS________NPM-NEXT:    call void @llvm.memset.p0i8.i64(i8* [[CALLOC_BC]], i8 0, i64 [[H2S_CALLOC_SIZE]], i1 false)
-; IS________NPM-NEXT:    [[RES:%.*]] = call i64 @subfn(i8* [[TMP0]]) #[[ATTR2]]
+; IS________NPM-NEXT:    [[TMP0:%.*]] = mul i64 [[LEN]], 8
+; IS________NPM-NEXT:    [[TMP1:%.*]] = alloca i8, i64 [[TMP0]], align 1
+; IS________NPM-NEXT:    call void @llvm.memset.p0i8.i64(i8* [[TMP1]], i8 0, i64 [[TMP0]], i1 false)
+; IS________NPM-NEXT:    [[RES:%.*]] = call i64 @subfn(i8* [[TMP1]]) #[[ATTR2]]
 ; IS________NPM-NEXT:    ret i64 [[RES]]
 ;
 entry:

diff  --git a/llvm/test/Transforms/Attributor/value-simplify-pointer-info.ll b/llvm/test/Transforms/Attributor/value-simplify-pointer-info.ll
index 4734fc9081a00..c5696082a1e47 100644
--- a/llvm/test/Transforms/Attributor/value-simplify-pointer-info.ll
+++ b/llvm/test/Transforms/Attributor/value-simplify-pointer-info.ll
@@ -3546,8 +3546,7 @@ define dso_local i32 @round_trip_calloc(i32 %x) {
 ; IS__TUNIT_NPM-SAME: (i32 [[X:%.*]]) {
 ; IS__TUNIT_NPM-NEXT:  entry:
 ; IS__TUNIT_NPM-NEXT:    [[TMP0:%.*]] = alloca i8, i64 4, align 1
-; IS__TUNIT_NPM-NEXT:    [[CALLOC_BC:%.*]] = bitcast i8* [[TMP0]] to i8*
-; IS__TUNIT_NPM-NEXT:    call void @llvm.memset.p0i8.i64(i8* [[CALLOC_BC]], i8 0, i64 4, i1 false)
+; IS__TUNIT_NPM-NEXT:    call void @llvm.memset.p0i8.i64(i8* [[TMP0]], i8 0, i64 4, i1 false)
 ; IS__TUNIT_NPM-NEXT:    [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i32*
 ; IS__TUNIT_NPM-NEXT:    store i32 [[X]], i32* [[TMP1]], align 4
 ; IS__TUNIT_NPM-NEXT:    [[TMP2:%.*]] = load i32, i32* [[TMP1]], align 4
@@ -3568,8 +3567,7 @@ define dso_local i32 @round_trip_calloc(i32 %x) {
 ; IS__CGSCC_NPM-SAME: (i32 [[X:%.*]]) #[[ATTR9]] {
 ; IS__CGSCC_NPM-NEXT:  entry:
 ; IS__CGSCC_NPM-NEXT:    [[TMP0:%.*]] = alloca i8, i64 4, align 1
-; IS__CGSCC_NPM-NEXT:    [[CALLOC_BC:%.*]] = bitcast i8* [[TMP0]] to i8*
-; IS__CGSCC_NPM-NEXT:    call void @llvm.memset.p0i8.i64(i8* [[CALLOC_BC]], i8 0, i64 4, i1 false)
+; IS__CGSCC_NPM-NEXT:    call void @llvm.memset.p0i8.i64(i8* [[TMP0]], i8 0, i64 4, i1 false)
 ; IS__CGSCC_NPM-NEXT:    [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i32*
 ; IS__CGSCC_NPM-NEXT:    store i32 [[X]], i32* [[TMP1]], align 4
 ; IS__CGSCC_NPM-NEXT:    [[TMP2:%.*]] = load i32, i32* [[TMP1]], align 4
@@ -3595,8 +3593,7 @@ define dso_local i32 @round_trip_calloc_constant() {
 ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@round_trip_calloc_constant() {
 ; IS__TUNIT_NPM-NEXT:  entry:
 ; IS__TUNIT_NPM-NEXT:    [[TMP0:%.*]] = alloca i8, i64 4, align 1
-; IS__TUNIT_NPM-NEXT:    [[CALLOC_BC:%.*]] = bitcast i8* [[TMP0]] to i8*
-; IS__TUNIT_NPM-NEXT:    call void @llvm.memset.p0i8.i64(i8* [[CALLOC_BC]], i8 0, i64 4, i1 false)
+; IS__TUNIT_NPM-NEXT:    call void @llvm.memset.p0i8.i64(i8* [[TMP0]], i8 0, i64 4, i1 false)
 ; IS__TUNIT_NPM-NEXT:    [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i32*
 ; IS__TUNIT_NPM-NEXT:    store i32 11, i32* [[TMP1]], align 4
 ; IS__TUNIT_NPM-NEXT:    [[TMP2:%.*]] = load i32, i32* [[TMP1]], align 4
@@ -3617,8 +3614,7 @@ define dso_local i32 @round_trip_calloc_constant() {
 ; IS__CGSCC_NPM-SAME: () #[[ATTR9]] {
 ; IS__CGSCC_NPM-NEXT:  entry:
 ; IS__CGSCC_NPM-NEXT:    [[TMP0:%.*]] = alloca i8, i64 4, align 1
-; IS__CGSCC_NPM-NEXT:    [[CALLOC_BC:%.*]] = bitcast i8* [[TMP0]] to i8*
-; IS__CGSCC_NPM-NEXT:    call void @llvm.memset.p0i8.i64(i8* [[CALLOC_BC]], i8 0, i64 4, i1 false)
+; IS__CGSCC_NPM-NEXT:    call void @llvm.memset.p0i8.i64(i8* [[TMP0]], i8 0, i64 4, i1 false)
 ; IS__CGSCC_NPM-NEXT:    [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i32*
 ; IS__CGSCC_NPM-NEXT:    store i32 11, i32* [[TMP1]], align 4
 ; IS__CGSCC_NPM-NEXT:    [[TMP2:%.*]] = load i32, i32* [[TMP1]], align 4
@@ -3655,8 +3651,7 @@ define dso_local i32 @conditional_calloc(i32 %x) {
 ; IS__TUNIT_NPM-SAME: (i32 [[X:%.*]]) {
 ; IS__TUNIT_NPM-NEXT:  entry:
 ; IS__TUNIT_NPM-NEXT:    [[TMP0:%.*]] = alloca i8, i64 4, align 1
-; IS__TUNIT_NPM-NEXT:    [[CALLOC_BC:%.*]] = bitcast i8* [[TMP0]] to i8*
-; IS__TUNIT_NPM-NEXT:    call void @llvm.memset.p0i8.i64(i8* [[CALLOC_BC]], i8 0, i64 4, i1 false)
+; IS__TUNIT_NPM-NEXT:    call void @llvm.memset.p0i8.i64(i8* [[TMP0]], i8 0, i64 4, i1 false)
 ; IS__TUNIT_NPM-NEXT:    [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i32*
 ; IS__TUNIT_NPM-NEXT:    [[TOBOOL:%.*]] = icmp ne i32 [[X]], 0
 ; IS__TUNIT_NPM-NEXT:    br i1 [[TOBOOL]], label [[IF_END:%.*]], label [[IF_THEN:%.*]]
@@ -3689,8 +3684,7 @@ define dso_local i32 @conditional_calloc(i32 %x) {
 ; IS__CGSCC_NPM-SAME: (i32 [[X:%.*]]) #[[ATTR9]] {
 ; IS__CGSCC_NPM-NEXT:  entry:
 ; IS__CGSCC_NPM-NEXT:    [[TMP0:%.*]] = alloca i8, i64 4, align 1
-; IS__CGSCC_NPM-NEXT:    [[CALLOC_BC:%.*]] = bitcast i8* [[TMP0]] to i8*
-; IS__CGSCC_NPM-NEXT:    call void @llvm.memset.p0i8.i64(i8* [[CALLOC_BC]], i8 0, i64 4, i1 false)
+; IS__CGSCC_NPM-NEXT:    call void @llvm.memset.p0i8.i64(i8* [[TMP0]], i8 0, i64 4, i1 false)
 ; IS__CGSCC_NPM-NEXT:    [[TMP1:%.*]] = bitcast i8* [[TMP0]] to i32*
 ; IS__CGSCC_NPM-NEXT:    [[TOBOOL:%.*]] = icmp ne i32 [[X]], 0
 ; IS__CGSCC_NPM-NEXT:    br i1 [[TOBOOL]], label [[IF_END:%.*]], label [[IF_THEN:%.*]]
@@ -3738,8 +3732,7 @@ define dso_local i32 @conditional_calloc_zero(i1 %c) {
 ; IS__TUNIT_NPM-SAME: (i1 [[C:%.*]]) {
 ; IS__TUNIT_NPM-NEXT:  entry:
 ; IS__TUNIT_NPM-NEXT:    [[TMP0:%.*]] = alloca i8, i64 4, align 1
-; IS__TUNIT_NPM-NEXT:    [[CALLOC_BC:%.*]] = bitcast i8* [[TMP0]] to i8*
-; IS__TUNIT_NPM-NEXT:    call void @llvm.memset.p0i8.i64(i8* [[CALLOC_BC]], i8 0, i64 4, i1 false)
+; IS__TUNIT_NPM-NEXT:    call void @llvm.memset.p0i8.i64(i8* [[TMP0]], i8 0, i64 4, i1 false)
 ; IS__TUNIT_NPM-NEXT:    br i1 [[C]], label [[IF_END:%.*]], label [[IF_THEN:%.*]]
 ; IS__TUNIT_NPM:       if.then:
 ; IS__TUNIT_NPM-NEXT:    br label [[IF_END]]
@@ -3767,8 +3760,7 @@ define dso_local i32 @conditional_calloc_zero(i1 %c) {
 ; IS__CGSCC_NPM-SAME: (i1 [[C:%.*]]) #[[ATTR9]] {
 ; IS__CGSCC_NPM-NEXT:  entry:
 ; IS__CGSCC_NPM-NEXT:    [[TMP0:%.*]] = alloca i8, i64 4, align 1
-; IS__CGSCC_NPM-NEXT:    [[CALLOC_BC:%.*]] = bitcast i8* [[TMP0]] to i8*
-; IS__CGSCC_NPM-NEXT:    call void @llvm.memset.p0i8.i64(i8* [[CALLOC_BC]], i8 0, i64 4, i1 false)
+; IS__CGSCC_NPM-NEXT:    call void @llvm.memset.p0i8.i64(i8* [[TMP0]], i8 0, i64 4, i1 false)
 ; IS__CGSCC_NPM-NEXT:    br i1 [[C]], label [[IF_END:%.*]], label [[IF_THEN:%.*]]
 ; IS__CGSCC_NPM:       if.then:
 ; IS__CGSCC_NPM-NEXT:    br label [[IF_END]]


        


More information about the llvm-commits mailing list