Skip to content

Commit 79c820c

Browse files
committed
[Inliner] Propagate range attributes to params when inlining
1 parent f102ef5 commit 79c820c

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
@@ -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

+4
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

+22
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

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

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

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

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

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

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

+8-8
Original file line numberDiff line numberDiff line change
@@ -592,7 +592,7 @@ define dso_local void @foo4(i32 %v) {
592592
define void @prop_range_empty_intersect(i32 %v) {
593593
; CHECK-LABEL: define {{[^@]+}}@prop_range_empty_intersect
594594
; CHECK-SAME: (i32 [[V:%.*]]) {
595-
; CHECK-NEXT: call void @bar4(i32 range(i32 0, 10) [[V]])
595+
; CHECK-NEXT: call void @bar4(i32 range(i32 0, 0) [[V]])
596596
; CHECK-NEXT: ret void
597597
;
598598
call void @foo4_range_0_10(i32 range(i32 11, 50) %v)
@@ -602,7 +602,7 @@ define void @prop_range_empty_intersect(i32 %v) {
602602
define void @prop_range_empty(i32 %v) {
603603
; CHECK-LABEL: define {{[^@]+}}@prop_range_empty
604604
; CHECK-SAME: (i32 [[V:%.*]]) {
605-
; CHECK-NEXT: call void @bar4(i32 [[V]])
605+
; CHECK-NEXT: call void @bar4(i32 range(i32 1, 0) [[V]])
606606
; CHECK-NEXT: ret void
607607
;
608608
call void @foo4(i32 range(i32 1, 0) %v)
@@ -612,7 +612,7 @@ define void @prop_range_empty(i32 %v) {
612612
define void @prop_range_empty_with_intersect(i32 %v) {
613613
; CHECK-LABEL: define {{[^@]+}}@prop_range_empty_with_intersect
614614
; CHECK-SAME: (i32 [[V:%.*]]) {
615-
; CHECK-NEXT: call void @bar4(i32 range(i32 0, 10) [[V]])
615+
; CHECK-NEXT: call void @bar4(i32 range(i32 1, 10) [[V]])
616616
; CHECK-NEXT: ret void
617617
;
618618
call void @foo4_range_0_10(i32 range(i32 1, 0) %v)
@@ -622,7 +622,7 @@ define void @prop_range_empty_with_intersect(i32 %v) {
622622
define void @prop_range_intersect1(i32 %v) {
623623
; CHECK-LABEL: define {{[^@]+}}@prop_range_intersect1
624624
; CHECK-SAME: (i32 [[V:%.*]]) {
625-
; CHECK-NEXT: call void @bar4(i32 range(i32 0, 10) [[V]])
625+
; CHECK-NEXT: call void @bar4(i32 range(i32 0, 9) [[V]])
626626
; CHECK-NEXT: ret void
627627
;
628628
call void @foo4_range_0_10(i32 range(i32 0, 9) %v)
@@ -632,7 +632,7 @@ define void @prop_range_intersect1(i32 %v) {
632632
define void @prop_range_intersect2(i32 %v) {
633633
; CHECK-LABEL: define {{[^@]+}}@prop_range_intersect2
634634
; CHECK-SAME: (i32 [[V:%.*]]) {
635-
; CHECK-NEXT: call void @bar4(i32 range(i32 0, 10) [[V]])
635+
; CHECK-NEXT: call void @bar4(i32 range(i32 1, 9) [[V]])
636636
; CHECK-NEXT: ret void
637637
;
638638
call void @foo4_range_0_10(i32 range(i32 1, 9) %v)
@@ -642,7 +642,7 @@ define void @prop_range_intersect2(i32 %v) {
642642
define void @prop_range_intersect3(i32 %v) {
643643
; CHECK-LABEL: define {{[^@]+}}@prop_range_intersect3
644644
; CHECK-SAME: (i32 [[V:%.*]]) {
645-
; CHECK-NEXT: call void @bar4(i32 [[V]])
645+
; CHECK-NEXT: call void @bar4(i32 range(i32 0, 11) [[V]])
646646
; CHECK-NEXT: ret void
647647
;
648648
call void @foo4_2_range_0_10(i32 range(i32 0, 11) %v)
@@ -652,7 +652,7 @@ define void @prop_range_intersect3(i32 %v) {
652652
define void @prop_range_intersect4(i32 %v) {
653653
; CHECK-LABEL: define {{[^@]+}}@prop_range_intersect4
654654
; CHECK-SAME: (i32 [[V:%.*]]) {
655-
; CHECK-NEXT: call void @bar4(i32 range(i32 0, 10) [[V]])
655+
; CHECK-NEXT: call void @bar4(i32 range(i32 0, 5) [[V]])
656656
; CHECK-NEXT: ret void
657657
;
658658
call void @foo4_range_0_10(i32 range(i32 40, 5) %v)
@@ -682,7 +682,7 @@ define void @prop_range_keep(i32 %v) {
682682
define void @prop_range_direct(i32 %v) {
683683
; CHECK-LABEL: define {{[^@]+}}@prop_range_direct
684684
; CHECK-SAME: (i32 [[V:%.*]]) {
685-
; CHECK-NEXT: call void @bar4(i32 [[V]])
685+
; CHECK-NEXT: call void @bar4(i32 range(i32 1, 11) [[V]])
686686
; CHECK-NEXT: ret void
687687
;
688688
call void @foo4(i32 range(i32 1, 11) %v)

0 commit comments

Comments
 (0)