| //@ revisions: x86_64 i686 |
| //@ assembly-output: emit-asm |
| //@ compile-flags: -O -C panic=abort |
| //@[x86_64] compile-flags: --target x86_64-unknown-linux-gnu |
| //@[x86_64] needs-llvm-components: x86 |
| //@[i686] compile-flags: --target i686-unknown-linux-gnu |
| //@[i686] needs-llvm-components: x86 |
| //@ compile-flags: -C llvm-args=--x86-asm-syntax=intel |
| //@ compile-flags: -C target-feature=+avx512bw |
| //@ compile-flags: -Zmerge-functions=disabled |
| |
| #![feature(no_core, lang_items, rustc_attrs)] |
| #![crate_type = "rlib"] |
| #![no_core] |
| #![allow(asm_sub_register)] |
| |
| #[rustc_builtin_macro] |
| macro_rules! asm { |
| () => {}; |
| } |
| #[rustc_builtin_macro] |
| macro_rules! concat { |
| () => {}; |
| } |
| #[rustc_builtin_macro] |
| macro_rules! stringify { |
| () => {}; |
| } |
| |
| #[lang = "sized"] |
| trait Sized {} |
| #[lang = "copy"] |
| trait Copy {} |
| |
| impl Copy for i32 {} |
| |
| macro_rules! check { |
| ($func:ident $modifier:literal $reg:ident $mov:literal) => { |
| // -O and extern "C" guarantee that the selected register is always ax/xmm0 |
| #[no_mangle] |
| pub unsafe extern "C" fn $func() -> i32 { |
| let y; |
| asm!(concat!($mov, " {0:", $modifier, "}, {0:", $modifier, "}"), out($reg) y); |
| y |
| } |
| }; |
| } |
| |
| // CHECK-LABEL: reg: |
| // CHECK: #APP |
| // x86_64: mov rax, rax |
| // i686: mov eax, eax |
| // CHECK: #NO_APP |
| check!(reg "" reg "mov"); |
| |
| // x86_64-LABEL: reg_l: |
| // x86_64: #APP |
| // x86_64: mov al, al |
| // x86_64: #NO_APP |
| #[cfg(x86_64)] |
| check!(reg_l "l" reg "mov"); |
| |
| // CHECK-LABEL: reg_x: |
| // CHECK: #APP |
| // CHECK: mov ax, ax |
| // CHECK: #NO_APP |
| check!(reg_x "x" reg "mov"); |
| |
| // CHECK-LABEL: reg_e: |
| // CHECK: #APP |
| // CHECK: mov eax, eax |
| // CHECK: #NO_APP |
| check!(reg_e "e" reg "mov"); |
| |
| // x86_64-LABEL: reg_r: |
| // x86_64: #APP |
| // x86_64: mov rax, rax |
| // x86_64: #NO_APP |
| #[cfg(x86_64)] |
| check!(reg_r "r" reg "mov"); |
| |
| // CHECK-LABEL: reg_abcd: |
| // CHECK: #APP |
| // x86_64: mov rax, rax |
| // i686: mov eax, eax |
| // CHECK: #NO_APP |
| check!(reg_abcd "" reg_abcd "mov"); |
| |
| // CHECK-LABEL: reg_abcd_l: |
| // CHECK: #APP |
| // CHECK: mov al, al |
| // CHECK: #NO_APP |
| check!(reg_abcd_l "l" reg_abcd "mov"); |
| |
| // CHECK-LABEL: reg_abcd_h: |
| // CHECK: #APP |
| // CHECK: mov ah, ah |
| // CHECK: #NO_APP |
| check!(reg_abcd_h "h" reg_abcd "mov"); |
| |
| // CHECK-LABEL: reg_abcd_x: |
| // CHECK: #APP |
| // CHECK: mov ax, ax |
| // CHECK: #NO_APP |
| check!(reg_abcd_x "x" reg_abcd "mov"); |
| |
| // CHECK-LABEL: reg_abcd_e: |
| // CHECK: #APP |
| // CHECK: mov eax, eax |
| // CHECK: #NO_APP |
| check!(reg_abcd_e "e" reg_abcd "mov"); |
| |
| // x86_64-LABEL: reg_abcd_r: |
| // x86_64: #APP |
| // x86_64: mov rax, rax |
| // x86_64: #NO_APP |
| #[cfg(x86_64)] |
| check!(reg_abcd_r "r" reg_abcd "mov"); |
| |
| // CHECK-LABEL: xmm_reg |
| // CHECK: #APP |
| // CHECK: movaps xmm0, xmm0 |
| // CHECK: #NO_APP |
| check!(xmm_reg "" xmm_reg "movaps"); |
| |
| // CHECK-LABEL: xmm_reg_x |
| // CHECK: #APP |
| // CHECK: movaps xmm0, xmm0 |
| // CHECK: #NO_APP |
| check!(xmm_reg_x "x" xmm_reg "movaps"); |
| |
| // CHECK-LABEL: xmm_reg_y |
| // CHECK: #APP |
| // CHECK: vmovaps ymm0, ymm0 |
| // CHECK: #NO_APP |
| check!(xmm_reg_y "y" xmm_reg "vmovaps"); |
| |
| // CHECK-LABEL: xmm_reg_z |
| // CHECK: #APP |
| // CHECK: vmovaps zmm0, zmm0 |
| // CHECK: #NO_APP |
| check!(xmm_reg_z "z" xmm_reg "vmovaps"); |
| |
| // CHECK-LABEL: ymm_reg |
| // CHECK: #APP |
| // CHECK: movaps ymm0, ymm0 |
| // CHECK: #NO_APP |
| check!(ymm_reg "" ymm_reg "vmovaps"); |
| |
| // CHECK-LABEL: ymm_reg_x |
| // CHECK: #APP |
| // CHECK: movaps xmm0, xmm0 |
| // CHECK: #NO_APP |
| check!(ymm_reg_x "x" ymm_reg "movaps"); |
| |
| // CHECK-LABEL: ymm_reg_y |
| // CHECK: #APP |
| // CHECK: vmovaps ymm0, ymm0 |
| // CHECK: #NO_APP |
| check!(ymm_reg_y "y" ymm_reg "vmovaps"); |
| |
| // CHECK-LABEL: ymm_reg_z |
| // CHECK: #APP |
| // CHECK: vmovaps zmm0, zmm0 |
| // CHECK: #NO_APP |
| check!(ymm_reg_z "z" ymm_reg "vmovaps"); |
| |
| // CHECK-LABEL: zmm_reg |
| // CHECK: #APP |
| // CHECK: movaps zmm0, zmm0 |
| // CHECK: #NO_APP |
| check!(zmm_reg "" zmm_reg "vmovaps"); |
| |
| // CHECK-LABEL: zmm_reg_x |
| // CHECK: #APP |
| // CHECK: movaps xmm0, xmm0 |
| // CHECK: #NO_APP |
| check!(zmm_reg_x "x" zmm_reg "movaps"); |
| |
| // CHECK-LABEL: zmm_reg_y |
| // CHECK: #APP |
| // CHECK: vmovaps ymm0, ymm0 |
| // CHECK: #NO_APP |
| check!(zmm_reg_y "y" zmm_reg "vmovaps"); |
| |
| // CHECK-LABEL: zmm_reg_z |
| // CHECK: #APP |
| // CHECK: vmovaps zmm0, zmm0 |
| // CHECK: #NO_APP |
| check!(zmm_reg_z "z" zmm_reg "vmovaps"); |
| |
| // Note: we don't have any way of ensuring that k1 is actually the register |
| // chosen by the register allocator, so this check may fail if a different |
| // register is chosen. |
| |
| // CHECK-LABEL: kreg: |
| // CHECK: #APP |
| // CHECK: kmovb k1, k1 |
| // CHECK: #NO_APP |
| check!(kreg "" kreg "kmovb"); |