[llvm] [X86] Improve helper for simplifying demanded bits of compares (PR #84360)
Simon Pilgrim via llvm-commits
llvm-commits at lists.llvm.org
Mon Mar 11 05:51:12 PDT 2024
================
@@ -41293,6 +41293,154 @@ static SDValue combineShuffle(SDNode *N, SelectionDAG &DAG,
return SDValue();
}
+// Simplify a decomposed (sext (setcc)). Assumes prior check that
+// bitwidth(sext)==bitwidth(setcc operands).
+static SDValue simplifySExtOfDecomposedSetCCImpl(
+ SelectionDAG &DAG, SDLoc &DL, ISD::CondCode CC, SDValue Op0, SDValue Op1,
+ const APInt &OriginalDemandedBits, const APInt &OriginalDemandedElts,
+ bool AllowNOT, unsigned Depth) {
+ // Possible TODO: We could handle any power of two demanded bit + unsigned
+ // comparison. There are no x86 specific comparisons that are unsigned so its
+ // unneeded.
+ if (!OriginalDemandedBits.isSignMask())
+ return SDValue();
+
+ EVT OpVT = Op0.getValueType();
+ // We need need nofpclass(nan inf nzero) to handle floats.
+ auto hasOkayFPFlags = [](SDValue Op) {
+ return Op->getFlags().hasNoNaNs() && Op->getFlags().hasNoInfs() &&
+ Op->getFlags().hasNoSignedZeros();
+ };
+
+ if (OpVT.isFloatingPoint() && !hasOkayFPFlags(Op0))
+ return SDValue();
+
+ auto ValsEq = [OpVT](const APInt &V0, APInt V1) -> bool {
+ if (OpVT.isFloatingPoint()) {
+ const fltSemantics &Sem = SelectionDAG::EVTToAPFloatSemantics(OpVT);
+ return V0.eq(APFloat(Sem, V1).bitcastToAPInt());
+ }
+ return V0.eq(V1);
+ };
+
+ // Assume we canonicalized constants to Op1. That isn't always true but we
+ // call this function twice with inverted CC/Operands so its fine either way.
+ APInt Op1C;
+ unsigned ValWidth = OriginalDemandedBits.getBitWidth();
+ if (ISD::isConstantSplatVectorAllZeros(Op1.getNode())) {
+ Op1C = APInt::getZero(ValWidth);
+ } else if (ISD::isConstantSplatVectorAllOnes(Op1.getNode())) {
+ Op1C = APInt::getAllOnes(ValWidth);
+ } else if (auto *C = dyn_cast<ConstantFPSDNode>(Op1)) {
+ Op1C = C->getValueAPF().bitcastToAPInt();
+ } else if (auto *C = dyn_cast<ConstantSDNode>(Op1)) {
+ Op1C = C->getAPIntValue();
+ } else if (ISD::isConstantSplatVector(Op1.getNode(), Op1C)) {
+ // isConstantSplatVector sets `Op1C`.
+ } else {
+ return SDValue();
+ }
+
+ bool Not = false;
+ bool Okay = false;
+ assert(OriginalDemandedBits.getBitWidth() == Op1C.getBitWidth() &&
+ "Invalid constant operand");
+
+ switch (CC) {
+ case ISD::SETGE:
+ case ISD::SETOGE:
+ Not = true;
+ [[fallthrough]];
+ case ISD::SETLT:
+ case ISD::SETOLT:
+ // signbit(sext(x s< 0)) == signbit(x)
+ // signbit(sext(x s>= 0)) == signbit(~x)
+ Okay = ValsEq(Op1C, APInt::getZero(ValWidth));
+ // For float ops we need to ensure Op0 is de-norm. Otherwise DAZ can break
+ // this fold.
+ // NB: We only need de-norm check here, for the rest of the constants any
+ // relationship with a de-norm value and zero will be identical.
+ if (Okay && OpVT.isFloatingPoint()) {
+ // Values from integers are always normal.
+ if (Op0.getOpcode() == ISD::SINT_TO_FP ||
+ Op0.getOpcode() == ISD::UINT_TO_FP)
+ break;
+
+ // See if we can prove normal with known bits.
+ KnownBits Op0Known =
+ DAG.computeKnownBits(Op0, OriginalDemandedElts, Depth);
+ // Negative/positive doesn't matter.
+ Op0Known.One.clearSignBit();
+ Op0Known.Zero.clearSignBit();
+
+ // Get min normal value.
+ const fltSemantics &Sem = SelectionDAG::EVTToAPFloatSemantics(OpVT);
+ KnownBits MinNormal = KnownBits::makeConstant(
+ APFloat::getSmallestNormalized(Sem).bitcastToAPInt());
+ // Are we above de-norm range?
+ std::optional<bool> Op0Normal = KnownBits::uge(Op0Known, MinNormal);
+ Okay = Op0Normal.has_value() && *Op0Normal;
----------------
RKSimon wrote:
`Okay = Op0Normal.value_or(false);`
https://github.com/llvm/llvm-project/pull/84360
More information about the llvm-commits
mailing list