; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=sparc | FileCheck %s -check-prefix=SPARC
; RUN: llc < %s -mtriple=sparc -mattr=popc | FileCheck %s -check-prefix=SPARC-POPC
; RUN: llc < %s -mtriple=sparc -mattr=vis3 | FileCheck %s -check-prefix=SPARC-VIS3
; RUN: llc < %s -mtriple=sparcv9 | FileCheck %s -check-prefix=SPARC64
; RUN: llc < %s -mtriple=sparcv9 -mattr=popc | FileCheck %s -check-prefix=SPARC64-POPC
; RUN: llc < %s -mtriple=sparcv9 -mattr=vis3 | FileCheck %s -check-prefix=SPARC64-VIS3

define i32 @i32_nopoison(i32 %x) nounwind {
; SPARC-LABEL: i32_nopoison:
; SPARC:       ! %bb.0:
; SPARC-NEXT:    save %sp, -96, %sp
; SPARC-NEXT:    cmp %i0, 0
; SPARC-NEXT:    be .LBB0_2
; SPARC-NEXT:    nop
; SPARC-NEXT:  ! %bb.1: ! %cond.false
; SPARC-NEXT:    call __clzsi2
; SPARC-NEXT:    mov %i0, %o0
; SPARC-NEXT:    ret
; SPARC-NEXT:    restore %g0, %o0, %o0
; SPARC-NEXT:  .LBB0_2:
; SPARC-NEXT:    ret
; SPARC-NEXT:    restore %g0, 32, %o0
;
; SPARC-POPC-LABEL: i32_nopoison:
; SPARC-POPC:       ! %bb.0:
; SPARC-POPC-NEXT:    save %sp, -96, %sp
; SPARC-POPC-NEXT:    cmp %i0, 0
; SPARC-POPC-NEXT:    be .LBB0_2
; SPARC-POPC-NEXT:    nop
; SPARC-POPC-NEXT:  ! %bb.1: ! %cond.false
; SPARC-POPC-NEXT:    call __clzsi2
; SPARC-POPC-NEXT:    mov %i0, %o0
; SPARC-POPC-NEXT:    ret
; SPARC-POPC-NEXT:    restore %g0, %o0, %o0
; SPARC-POPC-NEXT:  .LBB0_2:
; SPARC-POPC-NEXT:    ret
; SPARC-POPC-NEXT:    restore %g0, 32, %o0
;
; SPARC-VIS3-LABEL: i32_nopoison:
; SPARC-VIS3:       ! %bb.0:
; SPARC-VIS3-NEXT:    srl %o0, 0, %o0
; SPARC-VIS3-NEXT:    lzcnt %o0, %o0
; SPARC-VIS3-NEXT:    retl
; SPARC-VIS3-NEXT:    add %o0, -32, %o0
;
; SPARC64-LABEL: i32_nopoison:
; SPARC64:       ! %bb.0:
; SPARC64-NEXT:    save %sp, -176, %sp
; SPARC64-NEXT:    cmp %i0, 0
; SPARC64-NEXT:    be %icc, .LBB0_2
; SPARC64-NEXT:    nop
; SPARC64-NEXT:  ! %bb.1: ! %cond.false
; SPARC64-NEXT:    call __clzdi2
; SPARC64-NEXT:    sllx %i0, 32, %o0
; SPARC64-NEXT:    ret
; SPARC64-NEXT:    restore %g0, %o0, %o0
; SPARC64-NEXT:  .LBB0_2:
; SPARC64-NEXT:    ret
; SPARC64-NEXT:    restore %g0, 32, %o0
;
; SPARC64-POPC-LABEL: i32_nopoison:
; SPARC64-POPC:       ! %bb.0:
; SPARC64-POPC-NEXT:    cmp %o0, 0
; SPARC64-POPC-NEXT:    be %icc, .LBB0_2
; SPARC64-POPC-NEXT:    nop
; SPARC64-POPC-NEXT:  ! %bb.1: ! %cond.false
; SPARC64-POPC-NEXT:    srl %o0, 1, %o1
; SPARC64-POPC-NEXT:    or %o0, %o1, %o0
; SPARC64-POPC-NEXT:    srl %o0, 2, %o1
; SPARC64-POPC-NEXT:    or %o0, %o1, %o0
; SPARC64-POPC-NEXT:    srl %o0, 4, %o1
; SPARC64-POPC-NEXT:    or %o0, %o1, %o0
; SPARC64-POPC-NEXT:    srl %o0, 8, %o1
; SPARC64-POPC-NEXT:    or %o0, %o1, %o0
; SPARC64-POPC-NEXT:    srl %o0, 16, %o1
; SPARC64-POPC-NEXT:    or %o0, %o1, %o0
; SPARC64-POPC-NEXT:    xor %o0, -1, %o0
; SPARC64-POPC-NEXT:    srl %o0, 0, %o0
; SPARC64-POPC-NEXT:    retl
; SPARC64-POPC-NEXT:    popc %o0, %o0
; SPARC64-POPC-NEXT:  .LBB0_2:
; SPARC64-POPC-NEXT:    retl
; SPARC64-POPC-NEXT:    mov 32, %o0
;
; SPARC64-VIS3-LABEL: i32_nopoison:
; SPARC64-VIS3:       ! %bb.0:
; SPARC64-VIS3-NEXT:    srl %o0, 0, %o0
; SPARC64-VIS3-NEXT:    lzcnt %o0, %o0
; SPARC64-VIS3-NEXT:    retl
; SPARC64-VIS3-NEXT:    add %o0, -32, %o0
  %ret = call i32 @llvm.ctlz.i32(i32 %x, i1 false)
  ret i32 %ret
}

define i32 @i32_poison(i32 %x) nounwind {
; SPARC-LABEL: i32_poison:
; SPARC:       ! %bb.0:
; SPARC-NEXT:    save %sp, -96, %sp
; SPARC-NEXT:    call __clzsi2
; SPARC-NEXT:    mov %i0, %o0
; SPARC-NEXT:    ret
; SPARC-NEXT:    restore %g0, %o0, %o0
;
; SPARC-POPC-LABEL: i32_poison:
; SPARC-POPC:       ! %bb.0:
; SPARC-POPC-NEXT:    save %sp, -96, %sp
; SPARC-POPC-NEXT:    call __clzsi2
; SPARC-POPC-NEXT:    mov %i0, %o0
; SPARC-POPC-NEXT:    ret
; SPARC-POPC-NEXT:    restore %g0, %o0, %o0
;
; SPARC-VIS3-LABEL: i32_poison:
; SPARC-VIS3:       ! %bb.0:
; SPARC-VIS3-NEXT:    srl %o0, 0, %o0
; SPARC-VIS3-NEXT:    lzcnt %o0, %o0
; SPARC-VIS3-NEXT:    retl
; SPARC-VIS3-NEXT:    add %o0, -32, %o0
;
; SPARC64-LABEL: i32_poison:
; SPARC64:       ! %bb.0:
; SPARC64-NEXT:    save %sp, -176, %sp
; SPARC64-NEXT:    call __clzdi2
; SPARC64-NEXT:    sllx %i0, 32, %o0
; SPARC64-NEXT:    ret
; SPARC64-NEXT:    restore %g0, %o0, %o0
;
; SPARC64-POPC-LABEL: i32_poison:
; SPARC64-POPC:       ! %bb.0:
; SPARC64-POPC-NEXT:    srl %o0, 1, %o1
; SPARC64-POPC-NEXT:    or %o0, %o1, %o0
; SPARC64-POPC-NEXT:    srl %o0, 2, %o1
; SPARC64-POPC-NEXT:    or %o0, %o1, %o0
; SPARC64-POPC-NEXT:    srl %o0, 4, %o1
; SPARC64-POPC-NEXT:    or %o0, %o1, %o0
; SPARC64-POPC-NEXT:    srl %o0, 8, %o1
; SPARC64-POPC-NEXT:    or %o0, %o1, %o0
; SPARC64-POPC-NEXT:    srl %o0, 16, %o1
; SPARC64-POPC-NEXT:    or %o0, %o1, %o0
; SPARC64-POPC-NEXT:    xor %o0, -1, %o0
; SPARC64-POPC-NEXT:    srl %o0, 0, %o0
; SPARC64-POPC-NEXT:    retl
; SPARC64-POPC-NEXT:    popc %o0, %o0
;
; SPARC64-VIS3-LABEL: i32_poison:
; SPARC64-VIS3:       ! %bb.0:
; SPARC64-VIS3-NEXT:    srl %o0, 0, %o0
; SPARC64-VIS3-NEXT:    lzcnt %o0, %o0
; SPARC64-VIS3-NEXT:    retl
; SPARC64-VIS3-NEXT:    add %o0, -32, %o0
  %ret = call i32 @llvm.ctlz.i32(i32 %x, i1 true)
  ret i32 %ret
}

define i64 @i64_nopoison(i64 %x) nounwind {
; SPARC-LABEL: i64_nopoison:
; SPARC:       ! %bb.0:
; SPARC-NEXT:    save %sp, -96, %sp
; SPARC-NEXT:    orcc %i1, %i0, %g0
; SPARC-NEXT:    be .LBB2_4
; SPARC-NEXT:    nop
; SPARC-NEXT:  ! %bb.1: ! %cond.false
; SPARC-NEXT:    call __clzsi2
; SPARC-NEXT:    mov %i1, %o0
; SPARC-NEXT:    mov %o0, %i2
; SPARC-NEXT:    call __clzsi2
; SPARC-NEXT:    mov %i0, %o0
; SPARC-NEXT:    cmp %i0, 0
; SPARC-NEXT:    bne .LBB2_3
; SPARC-NEXT:    mov %o0, %i1
; SPARC-NEXT:  ! %bb.2: ! %cond.false
; SPARC-NEXT:    add %i2, 32, %i1
; SPARC-NEXT:  .LBB2_3: ! %cond.false
; SPARC-NEXT:    ret
; SPARC-NEXT:    restore %g0, %g0, %o0
; SPARC-NEXT:  .LBB2_4:
; SPARC-NEXT:    mov %g0, %i0
; SPARC-NEXT:    ret
; SPARC-NEXT:    restore %g0, 64, %o1
;
; SPARC-POPC-LABEL: i64_nopoison:
; SPARC-POPC:       ! %bb.0:
; SPARC-POPC-NEXT:    save %sp, -96, %sp
; SPARC-POPC-NEXT:    orcc %i1, %i0, %g0
; SPARC-POPC-NEXT:    be .LBB2_4
; SPARC-POPC-NEXT:    nop
; SPARC-POPC-NEXT:  ! %bb.1: ! %cond.false
; SPARC-POPC-NEXT:    call __clzsi2
; SPARC-POPC-NEXT:    mov %i1, %o0
; SPARC-POPC-NEXT:    mov %o0, %i2
; SPARC-POPC-NEXT:    call __clzsi2
; SPARC-POPC-NEXT:    mov %i0, %o0
; SPARC-POPC-NEXT:    cmp %i0, 0
; SPARC-POPC-NEXT:    bne .LBB2_3
; SPARC-POPC-NEXT:    mov %o0, %i1
; SPARC-POPC-NEXT:  ! %bb.2: ! %cond.false
; SPARC-POPC-NEXT:    add %i2, 32, %i1
; SPARC-POPC-NEXT:  .LBB2_3: ! %cond.false
; SPARC-POPC-NEXT:    ret
; SPARC-POPC-NEXT:    restore %g0, %g0, %o0
; SPARC-POPC-NEXT:  .LBB2_4:
; SPARC-POPC-NEXT:    mov %g0, %i0
; SPARC-POPC-NEXT:    ret
; SPARC-POPC-NEXT:    restore %g0, 64, %o1
;
; SPARC-VIS3-LABEL: i64_nopoison:
; SPARC-VIS3:       ! %bb.0:
; SPARC-VIS3-NEXT:    srl %o0, 0, %o2
; SPARC-VIS3-NEXT:    lzcnt %o2, %o2
; SPARC-VIS3-NEXT:    add %o2, -32, %o2
; SPARC-VIS3-NEXT:    srl %o1, 0, %o1
; SPARC-VIS3-NEXT:    lzcnt %o1, %o1
; SPARC-VIS3-NEXT:    add %o1, -32, %o1
; SPARC-VIS3-NEXT:    add %o1, 32, %o1
; SPARC-VIS3-NEXT:    cmp %o0, 0
; SPARC-VIS3-NEXT:    movne %icc, %o2, %o1
; SPARC-VIS3-NEXT:    retl
; SPARC-VIS3-NEXT:    mov %g0, %o0
;
; SPARC64-LABEL: i64_nopoison:
; SPARC64:       ! %bb.0:
; SPARC64-NEXT:    save %sp, -176, %sp
; SPARC64-NEXT:    brz %i0, .LBB2_2
; SPARC64-NEXT:    nop
; SPARC64-NEXT:  ! %bb.1: ! %cond.false
; SPARC64-NEXT:    call __clzdi2
; SPARC64-NEXT:    mov %i0, %o0
; SPARC64-NEXT:    ret
; SPARC64-NEXT:    restore %g0, %o0, %o0
; SPARC64-NEXT:  .LBB2_2:
; SPARC64-NEXT:    ret
; SPARC64-NEXT:    restore %g0, 64, %o0
;
; SPARC64-POPC-LABEL: i64_nopoison:
; SPARC64-POPC:       ! %bb.0:
; SPARC64-POPC-NEXT:    brz %o0, .LBB2_2
; SPARC64-POPC-NEXT:    nop
; SPARC64-POPC-NEXT:  ! %bb.1: ! %cond.false
; SPARC64-POPC-NEXT:    srlx %o0, 1, %o1
; SPARC64-POPC-NEXT:    or %o0, %o1, %o0
; SPARC64-POPC-NEXT:    srlx %o0, 2, %o1
; SPARC64-POPC-NEXT:    or %o0, %o1, %o0
; SPARC64-POPC-NEXT:    srlx %o0, 4, %o1
; SPARC64-POPC-NEXT:    or %o0, %o1, %o0
; SPARC64-POPC-NEXT:    srlx %o0, 8, %o1
; SPARC64-POPC-NEXT:    or %o0, %o1, %o0
; SPARC64-POPC-NEXT:    srlx %o0, 16, %o1
; SPARC64-POPC-NEXT:    or %o0, %o1, %o0
; SPARC64-POPC-NEXT:    srlx %o0, 32, %o1
; SPARC64-POPC-NEXT:    or %o0, %o1, %o0
; SPARC64-POPC-NEXT:    xor %o0, -1, %o0
; SPARC64-POPC-NEXT:    retl
; SPARC64-POPC-NEXT:    popc %o0, %o0
; SPARC64-POPC-NEXT:  .LBB2_2:
; SPARC64-POPC-NEXT:    retl
; SPARC64-POPC-NEXT:    mov 64, %o0
;
; SPARC64-VIS3-LABEL: i64_nopoison:
; SPARC64-VIS3:       ! %bb.0:
; SPARC64-VIS3-NEXT:    retl
; SPARC64-VIS3-NEXT:    lzcnt %o0, %o0
  %ret = call i64 @llvm.ctlz.i64(i64 %x, i1 false)
  ret i64 %ret
}

define i64 @i64_poison(i64 %x) nounwind {
; SPARC-LABEL: i64_poison:
; SPARC:       ! %bb.0:
; SPARC-NEXT:    save %sp, -96, %sp
; SPARC-NEXT:    mov %i1, %o0
; SPARC-NEXT:    call __clzsi2
; SPARC-NEXT:    mov %i0, %i1
; SPARC-NEXT:    mov %o0, %i0
; SPARC-NEXT:    call __clzsi2
; SPARC-NEXT:    mov %i1, %o0
; SPARC-NEXT:    cmp %i1, 0
; SPARC-NEXT:    bne .LBB3_2
; SPARC-NEXT:    nop
; SPARC-NEXT:  ! %bb.1:
; SPARC-NEXT:    add %i0, 32, %o0
; SPARC-NEXT:  .LBB3_2:
; SPARC-NEXT:    mov %g0, %i0
; SPARC-NEXT:    ret
; SPARC-NEXT:    restore %g0, %o0, %o1
;
; SPARC-POPC-LABEL: i64_poison:
; SPARC-POPC:       ! %bb.0:
; SPARC-POPC-NEXT:    save %sp, -96, %sp
; SPARC-POPC-NEXT:    mov %i1, %o0
; SPARC-POPC-NEXT:    call __clzsi2
; SPARC-POPC-NEXT:    mov %i0, %i1
; SPARC-POPC-NEXT:    mov %o0, %i0
; SPARC-POPC-NEXT:    call __clzsi2
; SPARC-POPC-NEXT:    mov %i1, %o0
; SPARC-POPC-NEXT:    cmp %i1, 0
; SPARC-POPC-NEXT:    bne .LBB3_2
; SPARC-POPC-NEXT:    nop
; SPARC-POPC-NEXT:  ! %bb.1:
; SPARC-POPC-NEXT:    add %i0, 32, %o0
; SPARC-POPC-NEXT:  .LBB3_2:
; SPARC-POPC-NEXT:    mov %g0, %i0
; SPARC-POPC-NEXT:    ret
; SPARC-POPC-NEXT:    restore %g0, %o0, %o1
;
; SPARC-VIS3-LABEL: i64_poison:
; SPARC-VIS3:       ! %bb.0:
; SPARC-VIS3-NEXT:    srl %o0, 0, %o2
; SPARC-VIS3-NEXT:    lzcnt %o2, %o2
; SPARC-VIS3-NEXT:    add %o2, -32, %o2
; SPARC-VIS3-NEXT:    srl %o1, 0, %o1
; SPARC-VIS3-NEXT:    lzcnt %o1, %o1
; SPARC-VIS3-NEXT:    add %o1, -32, %o1
; SPARC-VIS3-NEXT:    add %o1, 32, %o1
; SPARC-VIS3-NEXT:    cmp %o0, 0
; SPARC-VIS3-NEXT:    movne %icc, %o2, %o1
; SPARC-VIS3-NEXT:    retl
; SPARC-VIS3-NEXT:    mov %g0, %o0
;
; SPARC64-LABEL: i64_poison:
; SPARC64:       ! %bb.0:
; SPARC64-NEXT:    save %sp, -176, %sp
; SPARC64-NEXT:    call __clzdi2
; SPARC64-NEXT:    mov %i0, %o0
; SPARC64-NEXT:    ret
; SPARC64-NEXT:    restore %g0, %o0, %o0
;
; SPARC64-POPC-LABEL: i64_poison:
; SPARC64-POPC:       ! %bb.0:
; SPARC64-POPC-NEXT:    srlx %o0, 1, %o1
; SPARC64-POPC-NEXT:    or %o0, %o1, %o0
; SPARC64-POPC-NEXT:    srlx %o0, 2, %o1
; SPARC64-POPC-NEXT:    or %o0, %o1, %o0
; SPARC64-POPC-NEXT:    srlx %o0, 4, %o1
; SPARC64-POPC-NEXT:    or %o0, %o1, %o0
; SPARC64-POPC-NEXT:    srlx %o0, 8, %o1
; SPARC64-POPC-NEXT:    or %o0, %o1, %o0
; SPARC64-POPC-NEXT:    srlx %o0, 16, %o1
; SPARC64-POPC-NEXT:    or %o0, %o1, %o0
; SPARC64-POPC-NEXT:    srlx %o0, 32, %o1
; SPARC64-POPC-NEXT:    or %o0, %o1, %o0
; SPARC64-POPC-NEXT:    xor %o0, -1, %o0
; SPARC64-POPC-NEXT:    retl
; SPARC64-POPC-NEXT:    popc %o0, %o0
;
; SPARC64-VIS3-LABEL: i64_poison:
; SPARC64-VIS3:       ! %bb.0:
; SPARC64-VIS3-NEXT:    retl
; SPARC64-VIS3-NEXT:    lzcnt %o0, %o0
  %ret = call i64 @llvm.ctlz.i64(i64 %x, i1 true)
  ret i64 %ret
}
