Skip to content

Commit e8e15d6

Browse files
committed
[Inliner] Propagate range attributes to params when inlining
1 parent b34a4af commit e8e15d6

File tree

6 files changed

+66
-7
lines changed

6 files changed

+66
-7
lines changed

Diff for: 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;

Diff for: 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;

Diff for: 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
}

Diff for: 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())

Diff for: llvm/lib/Transforms/Utils/InlineFunction.cpp

+14
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,20 @@ 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->exactIntersectWith(*NewRange);
1439+
if (!CombinedRange.has_value())
1440+
CombinedRange =
1441+
ConstantRange::getEmpty(NewRange->getBitWidth());
1442+
AL = AL.removeParamAttribute(Context, I, Attribute::Range);
1443+
AL = AL.addRangeParamAttr(Context, I, *CombinedRange);
1444+
}
1445+
}
14321446
} else {
14331447
// Check if the underlying value for the parameter is an argument.
14341448
const Value *UnderlyingV =

Diff for: llvm/test/Transforms/Inline/access-attributes-prop.ll

+7-7
Original file line numberDiff line numberDiff line change
@@ -585,7 +585,7 @@ define dso_local void @foo4(i32 %v) {
585585
define void @prop_range_empty_intersect(i32 %v) {
586586
; CHECK-LABEL: define {{[^@]+}}@prop_range_empty_intersect
587587
; CHECK-SAME: (i32 [[V:%.*]]) {
588-
; CHECK-NEXT: call void @bar4(i32 range(i32 0, 10) [[V]])
588+
; CHECK-NEXT: call void @bar4(i32 range(i32 0, 0) [[V]])
589589
; CHECK-NEXT: ret void
590590
;
591591
call void @foo4_range_0_10(i32 range(i32 11, 50) %v)
@@ -595,7 +595,7 @@ define void @prop_range_empty_intersect(i32 %v) {
595595
define void @prop_range_empty(i32 %v) {
596596
; CHECK-LABEL: define {{[^@]+}}@prop_range_empty
597597
; CHECK-SAME: (i32 [[V:%.*]]) {
598-
; CHECK-NEXT: call void @bar4(i32 [[V]])
598+
; CHECK-NEXT: call void @bar4(i32 range(i32 1, 0) [[V]])
599599
; CHECK-NEXT: ret void
600600
;
601601
call void @foo4(i32 range(i32 1, 0) %v)
@@ -605,7 +605,7 @@ define void @prop_range_empty(i32 %v) {
605605
define void @prop_range_empty_with_intersect(i32 %v) {
606606
; CHECK-LABEL: define {{[^@]+}}@prop_range_empty_with_intersect
607607
; CHECK-SAME: (i32 [[V:%.*]]) {
608-
; CHECK-NEXT: call void @bar4(i32 range(i32 0, 10) [[V]])
608+
; CHECK-NEXT: call void @bar4(i32 range(i32 1, 10) [[V]])
609609
; CHECK-NEXT: ret void
610610
;
611611
call void @foo4_range_0_10(i32 range(i32 1, 0) %v)
@@ -615,7 +615,7 @@ define void @prop_range_empty_with_intersect(i32 %v) {
615615
define void @prop_range_intersect1(i32 %v) {
616616
; CHECK-LABEL: define {{[^@]+}}@prop_range_intersect1
617617
; CHECK-SAME: (i32 [[V:%.*]]) {
618-
; CHECK-NEXT: call void @bar4(i32 range(i32 0, 10) [[V]])
618+
; CHECK-NEXT: call void @bar4(i32 range(i32 0, 9) [[V]])
619619
; CHECK-NEXT: ret void
620620
;
621621
call void @foo4_range_0_10(i32 range(i32 0, 9) %v)
@@ -625,7 +625,7 @@ define void @prop_range_intersect1(i32 %v) {
625625
define void @prop_range_intersect2(i32 %v) {
626626
; CHECK-LABEL: define {{[^@]+}}@prop_range_intersect2
627627
; CHECK-SAME: (i32 [[V:%.*]]) {
628-
; CHECK-NEXT: call void @bar4(i32 range(i32 0, 10) [[V]])
628+
; CHECK-NEXT: call void @bar4(i32 range(i32 1, 9) [[V]])
629629
; CHECK-NEXT: ret void
630630
;
631631
call void @foo4_range_0_10(i32 range(i32 1, 9) %v)
@@ -635,7 +635,7 @@ define void @prop_range_intersect2(i32 %v) {
635635
define void @prop_range_intersect3(i32 %v) {
636636
; CHECK-LABEL: define {{[^@]+}}@prop_range_intersect3
637637
; CHECK-SAME: (i32 [[V:%.*]]) {
638-
; CHECK-NEXT: call void @bar4(i32 [[V]])
638+
; CHECK-NEXT: call void @bar4(i32 range(i32 0, 11) [[V]])
639639
; CHECK-NEXT: ret void
640640
;
641641
call void @foo4_2_range_0_10(i32 range(i32 0, 11) %v)
@@ -645,7 +645,7 @@ define void @prop_range_intersect3(i32 %v) {
645645
define void @prop_range_direct(i32 %v) {
646646
; CHECK-LABEL: define {{[^@]+}}@prop_range_direct
647647
; CHECK-SAME: (i32 [[V:%.*]]) {
648-
; CHECK-NEXT: call void @bar4(i32 [[V]])
648+
; CHECK-NEXT: call void @bar4(i32 range(i32 1, 11) [[V]])
649649
; CHECK-NEXT: ret void
650650
;
651651
call void @foo4(i32 range(i32 1, 11) %v)

0 commit comments

Comments
 (0)