Skip to content

Commit 406f3a3

Browse files
committed
[Inliner] Propagate range attributes to params when inlining
1 parent 949712e commit 406f3a3

File tree

6 files changed

+64
-9
lines changed

6 files changed

+64
-9
lines changed

llvm/include/llvm/IR/Attributes.h

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

790+
/// Add the range attribute to the attribute set at the given arg index.
791+
/// Returns a new list because attribute lists are immutable.
792+
[[nodiscard]] AttributeList addRangeParamAttr(LLVMContext &C, unsigned Index,
793+
const ConstantRange &CR) const;
794+
790795
/// Add the allocsize attribute to the attribute set at the given arg index.
791796
/// Returns a new list because attribute lists are immutable.
792797
[[nodiscard]] AttributeList
@@ -947,6 +952,9 @@ class AttributeList {
947952
/// arg.
948953
uint64_t getParamDereferenceableOrNullBytes(unsigned ArgNo) const;
949954

955+
/// Get range (or std::nullopt if unknown) of an arg.
956+
std::optional<ConstantRange> getParamRange(unsigned ArgNo) const;
957+
950958
/// Get the disallowed floating-point classes of the return value.
951959
FPClassTest getRetNoFPClass() const;
952960

@@ -1123,6 +1131,10 @@ class AttrBuilder {
11231131
/// invalid if the Kind is not present in the builder.
11241132
Attribute getAttribute(StringRef Kind) const;
11251133

1134+
/// Retrieve the range if the attribute exists (std::nullopt is returned
1135+
/// otherwise).
1136+
std::optional<ConstantRange> getRange() const;
1137+
11261138
/// Return raw (possibly packed/encoded) value of integer attribute or
11271139
/// std::nullopt if not set.
11281140
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
@@ -1868,6 +1868,10 @@ class CallBase : public Instruction {
18681868
/// parameter.
18691869
FPClassTest getParamNoFPClass(unsigned i) const;
18701870

1871+
/// If arg ArgNo has a range attribute, return the value range of the
1872+
/// argument. Otherwise, std::nullopt is returned.
1873+
std::optional<ConstantRange> getParamRange(unsigned ArgNo) const;
1874+
18711875
/// If this return value has a range attribute, return the value range of the
18721876
/// argument. Otherwise, std::nullopt is returned.
18731877
std::optional<ConstantRange> getRange() const;

llvm/lib/IR/Attributes.cpp

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

1782+
AttributeList AttributeList::addRangeParamAttr(LLVMContext &C, unsigned Index,
1783+
const ConstantRange &CR) const {
1784+
AttrBuilder B(C);
1785+
B.addRangeAttr(CR);
1786+
return addParamAttributes(C, Index, B);
1787+
}
1788+
17821789
AttributeList AttributeList::addRangeRetAttr(LLVMContext &C,
17831790
const ConstantRange &CR) const {
17841791
AttrBuilder B(C);
@@ -1931,6 +1938,14 @@ AttributeList::getParamDereferenceableOrNullBytes(unsigned Index) const {
19311938
return getParamAttrs(Index).getDereferenceableOrNullBytes();
19321939
}
19331940

1941+
std::optional<ConstantRange>
1942+
AttributeList::getParamRange(unsigned Index) const {
1943+
auto RangeAttr = getParamAttrs(Index).getAttribute(Attribute::Range);
1944+
if (RangeAttr.isValid())
1945+
return RangeAttr.getRange();
1946+
return std::nullopt;
1947+
}
1948+
19341949
FPClassTest AttributeList::getRetNoFPClass() const {
19351950
return getRetAttrs().getNoFPClass();
19361951
}
@@ -2277,6 +2292,13 @@ Attribute AttrBuilder::getAttribute(StringRef A) const {
22772292
return {};
22782293
}
22792294

2295+
std::optional<ConstantRange> AttrBuilder::getRange() const {
2296+
const Attribute RangeAttr = getAttribute(Attribute::Range);
2297+
if (RangeAttr.isValid())
2298+
return RangeAttr.getRange();
2299+
return std::nullopt;
2300+
}
2301+
22802302
bool AttrBuilder::contains(Attribute::AttrKind A) const {
22812303
return getAttribute(A).isValid();
22822304
}

llvm/lib/IR/Instructions.cpp

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

376+
std::optional<ConstantRange> CallBase::getParamRange(unsigned ArgNo) const {
377+
const Attribute RangeAttr = getParamAttr(ArgNo, llvm::Attribute::Range);
378+
if (RangeAttr.isValid())
379+
return RangeAttr.getRange();
380+
return std::nullopt;
381+
}
382+
376383
std::optional<ConstantRange> CallBase::getRange() const {
377384
const Attribute RangeAttr = getRetAttr(llvm::Attribute::Range);
378385
if (RangeAttr.isValid())

llvm/lib/Transforms/Utils/InlineFunction.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1369,7 +1369,7 @@ static void AddParamAndFnBasicAttributes(const CallBase &CB,
13691369
// behavior was just using a poison value.
13701370
static const Attribute::AttrKind ExactAttrsToPropagate[] = {
13711371
Attribute::Dereferenceable, Attribute::DereferenceableOrNull,
1372-
Attribute::NonNull, Attribute::Alignment};
1372+
Attribute::NonNull, Attribute::Alignment, Attribute::Range};
13731373

13741374
for (unsigned I = 0, E = CB.arg_size(); I < E; ++I) {
13751375
ValidObjParamAttrs.emplace_back(AttrBuilder{CB.getContext()});
@@ -1441,8 +1441,18 @@ static void AddParamAndFnBasicAttributes(const CallBase &CB,
14411441
NewAL.getAlignment().valueOrOne())
14421442
NewAL.removeAttribute(Attribute::Alignment);
14431443

1444+
auto ExistingRange = AL.getParamRange(I);
14441445
AL = AL.addParamAttributes(Context, I, NewAL);
14451446

1447+
// For range we use the intersection.
1448+
if (ExistingRange.has_value()) {
1449+
if (auto NewRange = NewAL.getRange()) {
1450+
ConstantRange CombinedRange =
1451+
ExistingRange->intersectWith(*NewRange);
1452+
AL = AL.removeParamAttribute(Context, I, Attribute::Range);
1453+
AL = AL.addRangeParamAttr(Context, I, CombinedRange);
1454+
}
1455+
}
14461456
} else {
14471457
// Check if the underlying value for the parameter is an argument.
14481458
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
@@ -634,7 +634,7 @@ define dso_local void @foo4(i32 %v) {
634634
define void @prop_range_empty_intersect(i32 %v) {
635635
; CHECK-LABEL: define {{[^@]+}}@prop_range_empty_intersect
636636
; CHECK-SAME: (i32 [[V:%.*]]) {
637-
; CHECK-NEXT: call void @bar5(i32 range(i32 0, 10) [[V]])
637+
; CHECK-NEXT: call void @bar5(i32 range(i32 0, 0) [[V]])
638638
; CHECK-NEXT: ret void
639639
;
640640
call void @foo4_range_0_10(i32 range(i32 11, 50) %v)
@@ -644,7 +644,7 @@ define void @prop_range_empty_intersect(i32 %v) {
644644
define void @prop_range_empty(i32 %v) {
645645
; CHECK-LABEL: define {{[^@]+}}@prop_range_empty
646646
; CHECK-SAME: (i32 [[V:%.*]]) {
647-
; CHECK-NEXT: call void @bar5(i32 [[V]])
647+
; CHECK-NEXT: call void @bar5(i32 range(i32 1, 0) [[V]])
648648
; CHECK-NEXT: ret void
649649
;
650650
call void @foo4(i32 range(i32 1, 0) %v)
@@ -654,7 +654,7 @@ define void @prop_range_empty(i32 %v) {
654654
define void @prop_range_empty_with_intersect(i32 %v) {
655655
; CHECK-LABEL: define {{[^@]+}}@prop_range_empty_with_intersect
656656
; CHECK-SAME: (i32 [[V:%.*]]) {
657-
; CHECK-NEXT: call void @bar5(i32 range(i32 0, 10) [[V]])
657+
; CHECK-NEXT: call void @bar5(i32 range(i32 1, 10) [[V]])
658658
; CHECK-NEXT: ret void
659659
;
660660
call void @foo4_range_0_10(i32 range(i32 1, 0) %v)
@@ -664,7 +664,7 @@ define void @prop_range_empty_with_intersect(i32 %v) {
664664
define void @prop_range_intersect1(i32 %v) {
665665
; CHECK-LABEL: define {{[^@]+}}@prop_range_intersect1
666666
; CHECK-SAME: (i32 [[V:%.*]]) {
667-
; CHECK-NEXT: call void @bar5(i32 range(i32 0, 10) [[V]])
667+
; CHECK-NEXT: call void @bar5(i32 range(i32 0, 9) [[V]])
668668
; CHECK-NEXT: ret void
669669
;
670670
call void @foo4_range_0_10(i32 range(i32 0, 9) %v)
@@ -674,7 +674,7 @@ define void @prop_range_intersect1(i32 %v) {
674674
define void @prop_range_intersect2(i32 %v) {
675675
; CHECK-LABEL: define {{[^@]+}}@prop_range_intersect2
676676
; CHECK-SAME: (i32 [[V:%.*]]) {
677-
; CHECK-NEXT: call void @bar5(i32 range(i32 0, 10) [[V]])
677+
; CHECK-NEXT: call void @bar5(i32 range(i32 1, 9) [[V]])
678678
; CHECK-NEXT: ret void
679679
;
680680
call void @foo4_range_0_10(i32 range(i32 1, 9) %v)
@@ -684,7 +684,7 @@ define void @prop_range_intersect2(i32 %v) {
684684
define void @prop_range_intersect3(i32 %v) {
685685
; CHECK-LABEL: define {{[^@]+}}@prop_range_intersect3
686686
; CHECK-SAME: (i32 [[V:%.*]]) {
687-
; CHECK-NEXT: call void @bar5(i32 [[V]])
687+
; CHECK-NEXT: call void @bar5(i32 range(i32 0, 11) [[V]])
688688
; CHECK-NEXT: ret void
689689
;
690690
call void @foo4_2_range_0_10(i32 range(i32 0, 11) %v)
@@ -694,7 +694,7 @@ define void @prop_range_intersect3(i32 %v) {
694694
define void @prop_range_intersect4(i32 %v) {
695695
; CHECK-LABEL: define {{[^@]+}}@prop_range_intersect4
696696
; CHECK-SAME: (i32 [[V:%.*]]) {
697-
; CHECK-NEXT: call void @bar5(i32 range(i32 0, 10) [[V]])
697+
; CHECK-NEXT: call void @bar5(i32 range(i32 0, 5) [[V]])
698698
; CHECK-NEXT: ret void
699699
;
700700
call void @foo4_range_0_10(i32 range(i32 40, 5) %v)
@@ -724,7 +724,7 @@ define void @prop_range_keep(i32 %v) {
724724
define void @prop_range_direct(i32 %v) {
725725
; CHECK-LABEL: define {{[^@]+}}@prop_range_direct
726726
; CHECK-SAME: (i32 [[V:%.*]]) {
727-
; CHECK-NEXT: call void @bar5(i32 [[V]])
727+
; CHECK-NEXT: call void @bar5(i32 range(i32 1, 11) [[V]])
728728
; CHECK-NEXT: ret void
729729
;
730730
call void @foo4(i32 range(i32 1, 11) %v)

0 commit comments

Comments
 (0)