[llvm] [WebAssembly] Fold extended vector shifts by constant to extmul (PR #184007)

via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 2 07:58:33 PST 2026


================
@@ -2797,9 +2797,81 @@ static SDValue unrollVectorShift(SDValue Op, SelectionDAG &DAG) {
   return DAG.getBuildVector(Op.getValueType(), DL, UnrolledOps);
 }
 
+/// Convert a vector shift of an extended value into a multiplication of
+/// extended values. By converting the shift amount to a multiplier (1 << C)
+/// and wrapping it in a matching extend node, we enable the instruction
+/// selector to match the pattern to WebAssembly extended multiplication
+/// instructions (e.g., i32x4.extmul_low_i16x8_s). Inactive lanes in the
+/// multiplier vector are populated with undefs.
+///
+/// Example transformation:
+/// Before:
+///   t1: v8i16 = ...
+///   t2: v4i32 = WebAssemblyISD::EXTEND_LOW_S t1
+///   t3: v4i32 = BUILD_VECTOR Constant:i32<12>, Constant:i32<0>, ...
+///   t4: v4i32 = shl t2, t3
+///
+/// After:
+///   t1: v8i16 = ...
+///   t2: v4i32 = WebAssemblyISD::EXTEND_LOW_S t1
+///   t3: v8i16 = BUILD_VECTOR Constant:i16<4096>, Constant:i16<1>, undef, ...
+///   t4: v4i32 = WebAssemblyISD::EXTEND_LOW_S t3 t5: v4i32 = mul t2, t4
+static SDValue foldShiftByConstantToExtMul(SDValue Op, SelectionDAG &DAG) {
+  if (Op.getOpcode() != ISD::SHL || !Op.getValueType().isVector())
+    return SDValue();
+
+  SDValue RHS = Op.getOperand(1);
+  if (RHS.getOpcode() != ISD::BUILD_VECTOR)
+    return SDValue();
+
+  for (SDValue LaneOp : RHS->ops()) {
+    if (!isa<ConstantSDNode>(LaneOp))
+      return SDValue();
+  }
+
+  SDLoc DL(Op);
+  SDValue LHS = Op.getOperand(0);
+  unsigned ExtOpc = LHS.getOpcode();
+  bool IsLow = false;
+  if (ExtOpc == WebAssemblyISD::EXTEND_LOW_S ||
----------------
ParkHanbum wrote:

got it. I'll change it. 

I can't comment on the review of the test code below, so I'm written here. When we create the constant vector, the reference vector is Extend's Operand. That is, v8i16 as shown in the following log.

```
Vector-legalized selection DAG: %bb.0 'combine_with_constant:'
SelectionDAG has 18 nodes:
  t2: v8i16 = WebAssemblyISD::ARGUMENT TargetConstant:i32<0>
    t58: v4i32 = WebAssemblyISD::EXTEND_LOW_S t2
      t63: v8i16 = BUILD_VECTOR Constant:i16<4096>, Constant:i16<1>, Constant:i16<4096>, Constant:i16<1>, poison:i16, poison:i16, poison:i16, poison:i16
    t64: v4i32 = WebAssemblyISD::EXTEND_LOW_S t63
  t65: v4i32 = mul t58, t64
    t59: v4i32 = WebAssemblyISD::EXTEND_HIGH_S t2
      t66: v8i16 = BUILD_VECTOR poison:i16, poison:i16, poison:i16, poison:i16, Constant:i16<4096>, Constant:i16<1>, Constant:i16<4096>, Constant:i16<1>
    t67: v4i32 = WebAssemblyISD::EXTEND_HIGH_S t66
  t68: v4i32 = mul t59, t67
 ```
 
 

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


More information about the llvm-commits mailing list