[llvm] [AArch64][SelectionDAG] Improve codegen for insert_into_scalable(zext_fixed_length_vector) (PR #192405)

via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 16 00:03:54 PDT 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-aarch64

Author: Sushant Gokhale (sushgokh)

<details>
<summary>Changes</summary>

For the above code, what we get before isel is:
`and(splat(1), sext(setcc_merge_zero))`

We can perform the following folding for better codegen:
`and(splat(1), sext(setcc_merge_zero)) -> zext(setcc_merge_zero)`

Acts  as enabler for PR #<!-- -->192052 in some of the cases

---
Full diff: https://github.com/llvm/llvm-project/pull/192405.diff


2 Files Affected:

- (modified) llvm/lib/Target/AArch64/AArch64ISelLowering.cpp (+18) 
- (added) llvm/test/CodeGen/AArch64/sve-icmp-sext-zext.ll (+138) 


``````````diff
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 9b34d9b385b4e..3cd23cdf68fc7 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -20942,12 +20942,30 @@ static SDValue performReinterpretCastCombine(SDNode *N) {
   return SDValue();
 }
 
+// and(splat(1), sext(setcc_merge_zero)) -> zext(setcc_merge_zero)
+SDValue performSVEAndSplatSetCCMergeZeroCombine(SDNode *N, SelectionDAG &DAG) {
+  SDLoc DL(N);
+  SDValue SplatOp = N->getOperand(0);
+  SDValue NonSplatOp = N->getOperand(1);
+  if (NonSplatOp.getOpcode() == ISD::SPLAT_VECTOR)
+    std::swap(SplatOp, NonSplatOp);
+  SDValue Compare = NonSplatOp.getOperand(0);
+  if (SplatOp.getOpcode() != ISD::SPLAT_VECTOR ||
+      NonSplatOp.getOpcode() != ISD::SIGN_EXTEND ||
+      Compare.getOpcode() != AArch64ISD::SETCC_MERGE_ZERO)
+    return SDValue();
+  return DAG.getNode(ISD::ZERO_EXTEND, DL, N->getValueType(0), Compare);
+}
+
 static SDValue performSVEAndCombine(SDNode *N,
                                     TargetLowering::DAGCombinerInfo &DCI) {
   SelectionDAG &DAG = DCI.DAG;
   SDValue Src = N->getOperand(0);
   unsigned Opc = Src->getOpcode();
 
+  if (SDValue R = performSVEAndSplatSetCCMergeZeroCombine(N, DAG))
+    return R;
+
   // Zero/any extend of an unsigned unpack
   if (Opc == AArch64ISD::UUNPKHI || Opc == AArch64ISD::UUNPKLO) {
     SDValue UnpkOp = Src->getOperand(0);
diff --git a/llvm/test/CodeGen/AArch64/sve-icmp-sext-zext.ll b/llvm/test/CodeGen/AArch64/sve-icmp-sext-zext.ll
new file mode 100644
index 0000000000000..c140deedbb6cf
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/sve-icmp-sext-zext.ll
@@ -0,0 +1,138 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -mtriple=aarch64 -mattr=+sve2 --aarch64-sve-vector-bits-min=256 -o - < %s | FileCheck %s
+
+define <vscale x 16 x i8> @zext_slt_test1(<vscale x 16 x i8> %a, <vscale x 16 x i8> %b)
+; CHECK-LABEL: zext_slt_test1:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    ptrue p0.b
+; CHECK-NEXT:    cmpgt p1.b, p0/z, z1.b, z0.b
+; CHECK-NEXT:    mov z0.b, p1/z, #1 // =0x1
+; CHECK-NEXT:    ret
+{
+  %1 = icmp slt <vscale x 16 x i8> %a, %b
+  %2 = zext <vscale x 16 x i1> %1 to <vscale x 16 x i8>
+  ret <vscale x 16 x i8> %2
+}
+
+define <vscale x 16 x i8> @zext_slt_test2(<32 x i8> %a, <32 x i8> %b)
+; CHECK-LABEL: zext_slt_test2:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    // kill: def $q1 killed $q1 killed $z0_z1 def $z0_z1
+; CHECK-NEXT:    ptrue p0.b, vl16
+; CHECK-NEXT:    // kill: def $q3 killed $q3 killed $z2_z3 def $z2_z3
+; CHECK-NEXT:    // kill: def $q0 killed $q0 killed $z0_z1 def $z0_z1
+; CHECK-NEXT:    // kill: def $q2 killed $q2 killed $z2_z3 def $z2_z3
+; CHECK-NEXT:    splice z0.b, p0, { z0.b, z1.b }
+; CHECK-NEXT:    splice z1.b, p0, { z2.b, z3.b }
+; CHECK-NEXT:    ptrue p0.b, vl32
+; CHECK-NEXT:    cmpgt p1.b, p0/z, z1.b, z0.b
+; CHECK-NEXT:    mov z0.b, p1/z, #1 // =0x1
+; CHECK-NEXT:    ret
+{
+  %1 = icmp slt <32 x i8> %a, %b
+  %2 = zext <32 x i1> %1 to <32 x i8>
+  %3 = tail call <vscale x 16 x i8> @llvm.vector.insert(<vscale x 16 x i8> poison, <32 x i8> %2, i64 0)
+  ret <vscale x 16 x i8> %3
+}
+
+define <vscale x 16 x i8> @zext_ult_test1(<vscale x 16 x i8> %a, <vscale x 16 x i8> %b)
+; CHECK-LABEL: zext_ult_test1:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    ptrue p0.b
+; CHECK-NEXT:    cmphi p1.b, p0/z, z1.b, z0.b
+; CHECK-NEXT:    mov z0.b, p1/z, #1 // =0x1
+; CHECK-NEXT:    ret
+{
+  %1 = icmp ult <vscale x 16 x i8> %a, %b
+  %2 = zext <vscale x 16 x i1> %1 to <vscale x 16 x i8>
+  ret <vscale x 16 x i8> %2
+}
+
+define <vscale x 16 x i8> @zext_ult_test2(<32 x i8> %a, <32 x i8> %b)
+; CHECK-LABEL: zext_ult_test2:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    // kill: def $q1 killed $q1 killed $z0_z1 def $z0_z1
+; CHECK-NEXT:    ptrue p0.b, vl16
+; CHECK-NEXT:    // kill: def $q3 killed $q3 killed $z2_z3 def $z2_z3
+; CHECK-NEXT:    // kill: def $q0 killed $q0 killed $z0_z1 def $z0_z1
+; CHECK-NEXT:    // kill: def $q2 killed $q2 killed $z2_z3 def $z2_z3
+; CHECK-NEXT:    splice z0.b, p0, { z0.b, z1.b }
+; CHECK-NEXT:    splice z1.b, p0, { z2.b, z3.b }
+; CHECK-NEXT:    ptrue p0.b, vl32
+; CHECK-NEXT:    cmphi p1.b, p0/z, z1.b, z0.b
+; CHECK-NEXT:    mov z0.b, p1/z, #1 // =0x1
+; CHECK-NEXT:    ret
+{
+  %1 = icmp ult <32 x i8> %a, %b
+  %2 = zext <32 x i1> %1 to <32 x i8>
+  %3 = tail call <vscale x 16 x i8> @llvm.vector.insert(<vscale x 16 x i8> poison, <32 x i8> %2, i64 0)
+  ret <vscale x 16 x i8> %3
+}
+
+define <vscale x 16 x i8> @zext_sgt_test1(<vscale x 16 x i8> %a, <vscale x 16 x i8> %b)
+; CHECK-LABEL: zext_sgt_test1:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    ptrue p0.b
+; CHECK-NEXT:    cmpgt p1.b, p0/z, z0.b, z1.b
+; CHECK-NEXT:    mov z0.b, p1/z, #1 // =0x1
+; CHECK-NEXT:    ret
+{
+  %1 = icmp sgt <vscale x 16 x i8> %a, %b
+  %2 = zext <vscale x 16 x i1> %1 to <vscale x 16 x i8>
+  ret <vscale x 16 x i8> %2
+}
+
+define <vscale x 16 x i8> @zext_sgt_test2(<32 x i8> %a, <32 x i8> %b)
+; CHECK-LABEL: zext_sgt_test2:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    // kill: def $q3 killed $q3 killed $z2_z3 def $z2_z3
+; CHECK-NEXT:    // kill: def $q1 killed $q1 killed $z0_z1 def $z0_z1
+; CHECK-NEXT:    ptrue p0.b, vl16
+; CHECK-NEXT:    // kill: def $q2 killed $q2 killed $z2_z3 def $z2_z3
+; CHECK-NEXT:    // kill: def $q0 killed $q0 killed $z0_z1 def $z0_z1
+; CHECK-NEXT:    splice z2.b, p0, { z2.b, z3.b }
+; CHECK-NEXT:    splice z0.b, p0, { z0.b, z1.b }
+; CHECK-NEXT:    ptrue p0.b, vl32
+; CHECK-NEXT:    cmpgt p1.b, p0/z, z0.b, z2.b
+; CHECK-NEXT:    mov z0.b, p1/z, #1 // =0x1
+; CHECK-NEXT:    ret
+{
+  %1 = icmp sgt <32 x i8> %a, %b
+  %2 = zext <32 x i1> %1 to <32 x i8>
+  %3 = tail call <vscale x 16 x i8> @llvm.vector.insert(<vscale x 16 x i8> poison, <32 x i8> %2, i64 0)
+  ret <vscale x 16 x i8> %3
+}
+
+define <vscale x 16 x i8> @zext_ugt_test1(<vscale x 16 x i8> %a, <vscale x 16 x i8> %b)
+; CHECK-LABEL: zext_ugt_test1:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    ptrue p0.b
+; CHECK-NEXT:    cmphi p1.b, p0/z, z0.b, z1.b
+; CHECK-NEXT:    mov z0.b, p1/z, #1 // =0x1
+; CHECK-NEXT:    ret
+{
+  %1 = icmp ugt <vscale x 16 x i8> %a, %b
+  %2 = zext <vscale x 16 x i1> %1 to <vscale x 16 x i8>
+  ret <vscale x 16 x i8> %2
+}
+
+define <vscale x 16 x i8> @zext_ugt_test2(<32 x i8> %a, <32 x i8> %b)
+; CHECK-LABEL: zext_ugt_test2:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    // kill: def $q3 killed $q3 killed $z2_z3 def $z2_z3
+; CHECK-NEXT:    // kill: def $q1 killed $q1 killed $z0_z1 def $z0_z1
+; CHECK-NEXT:    ptrue p0.b, vl16
+; CHECK-NEXT:    // kill: def $q2 killed $q2 killed $z2_z3 def $z2_z3
+; CHECK-NEXT:    // kill: def $q0 killed $q0 killed $z0_z1 def $z0_z1
+; CHECK-NEXT:    splice z2.b, p0, { z2.b, z3.b }
+; CHECK-NEXT:    splice z0.b, p0, { z0.b, z1.b }
+; CHECK-NEXT:    ptrue p0.b, vl32
+; CHECK-NEXT:    cmphi p1.b, p0/z, z0.b, z2.b
+; CHECK-NEXT:    mov z0.b, p1/z, #1 // =0x1
+; CHECK-NEXT:    ret
+{
+  %1 = icmp ugt <32 x i8> %a, %b
+  %2 = zext <32 x i1> %1 to <32 x i8>
+  %3 = tail call <vscale x 16 x i8> @llvm.vector.insert(<vscale x 16 x i8> poison, <32 x i8> %2, i64 0)
+  ret <vscale x 16 x i8> %3
+}

``````````

</details>


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


More information about the llvm-commits mailing list