Skip to content

Commit

Permalink
[Inliner] Propagate range attributes to params when inlining
Browse files Browse the repository at this point in the history
  • Loading branch information
goldsteinn committed May 22, 2024
1 parent f102ef5 commit a80d5c0
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 8 deletions.
12 changes: 12 additions & 0 deletions llvm/include/llvm/IR/Attributes.h
Original file line number Diff line number Diff line change
Expand Up @@ -752,6 +752,11 @@ class AttributeList {
[[nodiscard]] AttributeList addRangeRetAttr(LLVMContext &C,
const ConstantRange &CR) const;

/// Add the range attribute to the attribute set at the given arg index.
/// Returns a new list because attribute lists are immutable.
[[nodiscard]] AttributeList addRangeParamAttr(LLVMContext &C, unsigned Index,
const ConstantRange &CR) const;

/// Add the allocsize attribute to the attribute set at the given arg index.
/// Returns a new list because attribute lists are immutable.
[[nodiscard]] AttributeList
Expand Down Expand Up @@ -906,6 +911,9 @@ class AttributeList {
/// arg.
uint64_t getParamDereferenceableOrNullBytes(unsigned ArgNo) const;

/// Get range (or std::nullopt if unknown) of an arg.
std::optional<ConstantRange> getParamRange(unsigned ArgNo) const;

/// Get the disallowed floating-point classes of the return value.
FPClassTest getRetNoFPClass() const;

Expand Down Expand Up @@ -1082,6 +1090,10 @@ class AttrBuilder {
/// invalid if the Kind is not present in the builder.
Attribute getAttribute(StringRef Kind) const;

/// Retrieve the range if the attribute exists (std::nullopt is returned
/// otherwise).
std::optional<ConstantRange> getRange() const;

/// Return raw (possibly packed/encoded) value of integer attribute or
/// std::nullopt if not set.
std::optional<uint64_t> getRawIntAttr(Attribute::AttrKind Kind) const;
Expand Down
4 changes: 4 additions & 0 deletions llvm/include/llvm/IR/InstrTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -2204,6 +2204,10 @@ class CallBase : public Instruction {
/// parameter.
FPClassTest getParamNoFPClass(unsigned i) const;

/// If arg ArgNo has a range attribute, return the value range of the
/// argument. Otherwise, std::nullopt is returned.
std::optional<ConstantRange> getParamRange(unsigned ArgNo) const;

/// If this return value has a range attribute, return the value range of the
/// argument. Otherwise, std::nullopt is returned.
std::optional<ConstantRange> getRange() const;
Expand Down
22 changes: 22 additions & 0 deletions llvm/lib/IR/Attributes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1530,6 +1530,13 @@ AttributeList::addDereferenceableOrNullParamAttr(LLVMContext &C, unsigned Index,
return addParamAttributes(C, Index, B);
}

AttributeList AttributeList::addRangeParamAttr(LLVMContext &C, unsigned Index,
const ConstantRange &CR) const {
AttrBuilder B(C);
B.addRangeAttr(CR);
return addParamAttributes(C, Index, B);
}

AttributeList AttributeList::addRangeRetAttr(LLVMContext &C,
const ConstantRange &CR) const {
AttrBuilder B(C);
Expand Down Expand Up @@ -1658,6 +1665,14 @@ AttributeList::getParamDereferenceableOrNullBytes(unsigned Index) const {
return getParamAttrs(Index).getDereferenceableOrNullBytes();
}

std::optional<ConstantRange>
AttributeList::getParamRange(unsigned Index) const {
auto RangeAttr = getParamAttrs(Index).getAttribute(Attribute::Range);
if (RangeAttr.isValid())
return RangeAttr.getRange();
return std::nullopt;
}

FPClassTest AttributeList::getRetNoFPClass() const {
return getRetAttrs().getNoFPClass();
}
Expand Down Expand Up @@ -1991,6 +2006,13 @@ Attribute AttrBuilder::getAttribute(StringRef A) const {
return {};
}

std::optional<ConstantRange> AttrBuilder::getRange() const {
const Attribute RangeAttr = getAttribute(Attribute::Range);
if (RangeAttr.isValid())
return RangeAttr.getRange();
return std::nullopt;
}

bool AttrBuilder::contains(Attribute::AttrKind A) const {
return getAttribute(A).isValid();
}
Expand Down
7 changes: 7 additions & 0 deletions llvm/lib/IR/Instructions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,13 @@ FPClassTest CallBase::getParamNoFPClass(unsigned i) const {
return Mask;
}

std::optional<ConstantRange> CallBase::getParamRange(unsigned ArgNo) const {
const Attribute RangeAttr = getParamAttr(ArgNo, llvm::Attribute::Range);
if (RangeAttr.isValid())
return RangeAttr.getRange();
return std::nullopt;
}

std::optional<ConstantRange> CallBase::getRange() const {
const Attribute RangeAttr = getRetAttr(llvm::Attribute::Range);
if (RangeAttr.isValid())
Expand Down
11 changes: 11 additions & 0 deletions llvm/lib/Transforms/Utils/InlineFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1384,6 +1384,8 @@ static void AddParamAndFnBasicAttributes(const CallBase &CB,
ValidExactParamAttrs.back().addAttribute(Attribute::NonNull);
if (auto Align = CB.getParamAlign(I))
ValidExactParamAttrs.back().addAlignmentAttr(Align);
if (auto Range = CB.getParamRange(I))
ValidExactParamAttrs.back().addRangeAttr(*Range);

HasAttrToPropagate |= ValidObjParamAttrs.back().hasAttributes();
HasAttrToPropagate |= ValidExactParamAttrs.back().hasAttributes();
Expand Down Expand Up @@ -1427,8 +1429,17 @@ static void AddParamAndFnBasicAttributes(const CallBase &CB,
ValidExactParamAttrs[ArgNo].getAlignment().valueOrOne())
AL = AL.removeParamAttribute(Context, I, Attribute::Alignment);

auto ExistingRange = AL.getParamRange(I);
AL = AL.addParamAttributes(Context, I, ValidExactParamAttrs[ArgNo]);

// For range we use the intersection.
if (ExistingRange.has_value()) {
if (auto NewRange = ValidExactParamAttrs[ArgNo].getRange()) {
auto CombinedRange = ExistingRange->intersectWith(*NewRange);
AL = AL.removeParamAttribute(Context, I, Attribute::Range);
AL = AL.addRangeParamAttr(Context, I, CombinedRange);
}
}
} else {
// Check if the underlying value for the parameter is an argument.
const Value *UnderlyingV =
Expand Down
16 changes: 8 additions & 8 deletions llvm/test/Transforms/Inline/access-attributes-prop.ll
Original file line number Diff line number Diff line change
Expand Up @@ -592,7 +592,7 @@ define dso_local void @foo4(i32 %v) {
define void @prop_range_empty_intersect(i32 %v) {
; CHECK-LABEL: define {{[^@]+}}@prop_range_empty_intersect
; CHECK-SAME: (i32 [[V:%.*]]) {
; CHECK-NEXT: call void @bar4(i32 range(i32 0, 10) [[V]])
; CHECK-NEXT: call void @bar4(i32 range(i32 0, 0) [[V]])
; CHECK-NEXT: ret void
;
call void @foo4_range_0_10(i32 range(i32 11, 50) %v)
Expand All @@ -602,7 +602,7 @@ define void @prop_range_empty_intersect(i32 %v) {
define void @prop_range_empty(i32 %v) {
; CHECK-LABEL: define {{[^@]+}}@prop_range_empty
; CHECK-SAME: (i32 [[V:%.*]]) {
; CHECK-NEXT: call void @bar4(i32 [[V]])
; CHECK-NEXT: call void @bar4(i32 range(i32 1, 0) [[V]])
; CHECK-NEXT: ret void
;
call void @foo4(i32 range(i32 1, 0) %v)
Expand All @@ -612,7 +612,7 @@ define void @prop_range_empty(i32 %v) {
define void @prop_range_empty_with_intersect(i32 %v) {
; CHECK-LABEL: define {{[^@]+}}@prop_range_empty_with_intersect
; CHECK-SAME: (i32 [[V:%.*]]) {
; CHECK-NEXT: call void @bar4(i32 range(i32 0, 10) [[V]])
; CHECK-NEXT: call void @bar4(i32 range(i32 1, 10) [[V]])
; CHECK-NEXT: ret void
;
call void @foo4_range_0_10(i32 range(i32 1, 0) %v)
Expand All @@ -622,7 +622,7 @@ define void @prop_range_empty_with_intersect(i32 %v) {
define void @prop_range_intersect1(i32 %v) {
; CHECK-LABEL: define {{[^@]+}}@prop_range_intersect1
; CHECK-SAME: (i32 [[V:%.*]]) {
; CHECK-NEXT: call void @bar4(i32 range(i32 0, 10) [[V]])
; CHECK-NEXT: call void @bar4(i32 range(i32 0, 9) [[V]])
; CHECK-NEXT: ret void
;
call void @foo4_range_0_10(i32 range(i32 0, 9) %v)
Expand All @@ -632,7 +632,7 @@ define void @prop_range_intersect1(i32 %v) {
define void @prop_range_intersect2(i32 %v) {
; CHECK-LABEL: define {{[^@]+}}@prop_range_intersect2
; CHECK-SAME: (i32 [[V:%.*]]) {
; CHECK-NEXT: call void @bar4(i32 range(i32 0, 10) [[V]])
; CHECK-NEXT: call void @bar4(i32 range(i32 1, 9) [[V]])
; CHECK-NEXT: ret void
;
call void @foo4_range_0_10(i32 range(i32 1, 9) %v)
Expand All @@ -642,7 +642,7 @@ define void @prop_range_intersect2(i32 %v) {
define void @prop_range_intersect3(i32 %v) {
; CHECK-LABEL: define {{[^@]+}}@prop_range_intersect3
; CHECK-SAME: (i32 [[V:%.*]]) {
; CHECK-NEXT: call void @bar4(i32 [[V]])
; CHECK-NEXT: call void @bar4(i32 range(i32 0, 11) [[V]])
; CHECK-NEXT: ret void
;
call void @foo4_2_range_0_10(i32 range(i32 0, 11) %v)
Expand All @@ -652,7 +652,7 @@ define void @prop_range_intersect3(i32 %v) {
define void @prop_range_intersect4(i32 %v) {
; CHECK-LABEL: define {{[^@]+}}@prop_range_intersect4
; CHECK-SAME: (i32 [[V:%.*]]) {
; CHECK-NEXT: call void @bar4(i32 range(i32 0, 10) [[V]])
; CHECK-NEXT: call void @bar4(i32 range(i32 0, 5) [[V]])
; CHECK-NEXT: ret void
;
call void @foo4_range_0_10(i32 range(i32 40, 5) %v)
Expand Down Expand Up @@ -682,7 +682,7 @@ define void @prop_range_keep(i32 %v) {
define void @prop_range_direct(i32 %v) {
; CHECK-LABEL: define {{[^@]+}}@prop_range_direct
; CHECK-SAME: (i32 [[V:%.*]]) {
; CHECK-NEXT: call void @bar4(i32 [[V]])
; CHECK-NEXT: call void @bar4(i32 range(i32 1, 11) [[V]])
; CHECK-NEXT: ret void
;
call void @foo4(i32 range(i32 1, 11) %v)
Expand Down

0 comments on commit a80d5c0

Please sign in to comment.