[llvm] [KnownFPClass] Unify and refine interested classes for KnownFPClass::log (PR #219751)
via llvm-commits
llvm-commits at lists.llvm.org
Sat Aug 29 19:58:22 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-analysis
Author: ZERICO2005
<details>
<summary>Changes</summary>
Previously, `ValueTracking` and `GISelValueTracking` only called `KnownFPClass::log` when the requested classes included NaN or infinity. As a result, narrowly interested queries could miss unconditional deductions, for example, `log(x)` is never subnormal or negative zero. (With the exception of `PPCDoubleDouble` https://github.com/llvm/llvm-project/issues/217658).
This change makes the interested-class handling consistent between `ValueTracking` and `GISelValueTracking`. The source is queried only when its classes are needed, but `KnownFPClass::log` is always called so its unconditional deductions are preserved.
Future work:
- Fixing `KnownFPClass::log` for `PPCDoubleDouble`.
AI disclosure:
I used OpenAI Codex (sol 5.6) to help write the unit tests, which I reviewed and ran locally.
---
Full diff: https://github.com/llvm/llvm-project/pull/219751.diff
4 Files Affected:
- (modified) llvm/lib/Analysis/ValueTracking.cpp (+28-19)
- (modified) llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp (+21-10)
- (modified) llvm/unittests/Analysis/ValueTrackingTest.cpp (+12)
- (modified) llvm/unittests/CodeGen/GlobalISel/KnownFPClassTest.cpp (+24)
``````````diff
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index e028768f3a487..cc982958bc2bc 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -5554,29 +5554,38 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
case Intrinsic::experimental_constrained_log10:
case Intrinsic::experimental_constrained_log2:
case Intrinsic::amdgcn_log: {
- Type *EltTy = II->getType()->getScalarType();
+ FPClassTest InterestedSrcs = fcNone;
- // log(+inf) -> +inf
- // log([+-]0.0) -> -inf
- // log(-inf) -> nan
- // log(-x) -> nan
- if ((InterestedClasses & (fcNan | fcInf)) != fcNone) {
- FPClassTest InterestedSrcs = InterestedClasses;
- if ((InterestedClasses & fcNegInf) != fcNone)
- InterestedSrcs |= fcZero | fcSubnormal;
- if ((InterestedClasses & fcNan) != fcNone)
- InterestedSrcs |= fcNan | fcNegative;
+ // log(negative) produces NaN.
+ if ((InterestedClasses & fcNan) != fcNone)
+ InterestedSrcs |= fcNan | fcNegative;
- KnownFPClass KnownSrc;
- computeKnownFPClass(II->getArgOperand(0), DemandedElts, InterestedSrcs,
- KnownSrc, Q, Depth + 1);
+ // log(logical-zero) produces negative infinity.
+ if ((InterestedClasses & fcNegInf) != fcNone)
+ InterestedSrcs |= fcZero | fcSubnormal;
- const Function *F = II->getFunction();
- DenormalMode Mode = F ? F->getDenormalMode(EltTy->getFltSemantics())
- : DenormalMode::getDynamic();
- Known = KnownFPClass::log(KnownSrc, Mode);
- }
+ // log(x) < -0.0 if x < +1.0
+ if ((InterestedClasses & fcNegNormal) != fcNone)
+ InterestedSrcs |= fcPosSubnormal | fcPosNormal;
+
+ // log(x) >= +0.0 if x >= +1.0
+ if ((InterestedClasses & (fcPosZero | fcPosNormal)) != fcNone)
+ InterestedSrcs |= fcPosNormal;
+
+ // log(x) is positive infinity iff x is positive infinity.
+ if ((InterestedClasses & fcPosInf) != fcNone)
+ InterestedSrcs |= fcPosInf;
+ KnownFPClass KnownSrc;
+ if (InterestedSrcs != fcNone)
+ computeKnownFPClass(II->getArgOperand(0), DemandedElts, InterestedSrcs,
+ KnownSrc, Q, Depth + 1);
+ const Function *F = II->getFunction();
+ DenormalMode Mode =
+ F ? F->getDenormalMode(
+ II->getType()->getScalarType()->getFltSemantics())
+ : DenormalMode::getDynamic();
+ Known = KnownFPClass::log(KnownSrc, Mode);
break;
}
case Intrinsic::pow: {
diff --git a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
index 8dbb0c5f04ee2..df7141574748e 100644
--- a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
@@ -1618,22 +1618,33 @@ void GISelValueTracking::computeKnownFPClass(Register R,
case TargetOpcode::G_FLOG:
case TargetOpcode::G_FLOG2:
case TargetOpcode::G_FLOG10: {
- // log(+inf) -> +inf
- // log([+-]0.0) -> -inf
- // log(-inf) -> nan
- // log(-x) -> nan
- if ((InterestedClasses & (fcNan | fcInf)) == fcNone)
- break;
+ FPClassTest InterestedSrcs = fcNone;
- FPClassTest InterestedSrcs = InterestedClasses;
- if ((InterestedClasses & fcNegInf) != fcNone)
- InterestedSrcs |= fcZero | fcSubnormal;
+ // log(negative) produces NaN.
if ((InterestedClasses & fcNan) != fcNone)
InterestedSrcs |= fcNan | fcNegative;
+ // log(logical-zero) produces negative infinity.
+ if ((InterestedClasses & fcNegInf) != fcNone)
+ InterestedSrcs |= fcZero | fcSubnormal;
+
+ // log(x) < -0.0 if x < +1.0
+ if ((InterestedClasses & fcNegNormal) != fcNone)
+ InterestedSrcs |= fcPosSubnormal | fcPosNormal;
+
+ // log(x) >= +0.0 if x >= +1.0
+ if ((InterestedClasses & (fcPosZero | fcPosNormal)) != fcNone)
+ InterestedSrcs |= fcPosNormal;
+
+ // log(x) is positive infinity iff x is positive infinity.
+ if ((InterestedClasses & fcPosInf) != fcNone)
+ InterestedSrcs |= fcPosInf;
+
Register Val = MI.getOperand(1).getReg();
KnownFPClass KnownSrc;
- computeKnownFPClass(Val, DemandedElts, InterestedSrcs, KnownSrc, Depth + 1);
+ if (InterestedSrcs != fcNone)
+ computeKnownFPClass(Val, DemandedElts, InterestedSrcs, KnownSrc,
+ Depth + 1);
LLT Ty = MRI.getType(Val).getScalarType();
const fltSemantics &FltSem = getFltSemanticForLLT(Ty);
diff --git a/llvm/unittests/Analysis/ValueTrackingTest.cpp b/llvm/unittests/Analysis/ValueTrackingTest.cpp
index a969b8fdd866f..95a9cf496a4e4 100644
--- a/llvm/unittests/Analysis/ValueTrackingTest.cpp
+++ b/llvm/unittests/Analysis/ValueTrackingTest.cpp
@@ -1760,6 +1760,18 @@ TEST_F(ComputeKnownFPClassTest, CopySignNInfSrc0_PosSign) {
expectKnownFPClass(fcPosZero | fcPosNormal | fcNan, false);
}
+TEST_F(ComputeKnownFPClassTest, LogDeduceSubnormalOrNegativeZero) {
+ parseAssembly("declare float @llvm.log.f32(float)\n"
+ "define float @test(float %x) {\n"
+ " %A = call float @llvm.log.f32(float %x)\n"
+ " ret float %A\n"
+ "}\n");
+
+ KnownFPClass Known =
+ computeKnownFPClass(A, M->getDataLayout(), fcNegZero | fcSubnormal);
+ EXPECT_EQ(~(fcNegZero | fcSubnormal), Known.KnownFPClasses);
+}
+
TEST_F(ComputeKnownFPClassTest, UIToFP) {
parseAssembly(
"define float @test(i32 %arg0, i16 %arg1) {\n"
diff --git a/llvm/unittests/CodeGen/GlobalISel/KnownFPClassTest.cpp b/llvm/unittests/CodeGen/GlobalISel/KnownFPClassTest.cpp
index bdd2b3faf6d5c..7114737fdff79 100644
--- a/llvm/unittests/CodeGen/GlobalISel/KnownFPClassTest.cpp
+++ b/llvm/unittests/CodeGen/GlobalISel/KnownFPClassTest.cpp
@@ -878,6 +878,30 @@ TEST_F(AArch64GISelMITest, TestFPClassFLogNeg) {
EXPECT_EQ(std::nullopt, Known.SignBit);
}
+TEST_F(AArch64GISelMITest, TestFPClassFLogDeduceSubnormalOrNegativeZero) {
+ StringRef MIRString = R"(
+ %ptr:_(p0) = G_IMPLICIT_DEF
+ %val:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
+ %flog:_(s32) = G_FLOG %val
+ %copy_flog:_(s32) = COPY %flog
+)";
+
+ setUp(MIRString);
+ if (!TM)
+ GTEST_SKIP();
+
+ Register CopyReg = Copies[Copies.size() - 1];
+ MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
+ Register SrcReg = FinalCopy->getOperand(1).getReg();
+
+ GISelValueTracking Info(*MF);
+ KnownFPClass Known =
+ Info.computeKnownFPClass(SrcReg, fcNegZero | fcSubnormal);
+
+ EXPECT_EQ(~(fcNegZero | fcSubnormal), Known.KnownFPClasses);
+ EXPECT_EQ(std::nullopt, Known.SignBit);
+}
+
TEST_F(AArch64GISelMITest, TestFPClassFLogPosZero) {
StringRef MIRString = R"(
%val:_(s32) = G_FCONSTANT float 0.0
``````````
</details>
https://github.com/llvm/llvm-project/pull/219751
More information about the llvm-commits
mailing list