Skip to content

Commit 0af5c06

Browse files
authored
[InstCombine] Don't consider aligned_alloc removable if icmp uses result (#69474)
At the moment, all alloc-like functions are assumed to return non-null pointers, if their return value is only used in a compare. This is based on being allowed to substitute the allocation function with one that doesn't fail to allocate the required memory. aligned_alloc however must also return null if the required alignment cannot be satisfied, so I don't think the same reasoning as above can be applied to it. This patch adds a bail-out for aligned_alloc calls to isAllocSiteRemovable.
1 parent 44d4b30 commit 0af5c06

File tree

2 files changed

+31
-5
lines changed

2 files changed

+31
-5
lines changed

llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2430,6 +2430,26 @@ static bool isAllocSiteRemovable(Instruction *AI,
24302430
unsigned OtherIndex = (ICI->getOperand(0) == PI) ? 1 : 0;
24312431
if (!isNeverEqualToUnescapedAlloc(ICI->getOperand(OtherIndex), TLI, AI))
24322432
return false;
2433+
2434+
// Do not fold compares to aligned_alloc calls, as they may have to
2435+
// return null in case the required alignment cannot be satisfied,
2436+
// unless we can prove that both alignment and size are valid.
2437+
auto AlignmentAndSizeKnownValid = [](CallBase *CB) {
2438+
// Check if alignment and size of a call to aligned_alloc is valid,
2439+
// that is alignment is a power-of-2 and the size is a multiple of the
2440+
// alignment.
2441+
const APInt *Alignment;
2442+
const APInt *Size;
2443+
return match(CB->getArgOperand(0), m_APInt(Alignment)) &&
2444+
match(CB->getArgOperand(1), m_APInt(Size)) &&
2445+
Alignment->isPowerOf2() && Size->urem(*Alignment).isZero();
2446+
};
2447+
auto *CB = dyn_cast<CallBase>(AI);
2448+
LibFunc TheLibFunc;
2449+
if (CB && TLI.getLibFunc(*CB->getCalledFunction(), TheLibFunc) &&
2450+
TLI.has(TheLibFunc) && TheLibFunc == LibFunc_aligned_alloc &&
2451+
!AlignmentAndSizeKnownValid(CB))
2452+
return false;
24332453
Users.emplace_back(I);
24342454
continue;
24352455
}

llvm/test/Transforms/InstCombine/malloc-free.ll

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,11 @@ define i32 @dead_aligned_alloc(i32 %size, i32 %alignment, i8 %value) {
2626
ret i32 0
2727
}
2828

29-
define i1 @aligned_alloc_pointer_only_used_by_cmp(i32 %size, i32 %alignment, i8 %value) {
30-
; CHECK-LABEL: @aligned_alloc_pointer_only_used_by_cmp(
31-
; CHECK-NEXT: ret i1 true
29+
define i1 @aligned_alloc_only_pointe(i32 %size, i32 %alignment, i8 %value) {
30+
; CHECK-LABEL: @aligned_alloc_only_pointe(
31+
; CHECK-NEXT: [[ALIGNED_ALLOCATION:%.*]] = tail call ptr @aligned_alloc(i32 [[ALIGNMENT:%.*]], i32 [[SIZE:%.*]])
32+
; CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr [[ALIGNED_ALLOCATION]], null
33+
; CHECK-NEXT: ret i1 [[CMP]]
3234
;
3335
%aligned_allocation = tail call ptr @aligned_alloc(i32 %alignment, i32 %size)
3436
%cmp = icmp ne ptr %aligned_allocation, null
@@ -46,7 +48,9 @@ define i1 @aligned_alloc_pointer_only_used_by_cmp_alignment_and_value_known_ok(i
4648

4749
define i1 @aligned_alloc_pointer_only_used_by_cmp_alignment_no_power_of_2(i32 %size, i32 %alignment, i8 %value) {
4850
; CHECK-LABEL: @aligned_alloc_pointer_only_used_by_cmp_alignment_no_power_of_2(
49-
; CHECK-NEXT: ret i1 true
51+
; CHECK-NEXT: [[ALIGNED_ALLOCATION:%.*]] = tail call dereferenceable_or_null(32) ptr @aligned_alloc(i32 3, i32 32)
52+
; CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr [[ALIGNED_ALLOCATION]], null
53+
; CHECK-NEXT: ret i1 [[CMP]]
5054
;
5155
%aligned_allocation = tail call ptr @aligned_alloc(i32 3, i32 32)
5256
%cmp = icmp ne ptr %aligned_allocation, null
@@ -55,7 +59,9 @@ define i1 @aligned_alloc_pointer_only_used_by_cmp_alignment_no_power_of_2(i32 %s
5559

5660
define i1 @aligned_alloc_pointer_only_used_by_cmp_size_not_multiple_of_alignment(i32 %size, i32 %alignment, i8 %value) {
5761
; CHECK-LABEL: @aligned_alloc_pointer_only_used_by_cmp_size_not_multiple_of_alignment(
58-
; CHECK-NEXT: ret i1 true
62+
; CHECK-NEXT: [[ALIGNED_ALLOCATION:%.*]] = tail call dereferenceable_or_null(31) ptr @aligned_alloc(i32 8, i32 31)
63+
; CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr [[ALIGNED_ALLOCATION]], null
64+
; CHECK-NEXT: ret i1 [[CMP]]
5965
;
6066
%aligned_allocation = tail call ptr @aligned_alloc(i32 8, i32 31)
6167
%cmp = icmp ne ptr %aligned_allocation, null

0 commit comments

Comments
 (0)