Skip to content

Commit 89736bb

Browse files
committed
[ConstantFPRange] Add rounding mode parameter
1 parent cc0000b commit 89736bb

File tree

3 files changed

+83
-7
lines changed

3 files changed

+83
-7
lines changed

llvm/include/llvm/IR/ConstantFPRange.h

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,8 +217,27 @@ class [[nodiscard]] ConstantFPRange {
217217
/// range of operands/results.
218218
LLVM_ABI ConstantFPRange getWithoutInf() const;
219219

220-
/// Return a new range in the specified format.
221-
LLVM_ABI ConstantFPRange cast(const fltSemantics &DstSem) const;
220+
/// Calculate absolute value range.
221+
LLVM_ABI ConstantFPRange abs() const;
222+
223+
/// Calculate range of negated values.
224+
LLVM_ABI ConstantFPRange negate() const;
225+
226+
/// Get the range without NaNs. It is useful when we apply nnan flag to range
227+
/// of operands/results.
228+
ConstantFPRange getWithoutNaN() const {
229+
return ConstantFPRange(Lower, Upper, false, false);
230+
}
231+
232+
/// Get the range without infinities. It is useful when we apply ninf flag to
233+
/// range of operands/results.
234+
LLVM_ABI ConstantFPRange getWithoutInf() const;
235+
236+
/// Return a new range in the specified format with the specified rounding
237+
/// mode.
238+
LLVM_ABI ConstantFPRange
239+
cast(const fltSemantics &DstSem,
240+
APFloat::roundingMode RM = APFloat::rmNearestTiesToEven) const;
222241
};
223242

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

llvm/lib/IR/ConstantFPRange.cpp

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,8 @@ std::optional<bool> ConstantFPRange::getSignBit() const {
326326
}
327327

328328
bool ConstantFPRange::operator==(const ConstantFPRange &CR) const {
329+
assert(&getSemantics() == &CR.getSemantics() &&
330+
"Should only use the same semantics");
329331
if (MayBeSNaN != CR.MayBeSNaN || MayBeQNaN != CR.MayBeQNaN)
330332
return false;
331333
return Lower.bitwiseIsEqual(CR.Lower) && Upper.bitwiseIsEqual(CR.Upper);
@@ -426,17 +428,50 @@ ConstantFPRange ConstantFPRange::getWithoutInf() const {
426428
MayBeSNaN);
427429
}
428430

429-
ConstantFPRange ConstantFPRange::cast(const fltSemantics &DstSem) const {
431+
ConstantFPRange ConstantFPRange::abs() const {
432+
if (isNaNOnly())
433+
return *this;
434+
// Check if the range is all non-negative or all non-positive.
435+
if (Lower.isNegative() == Upper.isNegative()) {
436+
if (Lower.isNegative())
437+
return negate();
438+
return *this;
439+
}
440+
// The range contains both positive and negative values.
441+
APFloat NewLower = APFloat::getZero(getSemantics());
442+
APFloat NewUpper = maxnum(-Lower, Upper);
443+
return ConstantFPRange(std::move(NewLower), std::move(NewUpper), MayBeQNaN,
444+
MayBeSNaN);
445+
}
446+
447+
ConstantFPRange ConstantFPRange::negate() const {
448+
return ConstantFPRange(-Upper, -Lower, MayBeQNaN, MayBeSNaN);
449+
}
450+
451+
ConstantFPRange ConstantFPRange::getWithoutInf() const {
452+
if (isNaNOnly())
453+
return *this;
454+
APFloat NewLower = Lower;
455+
APFloat NewUpper = Upper;
456+
if (Lower.isNegInfinity())
457+
NewLower = APFloat::getLargest(getSemantics(), /*Negative=*/true);
458+
if (Upper.isPosInfinity())
459+
NewUpper = APFloat::getLargest(getSemantics(), /*Negative=*/false);
460+
canonicalizeRange(NewLower, NewUpper);
461+
return ConstantFPRange(std::move(NewLower), std::move(NewUpper), MayBeQNaN,
462+
MayBeSNaN);
463+
}
464+
465+
ConstantFPRange ConstantFPRange::cast(const fltSemantics &DstSem,
466+
APFloat::roundingMode RM) const {
430467
bool LosesInfo;
431468
APFloat NewLower = Lower;
432469
APFloat NewUpper = Upper;
433470
// For conservative, return full range if conversion is invalid.
434-
if (NewLower.convert(DstSem, APFloat::rmNearestTiesToEven, &LosesInfo) ==
435-
APFloat::opInvalidOp ||
471+
if (NewLower.convert(DstSem, RM, &LosesInfo) == APFloat::opInvalidOp ||
436472
NewLower.isNaN())
437473
return getFull(DstSem);
438-
if (NewUpper.convert(DstSem, APFloat::rmNearestTiesToEven, &LosesInfo) ==
439-
APFloat::opInvalidOp ||
474+
if (NewUpper.convert(DstSem, RM, &LosesInfo) == APFloat::opInvalidOp ||
440475
NewUpper.isNaN())
441476
return getFull(DstSem);
442477
return ConstantFPRange(std::move(NewLower), std::move(NewUpper),

llvm/unittests/IR/ConstantFPRangeTest.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -879,6 +879,28 @@ TEST_F(ConstantFPRangeTest, cast) {
879879
APFloat::getInf(Sem, /*Negative=*/false))
880880
.cast(F8NanOnlySem),
881881
ConstantFPRange::getFull(F8NanOnlySem));
882+
// other rounding modes
883+
EXPECT_EQ(
884+
ConstantFPRange::getNonNaN(APFloat::getSmallest(Sem, /*Negative=*/true),
885+
APFloat::getSmallest(Sem, /*Negative=*/false))
886+
.cast(F32Sem, APFloat::rmTowardNegative),
887+
ConstantFPRange::getNonNaN(
888+
APFloat::getSmallest(F32Sem, /*Negative=*/true),
889+
APFloat::getZero(F32Sem, /*Negative=*/false)));
890+
EXPECT_EQ(
891+
ConstantFPRange::getNonNaN(APFloat::getSmallest(Sem, /*Negative=*/true),
892+
APFloat::getSmallest(Sem, /*Negative=*/false))
893+
.cast(F32Sem, APFloat::rmTowardPositive),
894+
ConstantFPRange::getNonNaN(
895+
APFloat::getZero(F32Sem, /*Negative=*/true),
896+
APFloat::getSmallest(F32Sem, /*Negative=*/false)));
897+
EXPECT_EQ(
898+
ConstantFPRange::getNonNaN(
899+
APFloat::getSmallestNormalized(Sem, /*Negative=*/true),
900+
APFloat::getSmallestNormalized(Sem, /*Negative=*/false))
901+
.cast(F32Sem, APFloat::rmTowardZero),
902+
ConstantFPRange::getNonNaN(APFloat::getZero(F32Sem, /*Negative=*/true),
903+
APFloat::getZero(F32Sem, /*Negative=*/false)));
882904

883905
EnumerateValuesInConstantFPRange(
884906
ConstantFPRange::getFull(APFloat::Float8E4M3()),

0 commit comments

Comments
 (0)