Skip to content

Commit 6aca400

Browse files
committed
ValueTracking: Handle no-nan check for computeKnownFPClass for fadd/fsub
Copy the logic from isKnownNeverNaN for fadd/fsub.
1 parent eb8e43a commit 6aca400

File tree

3 files changed

+66
-1
lines changed

3 files changed

+66
-1
lines changed

llvm/include/llvm/Analysis/ValueTracking.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,17 @@ struct KnownFPClass {
238238
/// definitely set or false if the sign bit is definitely unset.
239239
std::optional<bool> SignBit;
240240

241+
242+
/// Return true if it's known this can never be a nan.
243+
bool isKnownNeverNaN() const {
244+
return (KnownFPClasses & fcNan) == fcNone;
245+
}
246+
247+
/// Return true if it's known this can never be an infinity.
248+
bool isKnownNeverInfinity() const {
249+
return (KnownFPClasses & fcInf) == fcNone;
250+
}
251+
241252
KnownFPClass &operator|=(const KnownFPClass &RHS) {
242253
KnownFPClasses = KnownFPClasses | RHS.KnownFPClasses;
243254

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4439,6 +4439,25 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
44394439

44404440
break;
44414441
}
4442+
case Instruction::FAdd:
4443+
case Instruction::FSub: {
4444+
KnownFPClass KnownLHS, KnownRHS;
4445+
computeKnownFPClass(Op->getOperand(1), DemandedElts, fcNan | fcInf,
4446+
KnownRHS, Depth + 1, Q, TLI);
4447+
if (KnownRHS.isKnownNeverNaN()) {
4448+
// RHS is canonically cheaper to compute. Skip inspecting the LHS if
4449+
// there's no point.
4450+
computeKnownFPClass(Op->getOperand(0), DemandedElts, fcNan | fcInf,
4451+
KnownLHS, Depth + 1, Q, TLI);
4452+
// Adding positive and negative infinity produces NaN.
4453+
// TODO: Check sign of infinities.
4454+
if (KnownLHS.isKnownNeverNaN() &&
4455+
(KnownLHS.isKnownNeverInfinity() || KnownRHS.isKnownNeverInfinity()))
4456+
Known.knownNot(fcNan);
4457+
}
4458+
4459+
break;
4460+
}
44424461
case Instruction::SIToFP:
44434462
case Instruction::UIToFP: {
44444463
// Cannot produce nan

llvm/unittests/Analysis/ValueTrackingTest.cpp

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ class ValueTrackingTest : public testing::Test {
7171
A2 = findInstructionByNameOrNull(F, "A2");
7272
A3 = findInstructionByNameOrNull(F, "A3");
7373
A4 = findInstructionByNameOrNull(F, "A4");
74+
A5 = findInstructionByNameOrNull(F, "A5");
7475

7576
CxtI = findInstructionByNameOrNull(F, "CxtI");
7677
CxtI2 = findInstructionByNameOrNull(F, "CxtI2");
@@ -82,7 +83,7 @@ class ValueTrackingTest : public testing::Test {
8283
Function *F = nullptr;
8384
Instruction *A = nullptr;
8485
// Instructions (optional)
85-
Instruction *A2 = nullptr, *A3 = nullptr, *A4 = nullptr;
86+
Instruction *A2 = nullptr, *A3 = nullptr, *A4 = nullptr, *A5 = nullptr;
8687

8788
// Context instructions (optional)
8889
Instruction *CxtI = nullptr, *CxtI2 = nullptr, *CxtI3 = nullptr;
@@ -1540,6 +1541,40 @@ TEST_F(ComputeKnownFPClassTest, SIToFP) {
15401541
expectKnownFPClass(~fcNan, std::nullopt, A3);
15411542
}
15421543

1544+
TEST_F(ComputeKnownFPClassTest, FAdd) {
1545+
parseAssembly(
1546+
"define float @test(float nofpclass(nan inf) %nnan.ninf, float nofpclass(nan) %nnan, float nofpclass(qnan) %no.qnan, float %unknown) {\n"
1547+
" %A = fadd float %nnan, %nnan.ninf"
1548+
" %A2 = fadd float %nnan.ninf, %nnan"
1549+
" %A3 = fadd float %nnan.ninf, %unknown"
1550+
" %A4 = fadd float %nnan.ninf, %no.qnan"
1551+
" %A5 = fadd float %nnan, %nnan"
1552+
" ret float %A\n"
1553+
"}\n");
1554+
expectKnownFPClass(fcFinite | fcInf, std::nullopt, A);
1555+
expectKnownFPClass(fcFinite | fcInf, std::nullopt, A2);
1556+
expectKnownFPClass(fcAllFlags, std::nullopt, A3);
1557+
expectKnownFPClass(fcAllFlags, std::nullopt, A4);
1558+
expectKnownFPClass(fcAllFlags, std::nullopt, A5);
1559+
}
1560+
1561+
TEST_F(ComputeKnownFPClassTest, FSub) {
1562+
parseAssembly(
1563+
"define float @test(float nofpclass(nan inf) %nnan.ninf, float nofpclass(nan) %nnan, float nofpclass(qnan) %no.qnan, float %unknown) {\n"
1564+
" %A = fsub float %nnan, %nnan.ninf"
1565+
" %A2 = fsub float %nnan.ninf, %nnan"
1566+
" %A3 = fsub float %nnan.ninf, %unknown"
1567+
" %A4 = fsub float %nnan.ninf, %no.qnan"
1568+
" %A5 = fsub float %nnan, %nnan"
1569+
" ret float %A\n"
1570+
"}\n");
1571+
expectKnownFPClass(fcFinite | fcInf, std::nullopt, A);
1572+
expectKnownFPClass(fcFinite | fcInf, std::nullopt, A2);
1573+
expectKnownFPClass(fcAllFlags, std::nullopt, A3);
1574+
expectKnownFPClass(fcAllFlags, std::nullopt, A4);
1575+
expectKnownFPClass(fcAllFlags, std::nullopt, A5);
1576+
}
1577+
15431578
TEST_F(ValueTrackingTest, isNonZeroRecurrence) {
15441579
parseAssembly(R"(
15451580
define i1 @test(i8 %n, i8 %r) {

0 commit comments

Comments
 (0)