diff --git a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp --- a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp +++ b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp @@ -5004,21 +5004,20 @@ << "\n"); Align Alignment; - Constant *Size; + Value *Size; if (isCallocLikeFn(MallocCall, TLI)) { - auto *Num = cast(MallocCall->getOperand(0)); - auto *SizeT = cast(MallocCall->getOperand(1)); - APInt TotalSize = SizeT->getValue() * Num->getValue(); - Size = - ConstantInt::get(MallocCall->getOperand(0)->getType(), TotalSize); + auto *Num = MallocCall->getOperand(0); + auto *SizeT = MallocCall->getOperand(1); + IRBuilder<> B(MallocCall); + Size = B.CreateMul(Num, SizeT, "h2s.calloc.size"); } else if (isAlignedAllocLikeFn(MallocCall, TLI)) { - Size = cast(MallocCall->getOperand(1)); + Size = MallocCall->getOperand(1); Alignment = MaybeAlign(cast(MallocCall->getOperand(0)) ->getValue() .getZExtValue()) .valueOrOne(); } else { - Size = cast(MallocCall->getOperand(0)); + Size = MallocCall->getOperand(0); } unsigned AS = cast(MallocCall->getType())->getAddressSpace(); @@ -5166,6 +5165,12 @@ } if (IsMalloc) { + if (MaxHeapToStackSize == -1) { + if (UsesCheck(I) || FreeCheck(I)) { + MallocCalls.insert(&I); + return true; + } + } if (auto *Size = dyn_cast(I.getOperand(0))) if (Size->getValue().ule(MaxHeapToStackSize)) if (UsesCheck(I) || FreeCheck(I)) { @@ -5173,6 +5178,12 @@ return true; } } else if (IsAlignedAllocLike && isa(I.getOperand(0))) { + if (MaxHeapToStackSize == -1) { + if (UsesCheck(I) || FreeCheck(I)) { + MallocCalls.insert(&I); + return true; + } + } // Only if the alignment and sizes are constant. if (auto *Size = dyn_cast(I.getOperand(1))) if (Size->getValue().ule(MaxHeapToStackSize)) @@ -5181,6 +5192,12 @@ return true; } } else if (IsCalloc) { + if (MaxHeapToStackSize == -1) { + if (UsesCheck(I) || FreeCheck(I)) { + MallocCalls.insert(&I); + return true; + } + } bool Overflow = false; if (auto *Num = dyn_cast(I.getOperand(0))) if (auto *Size = dyn_cast(I.getOperand(1))) diff --git a/llvm/test/Transforms/Attributor/lowerheap.ll b/llvm/test/Transforms/Attributor/lowerheap.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/Attributor/lowerheap.ll @@ -0,0 +1,63 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes +; RUN: opt -max-heap-to-stack-size=-1 -attributor -enable-new-pm=0 -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM +; RUN: opt -max-heap-to-stack-size=-1 -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM +; RUN: opt -max-heap-to-stack-size=-1 -attributor-cgscc -enable-new-pm=0 -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM +; RUN: opt -max-heap-to-stack-size=-1 -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_OPM,IS__CGSCC____,IS________NPM,IS__CGSCC_NPM + +declare i64 @subfn(i8*) #0 + +declare noalias i8* @malloc(i64) +declare noalias i8* @calloc(i64, i64) +declare void @free(i8*) + +define i64 @f(i64 %len) { +; IS________OPM-LABEL: define {{[^@]+}}@f +; IS________OPM-SAME: (i64 [[LEN:%.*]]) { +; IS________OPM-NEXT: entry: +; IS________OPM-NEXT: [[MEM:%.*]] = call noalias i8* @malloc(i64 [[LEN]]) +; IS________OPM-NEXT: [[RES:%.*]] = call i64 @subfn(i8* [[MEM]]) [[ATTR1:#.*]] +; IS________OPM-NEXT: call void @free(i8* [[MEM]]) +; IS________OPM-NEXT: ret i64 [[RES]] +; +; IS________NPM-LABEL: define {{[^@]+}}@f +; IS________NPM-SAME: (i64 [[LEN:%.*]]) { +; IS________NPM-NEXT: entry: +; IS________NPM-NEXT: [[TMP0:%.*]] = alloca i8, i64 [[LEN]], align 1 +; IS________NPM-NEXT: [[RES:%.*]] = call i64 @subfn(i8* [[TMP0]]) [[ATTR2:#.*]] +; IS________NPM-NEXT: ret i64 [[RES]] +; +entry: + %mem = call i8* @malloc(i64 %len) + %res = call i64 @subfn(i8* %mem) + call void @free(i8* %mem) + ret i64 %res +} + + +define i64 @g(i64 %len) { +; IS________OPM-LABEL: define {{[^@]+}}@g +; IS________OPM-SAME: (i64 [[LEN:%.*]]) { +; IS________OPM-NEXT: entry: +; IS________OPM-NEXT: [[MEM:%.*]] = call noalias i8* @calloc(i64 [[LEN]], i64 noundef 8) +; IS________OPM-NEXT: [[RES:%.*]] = call i64 @subfn(i8* [[MEM]]) [[ATTR1]] +; IS________OPM-NEXT: call void @free(i8* [[MEM]]) +; IS________OPM-NEXT: ret i64 [[RES]] +; +; IS________NPM-LABEL: define {{[^@]+}}@g +; IS________NPM-SAME: (i64 [[LEN:%.*]]) { +; IS________NPM-NEXT: entry: +; IS________NPM-NEXT: [[TMP0:%.*]] = mul i64 [[LEN]], 8 +; IS________NPM-NEXT: [[TMP1:%.*]] = alloca i8, i64 [[TMP0]], 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 [[TMP0]], i1 false) +; IS________NPM-NEXT: [[RES:%.*]] = call i64 @subfn(i8* [[TMP1]]) [[ATTR2]] +; IS________NPM-NEXT: ret i64 [[RES]] +; +entry: + %mem = call i8* @calloc(i64 %len, i64 8) + %res = call i64 @subfn(i8* %mem) + call void @free(i8* %mem) + ret i64 %res +} + +attributes #0 = { nounwind willreturn }