Skip to content

Commit d519556

Browse files
committed
[Inliner] Propagate range attributes to params when inlining
1 parent 3d28947 commit d519556

File tree

6 files changed

+64
-8
lines changed

6 files changed

+64
-8
lines changed

llvm/include/llvm/IR/Attributes.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -752,6 +752,11 @@ class AttributeList {
752752
[[nodiscard]] AttributeList addRangeRetAttr(LLVMContext &C,
753753
const ConstantRange &CR) const;
754754

755+
/// Add the range attribute to the attribute set at the given arg index.
756+
/// Returns a new list because attribute lists are immutable.
757+
[[nodiscard]] AttributeList addRangeParamAttr(LLVMContext &C, unsigned Index,
758+
const ConstantRange &CR) const;
759+
755760
/// Add the allocsize attribute to the attribute set at the given arg index.
756761
/// Returns a new list because attribute lists are immutable.
757762
[[nodiscard]] AttributeList
@@ -906,6 +911,9 @@ class AttributeList {
906911
/// arg.
907912
uint64_t getParamDereferenceableOrNullBytes(unsigned ArgNo) const;
908913

914+
/// Get range (or std::nullopt if unknown) of an arg.
915+
std::optional<ConstantRange> getParamRange(unsigned ArgNo) const;
916+
909917
/// Get the disallowed floating-point classes of the return value.
910918
FPClassTest getRetNoFPClass() const;
911919

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

1093+
/// Retrieve the range if the attribute exists (std::nullopt is returned
1094+
/// otherwise).
1095+
std::optional<ConstantRange> getRange() const;
1096+
10851097
/// Return raw (possibly packed/encoded) value of integer attribute or
10861098
/// std::nullopt if not set.
10871099
std::optional<uint64_t> getRawIntAttr(Attribute::AttrKind Kind) const;

llvm/include/llvm/IR/InstrTypes.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2204,6 +2204,10 @@ class CallBase : public Instruction {
22042204
/// parameter.
22052205
FPClassTest getParamNoFPClass(unsigned i) const;
22062206

2207+
/// If arg ArgNo has a range attribute, return the value range of the
2208+
/// argument. Otherwise, std::nullopt is returned.
2209+
std::optional<ConstantRange> getParamRange(unsigned ArgNo) const;
2210+
22072211
/// If this return value has a range attribute, return the value range of the
22082212
/// argument. Otherwise, std::nullopt is returned.
22092213
std::optional<ConstantRange> getRange() const;

llvm/lib/IR/Attributes.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1530,6 +1530,13 @@ AttributeList::addDereferenceableOrNullParamAttr(LLVMContext &C, unsigned Index,
15301530
return addParamAttributes(C, Index, B);
15311531
}
15321532

1533+
AttributeList AttributeList::addRangeParamAttr(LLVMContext &C, unsigned Index,
1534+
const ConstantRange &CR) const {
1535+
AttrBuilder B(C);
1536+
B.addRangeAttr(CR);
1537+
return addParamAttributes(C, Index, B);
1538+
}
1539+
15331540
AttributeList AttributeList::addRangeRetAttr(LLVMContext &C,
15341541
const ConstantRange &CR) const {
15351542
AttrBuilder B(C);
@@ -1658,6 +1665,14 @@ AttributeList::getParamDereferenceableOrNullBytes(unsigned Index) const {
16581665
return getParamAttrs(Index).getDereferenceableOrNullBytes();
16591666
}
16601667

1668+
std::optional<ConstantRange>
1669+
AttributeList::getParamRange(unsigned Index) const {
1670+
auto RangeAttr = getParamAttrs(Index).getAttribute(Attribute::Range);
1671+
if (RangeAttr.isValid())
1672+
return RangeAttr.getRange();
1673+
return std::nullopt;
1674+
}
1675+
16611676
FPClassTest AttributeList::getRetNoFPClass() const {
16621677
return getRetAttrs().getNoFPClass();
16631678
}
@@ -1991,6 +2006,13 @@ Attribute AttrBuilder::getAttribute(StringRef A) const {
19912006
return {};
19922007
}
19932008

2009+
std::optional<ConstantRange> AttrBuilder::getRange() const {
2010+
const Attribute RangeAttr = getAttribute(Attribute::Range);
2011+
if (RangeAttr.isValid())
2012+
return RangeAttr.getRange();
2013+
return std::nullopt;
2014+
}
2015+
19942016
bool AttrBuilder::contains(Attribute::AttrKind A) const {
19952017
return getAttribute(A).isValid();
19962018
}

llvm/lib/IR/Instructions.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,13 @@ FPClassTest CallBase::getParamNoFPClass(unsigned i) const {
396396
return Mask;
397397
}
398398

399+
std::optional<ConstantRange> CallBase::getParamRange(unsigned ArgNo) const {
400+
const Attribute RangeAttr = getParamAttr(ArgNo, llvm::Attribute::Range);
401+
if (RangeAttr.isValid())
402+
return RangeAttr.getRange();
403+
return std::nullopt;
404+
}
405+
399406
std::optional<ConstantRange> CallBase::getRange() const {
400407
const Attribute RangeAttr = getRetAttr(llvm::Attribute::Range);
401408
if (RangeAttr.isValid())

llvm/lib/Transforms/Utils/InlineFunction.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1385,6 +1385,8 @@ static void AddParamAndFnBasicAttributes(const CallBase &CB,
13851385
ValidExactParamAttrs.back().addAttribute(Attribute::NonNull);
13861386
if (auto Align = CB.getParamAlign(I))
13871387
ValidExactParamAttrs.back().addAlignmentAttr(Align);
1388+
if (auto Range = CB.getParamRange(I))
1389+
ValidExactParamAttrs.back().addRangeAttr(*Range);
13881390

13891391
HasAttrToPropagate |= ValidObjParamAttrs.back().hasAttributes();
13901392
HasAttrToPropagate |= ValidExactParamAttrs.back().hasAttributes();
@@ -1428,8 +1430,17 @@ static void AddParamAndFnBasicAttributes(const CallBase &CB,
14281430
ValidExactParamAttrs[ArgNo].getAlignment().valueOrOne())
14291431
AL = AL.removeParamAttribute(Context, I, Attribute::Alignment);
14301432

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

1436+
// For range we use the intersection.
1437+
if (ExistingRange.has_value()) {
1438+
if (auto NewRange = ValidExactParamAttrs[ArgNo].getRange()) {
1439+
auto CombinedRange = ExistingRange->intersectWith(*NewRange);
1440+
AL = AL.removeParamAttribute(Context, I, Attribute::Range);
1441+
AL = AL.addRangeParamAttr(Context, I, CombinedRange);
1442+
}
1443+
}
14331444
} else {
14341445
// Check if the underlying value for the parameter is an argument.
14351446
const Value *UnderlyingV =

llvm/test/Transforms/Inline/access-attributes-prop.ll

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -613,7 +613,7 @@ define dso_local void @foo4(i32 %v) {
613613
define void @prop_range_empty_intersect(i32 %v) {
614614
; CHECK-LABEL: define {{[^@]+}}@prop_range_empty_intersect
615615
; CHECK-SAME: (i32 [[V:%.*]]) {
616-
; CHECK-NEXT: call void @bar5(i32 range(i32 0, 10) [[V]])
616+
; CHECK-NEXT: call void @bar5(i32 range(i32 0, 0) [[V]])
617617
; CHECK-NEXT: ret void
618618
;
619619
call void @foo4_range_0_10(i32 range(i32 11, 50) %v)
@@ -623,7 +623,7 @@ define void @prop_range_empty_intersect(i32 %v) {
623623
define void @prop_range_empty(i32 %v) {
624624
; CHECK-LABEL: define {{[^@]+}}@prop_range_empty
625625
; CHECK-SAME: (i32 [[V:%.*]]) {
626-
; CHECK-NEXT: call void @bar5(i32 [[V]])
626+
; CHECK-NEXT: call void @bar5(i32 range(i32 1, 0) [[V]])
627627
; CHECK-NEXT: ret void
628628
;
629629
call void @foo4(i32 range(i32 1, 0) %v)
@@ -633,7 +633,7 @@ define void @prop_range_empty(i32 %v) {
633633
define void @prop_range_empty_with_intersect(i32 %v) {
634634
; CHECK-LABEL: define {{[^@]+}}@prop_range_empty_with_intersect
635635
; CHECK-SAME: (i32 [[V:%.*]]) {
636-
; CHECK-NEXT: call void @bar5(i32 range(i32 0, 10) [[V]])
636+
; CHECK-NEXT: call void @bar5(i32 range(i32 1, 10) [[V]])
637637
; CHECK-NEXT: ret void
638638
;
639639
call void @foo4_range_0_10(i32 range(i32 1, 0) %v)
@@ -643,7 +643,7 @@ define void @prop_range_empty_with_intersect(i32 %v) {
643643
define void @prop_range_intersect1(i32 %v) {
644644
; CHECK-LABEL: define {{[^@]+}}@prop_range_intersect1
645645
; CHECK-SAME: (i32 [[V:%.*]]) {
646-
; CHECK-NEXT: call void @bar5(i32 range(i32 0, 10) [[V]])
646+
; CHECK-NEXT: call void @bar5(i32 range(i32 0, 9) [[V]])
647647
; CHECK-NEXT: ret void
648648
;
649649
call void @foo4_range_0_10(i32 range(i32 0, 9) %v)
@@ -653,7 +653,7 @@ define void @prop_range_intersect1(i32 %v) {
653653
define void @prop_range_intersect2(i32 %v) {
654654
; CHECK-LABEL: define {{[^@]+}}@prop_range_intersect2
655655
; CHECK-SAME: (i32 [[V:%.*]]) {
656-
; CHECK-NEXT: call void @bar5(i32 range(i32 0, 10) [[V]])
656+
; CHECK-NEXT: call void @bar5(i32 range(i32 1, 9) [[V]])
657657
; CHECK-NEXT: ret void
658658
;
659659
call void @foo4_range_0_10(i32 range(i32 1, 9) %v)
@@ -663,7 +663,7 @@ define void @prop_range_intersect2(i32 %v) {
663663
define void @prop_range_intersect3(i32 %v) {
664664
; CHECK-LABEL: define {{[^@]+}}@prop_range_intersect3
665665
; CHECK-SAME: (i32 [[V:%.*]]) {
666-
; CHECK-NEXT: call void @bar5(i32 [[V]])
666+
; CHECK-NEXT: call void @bar5(i32 range(i32 0, 11) [[V]])
667667
; CHECK-NEXT: ret void
668668
;
669669
call void @foo4_2_range_0_10(i32 range(i32 0, 11) %v)
@@ -673,7 +673,7 @@ define void @prop_range_intersect3(i32 %v) {
673673
define void @prop_range_intersect4(i32 %v) {
674674
; CHECK-LABEL: define {{[^@]+}}@prop_range_intersect4
675675
; CHECK-SAME: (i32 [[V:%.*]]) {
676-
; CHECK-NEXT: call void @bar5(i32 range(i32 0, 10) [[V]])
676+
; CHECK-NEXT: call void @bar5(i32 range(i32 0, 5) [[V]])
677677
; CHECK-NEXT: ret void
678678
;
679679
call void @foo4_range_0_10(i32 range(i32 40, 5) %v)
@@ -703,7 +703,7 @@ define void @prop_range_keep(i32 %v) {
703703
define void @prop_range_direct(i32 %v) {
704704
; CHECK-LABEL: define {{[^@]+}}@prop_range_direct
705705
; CHECK-SAME: (i32 [[V:%.*]]) {
706-
; CHECK-NEXT: call void @bar5(i32 [[V]])
706+
; CHECK-NEXT: call void @bar5(i32 range(i32 1, 11) [[V]])
707707
; CHECK-NEXT: ret void
708708
;
709709
call void @foo4(i32 range(i32 1, 11) %v)

0 commit comments

Comments
 (0)