-
Notifications
You must be signed in to change notification settings - Fork 15.1k
[Attributor] Swap range metadata to attribute for calls. #108835
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
@llvm/pr-subscribers-llvm-transforms Author: Andreas Jonson (andjo403) ChangesThis is the last usage of range metadata for calls that I can find so after this we can deprecate range metadata for calls. Full diff: https://github.com/llvm/llvm-project/pull/108835.diff 5 Files Affected:
diff --git a/llvm/lib/Transforms/IPO/Attributor.cpp b/llvm/lib/Transforms/IPO/Attributor.cpp
index 56d1133b25549a..76043fcc8984ea 100644
--- a/llvm/lib/Transforms/IPO/Attributor.cpp
+++ b/llvm/lib/Transforms/IPO/Attributor.cpp
@@ -989,6 +989,13 @@ static bool addIfNotExistent(LLVMContext &Ctx, const Attribute &Attr,
AB.addAttribute(Attr);
return true;
}
+ if (Attr.isConstantRangeAttribute()) {
+ Attribute::AttrKind Kind = Attr.getKindAsEnum();
+ if (!ForceReplace && AttrSet.hasAttribute(Kind))
+ return false;
+ AB.addAttribute(Attr);
+ return true;
+ }
llvm_unreachable("Expected enum or string attribute!");
}
diff --git a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
index 217c7cccb5775a..f8f0f0074305ea 100644
--- a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
+++ b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
@@ -9161,44 +9161,58 @@ struct AAValueConstantRangeImpl : AAValueConstantRange {
return MDNode::get(Ctx, LowAndHigh);
}
- /// Return true if \p Assumed is included in \p KnownRanges.
- static bool isBetterRange(const ConstantRange &Assumed, MDNode *KnownRanges) {
-
+ /// Return true if \p Assumed is included in ranges from instruction \p I.
+ static bool isBetterRange(const ConstantRange &Assumed,
+ const Instruction &I) {
if (Assumed.isFullSet())
return false;
- if (!KnownRanges)
- return true;
-
- // If multiple ranges are annotated in IR, we give up to annotate assumed
- // range for now.
+ std::optional<ConstantRange> Known;
- // TODO: If there exists a known range which containts assumed range, we
- // can say assumed range is better.
- if (KnownRanges->getNumOperands() > 2)
- return false;
+ if (const auto *CB = dyn_cast<CallBase>(&I)) {
+ Known = CB->getRange();
+ } else if (MDNode *KnownRanges = I.getMetadata(LLVMContext::MD_range)) {
+ // If multiple ranges are annotated in IR, we give up to annotate assumed
+ // range for now.
+
+ // TODO: If there exists a known range which containts assumed range, we
+ // can say assumed range is better.
+ if (KnownRanges->getNumOperands() > 2)
+ return false;
- ConstantInt *Lower =
- mdconst::extract<ConstantInt>(KnownRanges->getOperand(0));
- ConstantInt *Upper =
- mdconst::extract<ConstantInt>(KnownRanges->getOperand(1));
+ ConstantInt *Lower =
+ mdconst::extract<ConstantInt>(KnownRanges->getOperand(0));
+ ConstantInt *Upper =
+ mdconst::extract<ConstantInt>(KnownRanges->getOperand(1));
- ConstantRange Known(Lower->getValue(), Upper->getValue());
- return Known.contains(Assumed) && Known != Assumed;
+ Known.emplace(Lower->getValue(), Upper->getValue());
+ }
+ return !Known || (*Known != Assumed && Known->contains(Assumed));
}
/// Helper function to set range metadata.
static bool
setRangeMetadataIfisBetterRange(Instruction *I,
const ConstantRange &AssumedConstantRange) {
- auto *OldRangeMD = I->getMetadata(LLVMContext::MD_range);
- if (isBetterRange(AssumedConstantRange, OldRangeMD)) {
- if (!AssumedConstantRange.isEmptySet()) {
- I->setMetadata(LLVMContext::MD_range,
- getMDNodeForConstantRange(I->getType(), I->getContext(),
- AssumedConstantRange));
- return true;
- }
+ if (isBetterRange(AssumedConstantRange, *I)) {
+ I->setMetadata(LLVMContext::MD_range,
+ getMDNodeForConstantRange(I->getType(), I->getContext(),
+ AssumedConstantRange));
+ return true;
+ }
+ return false;
+ }
+ /// Helper function to set range return attribute.
+ static bool
+ setRangeRetAttrIfisBetterRange(Attributor &A, const IRPosition &IRP,
+ Instruction *I,
+ const ConstantRange &AssumedConstantRange) {
+ if (isBetterRange(AssumedConstantRange, *I)) {
+ A.manifestAttrs(IRP,
+ Attribute::get(I->getContext(), Attribute::Range,
+ AssumedConstantRange),
+ /*ForceReplace*/ true);
+ return true;
}
return false;
}
@@ -9215,9 +9229,13 @@ struct AAValueConstantRangeImpl : AAValueConstantRange {
if (Instruction *I = dyn_cast<Instruction>(&V)) {
assert(I == getCtxI() && "Should not annotate an instruction which is "
"not the context instruction");
- if (isa<CallInst>(I) || isa<LoadInst>(I))
+ if (isa<LoadInst>(I))
if (setRangeMetadataIfisBetterRange(I, AssumedConstantRange))
Changed = ChangeStatus::CHANGED;
+ if (isa<CallInst>(I))
+ if (setRangeRetAttrIfisBetterRange(A, getIRPosition(), I,
+ AssumedConstantRange))
+ Changed = ChangeStatus::CHANGED;
}
}
@@ -9613,10 +9631,11 @@ struct AAValueConstantRangeCallSiteReturned
/// See AbstractAttribute::initialize(...).
void initialize(Attributor &A) override {
- // If it is a load instruction with range metadata, use the metadata.
- if (CallInst *CI = dyn_cast<CallInst>(&getAssociatedValue()))
- if (auto *RangeMD = CI->getMetadata(LLVMContext::MD_range))
- intersectKnown(getConstantRangeFromMetadata(*RangeMD));
+ // If it is a call instruction with range attribute, use the range.
+ if (CallInst *CI = dyn_cast<CallInst>(&getAssociatedValue())) {
+ if (std::optional<ConstantRange> Range = CI->getRange())
+ intersectKnown(*Range);
+ }
AAValueConstantRangeImpl::initialize(A);
}
diff --git a/llvm/test/Transforms/Attributor/IPConstantProp/PR16052.ll b/llvm/test/Transforms/Attributor/IPConstantProp/PR16052.ll
index b0446479dac4ba..6641fdb9b4ffeb 100644
--- a/llvm/test/Transforms/Attributor/IPConstantProp/PR16052.ll
+++ b/llvm/test/Transforms/Attributor/IPConstantProp/PR16052.ll
@@ -68,7 +68,7 @@ define i64 @fn2c() {
; CGSCC-NEXT: entry:
; CGSCC-NEXT: [[CONV:%.*]] = sext i32 undef to i64
; CGSCC-NEXT: [[ADD:%.*]] = add i64 42, [[CONV]]
-; CGSCC-NEXT: [[CALL2:%.*]] = call i64 @fn1(i64 [[ADD]]) #[[ATTR2]], !range [[RNG0:![0-9]+]]
+; CGSCC-NEXT: [[CALL2:%.*]] = call range(i64 -2147483606, 2147483690) i64 @fn1(i64 [[ADD]]) #[[ATTR2]]
; CGSCC-NEXT: ret i64 [[CALL2]]
;
entry:
@@ -91,13 +91,11 @@ entry:
ret i64 %cond
}
;.
+; TUNIT: attributes #[[ATTR0]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
+;.
; CGSCC: attributes #[[ATTR0]] = { mustprogress nofree nosync nounwind willreturn memory(none) }
; CGSCC: attributes #[[ATTR1]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
; CGSCC: attributes #[[ATTR2]] = { nofree nosync willreturn }
;.
-; TUNIT: attributes #[[ATTR0]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
-;.
-; CGSCC: [[RNG0]] = !{i64 -2147483606, i64 2147483690}
-;.
;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
; CHECK: {{.*}}
diff --git a/llvm/test/Transforms/Attributor/range.ll b/llvm/test/Transforms/Attributor/range.ll
index 48040fec772dc0..455de49c9e72b8 100644
--- a/llvm/test/Transforms/Attributor/range.ll
+++ b/llvm/test/Transforms/Attributor/range.ll
@@ -19,7 +19,7 @@ define i32 @test0-range-check(ptr %p) {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read)
; TUNIT-LABEL: define {{[^@]+}}@test0-range-check
; TUNIT-SAME: (ptr nocapture nofree readonly align 4 [[P:%.*]]) #[[ATTR0]] {
-; TUNIT-NEXT: [[A:%.*]] = tail call i32 @test0(ptr nocapture nofree noundef readonly align 4 [[P]]) #[[ATTR3:[0-9]+]], !range [[RNG0]]
+; TUNIT-NEXT: [[A:%.*]] = tail call range(i32 0, 10) i32 @test0(ptr nocapture nofree noundef readonly align 4 [[P]]) #[[ATTR3:[0-9]+]]
; TUNIT-NEXT: ret i32 [[A]]
;
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(argmem: read)
@@ -32,6 +32,40 @@ define i32 @test0-range-check(ptr %p) {
ret i32 %a
}
+define i32 @test0-range-check-smaller-current-range-attr(ptr %p) {
+; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read)
+; TUNIT-LABEL: define {{[^@]+}}@test0-range-check-smaller-current-range-attr
+; TUNIT-SAME: (ptr nocapture nofree readonly align 4 [[P:%.*]]) #[[ATTR0]] {
+; TUNIT-NEXT: [[A:%.*]] = tail call range(i32 2, 5) i32 @test0(ptr nocapture nofree noundef readonly align 4 [[P]]) #[[ATTR3]]
+; TUNIT-NEXT: ret i32 [[A]]
+;
+; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(argmem: read)
+; CGSCC-LABEL: define {{[^@]+}}@test0-range-check-smaller-current-range-attr
+; CGSCC-SAME: (ptr nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[P:%.*]]) #[[ATTR1]] {
+; CGSCC-NEXT: [[A:%.*]] = tail call range(i32 2, 5) i32 @test0(ptr nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[P]]) #[[ATTR5]]
+; CGSCC-NEXT: ret i32 [[A]]
+;
+ %a = tail call range(i32 2, 5) i32 @test0(ptr %p)
+ ret i32 %a
+}
+
+define i32 @test0-range-check-larger-current-range-attr(ptr %p) {
+; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read)
+; TUNIT-LABEL: define {{[^@]+}}@test0-range-check-larger-current-range-attr
+; TUNIT-SAME: (ptr nocapture nofree readonly align 4 [[P:%.*]]) #[[ATTR0]] {
+; TUNIT-NEXT: [[A:%.*]] = tail call range(i32 0, 10) i32 @test0(ptr nocapture nofree noundef readonly align 4 [[P]]) #[[ATTR3]]
+; TUNIT-NEXT: ret i32 [[A]]
+;
+; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(argmem: read)
+; CGSCC-LABEL: define {{[^@]+}}@test0-range-check-larger-current-range-attr
+; CGSCC-SAME: (ptr nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[P:%.*]]) #[[ATTR1]] {
+; CGSCC-NEXT: [[A:%.*]] = tail call range(i32 0, 100) i32 @test0(ptr nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[P]]) #[[ATTR5]]
+; CGSCC-NEXT: ret i32 [[A]]
+;
+ %a = tail call range(i32 0, 100) i32 @test0(ptr %p)
+ ret i32 %a
+}
+
declare void @use3-dummy(i1, i1, i1)
define void @use3(i1, i1, i1) {
; CHECK-LABEL: define {{[^@]+}}@use3
@@ -48,7 +82,7 @@ define void @test0-icmp-check(ptr %p){
; ret = [0, 10)
; TUNIT-LABEL: define {{[^@]+}}@test0-icmp-check
; TUNIT-SAME: (ptr nocapture nofree readonly align 4 [[P:%.*]]) {
-; TUNIT-NEXT: [[RET:%.*]] = tail call i32 @test0(ptr nocapture nofree noundef readonly align 4 [[P]]) #[[ATTR3]]
+; TUNIT-NEXT: [[RET:%.*]] = tail call range(i32 0, 10) i32 @test0(ptr nocapture nofree noundef readonly align 4 [[P]]) #[[ATTR3]]
; TUNIT-NEXT: [[CMP_EQ_1:%.*]] = icmp eq i32 [[RET]], 10
; TUNIT-NEXT: [[CMP_EQ_2:%.*]] = icmp eq i32 [[RET]], 9
; TUNIT-NEXT: [[CMP_EQ_3:%.*]] = icmp eq i32 [[RET]], 8
@@ -284,7 +318,7 @@ define i1 @test1-check(ptr %p) {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read)
; TUNIT-LABEL: define {{[^@]+}}@test1-check
; TUNIT-SAME: (ptr nocapture nofree readonly align 4 [[P:%.*]]) #[[ATTR0]] {
-; TUNIT-NEXT: [[RES:%.*]] = tail call i32 @test1(ptr nocapture nofree noundef readonly align 4 [[P]]) #[[ATTR3]], !range [[RNG2:![0-9]+]]
+; TUNIT-NEXT: [[RES:%.*]] = tail call range(i32 200, 1091) i32 @test1(ptr nocapture nofree noundef readonly align 4 [[P]]) #[[ATTR3]]
; TUNIT-NEXT: [[CMP:%.*]] = icmp eq i32 [[RES]], 500
; TUNIT-NEXT: ret i1 [[CMP]]
;
@@ -624,7 +658,7 @@ define dso_local i32 @test4-g2(i32 %u) {
; TUNIT-LABEL: define {{[^@]+}}@test4-g2
; TUNIT-SAME: (i32 [[U:%.*]]) #[[ATTR1]] {
; TUNIT-NEXT: entry:
-; TUNIT-NEXT: [[CALL:%.*]] = tail call i32 @test4-f2(i32 [[U]]) #[[ATTR4]], !range [[RNG3:![0-9]+]]
+; TUNIT-NEXT: [[CALL:%.*]] = tail call range(i32 1, -2147483648) i32 @test4-f2(i32 [[U]]) #[[ATTR4]]
; TUNIT-NEXT: ret i32 [[CALL]]
;
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
@@ -1760,6 +1794,7 @@ declare void @barney(i32 signext, i32 signext)
!0 = !{i32 0, i32 10}
!1 = !{i32 10, i32 100}
+!2 = !{i32 2, i32 5}
;.
; TUNIT: attributes #[[ATTR0]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) }
; TUNIT: attributes #[[ATTR1]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
@@ -1778,8 +1813,6 @@ declare void @barney(i32 signext, i32 signext)
;.
; TUNIT: [[RNG0]] = !{i32 0, i32 10}
; TUNIT: [[RNG1]] = !{i32 10, i32 100}
-; TUNIT: [[RNG2]] = !{i32 200, i32 1091}
-; TUNIT: [[RNG3]] = !{i32 1, i32 -2147483648}
;.
; CGSCC: [[RNG0]] = !{i32 0, i32 10}
; CGSCC: [[RNG1]] = !{i32 10, i32 100}
diff --git a/llvm/test/Transforms/Attributor/value-simplify.ll b/llvm/test/Transforms/Attributor/value-simplify.ll
index 68f179c88116e4..d7edff382df84f 100644
--- a/llvm/test/Transforms/Attributor/value-simplify.ll
+++ b/llvm/test/Transforms/Attributor/value-simplify.ll
@@ -1113,7 +1113,7 @@ define i32 @test(i1 %c) {
; TUNIT-LABEL: define {{[^@]+}}@test
; TUNIT-SAME: (i1 [[C:%.*]]) {
; TUNIT-NEXT: [[R1:%.*]] = call i32 @ctx_test1(i1 noundef [[C]])
-; TUNIT-NEXT: [[R2:%.*]] = call i32 @ctx_test2(i1 noundef [[C]]), !range [[RNG0:![0-9]+]]
+; TUNIT-NEXT: [[R2:%.*]] = call range(i32 0, -2147483648) i32 @ctx_test2(i1 noundef [[C]])
; TUNIT-NEXT: [[ADD:%.*]] = add i32 [[R1]], [[R2]]
; TUNIT-NEXT: ret i32 [[ADD]]
;
@@ -1671,8 +1671,6 @@ define i32 @readWeakOdrConst() {
; TUNIT: attributes #[[ATTR15]] = { nosync nounwind memory(read) }
; TUNIT: attributes #[[ATTR16]] = { nounwind memory(write) }
;.
-; TUNIT: [[RNG0]] = !{i32 0, i32 -2147483648}
-;.
; CGSCC: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nosync nounwind willreturn }
; CGSCC: attributes #[[ATTR1]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
; CGSCC: attributes #[[ATTR2]] = { memory(readwrite, argmem: none) }
|
|
ping |
|
ping @jdoerfert |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs a rebase, but otherwise LGTM.
7f519b1 to
cc4185b
Compare
This is the last usage of range metadata for calls that I can find so after this we can deprecate range metadata for calls.