Skip to content
11 changes: 6 additions & 5 deletions llvm/include/llvm/Analysis/ValueTracking.h
Original file line number Diff line number Diff line change
Expand Up @@ -330,12 +330,13 @@ bool isKnownNeverNaN(const Value *V, unsigned Depth, const SimplifyQuery &SQ);
std::optional<bool> computeKnownFPSignBit(const Value *V, unsigned Depth,
const SimplifyQuery &SQ);

/// Return true if the sign bit of result can be ignored when the result is
/// zero.
bool ignoreSignBitOfZero(Instruction &I);
/// Return true if the sign bit of result can be ignored by the user when the
/// result is zero.
bool ignoreSignBitOfZero(const Use &U);

/// Return true if the sign bit of result can be ignored when the result is NaN.
bool ignoreSignBitOfNaN(Instruction &I);
/// Return true if the sign bit of result can be ignored by the user when the
/// result is NaN.
bool ignoreSignBitOfNaN(const Use &U);

/// If the specified value can be set by repeating the same byte in memory,
/// return the i8 value that it is represented with. This is true for all i8
Expand Down
38 changes: 13 additions & 25 deletions llvm/lib/Analysis/ValueTracking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6357,17 +6357,10 @@ std::optional<bool> llvm::computeKnownFPSignBit(const Value *V, unsigned Depth,
return Known.SignBit;
}

/// Return true if the sign bit of result can be ignored when the result is
/// zero.
bool llvm::ignoreSignBitOfZero(Instruction &I) {
if (auto *FPOp = dyn_cast<FPMathOperator>(&I))
if (FPOp->hasNoSignedZeros())
return true;

// Check if the sign bit is ignored by the only user.
if (!I.hasOneUse())
return false;
Instruction *User = I.user_back();
/// Return true if the sign bit of result can be ignored by the user when the
/// result is zero.
bool llvm::ignoreSignBitOfZero(const Use &U) {
auto *User = cast<Instruction>(U.getUser());
if (auto *FPOp = dyn_cast<FPMathOperator>(User)) {
if (FPOp->hasNoSignedZeros())
return true;
Expand All @@ -6386,7 +6379,7 @@ bool llvm::ignoreSignBitOfZero(Instruction &I) {
case Intrinsic::fabs:
return true;
case Intrinsic::copysign:
return II->getArgOperand(0) == &I;
return U.getOperandNo() == 0;
case Intrinsic::is_fpclass:
case Intrinsic::vp_is_fpclass: {
auto Test =
Expand All @@ -6405,15 +6398,10 @@ bool llvm::ignoreSignBitOfZero(Instruction &I) {
}
}

bool llvm::ignoreSignBitOfNaN(Instruction &I) {
if (auto *FPOp = dyn_cast<FPMathOperator>(&I))
if (FPOp->hasNoNaNs())
return true;

// Check if the sign bit is ignored by the only user.
if (!I.hasOneUse())
return false;
Instruction *User = I.user_back();
/// Return true if the sign bit of result can be ignored by the user when the
/// result is NaN.
bool llvm::ignoreSignBitOfNaN(const Use &U) {
auto *User = cast<Instruction>(U.getUser());
if (auto *FPOp = dyn_cast<FPMathOperator>(User)) {
if (FPOp->hasNoNaNs())
return true;
Expand All @@ -6439,7 +6427,7 @@ bool llvm::ignoreSignBitOfNaN(Instruction &I) {
case Instruction::PHI:
return false;
case Instruction::Ret:
return I.getFunction()->getAttributes().getRetNoFPClass() &
return User->getFunction()->getAttributes().getRetNoFPClass() &
FPClassTest::fcNan;
case Instruction::Call:
case Instruction::Invoke: {
Expand All @@ -6448,7 +6436,7 @@ bool llvm::ignoreSignBitOfNaN(Instruction &I) {
case Intrinsic::fabs:
return true;
case Intrinsic::copysign:
return II->getArgOperand(0) == &I;
return U.getOperandNo() == 0;
// Other proper FP math intrinsics ignore the sign bit of NaN.
case Intrinsic::maxnum:
case Intrinsic::minnum:
Expand All @@ -6472,8 +6460,8 @@ bool llvm::ignoreSignBitOfNaN(Instruction &I) {
}
}

FPClassTest NoFPClass = cast<CallBase>(User)->getParamNoFPClass(
I.uses().begin()->getOperandNo());
FPClassTest NoFPClass =
cast<CallBase>(User)->getParamNoFPClass(U.getOperandNo());
return NoFPClass & FPClassTest::fcNan;
}
default:
Expand Down
9 changes: 7 additions & 2 deletions llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2797,7 +2797,8 @@ static Instruction *foldSelectWithFCmpToFabs(SelectInst &SI,
// of NAN, but IEEE-754 specifies the signbit of NAN values with
// fneg/fabs operations.
if (match(TrueVal, m_FSub(m_PosZeroFP(), m_Specific(X))) &&
(cast<FPMathOperator>(CondVal)->hasNoNaNs() || ignoreSignBitOfNaN(SI) ||
(cast<FPMathOperator>(CondVal)->hasNoNaNs() || SI.hasNoNaNs() ||
(SI.hasOneUse() && ignoreSignBitOfNaN(*SI.use_begin())) ||
isKnownNeverNaN(X, /*Depth=*/0,
IC.getSimplifyQuery().getWithInstruction(
cast<Instruction>(CondVal))))) {
Expand Down Expand Up @@ -2844,7 +2845,11 @@ static Instruction *foldSelectWithFCmpToFabs(SelectInst &SI,
// Note: We require "nnan" for this fold because fcmp ignores the signbit
// of NAN, but IEEE-754 specifies the signbit of NAN values with
// fneg/fabs operations.
if (!ignoreSignBitOfZero(SI) || !ignoreSignBitOfNaN(SI))
if (!SI.hasNoSignedZeros() &&
!(SI.hasOneUse() && ignoreSignBitOfZero(*SI.use_begin())))
return nullptr;
if (!SI.hasNoNaNs() &&
!(SI.hasOneUse() && ignoreSignBitOfNaN(*SI.use_begin())))
return nullptr;

if (Swap)
Expand Down