Skip to content

Commit d163e75

Browse files
committed
[Attributor] Enable heap-to-stack of any size
Enable Attributor's heap-to-stack to lower unbounded allocations given a max size of -1 Differential Revision: https://reviews.llvm.org/D97873
1 parent 9c139c5 commit d163e75

File tree

2 files changed

+88
-8
lines changed

2 files changed

+88
-8
lines changed

llvm/lib/Transforms/IPO/AttributorAttributes.cpp

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5004,21 +5004,20 @@ struct AAHeapToStackImpl : public AAHeapToStack {
50045004
<< "\n");
50055005

50065006
Align Alignment;
5007-
Constant *Size;
5007+
Value *Size;
50085008
if (isCallocLikeFn(MallocCall, TLI)) {
5009-
auto *Num = cast<ConstantInt>(MallocCall->getOperand(0));
5010-
auto *SizeT = cast<ConstantInt>(MallocCall->getOperand(1));
5011-
APInt TotalSize = SizeT->getValue() * Num->getValue();
5012-
Size =
5013-
ConstantInt::get(MallocCall->getOperand(0)->getType(), TotalSize);
5009+
auto *Num = MallocCall->getOperand(0);
5010+
auto *SizeT = MallocCall->getOperand(1);
5011+
IRBuilder<> B(MallocCall);
5012+
Size = B.CreateMul(Num, SizeT, "h2s.calloc.size");
50145013
} else if (isAlignedAllocLikeFn(MallocCall, TLI)) {
5015-
Size = cast<ConstantInt>(MallocCall->getOperand(1));
5014+
Size = MallocCall->getOperand(1);
50165015
Alignment = MaybeAlign(cast<ConstantInt>(MallocCall->getOperand(0))
50175016
->getValue()
50185017
.getZExtValue())
50195018
.valueOrOne();
50205019
} else {
5021-
Size = cast<ConstantInt>(MallocCall->getOperand(0));
5020+
Size = MallocCall->getOperand(0);
50225021
}
50235022

50245023
unsigned AS = cast<PointerType>(MallocCall->getType())->getAddressSpace();
@@ -5166,13 +5165,25 @@ ChangeStatus AAHeapToStackImpl::updateImpl(Attributor &A) {
51665165
}
51675166

51685167
if (IsMalloc) {
5168+
if (MaxHeapToStackSize == -1) {
5169+
if (UsesCheck(I) || FreeCheck(I)) {
5170+
MallocCalls.insert(&I);
5171+
return true;
5172+
}
5173+
}
51695174
if (auto *Size = dyn_cast<ConstantInt>(I.getOperand(0)))
51705175
if (Size->getValue().ule(MaxHeapToStackSize))
51715176
if (UsesCheck(I) || FreeCheck(I)) {
51725177
MallocCalls.insert(&I);
51735178
return true;
51745179
}
51755180
} else if (IsAlignedAllocLike && isa<ConstantInt>(I.getOperand(0))) {
5181+
if (MaxHeapToStackSize == -1) {
5182+
if (UsesCheck(I) || FreeCheck(I)) {
5183+
MallocCalls.insert(&I);
5184+
return true;
5185+
}
5186+
}
51765187
// Only if the alignment and sizes are constant.
51775188
if (auto *Size = dyn_cast<ConstantInt>(I.getOperand(1)))
51785189
if (Size->getValue().ule(MaxHeapToStackSize))
@@ -5181,6 +5192,12 @@ ChangeStatus AAHeapToStackImpl::updateImpl(Attributor &A) {
51815192
return true;
51825193
}
51835194
} else if (IsCalloc) {
5195+
if (MaxHeapToStackSize == -1) {
5196+
if (UsesCheck(I) || FreeCheck(I)) {
5197+
MallocCalls.insert(&I);
5198+
return true;
5199+
}
5200+
}
51845201
bool Overflow = false;
51855202
if (auto *Num = dyn_cast<ConstantInt>(I.getOperand(0)))
51865203
if (auto *Size = dyn_cast<ConstantInt>(I.getOperand(1)))
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes
2+
; 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
3+
; 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
4+
; 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
5+
; 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
6+
7+
declare i64 @subfn(i8*) #0
8+
9+
declare noalias i8* @malloc(i64)
10+
declare noalias i8* @calloc(i64, i64)
11+
declare void @free(i8*)
12+
13+
define i64 @f(i64 %len) {
14+
; IS________OPM-LABEL: define {{[^@]+}}@f
15+
; IS________OPM-SAME: (i64 [[LEN:%.*]]) {
16+
; IS________OPM-NEXT: entry:
17+
; IS________OPM-NEXT: [[MEM:%.*]] = call noalias i8* @malloc(i64 [[LEN]])
18+
; IS________OPM-NEXT: [[RES:%.*]] = call i64 @subfn(i8* [[MEM]]) [[ATTR1:#.*]]
19+
; IS________OPM-NEXT: call void @free(i8* [[MEM]])
20+
; IS________OPM-NEXT: ret i64 [[RES]]
21+
;
22+
; IS________NPM-LABEL: define {{[^@]+}}@f
23+
; IS________NPM-SAME: (i64 [[LEN:%.*]]) {
24+
; IS________NPM-NEXT: entry:
25+
; IS________NPM-NEXT: [[TMP0:%.*]] = alloca i8, i64 [[LEN]], align 1
26+
; IS________NPM-NEXT: [[RES:%.*]] = call i64 @subfn(i8* [[TMP0]]) [[ATTR2:#.*]]
27+
; IS________NPM-NEXT: ret i64 [[RES]]
28+
;
29+
entry:
30+
%mem = call i8* @malloc(i64 %len)
31+
%res = call i64 @subfn(i8* %mem)
32+
call void @free(i8* %mem)
33+
ret i64 %res
34+
}
35+
36+
37+
define i64 @g(i64 %len) {
38+
; IS________OPM-LABEL: define {{[^@]+}}@g
39+
; IS________OPM-SAME: (i64 [[LEN:%.*]]) {
40+
; IS________OPM-NEXT: entry:
41+
; IS________OPM-NEXT: [[MEM:%.*]] = call noalias i8* @calloc(i64 [[LEN]], i64 noundef 8)
42+
; IS________OPM-NEXT: [[RES:%.*]] = call i64 @subfn(i8* [[MEM]]) [[ATTR1]]
43+
; IS________OPM-NEXT: call void @free(i8* [[MEM]])
44+
; IS________OPM-NEXT: ret i64 [[RES]]
45+
;
46+
; IS________NPM-LABEL: define {{[^@]+}}@g
47+
; IS________NPM-SAME: (i64 [[LEN:%.*]]) {
48+
; IS________NPM-NEXT: entry:
49+
; IS________NPM-NEXT: [[TMP0:%.*]] = mul i64 [[LEN]], 8
50+
; IS________NPM-NEXT: [[TMP1:%.*]] = alloca i8, i64 [[TMP0]], align 1
51+
; IS________NPM-NEXT: [[CALLOC_BC:%.*]] = bitcast i8* [[TMP1]] to i8*
52+
; IS________NPM-NEXT: call void @llvm.memset.p0i8.i64(i8* [[CALLOC_BC]], i8 0, i64 [[TMP0]], i1 false)
53+
; IS________NPM-NEXT: [[RES:%.*]] = call i64 @subfn(i8* [[TMP1]]) [[ATTR2]]
54+
; IS________NPM-NEXT: ret i64 [[RES]]
55+
;
56+
entry:
57+
%mem = call i8* @calloc(i64 %len, i64 8)
58+
%res = call i64 @subfn(i8* %mem)
59+
call void @free(i8* %mem)
60+
ret i64 %res
61+
}
62+
63+
attributes #0 = { nounwind willreturn }

0 commit comments

Comments
 (0)