[llvm] [AArch64] Fix #94909: Optimize vector fmul(sitofp(x), 0.5) -> scvtf(x, 2) (PR #141480)

David Green via llvm-commits llvm-commits at lists.llvm.org
Sun Jun 29 13:55:41 PDT 2025


================
@@ -3952,6 +3960,125 @@ static bool checkCVTFixedPointOperandWithFBits(SelectionDAG *CurDAG, SDValue N,
   return true;
 }
 
+static bool checkCVTFixedPointOperandWithFBitsForVectors(SelectionDAG *CurDAG,
+                                                         SDValue N,
+                                                         SDValue &FixedPos,
+                                                         unsigned FloatWidth,
+                                                         bool IsReciprocal) {
+
+  if (N->getNumOperands() < 1)
+    return false;
+
+  SDValue ImmediateNode = N.getOperand(0);
+  if (N.getOpcode() == ISD::BITCAST || N.getOpcode() == AArch64ISD::NVCAST) {
+    // This could have been a bitcast to a scalar
+    if (!ImmediateNode.getValueType().isVector())
+      return false;
+  }
+
+  if (ImmediateNode.getOpcode() == AArch64ISD::DUP ||
+      ImmediateNode.getOpcode() == AArch64ISD::MOVIshift ||
+      ImmediateNode.getOpcode() == AArch64ISD::FMOV ||
+      ImmediateNode.getOpcode() == ISD::SPLAT_VECTOR ||
+      ImmediateNode.getOpcode() == ISD::BUILD_VECTOR) {
+    auto *C = dyn_cast<ConstantSDNode>(ImmediateNode.getOperand(0));
+    if (!C)
+      return false;
+  }
+
+  if (ImmediateNode.getOpcode() == ISD::BUILD_VECTOR) {
+    // For BUILD_VECTOR, we must explicitly check if it's a constant splat.
+    BuildVectorSDNode *BVN = cast<BuildVectorSDNode>(ImmediateNode.getNode());
+    APInt SplatValue;
+    APInt SplatUndef;
+    unsigned SplatBitSize;
+    bool HasAnyUndefs;
+    if (!BVN->isConstantSplat(SplatValue, SplatUndef, SplatBitSize,
+                              HasAnyUndefs)) {
+      return false;
+    }
+  }
+
+  APInt Imm;
+  bool IsIntConstant = false;
+  if (ImmediateNode.getOpcode() == AArch64ISD::MOVIshift) {
+    EVT NodeVT = N.getValueType();
+    Imm = APInt(NodeVT.getScalarSizeInBits(),
+                ImmediateNode.getConstantOperandVal(0)
+                    << ImmediateNode.getConstantOperandVal(1));
+    IsIntConstant = true;
+  } else if (ImmediateNode.getOpcode() == ISD::Constant) {
----------------
davemgreen wrote:

Could we end up with:
 - N is some random node with 1 constant operand. Say a MOVImsl.
 - Nothing checks N's opcode, only that is has >= 1 operand.
 - The ImmediateNode turns out to be a ISD::Constant, which is treated as a FMOV operand even though it wasn't.

(Granted a MOVImsl will no naturally be a fp type but it could be some other random operand type to the fmul).

https://github.com/llvm/llvm-project/pull/141480


More information about the llvm-commits mailing list