[llvm] [AArch64] Combine PTEST_FIRST(PTRUE, CONCAT(A, B)) -> PTEST_FIRST(PTRUE, A) (PR #161384)

Paul Walker via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 30 10:31:31 PDT 2025


================
@@ -27519,6 +27522,37 @@ static SDValue performMULLCombine(SDNode *N,
   return SDValue();
 }
 
+static SDValue performPTestFirstCombine(SDNode *N,
+                                        TargetLowering::DAGCombinerInfo &DCI,
+                                        SelectionDAG &DAG) {
+  if (DCI.isBeforeLegalize())
+    return SDValue();
+
+  SDLoc DL(N);
+  auto Mask = N->getOperand(0);
+  auto Pred = N->getOperand(1);
+
+  if (Mask->getOpcode() == AArch64ISD::REINTERPRET_CAST)
+    Mask = Mask->getOperand(0);
+
+  if (Pred->getOpcode() == AArch64ISD::REINTERPRET_CAST)
+    Pred = Pred->getOperand(0);
+
+  if (Pred->getValueType(0).getVectorElementType() != MVT::i1 ||
+      !isAllActivePredicate(DAG, Mask))
+    return SDValue();
+
+  if (Pred->getOpcode() == ISD::CONCAT_VECTORS) {
+    Pred = Pred->getOperand(0);
+    SDValue Mask = DAG.getSplatVector(Pred->getValueType(0), DL,
+                                      DAG.getAllOnesConstant(DL, MVT::i64));
+    return getPTest(DAG, N->getValueType(0), Mask, Pred,
+                    AArch64CC::FIRST_ACTIVE, /* EmitCSel */ false);
----------------
paulwalker-arm wrote:

I doubt you're using much in `getPTest` to warrant the `EmitCSel` change. Having already proven the DAG is testing the first lane of the predicate[1] there's no complexity related to "hidden lanes" and so this can be simplified to:
```
Pred = DAG.getNode(AArch64ISD::REINTERPRET_CAST, DL, nxv16i1, Pred)
Mask = DAG.getNode(AArch64ISD::REINTERPRET_CAST, DL, nxv16i1, Mask)
return DAG.getNode(AArch64ISD::PTEST_FIRST, DL, N->getValueType(0), Pred, Mask);
```

[1] Is worth adding commentary detailing the "we know we are testing the first lane" requirement because that's key to the combine.

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


More information about the llvm-commits mailing list