CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
802 lines
21 KiB
LLVM
802 lines
21 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
|
|
; RUN: llc < %s -mtriple=arm64 | FileCheck %s
|
|
|
|
define i1 @testSwapCmpWithLSL64_1(i64 %a, i64 %b) {
|
|
; CHECK-LABEL: testSwapCmpWithLSL64_1:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: cmp x1, x0, lsl #1
|
|
; CHECK-NEXT: cset w0, gt
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%shl = shl i64 %a, 1
|
|
%cmp = icmp slt i64 %shl, %b
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @testSwapCmpWithLSL64_63(i64 %a, i64 %b) {
|
|
; CHECK-LABEL: testSwapCmpWithLSL64_63:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: cmp x1, x0, lsl #63
|
|
; CHECK-NEXT: cset w0, gt
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%shl = shl i64 %a, 63
|
|
%cmp = icmp slt i64 %shl, %b
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @testSwapCmpWithLSL32_1(i32 %a, i32 %b) {
|
|
; CHECK-LABEL: testSwapCmpWithLSL32_1:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: cmp w1, w0, lsl #1
|
|
; CHECK-NEXT: cset w0, gt
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%shl = shl i32 %a, 1
|
|
%cmp = icmp slt i32 %shl, %b
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @testSwapCmpWithLSL32_31(i32 %a, i32 %b) {
|
|
; CHECK-LABEL: testSwapCmpWithLSL32_31:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: cmp w1, w0, lsl #31
|
|
; CHECK-NEXT: cset w0, gt
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%shl = shl i32 %a, 31
|
|
%cmp = icmp slt i32 %shl, %b
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @testSwapCmpWithLSR64_1(i64 %a, i64 %b) {
|
|
; CHECK-LABEL: testSwapCmpWithLSR64_1:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: cmp x1, x0, lsr #1
|
|
; CHECK-NEXT: cset w0, gt
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%lshr = lshr i64 %a, 1
|
|
%cmp = icmp slt i64 %lshr, %b
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @testSwapCmpWithLSR64_63(i64 %a, i64 %b) {
|
|
; CHECK-LABEL: testSwapCmpWithLSR64_63:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: cmp x1, x0, lsr #63
|
|
; CHECK-NEXT: cset w0, gt
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%lshr = lshr i64 %a, 63
|
|
%cmp = icmp slt i64 %lshr, %b
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @testSwapCmpWithLSR32_1(i32 %a, i32 %b) {
|
|
; CHECK-LABEL: testSwapCmpWithLSR32_1:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: cmp w1, w0, lsr #1
|
|
; CHECK-NEXT: cset w0, gt
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%lshr = lshr i32 %a, 1
|
|
%cmp = icmp slt i32 %lshr, %b
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @testSwapCmpWithLSR32_31(i32 %a, i32 %b) {
|
|
; CHECK-LABEL: testSwapCmpWithLSR32_31:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: cmp w1, w0, lsr #31
|
|
; CHECK-NEXT: cset w0, gt
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%lshr = lshr i32 %a, 31
|
|
%cmp = icmp slt i32 %lshr, %b
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @testSwapCmpWithASR64_1(i64 %a, i64 %b) {
|
|
; CHECK-LABEL: testSwapCmpWithASR64_1:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: cmp x1, x0, asr #1
|
|
; CHECK-NEXT: cset w0, gt
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%ashr = ashr i64 %a, 1
|
|
%cmp = icmp slt i64 %ashr, %b
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @testSwapCmpWithASR64_63(i64 %a, i64 %b) {
|
|
; CHECK-LABEL: testSwapCmpWithASR64_63:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: cmp x1, x0, asr #63
|
|
; CHECK-NEXT: cset w0, gt
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%ashr = ashr i64 %a, 63
|
|
%cmp = icmp slt i64 %ashr, %b
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @testSwapCmpWithASR32_1(i32 %a, i32 %b) {
|
|
; CHECK-LABEL: testSwapCmpWithASR32_1:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: cmp w1, w0, asr #1
|
|
; CHECK-NEXT: cset w0, gt
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%ashr = ashr i32 %a, 1
|
|
%cmp = icmp slt i32 %ashr, %b
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @testSwapCmpWithASR32_31(i32 %a, i32 %b) {
|
|
; CHECK-LABEL: testSwapCmpWithASR32_31:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: cmp w1, w0, asr #31
|
|
; CHECK-NEXT: cset w0, gt
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%ashr = ashr i32 %a, 31
|
|
%cmp = icmp slt i32 %ashr, %b
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @testSwapCmpWithShiftedZeroExtend32_64(i32 %a, i64 %b) {
|
|
; CHECK-LABEL: testSwapCmpWithShiftedZeroExtend32_64:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: cmp x1, w0, uxtw #2
|
|
; CHECK-NEXT: cset w0, lo
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%a64 = zext i32 %a to i64
|
|
%shl.0 = shl i64 %a64, 2
|
|
%cmp = icmp ugt i64 %shl.0, %b
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @testSwapCmpWithShiftedZeroExtend16_64(i16 %a, i64 %b) {
|
|
; CHECK-LABEL: testSwapCmpWithShiftedZeroExtend16_64:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: cmp x1, w0, uxth #2
|
|
; CHECK-NEXT: cset w0, lo
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%a64 = zext i16 %a to i64
|
|
%shl.0 = shl i64 %a64, 2
|
|
%cmp = icmp ugt i64 %shl.0, %b
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @testSwapCmpWithShiftedZeroExtend8_64(i8 %a, i64 %b) {
|
|
; CHECK-LABEL: testSwapCmpWithShiftedZeroExtend8_64:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: cmp x1, w0, uxtb #4
|
|
; CHECK-NEXT: cset w0, lo
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%a64 = zext i8 %a to i64
|
|
%shl.2 = shl i64 %a64, 4
|
|
%cmp = icmp ugt i64 %shl.2, %b
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @testSwapCmpWithShiftedZeroExtend16_32(i16 %a, i32 %b) {
|
|
; CHECK-LABEL: testSwapCmpWithShiftedZeroExtend16_32:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: cmp w1, w0, uxth #3
|
|
; CHECK-NEXT: cset w0, lo
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%a32 = zext i16 %a to i32
|
|
%shl = shl i32 %a32, 3
|
|
%cmp = icmp ugt i32 %shl, %b
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @testSwapCmpWithShiftedZeroExtend8_32(i8 %a, i32 %b) {
|
|
; CHECK-LABEL: testSwapCmpWithShiftedZeroExtend8_32:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: cmp w1, w0, uxtb #4
|
|
; CHECK-NEXT: cset w0, lo
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%a32 = zext i8 %a to i32
|
|
%shl = shl i32 %a32, 4
|
|
%cmp = icmp ugt i32 %shl, %b
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @testSwapCmpWithTooLargeShiftedZeroExtend8_32(i8 %a, i32 %b) {
|
|
; CHECK-LABEL: testSwapCmpWithTooLargeShiftedZeroExtend8_32:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: and w8, w0, #0xff
|
|
; CHECK-NEXT: cmp w1, w8, lsl #5
|
|
; CHECK-NEXT: cset w0, lo
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%a32 = zext i8 %a to i32
|
|
%shl = shl i32 %a32, 5
|
|
%cmp = icmp ugt i32 %shl, %b
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @testSwapCmpWithZeroExtend8_32(i8 %a, i32 %b) {
|
|
; CHECK-LABEL: testSwapCmpWithZeroExtend8_32:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: cmp w1, w0, uxtb
|
|
; CHECK-NEXT: cset w0, lo
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%a32 = zext i8 %a to i32
|
|
%cmp = icmp ugt i32 %a32, %b
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @testSwapCmpWithShiftedSignExtend32_64(i32 %a, i64 %b) {
|
|
; CHECK-LABEL: testSwapCmpWithShiftedSignExtend32_64:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: cmp x1, w0, sxtw #2
|
|
; CHECK-NEXT: cset w0, lo
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%a64 = sext i32 %a to i64
|
|
%shl.0 = shl i64 %a64, 2
|
|
%cmp = icmp ugt i64 %shl.0, %b
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @testSwapCmpWithShiftedSignExtend16_64(i16 %a, i64 %b) {
|
|
; CHECK-LABEL: testSwapCmpWithShiftedSignExtend16_64:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: cmp x1, w0, sxth #2
|
|
; CHECK-NEXT: cset w0, lo
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%a64 = sext i16 %a to i64
|
|
%shl.0 = shl i64 %a64, 2
|
|
%cmp = icmp ugt i64 %shl.0, %b
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @testSwapCmpWithShiftedSignExtend8_64(i8 %a, i64 %b) {
|
|
; CHECK-LABEL: testSwapCmpWithShiftedSignExtend8_64:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: cmp x1, w0, sxtb #4
|
|
; CHECK-NEXT: cset w0, lo
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%a64 = sext i8 %a to i64
|
|
%shl.2 = shl i64 %a64, 4
|
|
%cmp = icmp ugt i64 %shl.2, %b
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @testSwapCmpWithShiftedSignExtend16_32(i16 %a, i32 %b) {
|
|
; CHECK-LABEL: testSwapCmpWithShiftedSignExtend16_32:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: cmp w1, w0, sxth #3
|
|
; CHECK-NEXT: cset w0, lo
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%a32 = sext i16 %a to i32
|
|
%shl = shl i32 %a32, 3
|
|
%cmp = icmp ugt i32 %shl, %b
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @testSwapCmpWithShiftedSignExtend8_32(i8 %a, i32 %b) {
|
|
; CHECK-LABEL: testSwapCmpWithShiftedSignExtend8_32:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: cmp w1, w0, sxtb #4
|
|
; CHECK-NEXT: cset w0, lo
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%a32 = sext i8 %a to i32
|
|
%shl = shl i32 %a32, 4
|
|
%cmp = icmp ugt i32 %shl, %b
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @testSwapCmpWithTooLargeShiftedSignExtend8_32(i8 %a, i32 %b) {
|
|
; CHECK-LABEL: testSwapCmpWithTooLargeShiftedSignExtend8_32:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: sxtb w8, w0
|
|
; CHECK-NEXT: cmp w1, w8, lsl #5
|
|
; CHECK-NEXT: cset w0, lo
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%a32 = sext i8 %a to i32
|
|
%shl = shl i32 %a32, 5
|
|
%cmp = icmp ugt i32 %shl, %b
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @testSwapCmpWithSignExtend8_32(i8 %a, i32 %b) {
|
|
; CHECK-LABEL: testSwapCmpWithSignExtend8_32:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: cmp w1, w0, sxtb
|
|
; CHECK-NEXT: cset w0, lo
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%a32 = sext i8 %a to i32
|
|
%cmp = icmp ugt i32 %a32, %b
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @testSwapCmnWithLSL64_1(i64 %a, i64 %b) {
|
|
; CHECK-LABEL: testSwapCmnWithLSL64_1:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: cmn x1, x0, lsl #1
|
|
; CHECK-NEXT: cset w0, ne
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%shl = shl i64 %a, 1
|
|
%na = sub i64 0, %shl
|
|
%cmp = icmp ne i64 %na, %b
|
|
ret i1 %cmp
|
|
}
|
|
|
|
; Note: testing with a 62 bits shift as 63 has another optimization kicking in.
|
|
define i1 @testSwapCmnWithLSL64_62(i64 %a, i64 %b) {
|
|
; CHECK-LABEL: testSwapCmnWithLSL64_62:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: cmn x1, x0, lsl #62
|
|
; CHECK-NEXT: cset w0, ne
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%shl = shl i64 %a, 62
|
|
%na = sub i64 0, %shl
|
|
%cmp = icmp ne i64 %na, %b
|
|
ret i1 %cmp
|
|
}
|
|
|
|
; Note: the 63 bits shift triggers a different optimization path, which leads
|
|
; to a similar result in terms of performances. We try to catch here any change
|
|
; so that this test can be adapted should the optimization be done with the
|
|
; operand swap.
|
|
define i1 @testSwapCmnWithLSL64_63(i64 %a, i64 %b) {
|
|
; CHECK-LABEL: testSwapCmnWithLSL64_63:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: cmp x1, x0, lsl #63
|
|
; CHECK-NEXT: cset w0, ne
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%shl = shl i64 %a, 63
|
|
%na = sub i64 0, %shl
|
|
%cmp = icmp ne i64 %na, %b
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @testSwapCmnWithLSL32_1(i32 %a, i32 %b) {
|
|
; CHECK-LABEL: testSwapCmnWithLSL32_1:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: cmn w1, w0, lsl #1
|
|
; CHECK-NEXT: cset w0, ne
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%shl = shl i32 %a, 1
|
|
%na = sub i32 0, %shl
|
|
%cmp = icmp ne i32 %na, %b
|
|
ret i1 %cmp
|
|
}
|
|
|
|
; Note: testing with a 30 bits shift as 30 has another optimization kicking in.
|
|
define i1 @testSwapCmnWithLSL32_30(i32 %a, i32 %b) {
|
|
; CHECK-LABEL: testSwapCmnWithLSL32_30:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: cmn w1, w0, lsl #30
|
|
; CHECK-NEXT: cset w0, ne
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%shl = shl i32 %a, 30
|
|
%na = sub i32 0, %shl
|
|
%cmp = icmp ne i32 %na, %b
|
|
ret i1 %cmp
|
|
}
|
|
|
|
; Note: the 31 bits shift triggers a different optimization path, which leads
|
|
; to a similar result in terms of performances. We try to catch here any change
|
|
; so that this test can be adapted should the optimization be done with the
|
|
; operand swap.
|
|
define i1 @testSwapCmnWithLSL32_31(i32 %a, i32 %b) {
|
|
; CHECK-LABEL: testSwapCmnWithLSL32_31:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: cmp w1, w0, lsl #31
|
|
; CHECK-NEXT: cset w0, ne
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%shl = shl i32 %a, 31
|
|
%na = sub i32 0, %shl
|
|
%cmp = icmp ne i32 %na, %b
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @testSwapCmnWithLSR64_1(i64 %a, i64 %b) {
|
|
; CHECK-LABEL: testSwapCmnWithLSR64_1:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: cmn x1, x0, lsr #1
|
|
; CHECK-NEXT: cset w0, ne
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%lshr = lshr i64 %a, 1
|
|
%na = sub i64 0, %lshr
|
|
%cmp = icmp ne i64 %na, %b
|
|
ret i1 %cmp
|
|
}
|
|
|
|
; Note: testing with a 62 bits shift as 63 has another optimization kicking in.
|
|
define i1 @testSwapCmnWithLSR64_62(i64 %a, i64 %b) {
|
|
; CHECK-LABEL: testSwapCmnWithLSR64_62:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: cmn x1, x0, lsr #62
|
|
; CHECK-NEXT: cset w0, ne
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%lshr = lshr i64 %a, 62
|
|
%na = sub i64 0, %lshr
|
|
%cmp = icmp ne i64 %na, %b
|
|
ret i1 %cmp
|
|
}
|
|
|
|
; Note: the 63 bits shift triggers a different optimization path, which leads
|
|
; to a similar result in terms of performances. We try to catch here any change
|
|
; so that this test can be adapted should the optimization be done with the
|
|
; operand swap.
|
|
define i1 @testSwapCmnWithLSR64_63(i64 %a, i64 %b) {
|
|
; CHECK-LABEL: testSwapCmnWithLSR64_63:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: cmp x1, x0, asr #63
|
|
; CHECK-NEXT: cset w0, ne
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%lshr = lshr i64 %a, 63
|
|
%na = sub i64 0, %lshr
|
|
%cmp = icmp ne i64 %na, %b
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @testSwapCmnWithLSR32_1(i32 %a, i32 %b) {
|
|
; CHECK-LABEL: testSwapCmnWithLSR32_1:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: cmn w1, w0, lsr #1
|
|
; CHECK-NEXT: cset w0, ne
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%lshr = lshr i32 %a, 1
|
|
%na = sub i32 0, %lshr
|
|
%cmp = icmp ne i32 %na, %b
|
|
ret i1 %cmp
|
|
}
|
|
|
|
; Note: testing with a 30 bits shift as 31 has another optimization kicking in.
|
|
define i1 @testSwapCmnWithLSR32_30(i32 %a, i32 %b) {
|
|
; CHECK-LABEL: testSwapCmnWithLSR32_30:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: cmn w1, w0, lsr #30
|
|
; CHECK-NEXT: cset w0, ne
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%lshr = lshr i32 %a, 30
|
|
%na = sub i32 0, %lshr
|
|
%cmp = icmp ne i32 %na, %b
|
|
ret i1 %cmp
|
|
}
|
|
|
|
; Note: the 31 bits shift triggers a different optimization path, which leads
|
|
; to a similar result in terms of performances. We try to catch here any change
|
|
; so that this test can be adapted should the optimization be done with the
|
|
; operand swap.
|
|
define i1 @testSwapCmnWithLSR32_31(i32 %a, i32 %b) {
|
|
; CHECK-LABEL: testSwapCmnWithLSR32_31:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: cmp w1, w0, asr #31
|
|
; CHECK-NEXT: cset w0, ne
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%lshr = lshr i32 %a, 31
|
|
%na = sub i32 0, %lshr
|
|
%cmp = icmp ne i32 %na, %b
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @testSwapCmnWithASR64_1(i64 %a, i64 %b) {
|
|
; CHECK-LABEL: testSwapCmnWithASR64_1:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: cmn x1, x0, asr #3
|
|
; CHECK-NEXT: cset w0, ne
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%lshr = ashr i64 %a, 3
|
|
%na = sub i64 0, %lshr
|
|
%cmp = icmp ne i64 %na, %b
|
|
ret i1 %cmp
|
|
}
|
|
|
|
; Note: testing with a 62 bits shift as 63 has another optimization kicking in.
|
|
define i1 @testSwapCmnWithASR64_62(i64 %a, i64 %b) {
|
|
; CHECK-LABEL: testSwapCmnWithASR64_62:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: cmn x1, x0, asr #62
|
|
; CHECK-NEXT: cset w0, ne
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%lshr = ashr i64 %a, 62
|
|
%na = sub i64 0, %lshr
|
|
%cmp = icmp ne i64 %na, %b
|
|
ret i1 %cmp
|
|
}
|
|
|
|
; Note: the 63 bits shift triggers a different optimization path, which leads
|
|
; to a similar result in terms of performances. We try to catch here any change
|
|
; so that this test can be adapted should the optimization be done with the
|
|
; operand swap.
|
|
define i1 @testSwapCmnWithASR64_63(i64 %a, i64 %b) {
|
|
; CHECK-LABEL: testSwapCmnWithASR64_63:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: cmp x1, x0, lsr #63
|
|
; CHECK-NEXT: cset w0, ne
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%lshr = ashr i64 %a, 63
|
|
%na = sub i64 0, %lshr
|
|
%cmp = icmp ne i64 %na, %b
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @testSwapCmnWithASR32_1(i32 %a, i32 %b) {
|
|
; CHECK-LABEL: testSwapCmnWithASR32_1:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: cmn w1, w0, asr #1
|
|
; CHECK-NEXT: cset w0, eq
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%lshr = ashr i32 %a, 1
|
|
%na = sub i32 0, %lshr
|
|
%cmp = icmp eq i32 %na, %b
|
|
ret i1 %cmp
|
|
}
|
|
|
|
; Note: testing with a 30 bits shift as 31 has another optimization kicking in.
|
|
define i1 @testSwapCmnWithASR32_30(i32 %a, i32 %b) {
|
|
; CHECK-LABEL: testSwapCmnWithASR32_30:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: cmn w1, w0, asr #30
|
|
; CHECK-NEXT: cset w0, ne
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%lshr = ashr i32 %a, 30
|
|
%na = sub i32 0, %lshr
|
|
%cmp = icmp ne i32 %na, %b
|
|
ret i1 %cmp
|
|
}
|
|
|
|
; Note: the 31 bits shift triggers a different optimization path, which leads
|
|
; to a similar result in terms of performances. We try to catch here any change
|
|
; so that this test can be adapted should the optimization be done with the
|
|
; operand swap.
|
|
define i1 @testSwapCmnWithASR32_31(i32 %a, i32 %b) {
|
|
; CHECK-LABEL: testSwapCmnWithASR32_31:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: cmp w1, w0, lsr #31
|
|
; CHECK-NEXT: cset w0, ne
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%lshr = ashr i32 %a, 31
|
|
%na = sub i32 0, %lshr
|
|
%cmp = icmp ne i32 %na, %b
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i64 @testSwapCmpToCmnWithZeroExtend(i32 %a32, i16 %a16, i8 %a8, i64 %b64, i32 %b32) {
|
|
; CHECK-LABEL: testSwapCmpToCmnWithZeroExtend:
|
|
; CHECK: // %bb.0: // %t0
|
|
; CHECK-NEXT: cmn x3, w0, uxtw #1
|
|
; CHECK-NEXT: b.eq .LBB44_8
|
|
; CHECK-NEXT: // %bb.1: // %t1
|
|
; CHECK-NEXT: cmn x3, w1, uxth #4
|
|
; CHECK-NEXT: b.eq .LBB44_8
|
|
; CHECK-NEXT: // %bb.2: // %t2
|
|
; CHECK-NEXT: cmn x3, w2, uxtb #3
|
|
; CHECK-NEXT: b.eq .LBB44_8
|
|
; CHECK-NEXT: // %bb.3: // %t3
|
|
; CHECK-NEXT: cmn w4, w1, uxth #2
|
|
; CHECK-NEXT: b.eq .LBB44_8
|
|
; CHECK-NEXT: // %bb.4: // %t4
|
|
; CHECK-NEXT: cmn w4, w2, uxtb #1
|
|
; CHECK-NEXT: b.eq .LBB44_8
|
|
; CHECK-NEXT: // %bb.5: // %t5
|
|
; CHECK-NEXT: and w8, w2, #0xff
|
|
; CHECK-NEXT: cmn w4, w8, lsl #5
|
|
; CHECK-NEXT: b.eq .LBB44_8
|
|
; CHECK-NEXT: // %bb.6: // %t6
|
|
; CHECK-NEXT: cmn w4, w2, uxtb
|
|
; CHECK-NEXT: b.eq .LBB44_8
|
|
; CHECK-NEXT: // %bb.7:
|
|
; CHECK-NEXT: mov x0, xzr
|
|
; CHECK-NEXT: ret
|
|
; CHECK-NEXT: .LBB44_8: // %end
|
|
; CHECK-NEXT: mov w0, #1 // =0x1
|
|
; CHECK-NEXT: ret
|
|
t0:
|
|
%conv0 = zext i32 %a32 to i64
|
|
%shl0 = shl i64 %conv0, 1
|
|
%na0 = sub i64 0, %shl0
|
|
%cmp0 = icmp ne i64 %na0, %b64
|
|
br i1 %cmp0, label %t1, label %end
|
|
|
|
t1:
|
|
%conv1 = zext i16 %a16 to i64
|
|
%shl1 = shl i64 %conv1, 4
|
|
%na1 = sub i64 0, %shl1
|
|
%cmp1 = icmp ne i64 %na1, %b64
|
|
br i1 %cmp1, label %t2, label %end
|
|
|
|
t2:
|
|
%conv2 = zext i8 %a8 to i64
|
|
%shl2 = shl i64 %conv2, 3
|
|
%na2 = sub i64 0, %shl2
|
|
%cmp2 = icmp ne i64 %na2, %b64
|
|
br i1 %cmp2, label %t3, label %end
|
|
|
|
t3:
|
|
%conv3 = zext i16 %a16 to i32
|
|
%shl3 = shl i32 %conv3, 2
|
|
%na3 = sub i32 0, %shl3
|
|
%cmp3 = icmp ne i32 %na3, %b32
|
|
br i1 %cmp3, label %t4, label %end
|
|
|
|
t4:
|
|
%conv4 = zext i8 %a8 to i32
|
|
%shl4 = shl i32 %conv4, 1
|
|
%na4 = sub i32 0, %shl4
|
|
%cmp4 = icmp ne i32 %na4, %b32
|
|
br i1 %cmp4, label %t5, label %end
|
|
|
|
t5:
|
|
%conv5 = zext i8 %a8 to i32
|
|
%shl5 = shl i32 %conv5, 5
|
|
%na5 = sub i32 0, %shl5
|
|
%cmp5 = icmp ne i32 %na5, %b32
|
|
br i1 %cmp5, label %t6, label %end
|
|
|
|
t6:
|
|
%conv6 = zext i8 %a8 to i32
|
|
%na6 = sub i32 0, %conv6
|
|
%cmp6 = icmp ne i32 %na6, %b32
|
|
br i1 %cmp6, label %t7, label %end
|
|
|
|
t7:
|
|
ret i64 0
|
|
|
|
end:
|
|
ret i64 1
|
|
}
|
|
define i64 @testSwapCmpToCmnWithSignExtend(i32 %a32, i16 %a16, i8 %a8, i64 %b64, i32 %b32) {
|
|
; CHECK-LABEL: testSwapCmpToCmnWithSignExtend:
|
|
; CHECK: // %bb.0: // %t0
|
|
; CHECK-NEXT: cmn x3, w0, sxtw #1
|
|
; CHECK-NEXT: b.eq .LBB45_8
|
|
; CHECK-NEXT: // %bb.1: // %t1
|
|
; CHECK-NEXT: cmn x3, w1, sxth #4
|
|
; CHECK-NEXT: b.eq .LBB45_8
|
|
; CHECK-NEXT: // %bb.2: // %t2
|
|
; CHECK-NEXT: cmn x3, w2, sxtb #3
|
|
; CHECK-NEXT: b.eq .LBB45_8
|
|
; CHECK-NEXT: // %bb.3: // %t3
|
|
; CHECK-NEXT: cmn w4, w1, sxth #2
|
|
; CHECK-NEXT: b.eq .LBB45_8
|
|
; CHECK-NEXT: // %bb.4: // %t4
|
|
; CHECK-NEXT: cmn w4, w2, sxtb #1
|
|
; CHECK-NEXT: b.eq .LBB45_8
|
|
; CHECK-NEXT: // %bb.5: // %t5
|
|
; CHECK-NEXT: sxtb w8, w2
|
|
; CHECK-NEXT: cmn w4, w8, lsl #5
|
|
; CHECK-NEXT: b.eq .LBB45_8
|
|
; CHECK-NEXT: // %bb.6: // %t6
|
|
; CHECK-NEXT: cmn w4, w2, sxtb
|
|
; CHECK-NEXT: b.eq .LBB45_8
|
|
; CHECK-NEXT: // %bb.7:
|
|
; CHECK-NEXT: mov x0, xzr
|
|
; CHECK-NEXT: ret
|
|
; CHECK-NEXT: .LBB45_8: // %end
|
|
; CHECK-NEXT: mov w0, #1 // =0x1
|
|
; CHECK-NEXT: ret
|
|
t0:
|
|
%conv0 = sext i32 %a32 to i64
|
|
%shl0 = shl i64 %conv0, 1
|
|
%na0 = sub i64 0, %shl0
|
|
%cmp0 = icmp ne i64 %na0, %b64
|
|
br i1 %cmp0, label %t1, label %end
|
|
|
|
t1:
|
|
%conv1 = sext i16 %a16 to i64
|
|
%shl1 = shl i64 %conv1, 4
|
|
%na1 = sub i64 0, %shl1
|
|
%cmp1 = icmp ne i64 %na1, %b64
|
|
br i1 %cmp1, label %t2, label %end
|
|
|
|
t2:
|
|
%conv2 = sext i8 %a8 to i64
|
|
%shl2 = shl i64 %conv2, 3
|
|
%na2 = sub i64 0, %shl2
|
|
%cmp2 = icmp ne i64 %na2, %b64
|
|
br i1 %cmp2, label %t3, label %end
|
|
|
|
t3:
|
|
%conv3 = sext i16 %a16 to i32
|
|
%shl3 = shl i32 %conv3, 2
|
|
%na3 = sub i32 0, %shl3
|
|
%cmp3 = icmp ne i32 %na3, %b32
|
|
br i1 %cmp3, label %t4, label %end
|
|
|
|
t4:
|
|
%conv4 = sext i8 %a8 to i32
|
|
%shl4 = shl i32 %conv4, 1
|
|
%na4 = sub i32 0, %shl4
|
|
%cmp4 = icmp ne i32 %na4, %b32
|
|
br i1 %cmp4, label %t5, label %end
|
|
|
|
t5:
|
|
%conv5 = sext i8 %a8 to i32
|
|
%shl5 = shl i32 %conv5, 5
|
|
%na5 = sub i32 0, %shl5
|
|
%cmp5 = icmp ne i32 %na5, %b32
|
|
br i1 %cmp5, label %t6, label %end
|
|
|
|
t6:
|
|
%conv6 = sext i8 %a8 to i32
|
|
%na6 = sub i32 0, %conv6
|
|
%cmp6 = icmp ne i32 %na6, %b32
|
|
br i1 %cmp6, label %t7, label %end
|
|
|
|
t7:
|
|
ret i64 0
|
|
|
|
end:
|
|
ret i64 1
|
|
}
|
|
|
|
define i1 @testSwapCmpWithLSL32_20(i32 %a) {
|
|
; CHECK-LABEL: testSwapCmpWithLSL32_20:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: cmp wzr, w0, lsl #20
|
|
; CHECK-NEXT: cset w0, lt
|
|
; CHECK-NEXT: ret
|
|
%shl = shl i32 %a, 20
|
|
%cmp = icmp sgt i32 %shl, 0
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @testSwapCmpWithLSR64_40(i64 %a) {
|
|
; CHECK-LABEL: testSwapCmpWithLSR64_40:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: cmp xzr, x0, lsr #40
|
|
; CHECK-NEXT: cset w0, eq
|
|
; CHECK-NEXT: ret
|
|
%cmp = icmp ult i64 %a, 1099511627776
|
|
ret i1 %cmp
|
|
}
|
|
|
|
declare void @use(i32)
|
|
|
|
define i1 @testSwapCmpWithLSL32_12_multiuse(i32 %a) nounwind {
|
|
; CHECK-LABEL: testSwapCmpWithLSL32_12_multiuse:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: stp x30, x19, [sp, #-16]! // 16-byte Folded Spill
|
|
; CHECK-NEXT: lsl w19, w0, #12
|
|
; CHECK-NEXT: mov w0, w19
|
|
; CHECK-NEXT: bl use
|
|
; CHECK-NEXT: cmp w19, #0
|
|
; CHECK-NEXT: cset w0, gt
|
|
; CHECK-NEXT: ldp x30, x19, [sp], #16 // 16-byte Folded Reload
|
|
; CHECK-NEXT: ret
|
|
%shl = shl i32 %a, 12
|
|
call void @use(i32 %shl)
|
|
%cmp = icmp sgt i32 %shl, 0
|
|
ret i1 %cmp
|
|
}
|