[llvm] [AMDGPU][SDAG] Legalise v2i32 or/xor/and instructions to make use of 64-bit wide instructions (PR #140694)

Shilei Tian via llvm-commits llvm-commits at lists.llvm.org
Wed Jun 18 09:02:32 PDT 2025


================
@@ -4056,6 +4056,58 @@ 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.
+  // ConstantSDNode *CVANDRHS = dyn_cast<ConstantSDNode>(RHS->getOperand(1));
+  if (RHS->getOpcode() == ISD::EXTRACT_VECTOR_ELT) {
+    SDValue VAND = RHS.getOperand(0);
+    ConstantSDNode *CRRHS = dyn_cast<ConstantSDNode>(RHS->getOperand(1));
+    uint64_t AndIndex = RHS->getConstantOperandVal(1);
+    if (VAND->getOpcode() == ISD::AND && CRRHS) {
+      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.
+        ConstantSDNode *CANDL = dyn_cast<ConstantSDNode>(RHSAND->getOperand(0));
+        ConstantSDNode *CANDR = dyn_cast<ConstantSDNode>(RHSAND->getOperand(1));
+        if (CANDL && CANDR && 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);
+          SDValue Trunc = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, LHS);
+
+          if (AndIndex == 0) {
+            return DAG.getNode(ISD::SHL, SL, MVT::i32, Trunc, LoAnd,
+                               N->getFlags());
+          } else if (AndIndex == 1) {
+            return DAG.getNode(ISD::SHL, SL, MVT::i32, Trunc, HiAnd,
+                               N->getFlags());
+          } else {
+            return SDValue();
+          }
+        }
+    }
+  }
+  }
----------------
shiltian wrote:

why are they aligned?

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


More information about the llvm-commits mailing list