[llvm] [AArch64] Fold NEON splats into users by using SVE immediates (PR #165559)
Paul Walker via llvm-commits
llvm-commits at lists.llvm.org
Thu Mar 12 05:02:05 PDT 2026
================
@@ -597,6 +605,77 @@ static bool isIntImmediateEq(SDValue N, const uint64_t ImmExpected) {
}
#endif
+static APInt DecodeFMOVImm(SDValue N) {
+ unsigned RegWidth = N.getScalarValueSizeInBits();
+ assert(N->getOpcode() == AArch64ISD::FMOV);
+ assert(RegWidth == 32 || RegWidth == 64);
+ if (RegWidth == 32)
+ return APInt(RegWidth, (uint32_t)AArch64_AM::decodeAdvSIMDModImmType11(
+ N.getConstantOperandVal(0)));
+
+ return APInt(RegWidth, AArch64_AM::decodeAdvSIMDModImmType12(
+ N.getConstantOperandVal(0)));
+}
+
+// Decodes the integer splat value from a NEON splat operation.
+static std::optional<APInt> DecodeNEONSplat(SDValue N) {
+ assert(N.getValueType().isInteger() && "Only integers are supported");
+ unsigned SplatWidth = N.getScalarValueSizeInBits();
+ if (N->getOpcode() == AArch64ISD::NVCAST) {
+ SDValue Op = N->getOperand(0);
+ if (Op.getOpcode() != AArch64ISD::FMOV ||
+ Op.getScalarValueSizeInBits() != N.getScalarValueSizeInBits())
+ return std::nullopt;
+ return DecodeFMOVImm(Op);
+ }
+ if (N->getOpcode() == AArch64ISD::MOVI)
+ return APInt(SplatWidth, N.getConstantOperandVal(0));
+ if (N->getOpcode() == AArch64ISD::MOVIshift)
+ return APInt(SplatWidth, N.getConstantOperandVal(0)
+ << N.getConstantOperandVal(1));
+ if (N->getOpcode() == AArch64ISD::MVNIshift)
+ return ~APInt(SplatWidth, N.getConstantOperandVal(0)
+ << N.getConstantOperandVal(1));
+ if (N->getOpcode() == AArch64ISD::DUP) {
+ if (auto *Const = dyn_cast<ConstantSDNode>(N->getOperand(0)))
+ return Const->getAPIntValue();
+ }
----------------
paulwalker-arm wrote:
Unnecessary {}.
The DUP operand can be bigger than the element type so truncating to SplatWidth could yield more matches.
https://github.com/llvm/llvm-project/pull/165559
More information about the llvm-commits
mailing list