[llvm] Fold CMOV + cttz into AND (PR #195767)

via llvm-commits llvm-commits at lists.llvm.org
Mon May 4 17:45:53 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-arm

Author: LumioseSil (LumioseSil)

<details>
<summary>Changes</summary>



---

Patch is 23.43 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/195767.diff


4 Files Affected:

- (modified) llvm/lib/Target/ARM/ARMISelLowering.cpp (+53-1) 
- (modified) llvm/lib/Target/ARM/ARMInstrInfo.td (+3) 
- (modified) llvm/lib/Target/ARM/ARMInstrThumb2.td (+3) 
- (added) llvm/test/CodeGen/ARM/fold-cmov-cttz-and.ll (+560) 


``````````diff
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp
index cbff40f697b9b..5297cc29981af 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.cpp
+++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp
@@ -1018,7 +1018,8 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM_,
     setOperationAction(ISD::ROTL, VT, Expand);
     setOperationAction(ISD::ROTR, VT, Expand);
   }
-  setOperationAction(ISD::CTTZ,  MVT::i32, Custom);
+  if (!Subtarget->hasV6T2Ops())
+    setOperationAction(ISD::CTTZ,  MVT::i32, Custom);
   // TODO: These two should be set to LibCall, but this currently breaks
   //   the Linux kernel build. See #101786.
   setOperationAction(ISD::CTPOP, MVT::i32, Expand);
@@ -18439,6 +18440,53 @@ ARMTargetLowering::PerformBRCONDCombine(SDNode *N, SelectionDAG &DAG) const {
   return SDValue();
 }
 
+/// Fold (cmov cttz, 0, EQ, (cmpz X, 0)) and (cmov 0, cttz, NE, (cmpz X, 0)) on
+/// i32 to (and cttz, 31). CMOV(False, True, CC): when CC matches flags, result
+/// is True; else False (see getCMOV). 32-bit ARM only; no i64 cttz / trunc
+/// path.
+static SDValue foldCMOVofCTTZ(SDNode *N, SelectionDAG &DAG) {
+  if (N->getOpcode() != ARMISD::CMOV || N->getValueType(0) != MVT::i32)
+    return SDValue();
+
+  SDValue Cmp = N->getOperand(3);
+  if (Cmp.getOpcode() != ARMISD::CMPZ)
+    return SDValue();
+
+  auto CC = (ARMCC::CondCodes)N->getConstantOperandVal(2);
+  SDValue Zero, CTTZ;
+
+  if (CC == ARMCC::EQ) {
+    CTTZ = N->getOperand(0);
+    Zero = N->getOperand(1);
+  } else if (CC == ARMCC::NE) {
+    Zero = N->getOperand(0);
+    CTTZ = N->getOperand(1);
+  } else
+    return SDValue();
+
+  if (CTTZ.getOpcode() != ISD::CTTZ || CTTZ.getValueType() != MVT::i32)
+    return SDValue();
+
+  if (!isNullConstant(Zero))
+    return SDValue();
+
+  SDValue CmpLHS = Cmp.getOperand(0);
+  SDValue CmpRHS = Cmp.getOperand(1);
+  SDValue XFromCmp;
+  if (isNullConstant(CmpRHS))
+    XFromCmp = CmpLHS;
+  else if (isNullConstant(CmpLHS))
+    XFromCmp = CmpRHS;
+  else
+    return SDValue();
+
+  if (CTTZ.getOperand(0) != XFromCmp)
+    return SDValue();
+
+  SDValue BitWidthMinusOne = DAG.getConstant(31, SDLoc(N), MVT::i32);
+  return DAG.getNode(ISD::AND, SDLoc(N), MVT::i32, CTTZ, BitWidthMinusOne);
+}
+
 /// PerformCMOVCombine - Target-specific DAG combining for ARMISD::CMOV.
 SDValue
 ARMTargetLowering::PerformCMOVCombine(SDNode *N, SelectionDAG &DAG) const {
@@ -18516,6 +18564,10 @@ ARMTargetLowering::PerformCMOVCombine(SDNode *N, SelectionDAG &DAG) const {
   if (!VT.isInteger())
       return SDValue();
 
+
+  if (SDValue Folded = foldCMOVofCTTZ(N, DAG))
+    return Folded;
+
   // Fold away an unnecessary CMPZ/CMOV
   // CMOV A, B, C1, (CMPZ (CMOV 1, 0, C2, D), 0) ->
   // if C1==EQ -> CMOV A, B, C2, D
diff --git a/llvm/lib/Target/ARM/ARMInstrInfo.td b/llvm/lib/Target/ARM/ARMInstrInfo.td
index c74c84a2602b1..c583dc3296f1f 100644
--- a/llvm/lib/Target/ARM/ARMInstrInfo.td
+++ b/llvm/lib/Target/ARM/ARMInstrInfo.td
@@ -4915,6 +4915,9 @@ def REV16 : AMiscA1I<0b01101011, 0b1011, (outs GPR:$Rd), (ins GPR:$Rm),
                Requires<[IsARM, HasV6]>,
            Sched<[WriteALU]>;
 
+def : ARMV6T2Pat<(cttz GPR:$Rn),
+                 (CLZ (RBIT GPR:$Rn))>;
+
 def : ARMV6Pat<(srl (bswap (extloadi16 addrmode3:$addr)), (i32 16)),
               (REV16 (LDRH addrmode3:$addr))>;
 def : ARMV6Pat<(truncstorei16 (srl (bswap GPR:$Rn), (i32 16)), addrmode3:$addr),
diff --git a/llvm/lib/Target/ARM/ARMInstrThumb2.td b/llvm/lib/Target/ARM/ARMInstrThumb2.td
index e79adb370798e..f0d929981b42f 100644
--- a/llvm/lib/Target/ARM/ARMInstrThumb2.td
+++ b/llvm/lib/Target/ARM/ARMInstrThumb2.td
@@ -3378,6 +3378,9 @@ def t2REV16 : T2I_misc<0b01, 0b01, (outs rGPR:$Rd), (ins rGPR:$Rm), IIC_iUNAr,
                 [(set rGPR:$Rd, (rotr (bswap rGPR:$Rm), (i32 16)))]>,
                 Sched<[WriteALU]>;
 
+def : T2v6Pat<(cttz rGPR:$Rn),
+              (t2CLZ (t2RBIT rGPR:$Rn))>;
+
 def : T2Pat<(srl (bswap top16Zero:$Rn), (i32 16)),
             (t2REV16 rGPR:$Rn)>;
 
diff --git a/llvm/test/CodeGen/ARM/fold-cmov-cttz-and.ll b/llvm/test/CodeGen/ARM/fold-cmov-cttz-and.ll
new file mode 100644
index 0000000000000..9ad97ca4e7578
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/fold-cmov-cttz-and.ll
@@ -0,0 +1,560 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple arm-eabi -mattr=+v5t | FileCheck %s --check-prefix=CHECK-5
+; RUN: llc < %s -mtriple arm-eabi -mattr=+v6t2 | FileCheck %s
+; RUN: llc < %s -mtriple arm-eabi -mattr=+v6t2 -mattr=+neon | FileCheck %s
+; RUN: llc < %s -mtriple thumbv6m-none-eabi | FileCheck %s --check-prefix=CHECK-6M
+; RUN: llc < %s -mtriple thumbv8m.base-none-eabi | FileCheck %s --check-prefix=CHECK-8MBASE
+
+;; Check the transformation
+;; CMOV(0, cttz, cc) -> AND (cttz, numbits-1)
+;; for cttz in the case of i32
+
+;; Cases for which the optimzation takes place
+define i32 @cttzi32(i32 %x) {
+; CHECK-5-LABEL: cttzi32:
+; CHECK-5:       @ %bb.0: @ %entry
+; CHECK-5-NEXT:    sub r1, r0, #1
+; CHECK-5-NEXT:    cmp r0, #0
+; CHECK-5-NEXT:    bic r1, r1, r0
+; CHECK-5-NEXT:    clz r1, r1
+; CHECK-5-NEXT:    rsbne r0, r1, #32
+; CHECK-5-NEXT:    bx lr
+;
+; CHECK-LABEL: cttzi32:
+; CHECK:       @ %bb.0: @ %entry
+; CHECK-NEXT:    rbit r0, r0
+; CHECK-NEXT:    clz r0, r0
+; CHECK-NEXT:    and r0, r0, #31
+; CHECK-NEXT:    bx lr
+;
+; CHECK-6M-LABEL: cttzi32:
+; CHECK-6M:       @ %bb.0: @ %entry
+; CHECK-6M-NEXT:    rsbs r1, r0, #0
+; CHECK-6M-NEXT:    ands r1, r0
+; CHECK-6M-NEXT:    ldr r2, .LCPI0_0
+; CHECK-6M-NEXT:    muls r2, r1, r2
+; CHECK-6M-NEXT:    lsrs r2, r2, #27
+; CHECK-6M-NEXT:    movs r1, #32
+; CHECK-6M-NEXT:    cmp r0, #0
+; CHECK-6M-NEXT:    bne .LBB0_3
+; CHECK-6M-NEXT:  @ %bb.1: @ %entry
+; CHECK-6M-NEXT:    beq .LBB0_4
+; CHECK-6M-NEXT:  .LBB0_2: @ %entry
+; CHECK-6M-NEXT:    mov r0, r1
+; CHECK-6M-NEXT:    bx lr
+; CHECK-6M-NEXT:  .LBB0_3: @ %entry
+; CHECK-6M-NEXT:    adr r1, .LCPI0_1
+; CHECK-6M-NEXT:    ldrb r1, [r1, r2]
+; CHECK-6M-NEXT:    bne .LBB0_2
+; CHECK-6M-NEXT:  .LBB0_4: @ %entry
+; CHECK-6M-NEXT:    mov r1, r0
+; CHECK-6M-NEXT:    mov r0, r1
+; CHECK-6M-NEXT:    bx lr
+; CHECK-6M-NEXT:    .p2align 2
+; CHECK-6M-NEXT:  @ %bb.5:
+; CHECK-6M-NEXT:  .LCPI0_0:
+; CHECK-6M-NEXT:    .long 125613361 @ 0x77cb531
+; CHECK-6M-NEXT:  .LCPI0_1:
+; CHECK-6M-NEXT:    .ascii "\000\001\034\002\035\016\030\003\036\026\024\017\031\021\004\b\037\033\r\027\025\023\020\007\032\f\022\006\013\005\n\t"
+;
+; CHECK-8MBASE-LABEL: cttzi32:
+; CHECK-8MBASE:       @ %bb.0: @ %entry
+; CHECK-8MBASE-NEXT:    rsbs r1, r0, #0
+; CHECK-8MBASE-NEXT:    ands r1, r0
+; CHECK-8MBASE-NEXT:    movw r2, #46385
+; CHECK-8MBASE-NEXT:    movt r2, #1916
+; CHECK-8MBASE-NEXT:    muls r2, r1, r2
+; CHECK-8MBASE-NEXT:    lsrs r2, r2, #27
+; CHECK-8MBASE-NEXT:    movs r1, #32
+; CHECK-8MBASE-NEXT:    cmp r0, #0
+; CHECK-8MBASE-NEXT:    bne .LBB0_3
+; CHECK-8MBASE-NEXT:  @ %bb.1: @ %entry
+; CHECK-8MBASE-NEXT:    beq .LBB0_4
+; CHECK-8MBASE-NEXT:  .LBB0_2: @ %entry
+; CHECK-8MBASE-NEXT:    mov r0, r1
+; CHECK-8MBASE-NEXT:    bx lr
+; CHECK-8MBASE-NEXT:  .LBB0_3: @ %entry
+; CHECK-8MBASE-NEXT:    adr r1, .LCPI0_0
+; CHECK-8MBASE-NEXT:    ldrb r1, [r1, r2]
+; CHECK-8MBASE-NEXT:    bne .LBB0_2
+; CHECK-8MBASE-NEXT:  .LBB0_4: @ %entry
+; CHECK-8MBASE-NEXT:    mov r1, r0
+; CHECK-8MBASE-NEXT:    mov r0, r1
+; CHECK-8MBASE-NEXT:    bx lr
+; CHECK-8MBASE-NEXT:    .p2align 2
+; CHECK-8MBASE-NEXT:  @ %bb.5:
+; CHECK-8MBASE-NEXT:  .LCPI0_0:
+; CHECK-8MBASE-NEXT:    .ascii "\000\001\034\002\035\016\030\003\036\026\024\017\031\021\004\b\037\033\r\027\025\023\020\007\032\f\022\006\013\005\n\t"
+entry:
+  %0 = call i32 @llvm.cttz.i32(i32 %x, i1 true)
+  %1 = icmp eq i32 %x, 0
+  %2 = select i1 %1, i32 0, i32 %0
+  ret i32 %2
+}
+
+define i32 @cttzi32ne(i32 %x) {
+; CHECK-5-LABEL: cttzi32ne:
+; CHECK-5:       @ %bb.0: @ %entry
+; CHECK-5-NEXT:    sub r1, r0, #1
+; CHECK-5-NEXT:    cmp r0, #0
+; CHECK-5-NEXT:    bic r1, r1, r0
+; CHECK-5-NEXT:    clz r1, r1
+; CHECK-5-NEXT:    rsbne r0, r1, #32
+; CHECK-5-NEXT:    bx lr
+;
+; CHECK-LABEL: cttzi32ne:
+; CHECK:       @ %bb.0: @ %entry
+; CHECK-NEXT:    rbit r0, r0
+; CHECK-NEXT:    clz r0, r0
+; CHECK-NEXT:    and r0, r0, #31
+; CHECK-NEXT:    bx lr
+;
+; CHECK-6M-LABEL: cttzi32ne:
+; CHECK-6M:       @ %bb.0: @ %entry
+; CHECK-6M-NEXT:    rsbs r1, r0, #0
+; CHECK-6M-NEXT:    ands r1, r0
+; CHECK-6M-NEXT:    ldr r2, .LCPI1_0
+; CHECK-6M-NEXT:    muls r2, r1, r2
+; CHECK-6M-NEXT:    lsrs r2, r2, #27
+; CHECK-6M-NEXT:    movs r1, #32
+; CHECK-6M-NEXT:    cmp r0, #0
+; CHECK-6M-NEXT:    bne .LBB1_3
+; CHECK-6M-NEXT:  @ %bb.1: @ %entry
+; CHECK-6M-NEXT:    beq .LBB1_4
+; CHECK-6M-NEXT:  .LBB1_2: @ %entry
+; CHECK-6M-NEXT:    mov r0, r1
+; CHECK-6M-NEXT:    bx lr
+; CHECK-6M-NEXT:  .LBB1_3: @ %entry
+; CHECK-6M-NEXT:    adr r1, .LCPI1_1
+; CHECK-6M-NEXT:    ldrb r1, [r1, r2]
+; CHECK-6M-NEXT:    bne .LBB1_2
+; CHECK-6M-NEXT:  .LBB1_4: @ %entry
+; CHECK-6M-NEXT:    mov r1, r0
+; CHECK-6M-NEXT:    mov r0, r1
+; CHECK-6M-NEXT:    bx lr
+; CHECK-6M-NEXT:    .p2align 2
+; CHECK-6M-NEXT:  @ %bb.5:
+; CHECK-6M-NEXT:  .LCPI1_0:
+; CHECK-6M-NEXT:    .long 125613361 @ 0x77cb531
+; CHECK-6M-NEXT:  .LCPI1_1:
+; CHECK-6M-NEXT:    .ascii "\000\001\034\002\035\016\030\003\036\026\024\017\031\021\004\b\037\033\r\027\025\023\020\007\032\f\022\006\013\005\n\t"
+;
+; CHECK-8MBASE-LABEL: cttzi32ne:
+; CHECK-8MBASE:       @ %bb.0: @ %entry
+; CHECK-8MBASE-NEXT:    rsbs r1, r0, #0
+; CHECK-8MBASE-NEXT:    ands r1, r0
+; CHECK-8MBASE-NEXT:    movw r2, #46385
+; CHECK-8MBASE-NEXT:    movt r2, #1916
+; CHECK-8MBASE-NEXT:    muls r2, r1, r2
+; CHECK-8MBASE-NEXT:    lsrs r2, r2, #27
+; CHECK-8MBASE-NEXT:    movs r1, #32
+; CHECK-8MBASE-NEXT:    cmp r0, #0
+; CHECK-8MBASE-NEXT:    bne .LBB1_3
+; CHECK-8MBASE-NEXT:  @ %bb.1: @ %entry
+; CHECK-8MBASE-NEXT:    beq .LBB1_4
+; CHECK-8MBASE-NEXT:  .LBB1_2: @ %entry
+; CHECK-8MBASE-NEXT:    mov r0, r1
+; CHECK-8MBASE-NEXT:    bx lr
+; CHECK-8MBASE-NEXT:  .LBB1_3: @ %entry
+; CHECK-8MBASE-NEXT:    adr r1, .LCPI1_0
+; CHECK-8MBASE-NEXT:    ldrb r1, [r1, r2]
+; CHECK-8MBASE-NEXT:    bne .LBB1_2
+; CHECK-8MBASE-NEXT:  .LBB1_4: @ %entry
+; CHECK-8MBASE-NEXT:    mov r1, r0
+; CHECK-8MBASE-NEXT:    mov r0, r1
+; CHECK-8MBASE-NEXT:    bx lr
+; CHECK-8MBASE-NEXT:    .p2align 2
+; CHECK-8MBASE-NEXT:  @ %bb.5:
+; CHECK-8MBASE-NEXT:  .LCPI1_0:
+; CHECK-8MBASE-NEXT:    .ascii "\000\001\034\002\035\016\030\003\036\026\024\017\031\021\004\b\037\033\r\027\025\023\020\007\032\f\022\006\013\005\n\t"
+entry:
+  %0 = call i32 @llvm.cttz.i32(i32 %x, i1 true)
+  %1 = icmp ne i32 %x, 0
+  %2 = select i1 %1, i32 %0, i32 0
+  ret i32 %2
+}
+
+;; Cases for which the optimization does not take place
+define i32 @cttzne(i32 %x) {
+; CHECK-5-LABEL: cttzne:
+; CHECK-5:       @ %bb.0: @ %entry
+; CHECK-5-NEXT:    sub r1, r0, #1
+; CHECK-5-NEXT:    cmp r0, #0
+; CHECK-5-NEXT:    bic r1, r1, r0
+; CHECK-5-NEXT:    clz r1, r1
+; CHECK-5-NEXT:    rsb r1, r1, #32
+; CHECK-5-NEXT:    movne r1, #0
+; CHECK-5-NEXT:    mov r0, r1
+; CHECK-5-NEXT:    bx lr
+;
+; CHECK-LABEL: cttzne:
+; CHECK:       @ %bb.0: @ %entry
+; CHECK-NEXT:    rbit r1, r0
+; CHECK-NEXT:    cmp r0, #0
+; CHECK-NEXT:    clz r1, r1
+; CHECK-NEXT:    movwne r1, #0
+; CHECK-NEXT:    mov r0, r1
+; CHECK-NEXT:    bx lr
+;
+; CHECK-6M-LABEL: cttzne:
+; CHECK-6M:       @ %bb.0: @ %entry
+; CHECK-6M-NEXT:    mov r1, r0
+; CHECK-6M-NEXT:    rsbs r0, r0, #0
+; CHECK-6M-NEXT:    ands r0, r1
+; CHECK-6M-NEXT:    ldr r2, .LCPI2_0
+; CHECK-6M-NEXT:    muls r2, r0, r2
+; CHECK-6M-NEXT:    lsrs r3, r2, #27
+; CHECK-6M-NEXT:    movs r0, #0
+; CHECK-6M-NEXT:    movs r2, #32
+; CHECK-6M-NEXT:    cmp r1, #0
+; CHECK-6M-NEXT:    bne .LBB2_3
+; CHECK-6M-NEXT:  @ %bb.1: @ %entry
+; CHECK-6M-NEXT:    beq .LBB2_4
+; CHECK-6M-NEXT:  .LBB2_2: @ %entry
+; CHECK-6M-NEXT:    bx lr
+; CHECK-6M-NEXT:  .LBB2_3: @ %entry
+; CHECK-6M-NEXT:    adr r1, .LCPI2_1
+; CHECK-6M-NEXT:    ldrb r2, [r1, r3]
+; CHECK-6M-NEXT:    bne .LBB2_2
+; CHECK-6M-NEXT:  .LBB2_4: @ %entry
+; CHECK-6M-NEXT:    mov r0, r2
+; CHECK-6M-NEXT:    bx lr
+; CHECK-6M-NEXT:    .p2align 2
+; CHECK-6M-NEXT:  @ %bb.5:
+; CHECK-6M-NEXT:  .LCPI2_0:
+; CHECK-6M-NEXT:    .long 125613361 @ 0x77cb531
+; CHECK-6M-NEXT:  .LCPI2_1:
+; CHECK-6M-NEXT:    .ascii "\000\001\034\002\035\016\030\003\036\026\024\017\031\021\004\b\037\033\r\027\025\023\020\007\032\f\022\006\013\005\n\t"
+;
+; CHECK-8MBASE-LABEL: cttzne:
+; CHECK-8MBASE:       @ %bb.0: @ %entry
+; CHECK-8MBASE-NEXT:    mov r1, r0
+; CHECK-8MBASE-NEXT:    rsbs r0, r0, #0
+; CHECK-8MBASE-NEXT:    ands r0, r1
+; CHECK-8MBASE-NEXT:    movw r2, #46385
+; CHECK-8MBASE-NEXT:    movt r2, #1916
+; CHECK-8MBASE-NEXT:    muls r2, r0, r2
+; CHECK-8MBASE-NEXT:    lsrs r3, r2, #27
+; CHECK-8MBASE-NEXT:    movs r0, #0
+; CHECK-8MBASE-NEXT:    movs r2, #32
+; CHECK-8MBASE-NEXT:    cmp r1, #0
+; CHECK-8MBASE-NEXT:    bne .LBB2_3
+; CHECK-8MBASE-NEXT:  @ %bb.1: @ %entry
+; CHECK-8MBASE-NEXT:    beq .LBB2_4
+; CHECK-8MBASE-NEXT:  .LBB2_2: @ %entry
+; CHECK-8MBASE-NEXT:    bx lr
+; CHECK-8MBASE-NEXT:  .LBB2_3: @ %entry
+; CHECK-8MBASE-NEXT:    adr r1, .LCPI2_0
+; CHECK-8MBASE-NEXT:    ldrb r2, [r1, r3]
+; CHECK-8MBASE-NEXT:    bne .LBB2_2
+; CHECK-8MBASE-NEXT:  .LBB2_4: @ %entry
+; CHECK-8MBASE-NEXT:    mov r0, r2
+; CHECK-8MBASE-NEXT:    bx lr
+; CHECK-8MBASE-NEXT:    .p2align 2
+; CHECK-8MBASE-NEXT:  @ %bb.5:
+; CHECK-8MBASE-NEXT:  .LCPI2_0:
+; CHECK-8MBASE-NEXT:    .ascii "\000\001\034\002\035\016\030\003\036\026\024\017\031\021\004\b\037\033\r\027\025\023\020\007\032\f\022\006\013\005\n\t"
+entry:
+  %0 = call i32 @llvm.cttz.i32(i32 %x, i1 true)
+  %1 = icmp ne i32 %x, 0
+  %2 = select i1 %1, i32 0, i32 %0
+  ret i32 %2
+}
+
+define i32 @cttzxnot0(i32 %x) {
+; CHECK-5-LABEL: cttzxnot0:
+; CHECK-5:       @ %bb.0: @ %entry
+; CHECK-5-NEXT:    sub r1, r0, #1
+; CHECK-5-NEXT:    bic r1, r1, r0
+; CHECK-5-NEXT:    subs r0, r0, #10
+; CHECK-5-NEXT:    clz r1, r1
+; CHECK-5-NEXT:    rsbne r0, r1, #32
+; CHECK-5-NEXT:    bx lr
+;
+; CHECK-LABEL: cttzxnot0:
+; CHECK:       @ %bb.0: @ %entry
+; CHECK-NEXT:    rbit r1, r0
+; CHECK-NEXT:    subs r0, r0, #10
+; CHECK-NEXT:    clzne r0, r1
+; CHECK-NEXT:    bx lr
+;
+; CHECK-6M-LABEL: cttzxnot0:
+; CHECK-6M:       @ %bb.0: @ %entry
+; CHECK-6M-NEXT:    cmp r0, #0
+; CHECK-6M-NEXT:    beq .LBB3_2
+; CHECK-6M-NEXT:  @ %bb.1: @ %entry
+; CHECK-6M-NEXT:    rsbs r1, r0, #0
+; CHECK-6M-NEXT:    ands r1, r0
+; CHECK-6M-NEXT:    ldr r2, .LCPI3_0
+; CHECK-6M-NEXT:    muls r2, r1, r2
+; CHECK-6M-NEXT:    lsrs r1, r2, #27
+; CHECK-6M-NEXT:    adr r2, .LCPI3_1
+; CHECK-6M-NEXT:    ldrb r1, [r2, r1]
+; CHECK-6M-NEXT:    cmp r0, #10
+; CHECK-6M-NEXT:    beq .LBB3_3
+; CHECK-6M-NEXT:    b .LBB3_4
+; CHECK-6M-NEXT:  .LBB3_2:
+; CHECK-6M-NEXT:    movs r1, #32
+; CHECK-6M-NEXT:    cmp r0, #10
+; CHECK-6M-NEXT:    bne .LBB3_4
+; CHECK-6M-NEXT:  .LBB3_3:
+; CHECK-6M-NEXT:    movs r1, #0
+; CHECK-6M-NEXT:  .LBB3_4: @ %entry
+; CHECK-6M-NEXT:    mov r0, r1
+; CHECK-6M-NEXT:    bx lr
+; CHECK-6M-NEXT:    .p2align 2
+; CHECK-6M-NEXT:  @ %bb.5:
+; CHECK-6M-NEXT:  .LCPI3_0:
+; CHECK-6M-NEXT:    .long 125613361 @ 0x77cb531
+; CHECK-6M-NEXT:  .LCPI3_1:
+; CHECK-6M-NEXT:    .ascii "\000\001\034\002\035\016\030\003\036\026\024\017\031\021\004\b\037\033\r\027\025\023\020\007\032\f\022\006\013\005\n\t"
+;
+; CHECK-8MBASE-LABEL: cttzxnot0:
+; CHECK-8MBASE:       @ %bb.0: @ %entry
+; CHECK-8MBASE-NEXT:    cbz r0, .LBB3_2
+; CHECK-8MBASE-NEXT:  @ %bb.1: @ %entry
+; CHECK-8MBASE-NEXT:    rsbs r1, r0, #0
+; CHECK-8MBASE-NEXT:    ands r1, r0
+; CHECK-8MBASE-NEXT:    movw r2, #46385
+; CHECK-8MBASE-NEXT:    movt r2, #1916
+; CHECK-8MBASE-NEXT:    muls r2, r1, r2
+; CHECK-8MBASE-NEXT:    lsrs r1, r2, #27
+; CHECK-8MBASE-NEXT:    adr r2, .LCPI3_0
+; CHECK-8MBASE-NEXT:    ldrb r1, [r2, r1]
+; CHECK-8MBASE-NEXT:    cmp r0, #10
+; CHECK-8MBASE-NEXT:    beq .LBB3_3
+; CHECK-8MBASE-NEXT:    b .LBB3_4
+; CHECK-8MBASE-NEXT:  .LBB3_2:
+; CHECK-8MBASE-NEXT:    movs r1, #32
+; CHECK-8MBASE-NEXT:    cmp r0, #10
+; CHECK-8MBASE-NEXT:    bne .LBB3_4
+; CHECK-8MBASE-NEXT:  .LBB3_3:
+; CHECK-8MBASE-NEXT:    movs r1, #0
+; CHECK-8MBASE-NEXT:  .LBB3_4: @ %entry
+; CHECK-8MBASE-NEXT:    mov r0, r1
+; CHECK-8MBASE-NEXT:    bx lr
+; CHECK-8MBASE-NEXT:    .p2align 2
+; CHECK-8MBASE-NEXT:  @ %bb.5:
+; CHECK-8MBASE-NEXT:  .LCPI3_0:
+; CHECK-8MBASE-NEXT:    .ascii "\000\001\034\002\035\016\030\003\036\026\024\017\031\021\004\b\037\033\r\027\025\023\020\007\032\f\022\006\013\005\n\t"
+entry:
+  %0 = call i32 @llvm.cttz.i32(i32 %x, i1 true)
+  %1 = icmp eq i32 %x, 10
+  %2 = select i1 %1, i32 0, i32 %0
+  ret i32 %2
+}
+
+define i32 @cttzlhsnot0(i32 %x) {
+; CHECK-5-LABEL: cttzlhsnot0:
+; CHECK-5:       @ %bb.0: @ %entry
+; CHECK-5-NEXT:    sub r1, r0, #1
+; CHECK-5-NEXT:    cmp r0, #0
+; CHECK-5-NEXT:    bic r1, r1, r0
+; CHECK-5-NEXT:    clz r1, r1
+; CHECK-5-NEXT:    rsb r1, r1, #32
+; CHECK-5-NEXT:    moveq r1, #10
+; CHECK-5-NEXT:    mov r0, r1
+; CHECK-5-NEXT:    bx lr
+;
+; CHECK-LABEL: cttzlhsnot0:
+; CHECK:       @ %bb.0: @ %entry
+; CHECK-NEXT:    rbit r1, r0
+; CHECK-NEXT:    cmp r0, #0
+; CHECK-NEXT:    clz r1, r1
+; CHECK-NEXT:    movweq r1, #10
+; CHECK-NEXT:    mov r0, r1
+; CHECK-NEXT:    bx lr
+;
+; CHECK-6M-LABEL: cttzlhsnot0:
+; CHECK-6M:       @ %bb.0: @ %entry
+; CHECK-6M-NEXT:    mov r1, r0
+; CHECK-6M-NEXT:    rsbs r0, r0, #0
+; CHECK-6M-NEXT:    ands r0, r1
+; CHECK-6M-NEXT:    ldr r2, .LCPI4_0
+; CHECK-6M-NEXT:    muls r2, r0, r2
+; CHECK-6M-NEXT:    lsrs r3, r2, #27
+; CHECK-6M-NEXT:    movs r0, #10
+; CHECK-6M-NEXT:    movs r2, #32
+; CHECK-6M-NEXT:    cmp r1, #0
+; CHECK-6M-NEXT:    bne .LBB4_3
+; CHECK-6M-NEXT:  @ %bb.1: @ %entry
+; CHECK-6M-NEXT:    bne .LBB4_4
+; CHECK-6M-NEXT:  .LBB4_2: @ %entry
+; CHECK-6M-NEXT:    bx lr
+; CHECK-6M-NEXT:  .LBB4_3: @ %entry
+; CHECK-6M-NEXT:    adr r1, .LCPI4_1
+; CHECK-6M-NEXT:    ldrb r2, [r1, r3]
+; CHECK-6M-NEXT:    beq .LBB4_2
+; CHECK-6M-NEXT:  .LBB4_4: @ %entry
+; CHECK-6M-NEXT:    mov r0, r2
+; CHECK-6M-NEXT:    bx lr
+; CHECK-6M-NEXT:    .p2align 2
+; CHECK-6M-NEXT:  @ %bb.5:
+; CHECK-6M-NEXT:  .LCPI4_0:
+; CHECK-6M-NEXT:    .long 125613361 @ 0x77cb531
+; CHECK-6M-NEXT:  .LCPI4_1:
+; CHECK-6M-NEXT:    .ascii "\000\001\034\002\035\016\030\003\036\026\024\017\031\021\004\b\037\033\r\027\025\023\020\007\032\f\022\006\013\005\n\t"
+;
+; CHECK-8MBASE-LABEL: cttzlhsnot0:
+; CHECK-8MBASE:       @ %bb.0: @ %entry
+; CHECK-8MBASE-NEXT:    mov r1, r0
+; CHECK-8MBASE-NEXT:    rsbs r0, r0, #0
+; CHECK-8MBASE-NEXT:    ands r0, r1
+; CHECK-8MBASE-NEXT:    movw r2, #46385
+; CHECK-8MBASE-NEXT:    movt r2, #1916
+; CHECK-8MBASE-NEXT:    muls r2, r0, r2
+; CHECK-8MBASE-NEXT:    lsrs r3, r2, #27
+; CHECK-8MBASE-NEXT:    movs r0, #10
+; CHECK-8MBASE-NEXT:    movs r2, #32
+; CHECK-8MBASE-NEXT:    cmp r1, #0
+; CHECK-8MBASE-NEXT:    bne .LBB4_3
+; CHECK-8MBASE-NEXT:  @ %bb.1: @ %entry
+; CHECK-8MBASE-NEXT:    bne .LBB4_4
+; CHECK-8MBASE-NEXT:  .LBB4_2: @ %entry
+; CHECK-8MBASE-NEXT:    bx lr
+; CHECK-8MBASE-NEXT:  .LBB4_3: @ %entry
+; CHECK-8MBASE-NEXT:    adr r1, .LCPI4_0
+; CHECK-8MBASE-NEXT:    ldrb r2, [r1, r3]
+; CHECK-8MBASE-NEXT:    beq .LBB4_2
+; CHECK-8MBASE-NEXT:  .LBB4_4: @ %entry
+; CHECK-8MBASE-NEXT:    mov r0, r2
+; CHECK-8MBASE-NEXT:    bx lr
+; CHECK-8MBASE-NEXT:    .p2align 2
+; CHECK-8MBASE-NEXT:  @ %bb.5:
+; CHECK-8MBASE-NEXT:  .LCPI4_0:
+; CHECK-8MBASE-NEXT:    .ascii "\000\001\034\002\035\016\030\003\036\026\024\017\031\021\004\b\037\033\r\027\025\023\020\007\032\f\022\006\013\005\n\t"
+entry:
+  %0 = call i32 @llvm.cttz.i32(i32 %x, i1 true)
+  %1 = icmp eq i32 %x, 0
+  %2 = select i1 %1, i32 10, i32 %0
+  ret i32 %2
+}
+
+define i32 @notcttz(i32 %x) {
+; CHECK-5-LABEL: notcttz:
+; CHECK-5:       @ %bb.0: @ %entry
+; CHECK-5-NEXT:    cmp r0, #0
+; CHECK-5-NEXT:    clzne r0, r0
+; CHECK-5-NEXT:    bx lr
+;
+; CHECK-LABEL: notcttz:
+; CHECK:       @ %bb.0: @ %entry
+; CHECK-NEXT:    cmp r0, #0
+; CHECK-NEXT:    clzne r0, r0
+; CHECK-NEXT:    bx lr
+;
+; CHECK-6M-LABEL: notcttz:
+; CHECK-6M:       @ %bb.0: @ %entry
+; CHECK-6M-NEXT:    .save {r4, lr}
+; CHECK-6M-NEXT:    push {r4, lr}
+; CHECK-6M-NEXT:    mov r4, r0
+; CHECK-6M-NEXT:    bl __clzsi2
+; CHECK-6M-NEXT:    cmp r4, #0
+; CHECK-6M-NEXT:    bne .LBB5_2
+; CHECK-6M-NEXT:  @ %bb.1: @ %entry
+; CHECK-6M-NEXT:    mov r0, r4
+; CHECK-6M-NEXT:  .LBB5_2: @ %entry
+; CHECK-6M-NEXT:    pop {r4, ...
[truncated]

``````````

</details>


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


More information about the llvm-commits mailing list