[llvm] [SelectionDAG] Expand CLMUL of zero-extended all-ones operand via parallel prefix XOR (PR #207339)

Jan Schultke via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 3 03:22:44 PDT 2026


================
@@ -8909,16 +8909,30 @@ SDValue TargetLowering::expandCLMUL(SDNode *Node, SelectionDAG &DAG) const {
       }
     }
 
-    // Special case: clmul(X, ~0) is equivalent to a "parallel prefix XOR" or
-    // "bitwise parity" operation.
-    if (isAllOnesOrAllOnesSplat(Y)) {
-      SDValue R = X;
-      for (unsigned I = 1; I < BW; I <<= 1) {
-        SDValue ShAmt = DAG.getShiftAmountConstant(I, VT, DL);
-        SDValue Shifted = DAG.getNode(ISD::SHL, DL, VT, R, ShAmt);
-        R = DAG.getNode(ISD::XOR, DL, VT, R, Shifted);
+    // Special case: clmul(X, Y) where Y is a known constant (splat) that forms
+    // a contiguous block of trailing ones (e.g. i8 0xFF, i8 0x0F, ...). In this
+    // special case, clmul(X, Y) is equivalent to a "parallel prefix XOR" or
+    // "bitwise parity" operation on X, optionally surrounded by truncation
+    // and zero-extension.
----------------
eisenwave wrote:

Mathematically, CLMUL can be seen as just doing a bunch of left shifts of `X` (where `Y` has a 1-bit), reduced by XOR. If you prepend any amount of zeroes in front of `Y`, that doesn't change anything about those left shifts of `X` and the final XOR result.

However, I think I have a bug anyway because I just truncate `X` to whatever the width of `Y` is, which obviously gets rid of information, so that can't be right.

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


More information about the llvm-commits mailing list