[llvm] [AMDGPU][SDAG] Legalise v2i32 or/xor/and instructions to make use of 64-bit wide instructions (PR #140694)
Chris Jackson via llvm-commits
llvm-commits at lists.llvm.org
Thu Jun 19 04:47:02 PDT 2025
================
@@ -4056,6 +4056,53 @@ SDValue AMDGPUTargetLowering::performShlCombine(SDNode *N,
SDLoc SL(N);
SelectionDAG &DAG = DCI.DAG;
+ // When the shl64_reduce optimisation code is passed through vector
+ // legalization //some scalarising occurs. After ISD::AND was legalised, this
+ // resulted in the AND instructions no longer being elided, as mentioned
+ // below. The following code should make sure this takes place.
+ if (RHS->getOpcode() == ISD::EXTRACT_VECTOR_ELT) {
+ SDValue VAND = RHS.getOperand(0);
+ uint64_t AndIndex = RHS->getConstantOperandVal(1);
+ if (VAND->getOpcode() == ISD::AND) {
+ SDValue LHSAND = VAND.getOperand(0);
+ SDValue RHSAND = VAND.getOperand(1);
+ if (RHSAND->getOpcode() == ISD::BUILD_VECTOR)
+ // Part of shlcombine is to optimise for the case where its possible to
+ // reduce shl64 to shl32 if shift range is [63-32]. This transforms: DST
+ // = shl i64 X, Y to [0, shl i32 X, (Y & 32) ]. The '&' is then elided
+ // by ISel. The vector code for this was being completely scalarised by
+ // the vector legalizer, but now v2i32 is made legal the vector
+ // legaliser only partially scalarises the vector operations and the and
+ // was not elided. This check enables us to locate and scalarise the
+ // vwi32 and and re-enable ISel to elide the and instruction.
+ if (RHSAND->getConstantOperandVal(0) == 0x1f &&
+ RHSAND->getConstantOperandVal(1) == 0x1f) {
+ // Get the non-const AND operands and produce scalar AND
+ const SDValue Zero = DAG.getConstant(0, SL, MVT::i32);
+ const SDValue One = DAG.getConstant(1, SL, MVT::i32);
+ SDValue Lo =
+ DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, LHSAND, Zero);
+ SDValue Hi =
+ DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, LHSAND, One);
+ SDValue AndMask = DAG.getConstant(0x1f, SL, MVT::i32);
+ SDValue LoAnd = DAG.getNode(ISD::AND, SL, MVT::i32, Lo, AndMask);
+ SDValue HiAnd = DAG.getNode(ISD::AND, SL, MVT::i32, Hi, AndMask);
+
+ if (AndIndex == 0) {
+ SDValue TLo = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, LHS);
+ return DAG.getNode(ISD::SHL, SL, MVT::i32, TLo, LoAnd,
+ N->getFlags());
+ } else if (AndIndex == 1) {
+ SDValue TLo = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, LHS);
+ return DAG.getNode(ISD::SHL, SL, MVT::i32, TLo, HiAnd,
+ N->getFlags());
+ } else {
+ return SDValue();
----------------
chrisjbris wrote:
thanks, amended.
https://github.com/llvm/llvm-project/pull/140694
More information about the llvm-commits
mailing list