[llvm] [X86] Lower `minimum`/`maximum`/`minimumnum`/`maximumnum` using bitwise operations (PR #170069)
Matt Arsenault via llvm-commits
llvm-commits at lists.llvm.org
Mon Jan 12 12:50:12 PST 2026
================
@@ -29751,10 +29745,80 @@ static SDValue LowerFMINIMUM_FMAXIMUM(SDValue Op, const X86Subtarget &Subtarget,
SDValue MinMax = DAG.getNode(MinMaxOp, DL, VT, NewX, NewY, Op->getFlags());
+ // We handle signed-zero ordering by taking the larger (or smaller) sign bit.
+ if (ShouldHandleZeros) {
+ const fltSemantics &Sem = VT.getFltSemantics();
+ unsigned EltBits = VT.getScalarSizeInBits();
+ bool IsFakeVector = !VT.isVector();
+ MVT LogicVT = VT.getSimpleVT();
+ if (IsFakeVector)
+ LogicVT = (VT == MVT::f64) ? MVT::v2f64
+ : (VT == MVT::f32) ? MVT::v4f32
+ : MVT::v8f16;
+
+ // We take the sign bit from the first operand and combine it with the
+ // output sign bit (see below). Right now, if ShouldHandleZeros is true, the
+ // operands will never have been swapped. If you add another optimization
+ // that swaps the input operands if one is a known value, make sure this
+ // logic stays correct!
+ SDValue LogicX = NewX;
+ SDValue LogicMinMax = MinMax;
+ if (IsFakeVector) {
+ // Promote scalars to vectors for bitwise operations.
+ LogicX = DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, LogicVT, NewX);
+ LogicMinMax = DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, LogicVT, MinMax);
+ }
+
+ // x86's min/max operations return the second operand if both inputs are
+ // signed zero. For the maximum operation, we want to "and" the sign bit of
+ // the output with the sign bit of the first operand--that means that if the
+ // first operand is +0.0, the output will be too. For the minimum, it's the
+ // opposite: we "or" the output sign bit with the sign bit of the first
+ // operand, ensuring that if the first operand is -0.0, the output will be
+ // too.
+ SDValue Result;
+ if (IsMaxOp) {
+ // getSignedMaxValue returns a bit pattern of all ones but the highest
+ // bit. We "or" that with the first operand, then "and" that with the max
+ // operation's result. That clears only the sign bit, and only if the
+ // first operand is positive.
+ SDValue OrMask = DAG.getConstantFP(
+ APFloat(Sem, APInt::getSignedMaxValue(EltBits)), DL, LogicVT);
----------------
arsenm wrote:
I think we could cover nearly all uses with a signbit mask float, and a getPowerOfTwo(Log2) constructor
https://github.com/llvm/llvm-project/pull/170069
More information about the llvm-commits
mailing list