[llvm] [LegalizeTypes] Don't pad cttz_elts_zero_poison with ones when widening op (PR #206705)

via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 30 03:46:57 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-aarch64

Author: Luke Lau (lukel97)

<details>
<summary>Changes</summary>

We only need to pad the widened lanes with zeros to handle the case for an all zeroes input. But for cttz_elts_zero_poison, this is already poison.

The RISC-V scalable vector test can't be precomitted because it crashes otherwise trying to lower a get_active_lane_mask from getMaskFromElementCount.

Also while we're here, switch to using TLI.getTypeToTransformTo to be consistent with other `WidenVecOp_*` implementations.

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


3 Files Affected:

- (modified) llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp (+11-5) 
- (modified) llvm/test/CodeGen/AArch64/intrinsic-cttz-elts-sve.ll (+2-9) 
- (modified) llvm/test/CodeGen/RISCV/rvv/cttz-elts.ll (+36) 


``````````diff
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
index bdb8cddda4909..9f7ac8db9c5e4 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
@@ -8730,12 +8730,18 @@ SDValue DAGTypeLegalizer::WidenVecOp_VSELECT(SDNode *N) {
 SDValue DAGTypeLegalizer::WidenVecOp_CttzElements(SDNode *N) {
   SDLoc DL(N);
   SDValue Source = N->getOperand(0);
-  EVT WideVT = GetWidenedVector(Source).getValueType();
+  EVT WideVT =
+      TLI.getTypeToTransformTo(*DAG.getContext(), Source.getValueType());
 
-  // Pad the widened portion with all-ones so the extra lanes appear as
-  // active (non-zero) elements and do not contribute trailing zeros.
-  SDValue AllOnes = DAG.getAllOnesConstant(DL, WideVT);
-  SDValue WideSource = DAG.getInsertSubvector(DL, AllOnes, Source, 0);
+  SDValue WideSource;
+  if (N->getOpcode() == ISD::CTTZ_ELTS_ZERO_POISON)
+    WideSource = GetWidenedVector(Source);
+  else {
+    // Pad the widened portion with all-ones so the extra lanes appear as
+    // active (non-zero) elements and do not contribute trailing zeros.
+    SDValue AllOnes = DAG.getAllOnesConstant(DL, WideVT);
+    WideSource = DAG.getInsertSubvector(DL, AllOnes, Source, 0);
+  }
 
   return DAG.getNode(N->getOpcode(), DL, N->getValueType(0), WideSource,
                      N->getFlags());
diff --git a/llvm/test/CodeGen/AArch64/intrinsic-cttz-elts-sve.ll b/llvm/test/CodeGen/AArch64/intrinsic-cttz-elts-sve.ll
index fa3673feaee46..4a74a2587b39c 100644
--- a/llvm/test/CodeGen/AArch64/intrinsic-cttz-elts-sve.ll
+++ b/llvm/test/CodeGen/AArch64/intrinsic-cttz-elts-sve.ll
@@ -142,15 +142,8 @@ define i32 @ctz_nxv3i1(<vscale x 3 x i1> %a) {
 define i32 @ctz_nxv3i1_poison(<vscale x 3 x i1> %a) {
 ; CHECK-LABEL: ctz_nxv3i1_poison:
 ; CHECK:       // %bb.0:
-; CHECK-NEXT:    rdvl x8, #1
-; CHECK-NEXT:    mov w9, #3 // =0x3
-; CHECK-NEXT:    ptrue p2.s
-; CHECK-NEXT:    lsr x8, x8, #4
-; CHECK-NEXT:    mul x8, x8, x9
-; CHECK-NEXT:    whilelo p1.s, xzr, x8
-; CHECK-NEXT:    not p1.b, p2/z, p1.b
-; CHECK-NEXT:    mov p0.b, p1/m, p1.b
-; CHECK-NEXT:    brkb p0.b, p2/z, p0.b
+; CHECK-NEXT:    ptrue p1.s
+; CHECK-NEXT:    brkb p0.b, p1/z, p0.b
 ; CHECK-NEXT:    cntp x0, p0, p0.s
 ; CHECK-NEXT:    ret
   %res = call i32 @llvm.experimental.cttz.elts.i32.nxv3i1(<vscale x 3 x i1> %a, i1 1)
diff --git a/llvm/test/CodeGen/RISCV/rvv/cttz-elts.ll b/llvm/test/CodeGen/RISCV/rvv/cttz-elts.ll
index e761f14b0d4e7..99bf2360a0d44 100644
--- a/llvm/test/CodeGen/RISCV/rvv/cttz-elts.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/cttz-elts.ll
@@ -261,4 +261,40 @@ define i32 @ctz_v3i32(<3 x i32> %a) {
   ret i32 %res
 }
 
+define i32 @ctz_v3i32_poison(<3 x i32> %a) {
+; RV32-LABEL: ctz_v3i32_poison:
+; RV32:       # %bb.0:
+; RV32-NEXT:    vsetivli zero, 4, e32, m1, ta, ma
+; RV32-NEXT:    vmsne.vi v8, v8, 0
+; RV32-NEXT:    vfirst.m a0, v8
+; RV32-NEXT:    ret
+;
+; RV64-LABEL: ctz_v3i32_poison:
+; RV64:       # %bb.0:
+; RV64-NEXT:    vsetivli zero, 4, e32, m1, ta, ma
+; RV64-NEXT:    vmsne.vi v8, v8, 0
+; RV64-NEXT:    vfirst.m a0, v8
+; RV64-NEXT:    ret
+  %res = call i32 @llvm.experimental.cttz.elts(<3 x i32> %a, i1 1)
+  ret i32 %res
+}
+
+define i32 @ctz_nxv3i32_poison(<vscale x 3 x i32> %a) {
+; RV32-LABEL: ctz_nxv3i32_poison:
+; RV32:       # %bb.0:
+; RV32-NEXT:    vsetvli a0, zero, e32, m2, ta, ma
+; RV32-NEXT:    vmsne.vi v10, v8, 0
+; RV32-NEXT:    vfirst.m a0, v10
+; RV32-NEXT:    ret
+;
+; RV64-LABEL: ctz_nxv3i32_poison:
+; RV64:       # %bb.0:
+; RV64-NEXT:    vsetvli a0, zero, e32, m2, ta, ma
+; RV64-NEXT:    vmsne.vi v10, v8, 0
+; RV64-NEXT:    vfirst.m a0, v10
+; RV64-NEXT:    ret
+  %res = call i32 @llvm.experimental.cttz.elts(<vscale x 3 x i32> %a, i1 1)
+  ret i32 %res
+}
+
 attributes #0 = { vscale_range(2,1024) }

``````````

</details>


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


More information about the llvm-commits mailing list