[llvm] [ISel] Introduce `llvm.pext` and `llvm.pdep` intrinsics (PR #200570)
Craig Topper via llvm-commits
llvm-commits at lists.llvm.org
Tue Jun 2 23:45:38 PDT 2026
================
@@ -8962,6 +8962,82 @@ SDValue TargetLowering::expandCLMUL(SDNode *Node, SelectionDAG &DAG) const {
llvm_unreachable("Expected CLMUL, CLMULR, or CLMULH");
}
+SDValue TargetLowering::expandPEXT(SDNode *Node, SelectionDAG &DAG) const {
+ SDLoc DL(Node);
+ EVT VT = Node->getValueType(0);
+ SDValue Val = Node->getOperand(0);
+ SDValue Msk = Node->getOperand(1);
+ unsigned BW = VT.getScalarSizeInBits();
+
+ // Hacker's Delight ยง7-4: Compress, or Generalized Extract
+ SDValue X = DAG.getNode(ISD::AND, DL, VT, Val, Msk);
+ SDValue M = Msk;
+ SDValue One = DAG.getShiftAmountConstant(1, VT, DL);
+ SDValue Mk = DAG.getNode(ISD::SHL, DL, VT, DAG.getNOT(DL, M, VT), One);
+
+ // Repeatedly compute which bits would shift to the right by an odd amount,
+ // shift all such bits in parallel using a mask, and double the shift amount.
+ for (unsigned I = 1; I < BW; I <<= 1) {
+ // This expands the "parallel prefix" operation to clmul(Mk, ~0).
+ SDValue Mp =
+ DAG.getNode(ISD::CLMUL, DL, VT, Mk, DAG.getAllOnesConstant(DL, VT));
+ SDValue Mv = DAG.getNode(ISD::AND, DL, VT, Mp, M);
+ SDValue ShiftI = DAG.getShiftAmountConstant(I, VT, DL);
+ SDValue MvS = DAG.getNode(ISD::SRL, DL, VT, Mv, ShiftI);
+ M = DAG.getNode(ISD::OR, DL, VT, DAG.getNode(ISD::XOR, DL, VT, M, Mv), MvS);
+ SDValue T = DAG.getNode(ISD::AND, DL, VT, X, Mv);
+ SDValue TS = DAG.getNode(ISD::SRL, DL, VT, T, ShiftI);
+ X = DAG.getNode(ISD::OR, DL, VT, DAG.getNode(ISD::XOR, DL, VT, X, T), TS);
+ Mk = DAG.getNode(ISD::AND, DL, VT, Mk, DAG.getNOT(DL, Mp, VT));
----------------
topperc wrote:
I don't really like creating dead nodes on the last iteration of the loop.
https://github.com/llvm/llvm-project/pull/200570
More information about the llvm-commits
mailing list