[llvm] [AArch64][SelectionDAG][SVE] Fold following extend(icmp) patterns (PR #192052)

Ricardo Jesus via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 15 04:56:18 PDT 2026


================
@@ -24422,6 +24437,105 @@ static SDValue performExtendCombine(SDNode *N,
                                     TargetLowering::DAGCombinerInfo &DCI,
                                     SelectionDAG &DAG,
                                     const AArch64Subtarget *Subtarget) {
+  // sext(icmp slt a, b) --> asr (shsub a, b), bitwidth-1
+  // sext(icmp ult a, b) --> asr (uhsub a, b), bitwidth-1
+  // zext(icmp slt a, b) --> lsr (shsub a, b), bitwidth-1
+  // zext(icmp ult a, b) --> lsr (uhsub a, b), bitwidth-1
+  // sext(icmp sgt a, b) --> asr (shsub b, a), bitwidth-1
+  // sext(icmp ugt a, b) --> asr (uhsub b, a), bitwidth-1
+  // zext(icmp sgt a, b) --> lsr (shsub b, a), bitwidth-1
+  // zext(icmp ugt a, b) --> lsr (uhsub b, a), bitwidth-1
+  SDValue Compare = N->getOperand(0);
+  SDLoc DL(N);
+  if (Compare.getOpcode() == AArch64ISD::SETCC_MERGE_ZERO &&
+      N->getValueType(0).isScalableVector() &&
+      Compare.getOperand(1).getValueType().getScalarType().isInteger() &&
+      (Subtarget->hasSVE2() || Subtarget->isStreamingSVEAvailable())) {
+    SDValue ComparePred = Compare.getOperand(0);
+    unsigned ExtendTy = N->getOpcode(); // sext or zext
+    ISD::CondCode CC = cast<CondCodeSDNode>(Compare.getOperand(3))->get();
+    SDValue A = Compare.getOperand(1);
+    SDValue B = Compare.getOperand(2);
+    unsigned BitwidthMinusOne = N->getValueType(0).getScalarSizeInBits() - 1;
+    EVT PredVT =
+        N->getValueType(0).changeElementType(*DAG.getContext(), MVT::i1);
+    //SDValue AllTruePred = getPTrue(DAG, DL, PredVT, AArch64SVEPredPattern::all);
+    SDValue AllTruePred = ComparePred ;
+    EVT EltVT = N->getValueType(0).getVectorElementType();
+    MVT ConstantTy = EltVT.bitsGT(MVT::i32) ? MVT::i64 : MVT::i32;
+    SDValue ShiftAmt =
+        DAG.getSplatVector(N->getValueType(0), DL,
+                           DAG.getConstant(BitwidthMinusOne, DL, ConstantTy));
+    if (ExtendTy == ISD::SIGN_EXTEND) {
+      if (CC == ISD::SETLT) {
+        // sext(icmp slt a, b) --> asr (shsub a, b), bitwidth-1
+        SDValue Sub = DAG.getNode(
+            ISD::INTRINSIC_WO_CHAIN, DL, N->getValueType(0),
+            DAG.getConstant(Intrinsic::aarch64_sve_shsub_u, DL, MVT::i64),
+            AllTruePred, A, B);
+        return DAG.getNode(ISD::SRA, DL, N->getValueType(0), Sub, ShiftAmt);
+      }
+      if (CC == ISD::SETULT) {
+        // sext(icmp ult a, b) --> asr (uhsub a, b), bitwidth-1
+        SDValue Sub = DAG.getNode(
+            ISD::INTRINSIC_WO_CHAIN, DL, N->getValueType(0),
+            DAG.getConstant(Intrinsic::aarch64_sve_uhsub_u, DL, MVT::i64),
+            AllTruePred, A, B);
+        return DAG.getNode(ISD::SRA, DL, N->getValueType(0), Sub, ShiftAmt);
+      }
+      if (CC == ISD::SETGT) {
----------------
rj-jesus wrote:

Could you check the greater-than condition codes earlier and swap the operands (and code)? Something like:
```
if (CC == ISD::SETGT || CC == ISD::SETUGT) {
  std::swap(A, B);
  CC = ISD::getSetCCSwappedOperands(CC);
}
```

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


More information about the llvm-commits mailing list