Skip to content

Commit

Permalink
[Attributor][FIX] Use maximal access for dereferenceability deduction
Browse files Browse the repository at this point in the history
While we can use range information when we derive dereferenceability we
must make sure to pick he right end of the range. Before we always went
with the minimal offset, which is not correct if we want to combine
the base dereferenceability with some offset. In that case it's the
maximum that gives the correct result.
  • Loading branch information
jdoerfert committed Mar 7, 2022
1 parent 1fcd4d0 commit 5859ae6
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 10 deletions.
26 changes: 16 additions & 10 deletions llvm/lib/Transforms/IPO/AttributorAttributes.cpp
Expand Up @@ -440,10 +440,11 @@ bool AA::getAssumedUnderlyingObjects(Attributor &A, const Value &Ptr,
return true;
}

const Value *stripAndAccumulateMinimalOffsets(
Attributor &A, const AbstractAttribute &QueryingAA, const Value *Val,
const DataLayout &DL, APInt &Offset, bool AllowNonInbounds,
bool UseAssumed = false) {
static const Value *
stripAndAccumulateOffsets(Attributor &A, const AbstractAttribute &QueryingAA,
const Value *Val, const DataLayout &DL, APInt &Offset,
bool GetMinOffset, bool AllowNonInbounds,
bool UseAssumed = false) {

auto AttributorAnalysis = [&](Value &V, APInt &ROffset) -> bool {
const IRPosition &Pos = IRPosition::value(V);
Expand All @@ -456,12 +457,15 @@ const Value *stripAndAccumulateMinimalOffsets(
: ValueConstantRangeAA.getKnown();
// We can only use the lower part of the range because the upper part can
// be higher than what the value can really be.
ROffset = Range.getSignedMin();
if (GetMinOffset)
ROffset = Range.getSignedMin();
else
ROffset = Range.getSignedMax();
return true;
};

return Val->stripAndAccumulateConstantOffsets(DL, Offset, AllowNonInbounds,
/* AllowInvariant */ false,
/* AllowInvariant */ true,
AttributorAnalysis);
}

Expand All @@ -470,8 +474,9 @@ getMinimalBaseOfPointer(Attributor &A, const AbstractAttribute &QueryingAA,
const Value *Ptr, int64_t &BytesOffset,
const DataLayout &DL, bool AllowNonInbounds = false) {
APInt OffsetAPInt(DL.getIndexTypeSizeInBits(Ptr->getType()), 0);
const Value *Base = stripAndAccumulateMinimalOffsets(
A, QueryingAA, Ptr, DL, OffsetAPInt, AllowNonInbounds);
const Value *Base =
stripAndAccumulateOffsets(A, QueryingAA, Ptr, DL, OffsetAPInt,
/* GetMinOffset */ true, AllowNonInbounds);

BytesOffset = OffsetAPInt.getSExtValue();
return Base;
Expand Down Expand Up @@ -4274,8 +4279,9 @@ struct AADereferenceableFloating : AADereferenceableImpl {
unsigned IdxWidth =
DL.getIndexSizeInBits(V.getType()->getPointerAddressSpace());
APInt Offset(IdxWidth, 0);
const Value *Base =
stripAndAccumulateMinimalOffsets(A, *this, &V, DL, Offset, false);
const Value *Base = stripAndAccumulateOffsets(
A, *this, &V, DL, Offset, /* GetMinOffset */ false,
/* AllowNonInbounds */ true);

const auto &AA = A.getAAFor<AADereferenceable>(
*this, IRPosition::value(*Base), DepClassTy::REQUIRED);
Expand Down
29 changes: 29 additions & 0 deletions llvm/test/Transforms/Attributor/dereferenceable-1.ll
Expand Up @@ -10,6 +10,9 @@ declare void @deref_phi_user(i32* %a);
; TEST 1
; take mininimum of return values
;
;.
; CHECK: @[[G:[a-zA-Z0-9_$"\\.-]+]] = global i64 0
;.
define i32* @test1(i32* dereferenceable(4) %0, double* dereferenceable(8) %1, i1 zeroext %2) local_unnamed_addr {
; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; CHECK-LABEL: define {{[^@]+}}@test1
Expand Down Expand Up @@ -915,6 +918,32 @@ declare void @unknown_use8(i8*) willreturn nounwind
declare void @unknown_use32(i32*) willreturn nounwind
declare void @llvm.assume(i1)

@g = global i64 0
define void @max_offset(i1 %c) {
; CHECK: Function Attrs: nounwind willreturn
; CHECK-LABEL: define {{[^@]+}}@max_offset
; CHECK-SAME: (i1 [[C:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
; CHECK: t:
; CHECK-NEXT: br label [[F]]
; CHECK: f:
; CHECK-NEXT: [[PHI:%.*]] = phi i8* [ getelementptr (i8, i8* bitcast (i64* @g to i8*), i64 2), [[T]] ], [ bitcast (i64* @g to i8*), [[ENTRY:%.*]] ]
; CHECK-NEXT: call void @unknown_use8(i8* noundef align 2 dereferenceable_or_null(6) [[PHI]]) #[[ATTR1]]
; CHECK-NEXT: ret void
;
entry:
%bc = bitcast i64* @g to i8*
br i1 %c, label %t, label %f
t:
%gep = getelementptr i8, i8* %bc, i64 2
br label %f
f:
%phi = phi i8* [%gep, %t], [%bc, %entry]
call void @unknown_use8(i8* %phi)
ret void
}

!0 = !{i64 10, i64 100}

;.
Expand Down

0 comments on commit 5859ae6

Please sign in to comment.