[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