[llvm] Use range attribute to constant fold comparisons with constant values. (PR #84627)
Andreas Jonson via llvm-commits
llvm-commits at lists.llvm.org
Sat Mar 9 13:59:32 PST 2024
https://github.com/andjo403 updated https://github.com/llvm/llvm-project/pull/84627
>From 129f34ed1ddcd16fe41b1d36d98c9fe8848e68b1 Mon Sep 17 00:00:00 2001
From: Andreas Jonson <andjo403 at hotmail.com>
Date: Sat, 9 Mar 2024 12:50:42 +0100
Subject: [PATCH 1/4] Test for use range attribute to constant fold comparisons
with constant values.
---
.../test/Transforms/InstCombine/icmp-range.ll | 34 +++++++++++++++++++
1 file changed, 34 insertions(+)
diff --git a/llvm/test/Transforms/InstCombine/icmp-range.ll b/llvm/test/Transforms/InstCombine/icmp-range.ll
index 7af06e03fd4b2a..63cd8cf47e1a00 100644
--- a/llvm/test/Transforms/InstCombine/icmp-range.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-range.ll
@@ -160,6 +160,40 @@ define i1 @test_two_ranges2(ptr nocapture readonly %arg1, ptr nocapture readonly
ret i1 %rval
}
+; Values' ranges do not overlap each other, so it can simplified to false.
+define i1 @test_two_argument_ranges(i32 range(i32 1, 6) %arg1, i32 range(i32 8, 16) %arg2) {
+; CHECK-LABEL: @test_two_argument_ranges(
+; CHECK-NEXT: [[RVAL:%.*]] = icmp ult i32 [[ARG2:%.*]], [[ARG1:%.*]]
+; CHECK-NEXT: ret i1 [[RVAL]]
+;
+ %rval = icmp ult i32 %arg2, %arg1
+ ret i1 %rval
+}
+
+; Values' ranges do not overlap each other, so it can simplified to false.
+define i1 @test_one_range_and_one_argument_range(ptr nocapture readonly %arg1, i32 range(i32 8, 16) %arg2) {
+; CHECK-LABEL: @test_one_range_and_one_argument_range(
+; CHECK-NEXT: [[VAL1:%.*]] = load i32, ptr [[ARG1:%.*]], align 4, !range [[RNG2]]
+; CHECK-NEXT: [[RVAL:%.*]] = icmp ugt i32 [[VAL1]], [[ARG2:%.*]]
+; CHECK-NEXT: ret i1 [[RVAL]]
+;
+ %val1 = load i32, ptr %arg1, !range !0
+ %rval = icmp ult i32 %arg2, %val1
+ ret i1 %rval
+}
+
+; Values' ranges do not overlap each other, so it can simplified to false.
+define i1 @test_one_argument_range_and_one_range(i32 range(i32 1, 6) %arg1, ptr nocapture readonly %arg2) {
+; CHECK-LABEL: @test_one_argument_range_and_one_range(
+; CHECK-NEXT: [[VAL1:%.*]] = load i32, ptr [[ARG2:%.*]], align 4, !range [[RNG5]]
+; CHECK-NEXT: [[RVAL:%.*]] = icmp ult i32 [[VAL1]], [[ARG1:%.*]]
+; CHECK-NEXT: ret i1 [[RVAL]]
+;
+ %val1 = load i32, ptr %arg2, !range !6
+ %rval = icmp ult i32 %val1, %arg1
+ ret i1 %rval
+}
+
; Values' ranges do not overlap each other, so it can simplified to true.
define i1 @test_two_ranges3(ptr nocapture readonly %arg1, ptr nocapture readonly %arg2) {
; CHECK-LABEL: @test_two_ranges3(
>From 594074cfe88a04cacb0f268ca41fa403cc2c7cf9 Mon Sep 17 00:00:00 2001
From: Andreas Jonson <andjo403 at hotmail.com>
Date: Sat, 9 Mar 2024 12:52:06 +0100
Subject: [PATCH 2/4] Use range attribute to constant fold comparisons with
constant values.
---
llvm/lib/Analysis/InstructionSimplify.cpp | 38 ++++++++++---------
.../test/Transforms/InstCombine/icmp-range.ll | 11 ++----
2 files changed, 24 insertions(+), 25 deletions(-)
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 201472a3f10c2e..6a709f29db1e33 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -3729,6 +3729,19 @@ static Value *simplifyICmpWithIntrinsicOnLHS(CmpInst::Predicate Pred,
}
}
+/// Helper method to get range from metadata or attribute.
+static std::optional<ConstantRange> getRange(Value *V,
+ const InstrInfoQuery &IIQ) {
+ if (Instruction *I = dyn_cast<Instruction>(V))
+ if (MDNode *MD = IIQ.getMetadata(I, LLVMContext::MD_range))
+ return getConstantRangeFromMetadata(*MD);
+ if (const Argument *A = dyn_cast<Argument>(V))
+ if (A->hasAttribute(llvm::Attribute::Range))
+ return A->getAttribute(llvm::Attribute::Range).getRange();
+
+ return std::nullopt;
+}
+
/// Given operands for an ICmpInst, see if we can fold the result.
/// If not, this returns null.
static Value *simplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
@@ -3776,23 +3789,14 @@ static Value *simplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
// If both operands have range metadata, use the metadata
// to simplify the comparison.
- if (isa<Instruction>(RHS) && isa<Instruction>(LHS)) {
- auto RHS_Instr = cast<Instruction>(RHS);
- auto LHS_Instr = cast<Instruction>(LHS);
-
- if (Q.IIQ.getMetadata(RHS_Instr, LLVMContext::MD_range) &&
- Q.IIQ.getMetadata(LHS_Instr, LLVMContext::MD_range)) {
- auto RHS_CR = getConstantRangeFromMetadata(
- *RHS_Instr->getMetadata(LLVMContext::MD_range));
- auto LHS_CR = getConstantRangeFromMetadata(
- *LHS_Instr->getMetadata(LLVMContext::MD_range));
-
- if (LHS_CR.icmp(Pred, RHS_CR))
- return ConstantInt::getTrue(RHS->getContext());
-
- if (LHS_CR.icmp(CmpInst::getInversePredicate(Pred), RHS_CR))
- return ConstantInt::getFalse(RHS->getContext());
- }
+ std::optional<ConstantRange> RhsCr = getRange(RHS, Q.IIQ);
+ std::optional<ConstantRange> LhsCr = getRange(LHS, Q.IIQ);
+ if (RhsCr && LhsCr) {
+ if (LhsCr->icmp(Pred, *RhsCr))
+ return ConstantInt::getTrue(RHS->getContext());
+
+ if (LhsCr->icmp(CmpInst::getInversePredicate(Pred), *RhsCr))
+ return ConstantInt::getFalse(RHS->getContext());
}
// Compare of cast, for example (zext X) != 0 -> X != 0
diff --git a/llvm/test/Transforms/InstCombine/icmp-range.ll b/llvm/test/Transforms/InstCombine/icmp-range.ll
index 63cd8cf47e1a00..73da24f69c877a 100644
--- a/llvm/test/Transforms/InstCombine/icmp-range.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-range.ll
@@ -163,8 +163,7 @@ define i1 @test_two_ranges2(ptr nocapture readonly %arg1, ptr nocapture readonly
; Values' ranges do not overlap each other, so it can simplified to false.
define i1 @test_two_argument_ranges(i32 range(i32 1, 6) %arg1, i32 range(i32 8, 16) %arg2) {
; CHECK-LABEL: @test_two_argument_ranges(
-; CHECK-NEXT: [[RVAL:%.*]] = icmp ult i32 [[ARG2:%.*]], [[ARG1:%.*]]
-; CHECK-NEXT: ret i1 [[RVAL]]
+; CHECK-NEXT: ret i1 false
;
%rval = icmp ult i32 %arg2, %arg1
ret i1 %rval
@@ -173,9 +172,7 @@ define i1 @test_two_argument_ranges(i32 range(i32 1, 6) %arg1, i32 range(i32 8,
; Values' ranges do not overlap each other, so it can simplified to false.
define i1 @test_one_range_and_one_argument_range(ptr nocapture readonly %arg1, i32 range(i32 8, 16) %arg2) {
; CHECK-LABEL: @test_one_range_and_one_argument_range(
-; CHECK-NEXT: [[VAL1:%.*]] = load i32, ptr [[ARG1:%.*]], align 4, !range [[RNG2]]
-; CHECK-NEXT: [[RVAL:%.*]] = icmp ugt i32 [[VAL1]], [[ARG2:%.*]]
-; CHECK-NEXT: ret i1 [[RVAL]]
+; CHECK-NEXT: ret i1 false
;
%val1 = load i32, ptr %arg1, !range !0
%rval = icmp ult i32 %arg2, %val1
@@ -185,9 +182,7 @@ define i1 @test_one_range_and_one_argument_range(ptr nocapture readonly %arg1, i
; Values' ranges do not overlap each other, so it can simplified to false.
define i1 @test_one_argument_range_and_one_range(i32 range(i32 1, 6) %arg1, ptr nocapture readonly %arg2) {
; CHECK-LABEL: @test_one_argument_range_and_one_range(
-; CHECK-NEXT: [[VAL1:%.*]] = load i32, ptr [[ARG2:%.*]], align 4, !range [[RNG5]]
-; CHECK-NEXT: [[RVAL:%.*]] = icmp ult i32 [[VAL1]], [[ARG1:%.*]]
-; CHECK-NEXT: ret i1 [[RVAL]]
+; CHECK-NEXT: ret i1 false
;
%val1 = load i32, ptr %arg2, !range !6
%rval = icmp ult i32 %val1, %arg1
>From 08a6e29bb3fb29c5f2a93ae45dc3d9e06474f0d0 Mon Sep 17 00:00:00 2001
From: Andreas Jonson <andjo403 at hotmail.com>
Date: Sat, 9 Mar 2024 22:22:52 +0100
Subject: [PATCH 3/4] fixup! Test for use range attribute to constant fold
comparisons with constant values.
---
.../test/Transforms/InstCombine/icmp-range.ll | 93 ++++++++++++++++++-
1 file changed, 90 insertions(+), 3 deletions(-)
diff --git a/llvm/test/Transforms/InstCombine/icmp-range.ll b/llvm/test/Transforms/InstCombine/icmp-range.ll
index 73da24f69c877a..63385e989661cb 100644
--- a/llvm/test/Transforms/InstCombine/icmp-range.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-range.ll
@@ -149,6 +149,16 @@ define i1 @test_two_ranges(ptr nocapture readonly %arg1, ptr nocapture readonly
ret i1 %rval
}
+; Values' ranges overlap each other, so it can not be simplified.
+define i1 @test_two_attribute_ranges(i32 range(i32 5, 10) %arg1, i32 range(i32 8, 16) %arg2) {
+; CHECK-LABEL: @test_two_attribute_ranges(
+; CHECK-NEXT: [[RVAL:%.*]] = icmp ult i32 [[ARG1:%.*]], [[ARG2:%.*]]
+; CHECK-NEXT: ret i1 [[RVAL]]
+;
+ %rval = icmp ult i32 %arg2, %arg1
+ ret i1 %rval
+}
+
; Values' ranges do not overlap each other, so it can simplified to false.
define i1 @test_two_ranges2(ptr nocapture readonly %arg1, ptr nocapture readonly %arg2) {
; CHECK-LABEL: @test_two_ranges2(
@@ -163,7 +173,8 @@ define i1 @test_two_ranges2(ptr nocapture readonly %arg1, ptr nocapture readonly
; Values' ranges do not overlap each other, so it can simplified to false.
define i1 @test_two_argument_ranges(i32 range(i32 1, 6) %arg1, i32 range(i32 8, 16) %arg2) {
; CHECK-LABEL: @test_two_argument_ranges(
-; CHECK-NEXT: ret i1 false
+; CHECK-NEXT: [[RVAL:%.*]] = icmp ult i32 [[ARG2:%.*]], [[ARG1:%.*]]
+; CHECK-NEXT: ret i1 [[RVAL]]
;
%rval = icmp ult i32 %arg2, %arg1
ret i1 %rval
@@ -172,7 +183,9 @@ define i1 @test_two_argument_ranges(i32 range(i32 1, 6) %arg1, i32 range(i32 8,
; Values' ranges do not overlap each other, so it can simplified to false.
define i1 @test_one_range_and_one_argument_range(ptr nocapture readonly %arg1, i32 range(i32 8, 16) %arg2) {
; CHECK-LABEL: @test_one_range_and_one_argument_range(
-; CHECK-NEXT: ret i1 false
+; CHECK-NEXT: [[VAL1:%.*]] = load i32, ptr [[ARG1:%.*]], align 4, !range [[RNG2]]
+; CHECK-NEXT: [[RVAL:%.*]] = icmp ugt i32 [[VAL1]], [[ARG2:%.*]]
+; CHECK-NEXT: ret i1 [[RVAL]]
;
%val1 = load i32, ptr %arg1, !range !0
%rval = icmp ult i32 %arg2, %val1
@@ -182,7 +195,9 @@ define i1 @test_one_range_and_one_argument_range(ptr nocapture readonly %arg1, i
; Values' ranges do not overlap each other, so it can simplified to false.
define i1 @test_one_argument_range_and_one_range(i32 range(i32 1, 6) %arg1, ptr nocapture readonly %arg2) {
; CHECK-LABEL: @test_one_argument_range_and_one_range(
-; CHECK-NEXT: ret i1 false
+; CHECK-NEXT: [[VAL1:%.*]] = load i32, ptr [[ARG2:%.*]], align 4, !range [[RNG5]]
+; CHECK-NEXT: [[RVAL:%.*]] = icmp ult i32 [[VAL1]], [[ARG1:%.*]]
+; CHECK-NEXT: ret i1 [[RVAL]]
;
%val1 = load i32, ptr %arg2, !range !6
%rval = icmp ult i32 %val1, %arg1
@@ -200,6 +215,78 @@ define i1 @test_two_ranges3(ptr nocapture readonly %arg1, ptr nocapture readonly
ret i1 %rval
}
+declare i32 @create_range1()
+declare range(i32 8, 16) i32 @create_range2()
+declare range(i32 1, 6) i32 @create_range3()
+
+; Values' ranges overlap each other, so it can not be simplified.
+define i1 @test_two_return_attribute_ranges_not_simplified() {
+; CHECK-LABEL: @test_two_return_attribute_ranges_not_simplified(
+; CHECK-NEXT: [[ARG2:%.*]] = call range(i32 5, 10) i32 @create_range1()
+; CHECK-NEXT: [[ARG1:%.*]] = call i32 @create_range2()
+; CHECK-NEXT: [[RVAL:%.*]] = icmp ult i32 [[ARG1]], [[ARG2]]
+; CHECK-NEXT: ret i1 [[RVAL]]
+;
+ %val1 = call range(i32 5, 10) i32 @create_range1()
+ %val2 = call i32 @create_range2()
+ %rval = icmp ult i32 %val2, %val1
+ ret i1 %rval
+}
+
+; Values' ranges do not overlap each other, so it can simplified to false.
+define i1 @test_two_return_attribute_ranges_one_in_call() {
+; CHECK-LABEL: @test_two_return_attribute_ranges_one_in_call(
+; CHECK-NEXT: [[VAL1:%.*]] = call range(i32 1, 6) i32 @create_range1()
+; CHECK-NEXT: [[ARG1:%.*]] = call i32 @create_range2()
+; CHECK-NEXT: [[RVAL:%.*]] = icmp ult i32 [[ARG1]], [[VAL1]]
+; CHECK-NEXT: ret i1 [[RVAL]]
+;
+ %val1 = call range(i32 1, 6) i32 @create_range1()
+ %val2 = call i32 @create_range2()
+ %rval = icmp ult i32 %val2, %val1
+ ret i1 %rval
+}
+
+; Values' ranges do not overlap each other, so it can simplified to false.
+define i1 @test_two_return_attribute_ranges() {
+; CHECK-LABEL: @test_two_return_attribute_ranges(
+; CHECK-NEXT: [[VAL1:%.*]] = call i32 @create_range3()
+; CHECK-NEXT: [[ARG1:%.*]] = call i32 @create_range2()
+; CHECK-NEXT: [[RVAL:%.*]] = icmp ult i32 [[ARG1]], [[VAL1]]
+; CHECK-NEXT: ret i1 [[RVAL]]
+;
+ %val1 = call i32 @create_range3()
+ %val2 = call i32 @create_range2()
+ %rval = icmp ult i32 %val2, %val1
+ ret i1 %rval
+}
+
+; Values' ranges do not overlap each other, so it can simplified to false.
+define i1 @test_one_return_argument_and_one_argument_range(i32 range(i32 8, 16) %arg1) {
+; CHECK-LABEL: @test_one_return_argument_and_one_argument_range(
+; CHECK-NEXT: [[VAL1:%.*]] = call i32 @create_range3()
+; CHECK-NEXT: [[RVAL:%.*]] = icmp ugt i32 [[VAL1]], [[ARG1:%.*]]
+; CHECK-NEXT: ret i1 [[RVAL]]
+;
+ %val1 = call i32 @create_range3()
+ %rval = icmp ult i32 %arg1, %val1
+ ret i1 %rval
+}
+
+; Values' ranges do not overlap each other, so it can simplified to false.
+define i1 @test_one_range_and_one_return_argument(ptr nocapture readonly %arg1) {
+; CHECK-LABEL: @test_one_range_and_one_return_argument(
+; CHECK-NEXT: [[VAL1:%.*]] = call i32 @create_range3()
+; CHECK-NEXT: [[VAL2:%.*]] = load i32, ptr [[ARG1:%.*]], align 4, !range [[RNG5]]
+; CHECK-NEXT: [[RVAL:%.*]] = icmp ult i32 [[VAL2]], [[VAL1]]
+; CHECK-NEXT: ret i1 [[RVAL]]
+;
+ %val1 = call i32 @create_range3()
+ %val2 = load i32, ptr %arg1, !range !6
+ %rval = icmp ult i32 %val2, %val1
+ ret i1 %rval
+}
+
define i1 @ugt_zext(i1 %b, i8 %x) {
; CHECK-LABEL: @ugt_zext(
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i8 [[X:%.*]], 0
>From 38d8170ed8319318eba75073dd09c76eab6361df Mon Sep 17 00:00:00 2001
From: Andreas Jonson <andjo403 at hotmail.com>
Date: Sat, 9 Mar 2024 22:59:07 +0100
Subject: [PATCH 4/4] fixup! Use range attribute to constant fold comparisons
with constant values.
---
llvm/include/llvm/IR/Attributes.h | 5 ++++
llvm/include/llvm/IR/Function.h | 3 ++
llvm/include/llvm/IR/InstrTypes.h | 12 ++++++++
llvm/lib/Analysis/InstructionSimplify.cpp | 28 +++++++++++--------
llvm/lib/IR/Function.cpp | 4 +++
.../test/Transforms/InstCombine/icmp-range.ll | 24 +++++-----------
6 files changed, 48 insertions(+), 28 deletions(-)
diff --git a/llvm/include/llvm/IR/Attributes.h b/llvm/include/llvm/IR/Attributes.h
index 0c2a02514ba0e6..7dd8a329029a34 100644
--- a/llvm/include/llvm/IR/Attributes.h
+++ b/llvm/include/llvm/IR/Attributes.h
@@ -848,6 +848,11 @@ class AttributeList {
return getAttributeAtIndex(FunctionIndex, Kind);
}
+ /// Return the attribute for the given attribute kind for the return value.
+ Attribute getRetAttr(Attribute::AttrKind Kind) const {
+ return getAttributeAtIndex(ReturnIndex, Kind);
+ }
+
/// Return the alignment of the return value.
MaybeAlign getRetAlignment() const;
diff --git a/llvm/include/llvm/IR/Function.h b/llvm/include/llvm/IR/Function.h
index cb87a44980321a..d96d506a9b05d0 100644
--- a/llvm/include/llvm/IR/Function.h
+++ b/llvm/include/llvm/IR/Function.h
@@ -430,6 +430,9 @@ class LLVM_EXTERNAL_VISIBILITY Function : public GlobalObject,
/// Return the attribute for the given attribute kind.
Attribute getFnAttribute(StringRef Kind) const;
+ /// Return the attribute for the given attribute kind for the return value.
+ Attribute getRetAttribute(Attribute::AttrKind Kind) const;
+
/// For a string attribute \p Kind, parse attribute as an integer.
///
/// \returns \p Default if attribute is not present.
diff --git a/llvm/include/llvm/IR/InstrTypes.h b/llvm/include/llvm/IR/InstrTypes.h
index 0e81d3b391a083..fed21b992e3d10 100644
--- a/llvm/include/llvm/IR/InstrTypes.h
+++ b/llvm/include/llvm/IR/InstrTypes.h
@@ -1909,6 +1909,18 @@ class CallBase : public Instruction {
/// Determine whether the return value has the given attribute.
bool hasRetAttr(StringRef Kind) const { return hasRetAttrImpl(Kind); }
+ /// Return the attribute for the given attribute kind for the return value.
+ Attribute getRetAttr(Attribute::AttrKind Kind) const {
+ Attribute RetAttr = Attrs.getRetAttr(Kind);
+ if (RetAttr.isValid())
+ return RetAttr;
+
+ // Look at the callee, if available.
+ if (const Function *F = getCalledFunction())
+ return F->getAttributes().getRetAttr(Kind);
+ return Attribute();
+ }
+
/// Determine whether the argument or parameter has the given attribute.
bool paramHasAttr(unsigned ArgNo, Attribute::AttrKind Kind) const;
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 6a709f29db1e33..e8ecdfdeab37cb 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -3735,9 +3735,16 @@ static std::optional<ConstantRange> getRange(Value *V,
if (Instruction *I = dyn_cast<Instruction>(V))
if (MDNode *MD = IIQ.getMetadata(I, LLVMContext::MD_range))
return getConstantRangeFromMetadata(*MD);
- if (const Argument *A = dyn_cast<Argument>(V))
- if (A->hasAttribute(llvm::Attribute::Range))
- return A->getAttribute(llvm::Attribute::Range).getRange();
+
+ Attribute Range;
+ if (const Argument *A = dyn_cast<Argument>(V)) {
+ Range = A->getAttribute(llvm::Attribute::Range);
+ } else if (const CallBase *CB = dyn_cast<CallBase>(V)) {
+ Range = CB->getRetAttr(llvm::Attribute::Range);
+ }
+
+ if (Range.isValid())
+ return Range.getRange();
return std::nullopt;
}
@@ -3789,15 +3796,14 @@ static Value *simplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
// If both operands have range metadata, use the metadata
// to simplify the comparison.
- std::optional<ConstantRange> RhsCr = getRange(RHS, Q.IIQ);
- std::optional<ConstantRange> LhsCr = getRange(LHS, Q.IIQ);
- if (RhsCr && LhsCr) {
- if (LhsCr->icmp(Pred, *RhsCr))
- return ConstantInt::getTrue(RHS->getContext());
+ if (std::optional<ConstantRange> RhsCr = getRange(RHS, Q.IIQ))
+ if (std::optional<ConstantRange> LhsCr = getRange(LHS, Q.IIQ)) {
+ if (LhsCr->icmp(Pred, *RhsCr))
+ return ConstantInt::getTrue(RHS->getContext());
- if (LhsCr->icmp(CmpInst::getInversePredicate(Pred), *RhsCr))
- return ConstantInt::getFalse(RHS->getContext());
- }
+ if (LhsCr->icmp(CmpInst::getInversePredicate(Pred), *RhsCr))
+ return ConstantInt::getFalse(RHS->getContext());
+ }
// Compare of cast, for example (zext X) != 0 -> X != 0
if (isa<CastInst>(LHS) && (isa<Constant>(RHS) || isa<CastInst>(RHS))) {
diff --git a/llvm/lib/IR/Function.cpp b/llvm/lib/IR/Function.cpp
index 056e4f31981a72..d22e1c12311189 100644
--- a/llvm/lib/IR/Function.cpp
+++ b/llvm/lib/IR/Function.cpp
@@ -700,6 +700,10 @@ Attribute Function::getFnAttribute(StringRef Kind) const {
return AttributeSets.getFnAttr(Kind);
}
+Attribute Function::getRetAttribute(Attribute::AttrKind Kind) const {
+ return AttributeSets.getRetAttr(Kind);
+}
+
uint64_t Function::getFnAttributeAsParsedInteger(StringRef Name,
uint64_t Default) const {
Attribute A = getFnAttribute(Name);
diff --git a/llvm/test/Transforms/InstCombine/icmp-range.ll b/llvm/test/Transforms/InstCombine/icmp-range.ll
index 63385e989661cb..2dce8ba8e2ce2e 100644
--- a/llvm/test/Transforms/InstCombine/icmp-range.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-range.ll
@@ -173,8 +173,7 @@ define i1 @test_two_ranges2(ptr nocapture readonly %arg1, ptr nocapture readonly
; Values' ranges do not overlap each other, so it can simplified to false.
define i1 @test_two_argument_ranges(i32 range(i32 1, 6) %arg1, i32 range(i32 8, 16) %arg2) {
; CHECK-LABEL: @test_two_argument_ranges(
-; CHECK-NEXT: [[RVAL:%.*]] = icmp ult i32 [[ARG2:%.*]], [[ARG1:%.*]]
-; CHECK-NEXT: ret i1 [[RVAL]]
+; CHECK-NEXT: ret i1 false
;
%rval = icmp ult i32 %arg2, %arg1
ret i1 %rval
@@ -183,9 +182,7 @@ define i1 @test_two_argument_ranges(i32 range(i32 1, 6) %arg1, i32 range(i32 8,
; Values' ranges do not overlap each other, so it can simplified to false.
define i1 @test_one_range_and_one_argument_range(ptr nocapture readonly %arg1, i32 range(i32 8, 16) %arg2) {
; CHECK-LABEL: @test_one_range_and_one_argument_range(
-; CHECK-NEXT: [[VAL1:%.*]] = load i32, ptr [[ARG1:%.*]], align 4, !range [[RNG2]]
-; CHECK-NEXT: [[RVAL:%.*]] = icmp ugt i32 [[VAL1]], [[ARG2:%.*]]
-; CHECK-NEXT: ret i1 [[RVAL]]
+; CHECK-NEXT: ret i1 false
;
%val1 = load i32, ptr %arg1, !range !0
%rval = icmp ult i32 %arg2, %val1
@@ -195,9 +192,7 @@ define i1 @test_one_range_and_one_argument_range(ptr nocapture readonly %arg1, i
; Values' ranges do not overlap each other, so it can simplified to false.
define i1 @test_one_argument_range_and_one_range(i32 range(i32 1, 6) %arg1, ptr nocapture readonly %arg2) {
; CHECK-LABEL: @test_one_argument_range_and_one_range(
-; CHECK-NEXT: [[VAL1:%.*]] = load i32, ptr [[ARG2:%.*]], align 4, !range [[RNG5]]
-; CHECK-NEXT: [[RVAL:%.*]] = icmp ult i32 [[VAL1]], [[ARG1:%.*]]
-; CHECK-NEXT: ret i1 [[RVAL]]
+; CHECK-NEXT: ret i1 false
;
%val1 = load i32, ptr %arg2, !range !6
%rval = icmp ult i32 %val1, %arg1
@@ -238,8 +233,7 @@ define i1 @test_two_return_attribute_ranges_one_in_call() {
; CHECK-LABEL: @test_two_return_attribute_ranges_one_in_call(
; CHECK-NEXT: [[VAL1:%.*]] = call range(i32 1, 6) i32 @create_range1()
; CHECK-NEXT: [[ARG1:%.*]] = call i32 @create_range2()
-; CHECK-NEXT: [[RVAL:%.*]] = icmp ult i32 [[ARG1]], [[VAL1]]
-; CHECK-NEXT: ret i1 [[RVAL]]
+; CHECK-NEXT: ret i1 false
;
%val1 = call range(i32 1, 6) i32 @create_range1()
%val2 = call i32 @create_range2()
@@ -252,8 +246,7 @@ define i1 @test_two_return_attribute_ranges() {
; CHECK-LABEL: @test_two_return_attribute_ranges(
; CHECK-NEXT: [[VAL1:%.*]] = call i32 @create_range3()
; CHECK-NEXT: [[ARG1:%.*]] = call i32 @create_range2()
-; CHECK-NEXT: [[RVAL:%.*]] = icmp ult i32 [[ARG1]], [[VAL1]]
-; CHECK-NEXT: ret i1 [[RVAL]]
+; CHECK-NEXT: ret i1 false
;
%val1 = call i32 @create_range3()
%val2 = call i32 @create_range2()
@@ -265,8 +258,7 @@ define i1 @test_two_return_attribute_ranges() {
define i1 @test_one_return_argument_and_one_argument_range(i32 range(i32 8, 16) %arg1) {
; CHECK-LABEL: @test_one_return_argument_and_one_argument_range(
; CHECK-NEXT: [[VAL1:%.*]] = call i32 @create_range3()
-; CHECK-NEXT: [[RVAL:%.*]] = icmp ugt i32 [[VAL1]], [[ARG1:%.*]]
-; CHECK-NEXT: ret i1 [[RVAL]]
+; CHECK-NEXT: ret i1 false
;
%val1 = call i32 @create_range3()
%rval = icmp ult i32 %arg1, %val1
@@ -277,9 +269,7 @@ define i1 @test_one_return_argument_and_one_argument_range(i32 range(i32 8, 16)
define i1 @test_one_range_and_one_return_argument(ptr nocapture readonly %arg1) {
; CHECK-LABEL: @test_one_range_and_one_return_argument(
; CHECK-NEXT: [[VAL1:%.*]] = call i32 @create_range3()
-; CHECK-NEXT: [[VAL2:%.*]] = load i32, ptr [[ARG1:%.*]], align 4, !range [[RNG5]]
-; CHECK-NEXT: [[RVAL:%.*]] = icmp ult i32 [[VAL2]], [[VAL1]]
-; CHECK-NEXT: ret i1 [[RVAL]]
+; CHECK-NEXT: ret i1 false
;
%val1 = call i32 @create_range3()
%val2 = load i32, ptr %arg1, !range !6
More information about the llvm-commits
mailing list