[llvm] [WebAssembly] Optimizes [zext](and 63|32) for shl, srl and sra with selectShiftMask (PR #170572)

Luke Lau via llvm-commits llvm-commits at lists.llvm.org
Fri Dec 12 08:18:25 PST 2025


================
@@ -548,6 +557,49 @@ bool WebAssemblyDAGToDAGISel::SelectAddrOperands64(SDValue Op, SDValue &Offset,
   return SelectAddrOperands(MVT::i64, WebAssembly::CONST_I64, Op, Offset, Addr);
 }
 
+bool WebAssemblyDAGToDAGISel::selectShiftMask(SDValue N, unsigned ShiftWidth,
+                                              SDValue &ShAmt) {
+
+  ShAmt = N;
+
+  bool HasZext = false;
+  // Peek through zext.
+  if (ShAmt->getOpcode() == ISD::ZERO_EXTEND) {
+    ShAmt = ShAmt.getOperand(0);
+    HasZext = true;
+  }
+
+  if (ShAmt.getOpcode() == ISD::AND &&
+      isa<ConstantSDNode>(ShAmt.getOperand(1))) {
+    const APInt &AndMask = ShAmt.getConstantOperandAPInt(1);
+
+    // Since the max shift amount is a power of 2 we can subtract 1 to make a
+    // mask that covers the bits needed to represent all shift amounts.
+    assert(isPowerOf2_32(ShiftWidth) && "Unexpected max shift amount!");
+    APInt ShMask(AndMask.getBitWidth(), ShiftWidth - 1);
+
+    if (ShMask.isSubsetOf(AndMask)) {
+      ShAmt = ShAmt.getOperand(0);
+    } else {
+      // TODO: port computeKnownBits from riscv in another PR about rotr and
+      // rotl
+      return false;
+    }
+
+    // Only reinstate zext if it's i32 -> i64, WebAssembly would have legalize
+    // i16 to i32 in the dag otherwise.
+    if (HasZext && ShiftWidth == 64) {
+      ShAmt = SDValue(CurDAG->getMachineNode(WebAssembly::I64_EXTEND_U_I32,
+                                             SDLoc(N), MVT::i64, ShAmt),
+                      0);
+    }
+    return true;
+  }
+
+  // TODO: Port rest of riscv if applicable
----------------
lukel97 wrote:

```suggestion
  // TODO: Port rest of RISCVDAGToDAGISel::selectShiftMask if applicable
```

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


More information about the llvm-commits mailing list