[llvm] [WebAssembly] Fold extended vector shifts by constant to extmul (PR #184007)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Mar 2 04:19:25 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 ||
+ ExtOpc == WebAssemblyISD::EXTEND_HIGH_S) {
+ IsLow = (ExtOpc == WebAssemblyISD::EXTEND_LOW_S);
+ } else if (ExtOpc == WebAssemblyISD::EXTEND_LOW_U ||
+ ExtOpc == WebAssemblyISD::EXTEND_HIGH_U) {
+ IsLow = (ExtOpc == WebAssemblyISD::EXTEND_LOW_U);
+ } else {
+ return SDValue();
+ }
+
+ SDValue SrcVec = LHS.getOperand(0);
+ EVT SrcVecTy = SrcVec.getValueType();
+ unsigned SrcVecEltNum = SrcVecTy.getVectorNumElements();
+ unsigned ConstVecEltNum = SrcVecEltNum / 2;
+ SmallVector<SDValue, 16> MulConsts(SrcVecEltNum,
+ DAG.getUNDEF(SrcVecTy.getScalarType()));
----------------
ParkHanbum wrote:
I have a question, it seems that other architectures use undef a lot, not just ISelLowering by WebAscembly. In this case as well, I can see you using undef in the debugging log. Can you tell me why we use undef a lot at the backend?
Optimized type-legalized selection DAG: %bb.0 'dot_sext_2:'
SelectionDAG has 18 nodes:
t2: v8i16 = WebAssemblyISD::ARGUMENT TargetConstant:i32<0>
t4: v8i16 = WebAssemblyISD::ARGUMENT TargetConstant:i32<1>
t64: v4i32 = sign_extend_vector_inreg t2
t47: v4i32 = sign_extend_vector_inreg t4
t52: v4i32 = mul t64, t47
t66: v8i16 = vector_shuffle<4,5,6,7,u,u,u,u> t2, poison:v8i16
t59: v4i32 = sign_extend_vector_inreg t66
t67: v8i16 = vector_shuffle<4,5,6,7,u,u,u,u> t4, poison:v8i16
t41: v4i32 = sign_extend_vector_inreg t67
t53: v4i32 = mul t59, t41
t0: ch,glue = EntryToken
t69: v4i32 = vector_shuffle<1,3,5,7> t52, t53
t70: v4i32 = vector_shuffle<0,2,4,6> t52, t53
t28: v4i32 = add t69, t70
t29: ch = WebAssemblyISD::RETURN t0, t28
https://github.com/llvm/llvm-project/pull/184007
More information about the llvm-commits
mailing list