Files
TheRock/compiler/amd-llvm/llvm/test/CodeGen/AArch64/hadd-combine-scalar.ll
T
derek.holloway 7502bf64a4
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
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

869 lines
25 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=aarch64 | FileCheck %s --check-prefixes=CHECK,CHECK-SD
; RUN: llc < %s -mtriple=aarch64 -global-isel | FileCheck %s --check-prefixes=CHECK,CHECK-GI
define i32 @haddu_base(i32 %src1, i32 %src2) {
; CHECK-SD-LABEL: haddu_base:
; CHECK-SD: // %bb.0:
; CHECK-SD-NEXT: mov w8, w0
; CHECK-SD-NEXT: add x8, x8, w1, uxtw
; CHECK-SD-NEXT: lsr x0, x8, #1
; CHECK-SD-NEXT: // kill: def $w0 killed $w0 killed $x0
; CHECK-SD-NEXT: ret
;
; CHECK-GI-LABEL: haddu_base:
; CHECK-GI: // %bb.0:
; CHECK-GI-NEXT: mov w8, w1
; CHECK-GI-NEXT: add x8, x8, w0, uxtw
; CHECK-GI-NEXT: lsr x0, x8, #1
; CHECK-GI-NEXT: // kill: def $w0 killed $w0 killed $x0
; CHECK-GI-NEXT: ret
%zextsrc1 = zext i32 %src1 to i64
%zextsrc2 = zext i32 %src2 to i64
%add = add i64 %zextsrc1, %zextsrc2
%resulti32 = lshr i64 %add, 1
%result = trunc i64 %resulti32 to i32
ret i32 %result
}
define i32 @haddu_const(i32 %src1) {
; CHECK-LABEL: haddu_const:
; CHECK: // %bb.0:
; CHECK-NEXT: mov w8, w0
; CHECK-NEXT: add x8, x8, #1
; CHECK-NEXT: lsr x0, x8, #1
; CHECK-NEXT: // kill: def $w0 killed $w0 killed $x0
; CHECK-NEXT: ret
%zextsrc1 = zext i32 %src1 to i64
%add = add i64 %zextsrc1, 1
%resulti32 = lshr i64 %add, 1
%result = trunc i64 %resulti32 to i32
ret i32 %result
}
define i32 @haddu_const_lhs(i32 %src1) {
; CHECK-LABEL: haddu_const_lhs:
; CHECK: // %bb.0:
; CHECK-NEXT: mov w8, w0
; CHECK-NEXT: add x8, x8, #1
; CHECK-NEXT: lsr x0, x8, #1
; CHECK-NEXT: // kill: def $w0 killed $w0 killed $x0
; CHECK-NEXT: ret
%zextsrc1 = zext i32 %src1 to i64
%add = add i64 1, %zextsrc1
%resulti32 = lshr i64 %add, 1
%result = trunc i64 %resulti32 to i32
ret i32 %result
}
define i32 @haddu_const_zero(i32 %src1) {
; CHECK-LABEL: haddu_const_zero:
; CHECK: // %bb.0:
; CHECK-NEXT: mov w8, w0
; CHECK-NEXT: lsr x0, x8, #1
; CHECK-NEXT: // kill: def $w0 killed $w0 killed $x0
; CHECK-NEXT: ret
%zextsrc1 = zext i32 %src1 to i64
%add = add i64 0, %zextsrc1
%resulti32 = lshr i64 %add, 1
%result = trunc i64 %resulti32 to i32
ret i32 %result
}
define i32 @haddu_poison(i32 %src1) {
; CHECK-SD-LABEL: haddu_poison:
; CHECK-SD: // %bb.0:
; CHECK-SD-NEXT: mov w0, wzr
; CHECK-SD-NEXT: ret
;
; CHECK-GI-LABEL: haddu_poison:
; CHECK-GI: // %bb.0:
; CHECK-GI-NEXT: mov w8, w0
; CHECK-GI-NEXT: lsr x0, x8, #1
; CHECK-GI-NEXT: // kill: def $w0 killed $w0 killed $x0
; CHECK-GI-NEXT: ret
%zextsrc1 = zext i32 %src1 to i64
%zextsrc2 = zext i32 poison to i64
%add = add i64 %zextsrc2, %zextsrc1
%resulti32 = lshr i64 %add, 1
%result = trunc i64 %resulti32 to i32
ret i32 %result
}
define i32 @hadds_base(i32 %src1, i32 %src2) {
; CHECK-SD-LABEL: hadds_base:
; CHECK-SD: // %bb.0:
; CHECK-SD-NEXT: // kill: def $w0 killed $w0 def $x0
; CHECK-SD-NEXT: sxtw x8, w0
; CHECK-SD-NEXT: add x8, x8, w1, sxtw
; CHECK-SD-NEXT: lsr x0, x8, #1
; CHECK-SD-NEXT: // kill: def $w0 killed $w0 killed $x0
; CHECK-SD-NEXT: ret
;
; CHECK-GI-LABEL: hadds_base:
; CHECK-GI: // %bb.0:
; CHECK-GI-NEXT: // kill: def $w1 killed $w1 def $x1
; CHECK-GI-NEXT: sxtw x8, w1
; CHECK-GI-NEXT: add x8, x8, w0, sxtw
; CHECK-GI-NEXT: asr x0, x8, #1
; CHECK-GI-NEXT: // kill: def $w0 killed $w0 killed $x0
; CHECK-GI-NEXT: ret
%zextsrc1 = sext i32 %src1 to i64
%zextsrc2 = sext i32 %src2 to i64
%add = add i64 %zextsrc1, %zextsrc2
%resulti32 = ashr i64 %add, 1
%result = trunc i64 %resulti32 to i32
ret i32 %result
}
define i32 @hadds_const(i32 %src1) {
; CHECK-SD-LABEL: hadds_const:
; CHECK-SD: // %bb.0:
; CHECK-SD-NEXT: // kill: def $w0 killed $w0 def $x0
; CHECK-SD-NEXT: sxtw x8, w0
; CHECK-SD-NEXT: add x8, x8, #1
; CHECK-SD-NEXT: lsr x0, x8, #1
; CHECK-SD-NEXT: // kill: def $w0 killed $w0 killed $x0
; CHECK-SD-NEXT: ret
;
; CHECK-GI-LABEL: hadds_const:
; CHECK-GI: // %bb.0:
; CHECK-GI-NEXT: // kill: def $w0 killed $w0 def $x0
; CHECK-GI-NEXT: sxtw x8, w0
; CHECK-GI-NEXT: add x8, x8, #1
; CHECK-GI-NEXT: asr x0, x8, #1
; CHECK-GI-NEXT: // kill: def $w0 killed $w0 killed $x0
; CHECK-GI-NEXT: ret
%zextsrc1 = sext i32 %src1 to i64
%add = add i64 %zextsrc1, 1
%resulti32 = ashr i64 %add, 1
%result = trunc i64 %resulti32 to i32
ret i32 %result
}
define i32 @hadds_const_lhs(i32 %src1) {
; CHECK-SD-LABEL: hadds_const_lhs:
; CHECK-SD: // %bb.0:
; CHECK-SD-NEXT: // kill: def $w0 killed $w0 def $x0
; CHECK-SD-NEXT: sxtw x8, w0
; CHECK-SD-NEXT: add x8, x8, #1
; CHECK-SD-NEXT: lsr x0, x8, #1
; CHECK-SD-NEXT: // kill: def $w0 killed $w0 killed $x0
; CHECK-SD-NEXT: ret
;
; CHECK-GI-LABEL: hadds_const_lhs:
; CHECK-GI: // %bb.0:
; CHECK-GI-NEXT: // kill: def $w0 killed $w0 def $x0
; CHECK-GI-NEXT: sxtw x8, w0
; CHECK-GI-NEXT: add x8, x8, #1
; CHECK-GI-NEXT: asr x0, x8, #1
; CHECK-GI-NEXT: // kill: def $w0 killed $w0 killed $x0
; CHECK-GI-NEXT: ret
%zextsrc1 = sext i32 %src1 to i64
%add = add i64 1, %zextsrc1
%resulti32 = ashr i64 %add, 1
%result = trunc i64 %resulti32 to i32
ret i32 %result
}
define i32 @hadds_const_zero(i32 %src1) {
; CHECK-SD-LABEL: hadds_const_zero:
; CHECK-SD: // %bb.0:
; CHECK-SD-NEXT: // kill: def $w0 killed $w0 def $x0
; CHECK-SD-NEXT: sxtw x8, w0
; CHECK-SD-NEXT: lsr x0, x8, #1
; CHECK-SD-NEXT: // kill: def $w0 killed $w0 killed $x0
; CHECK-SD-NEXT: ret
;
; CHECK-GI-LABEL: hadds_const_zero:
; CHECK-GI: // %bb.0:
; CHECK-GI-NEXT: // kill: def $w0 killed $w0 def $x0
; CHECK-GI-NEXT: sbfx x0, x0, #1, #31
; CHECK-GI-NEXT: // kill: def $w0 killed $w0 killed $x0
; CHECK-GI-NEXT: ret
%zextsrc1 = sext i32 %src1 to i64
%add = add i64 0, %zextsrc1
%resulti32 = ashr i64 %add, 1
%result = trunc i64 %resulti32 to i32
ret i32 %result
}
define i32 @hadds_poison(i32 %src1) {
; CHECK-SD-LABEL: hadds_poison:
; CHECK-SD: // %bb.0:
; CHECK-SD-NEXT: mov w0, wzr
; CHECK-SD-NEXT: ret
;
; CHECK-GI-LABEL: hadds_poison:
; CHECK-GI: // %bb.0:
; CHECK-GI-NEXT: // kill: def $w0 killed $w0 def $x0
; CHECK-GI-NEXT: sbfx x0, x0, #1, #31
; CHECK-GI-NEXT: // kill: def $w0 killed $w0 killed $x0
; CHECK-GI-NEXT: ret
%zextsrc1 = sext i32 %src1 to i64
%zextsrc2 = sext i32 poison to i64
%add = add i64 %zextsrc2, %zextsrc1
%resulti32 = ashr i64 %add, 1
%result = trunc i64 %resulti32 to i32
ret i32 %result
}
define i32 @sub_i64(i32 %a0, i32 %a1) {
; CHECK-SD-LABEL: sub_i64:
; CHECK-SD: // %bb.0:
; CHECK-SD-NEXT: mov w8, w0
; CHECK-SD-NEXT: add x8, x8, w1, uxtw
; CHECK-SD-NEXT: add x8, x8, #1
; CHECK-SD-NEXT: lsr x0, x8, #1
; CHECK-SD-NEXT: // kill: def $w0 killed $w0 killed $x0
; CHECK-SD-NEXT: ret
;
; CHECK-GI-LABEL: sub_i64:
; CHECK-GI: // %bb.0:
; CHECK-GI-NEXT: orr w8, w0, w1
; CHECK-GI-NEXT: eor w9, w0, w1
; CHECK-GI-NEXT: sub w0, w8, w9, lsr #1
; CHECK-GI-NEXT: ret
%or = or i32 %a0, %a1
%xor = xor i32 %a0, %a1
%srl = lshr i32 %xor, 1
%res = sub i32 %or, %srl
ret i32 %res
}
define i32 @srhadd_i32(i32 %a0, i32 %a1) {
; CHECK-SD-LABEL: srhadd_i32:
; CHECK-SD: // %bb.0:
; CHECK-SD-NEXT: // kill: def $w0 killed $w0 def $x0
; CHECK-SD-NEXT: sxtw x8, w0
; CHECK-SD-NEXT: add x8, x8, w1, sxtw
; CHECK-SD-NEXT: add x8, x8, #1
; CHECK-SD-NEXT: lsr x0, x8, #1
; CHECK-SD-NEXT: // kill: def $w0 killed $w0 killed $x0
; CHECK-SD-NEXT: ret
;
; CHECK-GI-LABEL: srhadd_i32:
; CHECK-GI: // %bb.0:
; CHECK-GI-NEXT: orr w8, w0, w1
; CHECK-GI-NEXT: eor w9, w0, w1
; CHECK-GI-NEXT: sub w0, w8, w9, asr #1
; CHECK-GI-NEXT: ret
%or = or i32 %a0, %a1
%xor = xor i32 %a0, %a1
%srl = ashr i32 %xor, 1
%res = sub i32 %or, %srl
ret i32 %res
}
define i32 @rhaddu_base(i32 %src1, i32 %src2) {
; CHECK-SD-LABEL: rhaddu_base:
; CHECK-SD: // %bb.0:
; CHECK-SD-NEXT: mov w8, w0
; CHECK-SD-NEXT: add x8, x8, w1, uxtw
; CHECK-SD-NEXT: add x8, x8, #1
; CHECK-SD-NEXT: lsr x0, x8, #1
; CHECK-SD-NEXT: // kill: def $w0 killed $w0 killed $x0
; CHECK-SD-NEXT: ret
;
; CHECK-GI-LABEL: rhaddu_base:
; CHECK-GI: // %bb.0:
; CHECK-GI-NEXT: mov w8, w1
; CHECK-GI-NEXT: add x8, x8, w0, uxtw
; CHECK-GI-NEXT: add x8, x8, #1
; CHECK-GI-NEXT: lsr x0, x8, #1
; CHECK-GI-NEXT: // kill: def $w0 killed $w0 killed $x0
; CHECK-GI-NEXT: ret
%zextsrc1 = zext i32 %src1 to i64
%zextsrc2 = zext i32 %src2 to i64
%add1 = add i64 %zextsrc1, %zextsrc2
%add = add i64 %add1, 1
%resulti32 = lshr i64 %add, 1
%result = trunc i64 %resulti32 to i32
ret i32 %result
}
define i32 @rhaddu_const(i32 %src1) {
; CHECK-LABEL: rhaddu_const:
; CHECK: // %bb.0:
; CHECK-NEXT: mov w8, w0
; CHECK-NEXT: add x8, x8, #2
; CHECK-NEXT: lsr x0, x8, #1
; CHECK-NEXT: // kill: def $w0 killed $w0 killed $x0
; CHECK-NEXT: ret
%zextsrc1 = zext i32 %src1 to i64
%add1 = add i64 %zextsrc1, 1
%add = add i64 %add1, 1
%resulti32 = lshr i64 %add, 1
%result = trunc i64 %resulti32 to i32
ret i32 %result
}
define i32 @rhaddu_const_lhs(i32 %src1) {
; CHECK-LABEL: rhaddu_const_lhs:
; CHECK: // %bb.0:
; CHECK-NEXT: mov w8, w0
; CHECK-NEXT: add x8, x8, #2
; CHECK-NEXT: lsr x0, x8, #1
; CHECK-NEXT: // kill: def $w0 killed $w0 killed $x0
; CHECK-NEXT: ret
%zextsrc1 = zext i32 %src1 to i64
%add1 = add i64 1, %zextsrc1
%add = add i64 %add1, 1
%resulti32 = lshr i64 %add, 1
%result = trunc i64 %resulti32 to i32
ret i32 %result
}
define i32 @rhaddu_const_zero(i32 %src1) {
; CHECK-LABEL: rhaddu_const_zero:
; CHECK: // %bb.0:
; CHECK-NEXT: mov w8, w0
; CHECK-NEXT: add x8, x8, #1
; CHECK-NEXT: lsr x0, x8, #1
; CHECK-NEXT: // kill: def $w0 killed $w0 killed $x0
; CHECK-NEXT: ret
%zextsrc1 = zext i32 %src1 to i64
%add1 = add i64 0, %zextsrc1
%add = add i64 %add1, 1
%resulti32 = lshr i64 %add, 1
%result = trunc i64 %resulti32 to i32
ret i32 %result
}
define i32 @rhaddu_poison(i32 %src1) {
; CHECK-SD-LABEL: rhaddu_poison:
; CHECK-SD: // %bb.0:
; CHECK-SD-NEXT: mov w0, wzr
; CHECK-SD-NEXT: ret
;
; CHECK-GI-LABEL: rhaddu_poison:
; CHECK-GI: // %bb.0:
; CHECK-GI-NEXT: mov w8, w0
; CHECK-GI-NEXT: add x8, x8, #1
; CHECK-GI-NEXT: lsr x0, x8, #1
; CHECK-GI-NEXT: // kill: def $w0 killed $w0 killed $x0
; CHECK-GI-NEXT: ret
%zextsrc1 = zext i32 %src1 to i64
%zextsrc2 = zext i32 poison to i64
%add1 = add i64 %zextsrc2, %zextsrc1
%add = add i64 %add1, 1
%resulti32 = lshr i64 %add, 1
%result = trunc i64 %resulti32 to i32
ret i32 %result
}
define i32 @rhadds_base(i32 %src1, i32 %src2) {
; CHECK-SD-LABEL: rhadds_base:
; CHECK-SD: // %bb.0:
; CHECK-SD-NEXT: // kill: def $w0 killed $w0 def $x0
; CHECK-SD-NEXT: sxtw x8, w0
; CHECK-SD-NEXT: add x8, x8, w1, sxtw
; CHECK-SD-NEXT: add x8, x8, #1
; CHECK-SD-NEXT: lsr x0, x8, #1
; CHECK-SD-NEXT: // kill: def $w0 killed $w0 killed $x0
; CHECK-SD-NEXT: ret
;
; CHECK-GI-LABEL: rhadds_base:
; CHECK-GI: // %bb.0:
; CHECK-GI-NEXT: // kill: def $w1 killed $w1 def $x1
; CHECK-GI-NEXT: sxtw x8, w1
; CHECK-GI-NEXT: add x8, x8, w0, sxtw
; CHECK-GI-NEXT: add x8, x8, #1
; CHECK-GI-NEXT: asr x0, x8, #1
; CHECK-GI-NEXT: // kill: def $w0 killed $w0 killed $x0
; CHECK-GI-NEXT: ret
%zextsrc1 = sext i32 %src1 to i64
%zextsrc2 = sext i32 %src2 to i64
%add1 = add i64 %zextsrc1, %zextsrc2
%add = add i64 %add1, 1
%resulti32 = ashr i64 %add, 1
%result = trunc i64 %resulti32 to i32
ret i32 %result
}
define i32 @rhadds_const(i32 %src1) {
; CHECK-SD-LABEL: rhadds_const:
; CHECK-SD: // %bb.0:
; CHECK-SD-NEXT: // kill: def $w0 killed $w0 def $x0
; CHECK-SD-NEXT: sxtw x8, w0
; CHECK-SD-NEXT: add x8, x8, #2
; CHECK-SD-NEXT: lsr x0, x8, #1
; CHECK-SD-NEXT: // kill: def $w0 killed $w0 killed $x0
; CHECK-SD-NEXT: ret
;
; CHECK-GI-LABEL: rhadds_const:
; CHECK-GI: // %bb.0:
; CHECK-GI-NEXT: // kill: def $w0 killed $w0 def $x0
; CHECK-GI-NEXT: sxtw x8, w0
; CHECK-GI-NEXT: add x8, x8, #2
; CHECK-GI-NEXT: asr x0, x8, #1
; CHECK-GI-NEXT: // kill: def $w0 killed $w0 killed $x0
; CHECK-GI-NEXT: ret
%zextsrc1 = sext i32 %src1 to i64
%add1 = add i64 %zextsrc1, 1
%add = add i64 %add1, 1
%resulti32 = ashr i64 %add, 1
%result = trunc i64 %resulti32 to i32
ret i32 %result
}
define i32 @rhadds_const_lhs(i32 %src1) {
; CHECK-SD-LABEL: rhadds_const_lhs:
; CHECK-SD: // %bb.0:
; CHECK-SD-NEXT: // kill: def $w0 killed $w0 def $x0
; CHECK-SD-NEXT: sxtw x8, w0
; CHECK-SD-NEXT: add x8, x8, #2
; CHECK-SD-NEXT: lsr x0, x8, #1
; CHECK-SD-NEXT: // kill: def $w0 killed $w0 killed $x0
; CHECK-SD-NEXT: ret
;
; CHECK-GI-LABEL: rhadds_const_lhs:
; CHECK-GI: // %bb.0:
; CHECK-GI-NEXT: // kill: def $w0 killed $w0 def $x0
; CHECK-GI-NEXT: sxtw x8, w0
; CHECK-GI-NEXT: add x8, x8, #2
; CHECK-GI-NEXT: asr x0, x8, #1
; CHECK-GI-NEXT: // kill: def $w0 killed $w0 killed $x0
; CHECK-GI-NEXT: ret
%zextsrc1 = sext i32 %src1 to i64
%add1 = add i64 1, %zextsrc1
%add = add i64 %add1, 1
%resulti32 = ashr i64 %add, 1
%result = trunc i64 %resulti32 to i32
ret i32 %result
}
define i32 @rhadds_const_zero(i32 %src1) {
; CHECK-SD-LABEL: rhadds_const_zero:
; CHECK-SD: // %bb.0:
; CHECK-SD-NEXT: // kill: def $w0 killed $w0 def $x0
; CHECK-SD-NEXT: sxtw x8, w0
; CHECK-SD-NEXT: add x8, x8, #1
; CHECK-SD-NEXT: lsr x0, x8, #1
; CHECK-SD-NEXT: // kill: def $w0 killed $w0 killed $x0
; CHECK-SD-NEXT: ret
;
; CHECK-GI-LABEL: rhadds_const_zero:
; CHECK-GI: // %bb.0:
; CHECK-GI-NEXT: // kill: def $w0 killed $w0 def $x0
; CHECK-GI-NEXT: sxtw x8, w0
; CHECK-GI-NEXT: add x8, x8, #1
; CHECK-GI-NEXT: asr x0, x8, #1
; CHECK-GI-NEXT: // kill: def $w0 killed $w0 killed $x0
; CHECK-GI-NEXT: ret
%zextsrc1 = sext i32 %src1 to i64
%add1 = add i64 0, %zextsrc1
%add = add i64 %add1, 1
%resulti32 = ashr i64 %add, 1
%result = trunc i64 %resulti32 to i32
ret i32 %result
}
define i32 @rhadds_const_both() {
; CHECK-LABEL: rhadds_const_both:
; CHECK: // %bb.0:
; CHECK-NEXT: mov w0, #2 // =0x2
; CHECK-NEXT: ret
%add1 = add i64 3, 1
%add = add i64 %add1, 1
%resulti32 = ashr i64 %add, 1
%result = trunc i64 %resulti32 to i32
ret i32 %result
}
define i32 @rhadds_const_bothhigh() {
; CHECK-LABEL: rhadds_const_bothhigh:
; CHECK: // %bb.0:
; CHECK-NEXT: mov w0, #32767 // =0x7fff
; CHECK-NEXT: ret
%ext1 = sext i32 32766 to i64
%ext2 = sext i32 32767 to i64
%add1 = add i64 %ext1, %ext2
%add = add i64 %add1, 1
%resulti32 = ashr i64 %add, 1
%result = trunc i64 %resulti32 to i32
ret i32 %result
}
define i32 @rhadds_poison(i32 %src1) {
; CHECK-SD-LABEL: rhadds_poison:
; CHECK-SD: // %bb.0:
; CHECK-SD-NEXT: mov w0, wzr
; CHECK-SD-NEXT: ret
;
; CHECK-GI-LABEL: rhadds_poison:
; CHECK-GI: // %bb.0:
; CHECK-GI-NEXT: // kill: def $w0 killed $w0 def $x0
; CHECK-GI-NEXT: sxtw x8, w0
; CHECK-GI-NEXT: add x8, x8, #1
; CHECK-GI-NEXT: asr x0, x8, #1
; CHECK-GI-NEXT: // kill: def $w0 killed $w0 killed $x0
; CHECK-GI-NEXT: ret
%zextsrc1 = sext i32 %src1 to i64
%zextsrc2 = sext i32 poison to i64
%add1 = add i64 %zextsrc2, %zextsrc1
%add = add i64 %add1, 1
%resulti32 = ashr i64 %add, 1
%result = trunc i64 %resulti32 to i32
ret i32 %result
}
define i32 @uhadd_i64(i32 %a0, i32 %a1) {
; CHECK-SD-LABEL: uhadd_i64:
; CHECK-SD: // %bb.0:
; CHECK-SD-NEXT: mov w8, w0
; CHECK-SD-NEXT: add x8, x8, w1, uxtw
; CHECK-SD-NEXT: lsr x0, x8, #1
; CHECK-SD-NEXT: // kill: def $w0 killed $w0 killed $x0
; CHECK-SD-NEXT: ret
;
; CHECK-GI-LABEL: uhadd_i64:
; CHECK-GI: // %bb.0:
; CHECK-GI-NEXT: and w8, w0, w1
; CHECK-GI-NEXT: eor w9, w0, w1
; CHECK-GI-NEXT: add w0, w8, w9, lsr #1
; CHECK-GI-NEXT: ret
%and = and i32 %a0, %a1
%xor = xor i32 %a0, %a1
%srl = lshr i32 %xor, 1
%res = add i32 %and, %srl
ret i32 %res
}
define i32 @shadd_i32(i32 %a0, i32 %a1) {
; CHECK-SD-LABEL: shadd_i32:
; CHECK-SD: // %bb.0:
; CHECK-SD-NEXT: // kill: def $w0 killed $w0 def $x0
; CHECK-SD-NEXT: sxtw x8, w0
; CHECK-SD-NEXT: add x8, x8, w1, sxtw
; CHECK-SD-NEXT: lsr x0, x8, #1
; CHECK-SD-NEXT: // kill: def $w0 killed $w0 killed $x0
; CHECK-SD-NEXT: ret
;
; CHECK-GI-LABEL: shadd_i32:
; CHECK-GI: // %bb.0:
; CHECK-GI-NEXT: and w8, w0, w1
; CHECK-GI-NEXT: eor w9, w0, w1
; CHECK-GI-NEXT: add w0, w8, w9, asr #1
; CHECK-GI-NEXT: ret
%and = and i32 %a0, %a1
%xor = xor i32 %a0, %a1
%srl = ashr i32 %xor, 1
%res = add i32 %and, %srl
ret i32 %res
}
define i64 @shadd_signbits_i64(i64 %a0, i64 %a1, ptr %p2) {
; CHECK-SD-LABEL: shadd_signbits_i64:
; CHECK-SD: // %bb.0:
; CHECK-SD-NEXT: asr x8, x0, #17
; CHECK-SD-NEXT: add x8, x8, x1, asr #17
; CHECK-SD-NEXT: asr x0, x8, #1
; CHECK-SD-NEXT: str x0, [x2]
; CHECK-SD-NEXT: ret
;
; CHECK-GI-LABEL: shadd_signbits_i64:
; CHECK-GI: // %bb.0:
; CHECK-GI-NEXT: asr x8, x0, #17
; CHECK-GI-NEXT: asr x9, x1, #17
; CHECK-GI-NEXT: and x10, x8, x9
; CHECK-GI-NEXT: eor x8, x8, x9
; CHECK-GI-NEXT: add x8, x10, x8, asr #1
; CHECK-GI-NEXT: sbfx x0, x8, #0, #47
; CHECK-GI-NEXT: str x8, [x2]
; CHECK-GI-NEXT: ret
%x0 = ashr i64 %a0, 17
%x1 = ashr i64 %a1, 17
%m = and i64 %x0, %x1
%s = xor i64 %x0, %x1
%x = ashr i64 %s, 1
%avg = add i64 %m, %x
%avg1 = shl i64 %avg, 17
%avg2 = ashr i64 %avg1, 17
store i64 %avg, ptr %p2 ; extra use
ret i64 %avg2
}
define i64 @srhadd_signbits_i64(i64 %a0, i64 %a1, ptr %p2) {
; CHECK-SD-LABEL: srhadd_signbits_i64:
; CHECK-SD: // %bb.0:
; CHECK-SD-NEXT: asr x8, x0, #17
; CHECK-SD-NEXT: add x8, x8, x1, asr #17
; CHECK-SD-NEXT: add x8, x8, #1
; CHECK-SD-NEXT: asr x0, x8, #1
; CHECK-SD-NEXT: str x0, [x2]
; CHECK-SD-NEXT: ret
;
; CHECK-GI-LABEL: srhadd_signbits_i64:
; CHECK-GI: // %bb.0:
; CHECK-GI-NEXT: asr x8, x0, #17
; CHECK-GI-NEXT: asr x9, x1, #17
; CHECK-GI-NEXT: orr x10, x8, x9
; CHECK-GI-NEXT: eor x8, x8, x9
; CHECK-GI-NEXT: sub x8, x10, x8, asr #1
; CHECK-GI-NEXT: sbfx x0, x8, #0, #47
; CHECK-GI-NEXT: str x8, [x2]
; CHECK-GI-NEXT: ret
%x0 = ashr i64 %a0, 17
%x1 = ashr i64 %a1, 17
%m = or i64 %x0, %x1
%s = xor i64 %x0, %x1
%x = ashr i64 %s, 1
%avg = sub i64 %m, %x
%avg1 = shl i64 %avg, 17
%avg2 = ashr i64 %avg1, 17
store i64 %avg, ptr %p2 ; extra use
ret i64 %avg2
}
; negative test - not enough signbits to remove sign_extend_inreg after srhadd
define i64 @srhadd_signbits_i64_negative(i64 %a0, i64 %a1, ptr %p2) {
; CHECK-SD-LABEL: srhadd_signbits_i64_negative:
; CHECK-SD: // %bb.0:
; CHECK-SD-NEXT: asr x8, x0, #17
; CHECK-SD-NEXT: add x8, x8, x1, asr #17
; CHECK-SD-NEXT: add x8, x8, #1
; CHECK-SD-NEXT: asr x8, x8, #1
; CHECK-SD-NEXT: sbfx x0, x8, #0, #42
; CHECK-SD-NEXT: str x8, [x2]
; CHECK-SD-NEXT: ret
;
; CHECK-GI-LABEL: srhadd_signbits_i64_negative:
; CHECK-GI: // %bb.0:
; CHECK-GI-NEXT: asr x8, x0, #17
; CHECK-GI-NEXT: asr x9, x1, #17
; CHECK-GI-NEXT: orr x10, x8, x9
; CHECK-GI-NEXT: eor x8, x8, x9
; CHECK-GI-NEXT: sub x8, x10, x8, asr #1
; CHECK-GI-NEXT: sbfx x0, x8, #0, #42
; CHECK-GI-NEXT: str x8, [x2]
; CHECK-GI-NEXT: ret
%x0 = ashr i64 %a0, 17
%x1 = ashr i64 %a1, 17
%m = or i64 %x0, %x1
%s = xor i64 %x0, %x1
%x = ashr i64 %s, 1
%avg = sub i64 %m, %x
%avg1 = shl i64 %avg, 22
%avg2 = ashr i64 %avg1, 22
store i64 %avg, ptr %p2 ; extra use
ret i64 %avg2
}
define i32 @haddu_nuw(i32 %src1, i32 %src2) {
; CHECK-LABEL: haddu_nuw:
; CHECK: // %bb.0:
; CHECK-NEXT: add w8, w0, w1
; CHECK-NEXT: lsr w0, w8, #1
; CHECK-NEXT: ret
%add = add nuw i32 %src1, %src2
%result = lshr i32 %add, 1
ret i32 %result
}
define i32 @hadds_nsw(i32 %src1, i32 %src2) {
; CHECK-LABEL: hadds_nsw:
; CHECK: // %bb.0:
; CHECK-NEXT: add w8, w0, w1
; CHECK-NEXT: asr w0, w8, #1
; CHECK-NEXT: ret
%add = add nsw i32 %src1, %src2
%result = ashr i32 %add, 1
ret i32 %result
}
define i32 @hraddu_nuw(i32 %src1, i32 %src2) {
; CHECK-LABEL: hraddu_nuw:
; CHECK: // %bb.0:
; CHECK-NEXT: add w8, w0, w1
; CHECK-NEXT: add w8, w8, #1
; CHECK-NEXT: lsr w0, w8, #1
; CHECK-NEXT: ret
%add = add nuw i32 %src1, %src2
%add2 = add nsw i32 %add, 1
%result = lshr i32 %add2, 1
ret i32 %result
}
define i32 @hradds_nsw(i32 %src1, i32 %src2) {
; CHECK-LABEL: hradds_nsw:
; CHECK: // %bb.0:
; CHECK-NEXT: add w8, w0, w1
; CHECK-NEXT: add w8, w8, #1
; CHECK-NEXT: asr w0, w8, #1
; CHECK-NEXT: ret
%add = add nsw i32 %src1, %src2
%add2 = add nsw i32 %add, 1
%result = ashr i32 %add2, 1
ret i32 %result
}
; avgfloor(A, B) from (A & B) + ((A ^ B) >> 1)
define i32 @avgflooru_from_andaddshift(i32 %a, i32 %b) {
; CHECK-SD-LABEL: avgflooru_from_andaddshift:
; CHECK-SD: // %bb.0:
; CHECK-SD-NEXT: mov w8, w0
; CHECK-SD-NEXT: add x8, x8, w1, uxtw
; CHECK-SD-NEXT: lsr x0, x8, #1
; CHECK-SD-NEXT: // kill: def $w0 killed $w0 killed $x0
; CHECK-SD-NEXT: ret
;
; CHECK-GI-LABEL: avgflooru_from_andaddshift:
; CHECK-GI: // %bb.0:
; CHECK-GI-NEXT: eor w8, w0, w1
; CHECK-GI-NEXT: and w9, w0, w1
; CHECK-GI-NEXT: add w0, w9, w8, lsr #1
; CHECK-GI-NEXT: ret
%c = xor i32 %a, %b
%d = lshr i32 %c, 1
%e = and i32 %a, %b
%f = add i32 %d, %e
ret i32 %f
}
; avgfloor(A, B) from (A & B) + ((A ^ B) >> 1)
define i32 @avgfloors_from_andaddshift(i32 %a, i32 %b) {
; CHECK-SD-LABEL: avgfloors_from_andaddshift:
; CHECK-SD: // %bb.0:
; CHECK-SD-NEXT: // kill: def $w0 killed $w0 def $x0
; CHECK-SD-NEXT: sxtw x8, w0
; CHECK-SD-NEXT: add x8, x8, w1, sxtw
; CHECK-SD-NEXT: lsr x0, x8, #1
; CHECK-SD-NEXT: // kill: def $w0 killed $w0 killed $x0
; CHECK-SD-NEXT: ret
;
; CHECK-GI-LABEL: avgfloors_from_andaddshift:
; CHECK-GI: // %bb.0:
; CHECK-GI-NEXT: eor w8, w0, w1
; CHECK-GI-NEXT: and w9, w0, w1
; CHECK-GI-NEXT: add w0, w9, w8, asr #1
; CHECK-GI-NEXT: ret
%c = xor i32 %a, %b
%d = ashr i32 %c, 1
%e = and i32 %a, %b
%f = add i32 %d, %e
ret i32 %f
}
; avgfloor(A, B) from ((A >> 1) + (B >> 1)) + (A & B & 1)
define i32 @avgflooru_from_shiftaddand(i32 %a, i32 %b) {
; CHECK-SD-LABEL: avgflooru_from_shiftaddand:
; CHECK-SD: // %bb.0:
; CHECK-SD-NEXT: mov w8, w0
; CHECK-SD-NEXT: add x8, x8, w1, uxtw
; CHECK-SD-NEXT: lsr x0, x8, #1
; CHECK-SD-NEXT: // kill: def $w0 killed $w0 killed $x0
; CHECK-SD-NEXT: ret
;
; CHECK-GI-LABEL: avgflooru_from_shiftaddand:
; CHECK-GI: // %bb.0:
; CHECK-GI-NEXT: lsr w8, w1, #1
; CHECK-GI-NEXT: and w9, w0, w1
; CHECK-GI-NEXT: and w9, w9, #0x1
; CHECK-GI-NEXT: add w8, w8, w0, lsr #1
; CHECK-GI-NEXT: add w0, w8, w9
; CHECK-GI-NEXT: ret
%c = lshr i32 %a, 1
%d = lshr i32 %b, 1
%e = add i32 %c, %d
%f = and i32 %a, %b
%g = and i32 %f, 1
%h = add i32 %e, %g
ret i32 %h
}
; avgfloor(A, B) from ((A >> 1) + (B >> 1)) + (A & B & 1)
define i32 @avgfloors_from_shiftaddand(i32 %a, i32 %b) {
; CHECK-SD-LABEL: avgfloors_from_shiftaddand:
; CHECK-SD: // %bb.0:
; CHECK-SD-NEXT: // kill: def $w0 killed $w0 def $x0
; CHECK-SD-NEXT: sxtw x8, w0
; CHECK-SD-NEXT: add x8, x8, w1, sxtw
; CHECK-SD-NEXT: lsr x0, x8, #1
; CHECK-SD-NEXT: // kill: def $w0 killed $w0 killed $x0
; CHECK-SD-NEXT: ret
;
; CHECK-GI-LABEL: avgfloors_from_shiftaddand:
; CHECK-GI: // %bb.0:
; CHECK-GI-NEXT: asr w8, w1, #1
; CHECK-GI-NEXT: and w9, w0, w1
; CHECK-GI-NEXT: and w9, w9, #0x1
; CHECK-GI-NEXT: add w8, w8, w0, asr #1
; CHECK-GI-NEXT: add w0, w8, w9
; CHECK-GI-NEXT: ret
%c = ashr i32 %a, 1
%d = ashr i32 %b, 1
%e = add i32 %c, %d
%f = and i32 %a, %b
%g = and i32 %f, 1
%h = add i32 %e, %g
ret i32 %h
}
; avgceil(A, B) from ((A >> 1) + (B >> 1)) + ((A | B) & 1)
define i32 @avgceilu_from_shiftaddand(i32 %a, i32 %b) {
; CHECK-SD-LABEL: avgceilu_from_shiftaddand:
; CHECK-SD: // %bb.0:
; CHECK-SD-NEXT: mov w8, w0
; CHECK-SD-NEXT: add x8, x8, w1, uxtw
; CHECK-SD-NEXT: add x8, x8, #1
; CHECK-SD-NEXT: lsr x0, x8, #1
; CHECK-SD-NEXT: // kill: def $w0 killed $w0 killed $x0
; CHECK-SD-NEXT: ret
;
; CHECK-GI-LABEL: avgceilu_from_shiftaddand:
; CHECK-GI: // %bb.0:
; CHECK-GI-NEXT: lsr w8, w1, #1
; CHECK-GI-NEXT: orr w9, w0, w1
; CHECK-GI-NEXT: and w9, w9, #0x1
; CHECK-GI-NEXT: add w8, w8, w0, lsr #1
; CHECK-GI-NEXT: add w0, w8, w9
; CHECK-GI-NEXT: ret
%c = lshr i32 %a, 1
%d = lshr i32 %b, 1
%e = add i32 %c, %d
%f = or i32 %a, %b
%g = and i32 %f, 1
%h = add i32 %e, %g
ret i32 %h
}
; avgceil(A, B) from ((A >> 1) + (B >> 1)) + ((A | B) & 1)
define i32 @avgceils_from_shiftaddand(i32 %a, i32 %b) {
; CHECK-SD-LABEL: avgceils_from_shiftaddand:
; CHECK-SD: // %bb.0:
; CHECK-SD-NEXT: // kill: def $w0 killed $w0 def $x0
; CHECK-SD-NEXT: sxtw x8, w0
; CHECK-SD-NEXT: add x8, x8, w1, sxtw
; CHECK-SD-NEXT: add x8, x8, #1
; CHECK-SD-NEXT: lsr x0, x8, #1
; CHECK-SD-NEXT: // kill: def $w0 killed $w0 killed $x0
; CHECK-SD-NEXT: ret
;
; CHECK-GI-LABEL: avgceils_from_shiftaddand:
; CHECK-GI: // %bb.0:
; CHECK-GI-NEXT: asr w8, w1, #1
; CHECK-GI-NEXT: orr w9, w0, w1
; CHECK-GI-NEXT: and w9, w9, #0x1
; CHECK-GI-NEXT: add w8, w8, w0, asr #1
; CHECK-GI-NEXT: add w0, w8, w9
; CHECK-GI-NEXT: ret
%c = ashr i32 %a, 1
%d = ashr i32 %b, 1
%e = add i32 %c, %d
%f = or i32 %a, %b
%g = and i32 %f, 1
%h = add i32 %e, %g
ret i32 %h
}