Skip to content

Commit 86e5007

Browse files
committed
[Inliner] Propagate range attributes to params when inlining
1 parent 47c4145 commit 86e5007

File tree

6 files changed

+64
-8
lines changed

6 files changed

+64
-8
lines changed

llvm/include/llvm/IR/Attributes.h

+12
Original file line numberDiff line numberDiff line change
@@ -769,6 +769,11 @@ class AttributeList {
769769
[[nodiscard]] AttributeList addRangeRetAttr(LLVMContext &C,
770770
const ConstantRange &CR) const;
771771

772+
/// Add the range attribute to the attribute set at the given arg index.
773+
/// Returns a new list because attribute lists are immutable.
774+
[[nodiscard]] AttributeList addRangeParamAttr(LLVMContext &C, unsigned Index,
775+
const ConstantRange &CR) const;
776+
772777
/// Add the allocsize attribute to the attribute set at the given arg index.
773778
/// Returns a new list because attribute lists are immutable.
774779
[[nodiscard]] AttributeList
@@ -923,6 +928,9 @@ class AttributeList {
923928
/// arg.
924929
uint64_t getParamDereferenceableOrNullBytes(unsigned ArgNo) const;
925930

931+
/// Get range (or std::nullopt if unknown) of an arg.
932+
std::optional<ConstantRange> getParamRange(unsigned ArgNo) const;
933+
926934
/// Get the disallowed floating-point classes of the return value.
927935
FPClassTest getRetNoFPClass() const;
928936

@@ -1099,6 +1107,10 @@ class AttrBuilder {
10991107
/// invalid if the Kind is not present in the builder.
11001108
Attribute getAttribute(StringRef Kind) const;
11011109

1110+
/// Retrieve the range if the attribute exists (std::nullopt is returned
1111+
/// otherwise).
1112+
std::optional<ConstantRange> getRange() const;
1113+
11021114
/// Return raw (possibly packed/encoded) value of integer attribute or
11031115
/// std::nullopt if not set.
11041116
std::optional<uint64_t> getRawIntAttr(Attribute::AttrKind Kind) const;

llvm/include/llvm/IR/InstrTypes.h

+4
Original file line numberDiff line numberDiff line change
@@ -1936,6 +1936,10 @@ class CallBase : public Instruction {
19361936
/// parameter.
19371937
FPClassTest getParamNoFPClass(unsigned i) const;
19381938

1939+
/// If arg ArgNo has a range attribute, return the value range of the
1940+
/// argument. Otherwise, std::nullopt is returned.
1941+
std::optional<ConstantRange> getParamRange(unsigned ArgNo) const;
1942+
19391943
/// If this return value has a range attribute, return the value range of the
19401944
/// argument. Otherwise, std::nullopt is returned.
19411945
std::optional<ConstantRange> getRange() const;

llvm/lib/IR/Attributes.cpp

+22
Original file line numberDiff line numberDiff line change
@@ -1598,6 +1598,13 @@ AttributeList::addDereferenceableOrNullParamAttr(LLVMContext &C, unsigned Index,
15981598
return addParamAttributes(C, Index, B);
15991599
}
16001600

1601+
AttributeList AttributeList::addRangeParamAttr(LLVMContext &C, unsigned Index,
1602+
const ConstantRange &CR) const {
1603+
AttrBuilder B(C);
1604+
B.addRangeAttr(CR);
1605+
return addParamAttributes(C, Index, B);
1606+
}
1607+
16011608
AttributeList AttributeList::addRangeRetAttr(LLVMContext &C,
16021609
const ConstantRange &CR) const {
16031610
AttrBuilder B(C);
@@ -1726,6 +1733,14 @@ AttributeList::getParamDereferenceableOrNullBytes(unsigned Index) const {
17261733
return getParamAttrs(Index).getDereferenceableOrNullBytes();
17271734
}
17281735

1736+
std::optional<ConstantRange>
1737+
AttributeList::getParamRange(unsigned Index) const {
1738+
auto RangeAttr = getParamAttrs(Index).getAttribute(Attribute::Range);
1739+
if (RangeAttr.isValid())
1740+
return RangeAttr.getRange();
1741+
return std::nullopt;
1742+
}
1743+
17291744
FPClassTest AttributeList::getRetNoFPClass() const {
17301745
return getRetAttrs().getNoFPClass();
17311746
}
@@ -2069,6 +2084,13 @@ Attribute AttrBuilder::getAttribute(StringRef A) const {
20692084
return {};
20702085
}
20712086

2087+
std::optional<ConstantRange> AttrBuilder::getRange() const {
2088+
const Attribute RangeAttr = getAttribute(Attribute::Range);
2089+
if (RangeAttr.isValid())
2090+
return RangeAttr.getRange();
2091+
return std::nullopt;
2092+
}
2093+
20722094
bool AttrBuilder::contains(Attribute::AttrKind A) const {
20732095
return getAttribute(A).isValid();
20742096
}

llvm/lib/IR/Instructions.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,13 @@ FPClassTest CallBase::getParamNoFPClass(unsigned i) const {
363363
return Mask;
364364
}
365365

366+
std::optional<ConstantRange> CallBase::getParamRange(unsigned ArgNo) const {
367+
const Attribute RangeAttr = getParamAttr(ArgNo, llvm::Attribute::Range);
368+
if (RangeAttr.isValid())
369+
return RangeAttr.getRange();
370+
return std::nullopt;
371+
}
372+
366373
std::optional<ConstantRange> CallBase::getRange() const {
367374
const Attribute RangeAttr = getRetAttr(llvm::Attribute::Range);
368375
if (RangeAttr.isValid())

llvm/lib/Transforms/Utils/InlineFunction.cpp

+11
Original file line numberDiff line numberDiff line change
@@ -1383,6 +1383,8 @@ static void AddParamAndFnBasicAttributes(const CallBase &CB,
13831383
ValidExactParamAttrs.back().addAttribute(Attribute::NonNull);
13841384
if (auto Align = CB.getParamAlign(I))
13851385
ValidExactParamAttrs.back().addAlignmentAttr(Align);
1386+
if (auto Range = CB.getParamRange(I))
1387+
ValidExactParamAttrs.back().addRangeAttr(*Range);
13861388

13871389
HasAttrToPropagate |= ValidObjParamAttrs.back().hasAttributes();
13881390
HasAttrToPropagate |= ValidExactParamAttrs.back().hasAttributes();
@@ -1426,8 +1428,17 @@ static void AddParamAndFnBasicAttributes(const CallBase &CB,
14261428
ValidExactParamAttrs[ArgNo].getAlignment().valueOrOne())
14271429
AL = AL.removeParamAttribute(Context, I, Attribute::Alignment);
14281430

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

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

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

+8-8
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)