Skip to content

[llvm][GISel] Use computeKnownFPClass #141484

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions llvm/include/llvm/CodeGen/GlobalISel/Utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -346,11 +346,12 @@ isKnownToBeAPowerOfTwo(Register Val, const MachineRegisterInfo &MRI,
/// Returns true if \p Val can be assumed to never be a NaN. If \p SNaN is true,
/// this returns if \p Val can be assumed to never be a signaling NaN.
LLVM_ABI bool isKnownNeverNaN(Register Val, const MachineRegisterInfo &MRI,
bool SNaN = false);
GISelValueTracking *ValueTracking, bool SNaN = false);

/// Returns true if \p Val can be assumed to never be a signaling NaN.
inline bool isKnownNeverSNaN(Register Val, const MachineRegisterInfo &MRI) {
return isKnownNeverNaN(Val, MRI, true);
inline bool isKnownNeverSNaN(Register Val, const MachineRegisterInfo &MRI,
GISelValueTracking *ValueTracking) {
return isKnownNeverNaN(Val, MRI, ValueTracking, true);
}

LLVM_ABI Align inferAlignFromPtrInfo(MachineFunction &MF,
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6519,8 +6519,8 @@ unsigned CombinerHelper::getFPMinMaxOpcForSelect(
CombinerHelper::SelectPatternNaNBehaviour
CombinerHelper::computeRetValAgainstNaN(Register LHS, Register RHS,
bool IsOrderedComparison) const {
bool LHSSafe = isKnownNeverNaN(LHS, MRI);
bool RHSSafe = isKnownNeverNaN(RHS, MRI);
bool LHSSafe = isKnownNeverNaN(LHS, MRI, VT);
bool RHSSafe = isKnownNeverNaN(RHS, MRI, VT);
// Completely unsafe.
if (!LHSSafe && !RHSSafe)
return SelectPatternNaNBehaviour::NOT_APPLICABLE;
Expand Down
145 changes: 141 additions & 4 deletions llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -937,8 +937,6 @@ void GISelValueTracking::computeKnownFPClass(Register R,

if (KnownSrc.isKnownNeverPosInfinity())
Known.knownNot(fcPosInf);
if (KnownSrc.isKnownNever(fcSNan))
Known.knownNot(fcSNan);

// Any negative value besides -0 returns a nan.
if (KnownSrc.isKnownNeverNaN() && KnownSrc.cannotBeOrderedLessThanZero())
Expand All @@ -961,25 +959,27 @@ void GISelValueTracking::computeKnownFPClass(Register R,
}
case TargetOpcode::G_FSIN:
case TargetOpcode::G_FCOS:
case TargetOpcode::G_FTAN:
case TargetOpcode::G_FSINCOS: {
// Return NaN on infinite inputs.
Register Val = MI.getOperand(1).getReg();
KnownFPClass KnownSrc;

computeKnownFPClass(Val, DemandedElts, InterestedClasses, KnownSrc,
Depth + 1);

Known.knownNot(fcInf);

if (KnownSrc.isKnownNeverNaN() && KnownSrc.isKnownNeverInfinity())
Known.knownNot(fcNan);
break;
}
case TargetOpcode::G_FMAXNUM_IEEE:
case TargetOpcode::G_FMINNUM_IEEE:
case TargetOpcode::G_FMAXNUM:
case TargetOpcode::G_FMINNUM:
case TargetOpcode::G_FMINNUM_IEEE:
case TargetOpcode::G_FMAXIMUM:
case TargetOpcode::G_FMINIMUM:
case TargetOpcode::G_FMAXNUM_IEEE:
case TargetOpcode::G_FMAXIMUMNUM:
case TargetOpcode::G_FMINIMUMNUM: {
Register LHS = MI.getOperand(1).getReg();
Expand All @@ -994,13 +994,23 @@ void GISelValueTracking::computeKnownFPClass(Register R,
bool NeverNaN = KnownLHS.isKnownNeverNaN() || KnownRHS.isKnownNeverNaN();
Known = KnownLHS | KnownRHS;

if (Opcode == TargetOpcode::G_FMAXNUM_IEEE ||
Opcode == TargetOpcode::G_FMINNUM_IEEE)
Known.knownNot(fcSNan);

// If either operand is not NaN, the result is not NaN.
if (NeverNaN && (Opcode == TargetOpcode::G_FMINNUM ||
Opcode == TargetOpcode::G_FMAXNUM ||
Opcode == TargetOpcode::G_FMINIMUMNUM ||
Opcode == TargetOpcode::G_FMAXIMUMNUM))
Known.knownNot(fcNan);

if ((Opcode == TargetOpcode::G_FMAXNUM_IEEE ||
Opcode == TargetOpcode::G_FMINNUM_IEEE) &&
((KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNever(fcSNan)) ||
(KnownLHS.isKnownNever(fcSNan) && KnownRHS.isKnownNeverNaN())))
Known.knownNot(fcNan);

if (Opcode == TargetOpcode::G_FMAXNUM ||
Opcode == TargetOpcode::G_FMAXIMUMNUM ||
Opcode == TargetOpcode::G_FMAXNUM_IEEE) {
Expand Down Expand Up @@ -1089,6 +1099,7 @@ void GISelValueTracking::computeKnownFPClass(Register R,
case TargetOpcode::G_FCANONICALIZE: {
Register Val = MI.getOperand(1).getReg();
KnownFPClass KnownSrc;

computeKnownFPClass(Val, DemandedElts, InterestedClasses, KnownSrc,
Depth + 1);

Expand Down Expand Up @@ -1190,6 +1201,8 @@ void GISelValueTracking::computeKnownFPClass(Register R,
if (KnownSrc.isKnownNeverNaN()) {
Known.knownNot(fcNan);
Known.signBitMustBeZero();
} else {
Known.knownNot(fcSNan);
}

break;
Expand Down Expand Up @@ -1300,6 +1313,7 @@ void GISelValueTracking::computeKnownFPClass(Register R,
Register LHS = MI.getOperand(1).getReg();
Register RHS = MI.getOperand(2).getReg();
KnownFPClass KnownLHS, KnownRHS;

bool WantNegative =
(Opcode == TargetOpcode::G_FADD ||
Opcode == TargetOpcode::G_STRICT_FADD) &&
Expand Down Expand Up @@ -1364,6 +1378,7 @@ void GISelValueTracking::computeKnownFPClass(Register R,
case TargetOpcode::G_STRICT_FMUL: {
Register LHS = MI.getOperand(1).getReg();
Register RHS = MI.getOperand(2).getReg();

// X * X is always non-negative or a NaN.
if (LHS == RHS)
Known.knownNot(fcNegative);
Expand Down Expand Up @@ -1494,6 +1509,7 @@ void GISelValueTracking::computeKnownFPClass(Register R,
Register Src = MI.getOperand(1).getReg();
// Infinity, nan and zero propagate from source.
computeKnownFPClass(R, DemandedElts, InterestedClasses, Known, Depth + 1);
Known.knownNot(fcSNan);

LLT DstTy = MRI.getType(Dst).getScalarType();
const fltSemantics &DstSem = getFltSemanticForLLT(DstTy);
Expand All @@ -1517,6 +1533,7 @@ void GISelValueTracking::computeKnownFPClass(Register R,
case TargetOpcode::G_FPTRUNC: {
computeKnownFPClassForFPTrunc(MI, DemandedElts, InterestedClasses, Known,
Depth);
Known.knownNot(fcSNan);
break;
}
case TargetOpcode::G_SITOFP:
Expand Down Expand Up @@ -1698,6 +1715,126 @@ void GISelValueTracking::computeKnownFPClass(Register R,
computeKnownFPClass(Src, DemandedElts, InterestedClasses, Known, Depth + 1);
break;
}
case TargetOpcode::G_FATAN: {
Register Val = MI.getOperand(1).getReg();
KnownFPClass KnownSrc;

computeKnownFPClass(Val, DemandedElts, InterestedClasses, KnownSrc,
Depth + 1);

if (KnownSrc.isKnownAlways(fcInf))
Known.KnownFPClasses = fcNan;

break;
}
case TargetOpcode::G_FATAN2: {
Register LHS = MI.getOperand(1).getReg();
Register RHS = MI.getOperand(2).getReg();
KnownFPClass KnownLHS;
KnownFPClass KnownRHS;

computeKnownFPClass(LHS, DemandedElts, InterestedClasses, KnownLHS,
Depth + 1);

computeKnownFPClass(RHS, DemandedElts, InterestedClasses, KnownRHS,
Depth + 1);

if (!KnownRHS.isKnownNeverNaN() || !KnownRHS.isKnownNeverNaN())
break;

if (KnownLHS.isKnownAlways(fcZero)) {
// atan2(+-0, −0) -> +-pi
// atan2(+-0, x) -> +-pi for x < 0
if (KnownRHS.isKnownAlways(fcNegFinite)) {
Known.KnownFPClasses = fcFinite;
break;
}

// atan2(+-0, +0) -> +-0
// atan2(+-0, x) -> +-0 for x > 0
if (KnownRHS.isKnownAlways(fcPosFinite)) {
Known.KnownFPClasses = fcZero;
break;
}
}

if (KnownRHS.isKnownAlways(fcZero)) {
// atan2(y, +-0) -> -pi/2 for y < 0
if (KnownLHS.isKnownNeverZero() && KnownLHS.isKnownAlways(fcNegFinite)) {
Known.KnownFPClasses = fcNegFinite;
break;
}

// atan2(y, +-0) -> +pi/2 for y > 0
if (KnownLHS.isKnownNeverZero() && KnownLHS.isKnownAlways(fcPosFinite)) {
Known.KnownFPClasses = fcPosFinite;
break;
}
}

if (KnownLHS.isKnownAlways(fcPosFinite) && KnownLHS.isKnownNeverZero()) {
// atan2(+-y, -inf) -> +-pi for finite y > 0
if (KnownRHS.isKnownAlways(fcNegInf)) {
Known.KnownFPClasses = fcFinite;
break;
}

// atan2(+-y, +inf) -> +-0 for finite y > 0
if (KnownRHS.isKnownAlways(fcPosInf)) {
Known.KnownFPClasses = fcZero;
break;
}
}

if (KnownLHS.isKnownAlways(fcInf)) {
// atan2(+-inf, x) -> +-pi/2 for finite x
// atan2(+-inf, -inf) -> +-3pi/4
// atan2(+-inf, +inf) -> +-pi/4
Known.KnownFPClasses = fcFinite;
break;
}

break;
}
case TargetOpcode::G_FCOSH: {
Register Val = MI.getOperand(1).getReg();
KnownFPClass KnownSrc;

computeKnownFPClass(Val, DemandedElts, InterestedClasses, KnownSrc,
Depth + 1);

// cosh(+-inf) -> +inf
if (KnownSrc.isKnownAlways(fcInf))
Known.KnownFPClasses = fcPosInf;

break;
}
case TargetOpcode::G_FSINH: {
Register Val = MI.getOperand(1).getReg();
KnownFPClass KnownSrc;

computeKnownFPClass(Val, DemandedElts, InterestedClasses, KnownSrc,
Depth + 1);

// sinh(±∞) is ±∞
if (KnownSrc.isKnownAlways(fcInf))
Known.KnownFPClasses = fcInf;

break;
}
case TargetOpcode::G_FTANH: {
Register Val = MI.getOperand(1).getReg();
KnownFPClass KnownSrc;

computeKnownFPClass(Val, DemandedElts, InterestedClasses, KnownSrc,
Depth + 1);

// tanh(+-inf) is +-1
if (KnownSrc.isKnownAlways(fcInf))
Known.KnownFPClasses = fcFinite;

break;
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8179,10 +8179,10 @@ LegalizerHelper::lowerFMinNumMaxNum(MachineInstr &MI) {
// Note this must be done here, and not as an optimization combine in the
// absence of a dedicate quiet-snan instruction as we're using an
// omni-purpose G_FCANONICALIZE.
if (!isKnownNeverSNaN(Src0, MRI))
if (!isKnownNeverSNaN(Src0, MRI, VT))
Src0 = MIRBuilder.buildFCanonicalize(Ty, Src0, MI.getFlags()).getReg(0);

if (!isKnownNeverSNaN(Src1, MRI))
if (!isKnownNeverSNaN(Src1, MRI, VT))
Src1 = MIRBuilder.buildFCanonicalize(Ty, Src1, MI.getFlags()).getReg(0);
}

Expand Down
78 changes: 6 additions & 72 deletions llvm/lib/CodeGen/GlobalISel/Utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "llvm/CodeGen/GlobalISel/Utils.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/FloatingPointMode.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/CodeGen/CodeGenCommonISel.h"
#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
Expand Down Expand Up @@ -807,7 +808,7 @@ llvm::ConstantFoldVectorBinop(unsigned Opcode, const Register Op1,
}

bool llvm::isKnownNeverNaN(Register Val, const MachineRegisterInfo &MRI,
bool SNaN) {
GISelValueTracking *VT, bool SNaN) {
const MachineInstr *DefMI = MRI.getVRegDef(Val);
if (!DefMI)
return false;
Expand All @@ -816,78 +817,11 @@ bool llvm::isKnownNeverNaN(Register Val, const MachineRegisterInfo &MRI,
if (DefMI->getFlag(MachineInstr::FmNoNans) || TM.Options.NoNaNsFPMath)
return true;

// If the value is a constant, we can obviously see if it is a NaN or not.
if (const ConstantFP *FPVal = getConstantFPVRegVal(Val, MRI)) {
return !FPVal->getValueAPF().isNaN() ||
(SNaN && !FPVal->getValueAPF().isSignaling());
}

if (DefMI->getOpcode() == TargetOpcode::G_BUILD_VECTOR) {
for (const auto &Op : DefMI->uses())
if (!isKnownNeverNaN(Op.getReg(), MRI, SNaN))
return false;
return true;
}
KnownFPClass FPClass = VT->computeKnownFPClass(Val, fcNan);
if (SNaN)
return FPClass.isKnownNever(fcSNan);

switch (DefMI->getOpcode()) {
default:
break;
case TargetOpcode::G_FADD:
case TargetOpcode::G_FSUB:
case TargetOpcode::G_FMUL:
case TargetOpcode::G_FDIV:
case TargetOpcode::G_FREM:
case TargetOpcode::G_FSIN:
case TargetOpcode::G_FCOS:
case TargetOpcode::G_FTAN:
case TargetOpcode::G_FACOS:
case TargetOpcode::G_FASIN:
case TargetOpcode::G_FATAN:
case TargetOpcode::G_FATAN2:
case TargetOpcode::G_FCOSH:
case TargetOpcode::G_FSINH:
case TargetOpcode::G_FTANH:
case TargetOpcode::G_FMA:
case TargetOpcode::G_FMAD:
if (SNaN)
return true;

// TODO: Need isKnownNeverInfinity
return false;
case TargetOpcode::G_FMINNUM_IEEE:
case TargetOpcode::G_FMAXNUM_IEEE: {
if (SNaN)
return true;
// This can return a NaN if either operand is an sNaN, or if both operands
// are NaN.
return (isKnownNeverNaN(DefMI->getOperand(1).getReg(), MRI) &&
isKnownNeverSNaN(DefMI->getOperand(2).getReg(), MRI)) ||
(isKnownNeverSNaN(DefMI->getOperand(1).getReg(), MRI) &&
isKnownNeverNaN(DefMI->getOperand(2).getReg(), MRI));
}
case TargetOpcode::G_FMINNUM:
case TargetOpcode::G_FMAXNUM: {
// Only one needs to be known not-nan, since it will be returned if the
// other ends up being one.
return isKnownNeverNaN(DefMI->getOperand(1).getReg(), MRI, SNaN) ||
isKnownNeverNaN(DefMI->getOperand(2).getReg(), MRI, SNaN);
}
}

if (SNaN) {
// FP operations quiet. For now, just handle the ones inserted during
// legalization.
switch (DefMI->getOpcode()) {
case TargetOpcode::G_FPEXT:
case TargetOpcode::G_FPTRUNC:
case TargetOpcode::G_FCANONICALIZE:
return true;
default:
return false;
}
}

return false;
return FPClass.isKnownNeverNaN();
}

Align llvm::inferAlignFromPtrInfo(MachineFunction &MF,
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/AMDGPU/AMDGPUInstructions.td
Original file line number Diff line number Diff line change
Expand Up @@ -859,7 +859,7 @@ class NeverNaNPats<dag ops, list<dag> frags> : PatFrags<ops, frags> {
return CurDAG->isKnownNeverNaN(SDValue(N,0));
}];
let GISelPredicateCode = [{
return isKnownNeverNaN(MI.getOperand(0).getReg(), MRI);
return isKnownNeverNaN(MI.getOperand(0).getReg(), MRI, VT);
}];
}

Expand Down
Loading
Loading