| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py | |
| ; RUN: llc < %s --mtriple=aarch64 -verify-machineinstrs | FileCheck %s --check-prefixes=CHECK,CHECK-SD | |
| ; RUN: llc < %s --mtriple=aarch64 -global-isel -verify-machineinstrs | FileCheck %s --check-prefixes=CHECK,CHECK-GI | |
| declare i8 @llvm.ctlz.i8(i8, i1) | |
| declare i16 @llvm.ctlz.i16(i16, i1) | |
| declare i32 @llvm.ctlz.i32(i32, i1) | |
| declare i64 @llvm.ctlz.i64(i64, i1) | |
| define i8 @ctlo_i8(i8 %x) { | |
| ; CHECK-SD-LABEL: ctlo_i8: | |
| ; CHECK-SD: // %bb.0: | |
| ; CHECK-SD-NEXT: mvn w8, w0, lsl #24 | |
| ; CHECK-SD-NEXT: clz w0, w8 | |
| ; CHECK-SD-NEXT: ret | |
| ; | |
| ; CHECK-GI-LABEL: ctlo_i8: | |
| ; CHECK-GI: // %bb.0: | |
| ; CHECK-GI-NEXT: mov w8, #255 // =0xff | |
| ; CHECK-GI-NEXT: bic w8, w8, w0 | |
| ; CHECK-GI-NEXT: clz w8, w8 | |
| ; CHECK-GI-NEXT: sub w0, w8, #24 | |
| ; CHECK-GI-NEXT: ret | |
| %tmp1 = xor i8 %x, -1 | |
| %tmp2 = call i8 @llvm.ctlz.i8( i8 %tmp1, i1 false ) | |
| ret i8 %tmp2 | |
| } | |
| define i8 @ctlo_i8_undef(i8 %x) { | |
| ; CHECK-SD-LABEL: ctlo_i8_undef: | |
| ; CHECK-SD: // %bb.0: | |
| ; CHECK-SD-NEXT: mvn w8, w0 | |
| ; CHECK-SD-NEXT: lsl w8, w8, #24 | |
| ; CHECK-SD-NEXT: clz w0, w8 | |
| ; CHECK-SD-NEXT: ret | |
| ; | |
| ; CHECK-GI-LABEL: ctlo_i8_undef: | |
| ; CHECK-GI: // %bb.0: | |
| ; CHECK-GI-NEXT: mov w8, #255 // =0xff | |
| ; CHECK-GI-NEXT: bic w8, w8, w0 | |
| ; CHECK-GI-NEXT: clz w8, w8 | |
| ; CHECK-GI-NEXT: sub w0, w8, #24 | |
| ; CHECK-GI-NEXT: ret | |
| %tmp1 = xor i8 %x, -1 | |
| %tmp2 = call i8 @llvm.ctlz.i8( i8 %tmp1, i1 true ) | |
| ret i8 %tmp2 | |
| } | |
| define i16 @ctlo_i16(i16 %x) { | |
| ; CHECK-SD-LABEL: ctlo_i16: | |
| ; CHECK-SD: // %bb.0: | |
| ; CHECK-SD-NEXT: mvn w8, w0, lsl #16 | |
| ; CHECK-SD-NEXT: clz w0, w8 | |
| ; CHECK-SD-NEXT: ret | |
| ; | |
| ; CHECK-GI-LABEL: ctlo_i16: | |
| ; CHECK-GI: // %bb.0: | |
| ; CHECK-GI-NEXT: mov w8, #65535 // =0xffff | |
| ; CHECK-GI-NEXT: bic w8, w8, w0 | |
| ; CHECK-GI-NEXT: clz w8, w8 | |
| ; CHECK-GI-NEXT: sub w0, w8, #16 | |
| ; CHECK-GI-NEXT: ret | |
| %tmp1 = xor i16 %x, -1 | |
| %tmp2 = call i16 @llvm.ctlz.i16( i16 %tmp1, i1 false ) | |
| ret i16 %tmp2 | |
| } | |
| define i16 @ctlo_i16_undef(i16 %x) { | |
| ; CHECK-SD-LABEL: ctlo_i16_undef: | |
| ; CHECK-SD: // %bb.0: | |
| ; CHECK-SD-NEXT: mvn w8, w0 | |
| ; CHECK-SD-NEXT: lsl w8, w8, #16 | |
| ; CHECK-SD-NEXT: clz w0, w8 | |
| ; CHECK-SD-NEXT: ret | |
| ; | |
| ; CHECK-GI-LABEL: ctlo_i16_undef: | |
| ; CHECK-GI: // %bb.0: | |
| ; CHECK-GI-NEXT: mov w8, #65535 // =0xffff | |
| ; CHECK-GI-NEXT: bic w8, w8, w0 | |
| ; CHECK-GI-NEXT: clz w8, w8 | |
| ; CHECK-GI-NEXT: sub w0, w8, #16 | |
| ; CHECK-GI-NEXT: ret | |
| %tmp1 = xor i16 %x, -1 | |
| %tmp2 = call i16 @llvm.ctlz.i16( i16 %tmp1, i1 true ) | |
| ret i16 %tmp2 | |
| } | |
| define i32 @ctlo_i32(i32 %x) { | |
| ; CHECK-LABEL: ctlo_i32: | |
| ; CHECK: // %bb.0: | |
| ; CHECK-NEXT: mvn w8, w0 | |
| ; CHECK-NEXT: clz w0, w8 | |
| ; CHECK-NEXT: ret | |
| %tmp1 = xor i32 %x, -1 | |
| %tmp2 = call i32 @llvm.ctlz.i32( i32 %tmp1, i1 false ) | |
| ret i32 %tmp2 | |
| } | |
| define i32 @ctlo_i32_undef(i32 %x) { | |
| ; CHECK-LABEL: ctlo_i32_undef: | |
| ; CHECK: // %bb.0: | |
| ; CHECK-NEXT: mvn w8, w0 | |
| ; CHECK-NEXT: clz w0, w8 | |
| ; CHECK-NEXT: ret | |
| %tmp1 = xor i32 %x, -1 | |
| %tmp2 = call i32 @llvm.ctlz.i32( i32 %tmp1, i1 true ) | |
| ret i32 %tmp2 | |
| } | |
| define i64 @ctlo_i64(i64 %x) { | |
| ; CHECK-LABEL: ctlo_i64: | |
| ; CHECK: // %bb.0: | |
| ; CHECK-NEXT: mvn x8, x0 | |
| ; CHECK-NEXT: clz x0, x8 | |
| ; CHECK-NEXT: ret | |
| %tmp1 = xor i64 %x, -1 | |
| %tmp2 = call i64 @llvm.ctlz.i64( i64 %tmp1, i1 false ) | |
| ret i64 %tmp2 | |
| } | |
| define i64 @ctlo_i64_undef(i64 %x) { | |
| ; CHECK-LABEL: ctlo_i64_undef: | |
| ; CHECK: // %bb.0: | |
| ; CHECK-NEXT: mvn x8, x0 | |
| ; CHECK-NEXT: clz x0, x8 | |
| ; CHECK-NEXT: ret | |
| %tmp1 = xor i64 %x, -1 | |
| %tmp2 = call i64 @llvm.ctlz.i64( i64 %tmp1, i1 true ) | |
| ret i64 %tmp2 | |
| } |