Skip to content

Commit 4df4b36

Browse files
authored
[ConstantFPRange] Add support for fneg/fabs (#162690)
This patch adds support for fneg/fabs operations. For other bit manipulation operations (select/copysign), we don't need new APIs.
1 parent 07ca4db commit 4df4b36

File tree

3 files changed

+61
-0
lines changed

3 files changed

+61
-0
lines changed

llvm/include/llvm/IR/ConstantFPRange.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,12 @@ class [[nodiscard]] ConstantFPRange {
200200
/// with another range. The resultant range is guaranteed to include the
201201
/// elements of both sets, but may contain more.
202202
LLVM_ABI ConstantFPRange unionWith(const ConstantFPRange &CR) const;
203+
204+
/// Calculate absolute value range.
205+
LLVM_ABI ConstantFPRange abs() const;
206+
207+
/// Calculate range of negated values.
208+
LLVM_ABI ConstantFPRange negate() const;
203209
};
204210

205211
inline raw_ostream &operator<<(raw_ostream &OS, const ConstantFPRange &CR) {

llvm/lib/IR/ConstantFPRange.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,3 +391,23 @@ ConstantFPRange ConstantFPRange::unionWith(const ConstantFPRange &CR) const {
391391
return ConstantFPRange(minnum(Lower, CR.Lower), maxnum(Upper, CR.Upper),
392392
MayBeQNaN | CR.MayBeQNaN, MayBeSNaN | CR.MayBeSNaN);
393393
}
394+
395+
ConstantFPRange ConstantFPRange::abs() const {
396+
if (isNaNOnly())
397+
return *this;
398+
// Check if the range is all non-negative or all non-positive.
399+
if (Lower.isNegative() == Upper.isNegative()) {
400+
if (Lower.isNegative())
401+
return negate();
402+
return *this;
403+
}
404+
// The range contains both positive and negative values.
405+
APFloat NewLower = APFloat::getZero(getSemantics());
406+
APFloat NewUpper = maxnum(-Lower, Upper);
407+
return ConstantFPRange(std::move(NewLower), std::move(NewUpper), MayBeQNaN,
408+
MayBeSNaN);
409+
}
410+
411+
ConstantFPRange ConstantFPRange::negate() const {
412+
return ConstantFPRange(-Upper, -Lower, MayBeQNaN, MayBeSNaN);
413+
}

llvm/unittests/IR/ConstantFPRangeTest.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -767,4 +767,39 @@ TEST_F(ConstantFPRangeTest, makeExactFCmpRegion) {
767767
}
768768
}
769769

770+
TEST_F(ConstantFPRangeTest, abs) {
771+
EXPECT_EQ(Full.abs(),
772+
ConstantFPRange(APFloat::getZero(Sem, /*Negative=*/false),
773+
APFloat::getInf(Sem, /*Negative=*/false),
774+
/*MayBeQNaN=*/true,
775+
/*MayBeSNaN=*/true));
776+
EXPECT_EQ(Empty.abs(), Empty);
777+
EXPECT_EQ(Zero.abs(), PosZero);
778+
EXPECT_EQ(PosInf.abs(), PosInf);
779+
EXPECT_EQ(NegInf.abs(), PosInf);
780+
EXPECT_EQ(Some.abs(), SomePos);
781+
EXPECT_EQ(SomeNeg.abs(), SomePos);
782+
EXPECT_EQ(NaN.abs(), NaN);
783+
EXPECT_EQ(ConstantFPRange::getNonNaN(APFloat(-2.0), APFloat(3.0)).abs(),
784+
ConstantFPRange::getNonNaN(APFloat(0.0), APFloat(3.0)));
785+
EXPECT_EQ(ConstantFPRange::getNonNaN(APFloat(-3.0), APFloat(2.0)).abs(),
786+
ConstantFPRange::getNonNaN(APFloat(0.0), APFloat(3.0)));
787+
}
788+
789+
TEST_F(ConstantFPRangeTest, negate) {
790+
EXPECT_EQ(Full.negate(), Full);
791+
EXPECT_EQ(Empty.negate(), Empty);
792+
EXPECT_EQ(Zero.negate(), Zero);
793+
EXPECT_EQ(PosInf.negate(), NegInf);
794+
EXPECT_EQ(NegInf.negate(), PosInf);
795+
EXPECT_EQ(Some.negate(), Some);
796+
EXPECT_EQ(SomePos.negate(), SomeNeg);
797+
EXPECT_EQ(SomeNeg.negate(), SomePos);
798+
EXPECT_EQ(NaN.negate(), NaN);
799+
EXPECT_EQ(ConstantFPRange::getNonNaN(APFloat(-2.0), APFloat(3.0)).negate(),
800+
ConstantFPRange::getNonNaN(APFloat(-3.0), APFloat(2.0)));
801+
EXPECT_EQ(ConstantFPRange::getNonNaN(APFloat(-3.0), APFloat(2.0)).negate(),
802+
ConstantFPRange::getNonNaN(APFloat(-2.0), APFloat(3.0)));
803+
}
804+
770805
} // anonymous namespace

0 commit comments

Comments
 (0)