llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
26.7k stars 10.94k forks source link

ARM32 fcpyd ASM generates redundant vmov.f64 instructions #92226

Open kongy opened 1 month ago

kongy commented 1 month ago

https://godbolt.org/z/jns6Y4M97

Input:

extern bool USE(double a, double b);

#define SET_FREG(n, v) \
  ({ const double _v{v}; asm volatile("fcpyd d"#n ", %P0" : : "w"(_v) : "d"#n); })
#define GET_FREG(n) ({ double _r; asm volatile("fcpyd %P0, d"#n : "=w"(_r) : :); _r;})

void foo() {
  SET_FREG(8, 8);
  SET_FREG(9, 9);
  SET_FREG(10, 10);
  SET_FREG(11, 11);
  SET_FREG(12, 12);
  SET_FREG(13, 13);
  USE(8.0, GET_FREG(8));
  USE(9.0, GET_FREG(9));
  USE(10.0, GET_FREG(10));
  USE(11.0, GET_FREG(11));
  USE(12.0, GET_FREG(12));
  USE(13.0, GET_FREG(13));
}

Command: clang++ test.cpp -c -target armv7a-linux-androideabi -march=armv8-a -O2 -S -o -

Output:

foo():
        push    {r11, lr}
        vpush   {d8, d9, d10, d11, d12, d13, d14, d15}
        vmov.f64        d16, #8.000000e+00
        vmov.f64        d8, d16
        vmov.f64        d17, #1.300000e+01
        vmov.f64        d14, #9.000000e+00
        vmov.f64        d9, d14
        vmov.f64        d18, #1.200000e+01
        vmov.f64        d15, #1.000000e+01
        vmov.f64        d10, d15
        vmov.f64        d19, #1.100000e+01
        vmov.f64        d11, d19
        vmov.f64        d12, d18
        vmov.f64        d13, d17
        vmov.f64        d8, d17         <-- Redundant vmov
        vmov.f64        d17, d8
        vmov    r0, r1, d16
        vmov    r2, r3, d17
        vmov.f64        d10, d19        <-- Redundant vmov
        vmov.f64        d9, d18         <-- Redundant vmov
        bl      USE(double, double)
        vmov.f64        d16, d9
        vmov    r0, r1, d14
        vmov    r2, r3, d16
        bl      USE(double, double)
        vmov.f64        d16, d10
        vmov    r0, r1, d15
        vmov    r2, r3, d16
        bl      USE(double, double)
        vmov.f64        d16, d11
        vmov    r0, r1, d10
        vmov    r2, r3, d16
        bl      USE(double, double)
        vmov.f64        d16, d12
        vmov    r0, r1, d9
        vmov    r2, r3, d16
        bl      USE(double, double)
        vmov.f64        d16, d13
        vmov    r0, r1, d8
        vmov    r2, r3, d16
        vpop    {d8, d9, d10, d11, d12, d13, d14, d15}
        pop     {r11, lr}
        b       USE(double, double)

This issue has been there since at least LLVM 9.0.

llvmbot commented 1 month ago

@llvm/issue-subscribers-backend-arm

Author: Yi Kong (kongy)

https://godbolt.org/z/jns6Y4M97 Input: ``` extern bool USE(double a, double b); #define SET_FREG(n, v) \ ({ const double _v{v}; asm volatile("fcpyd d"#n ", %P0" : : "w"(_v) : "d"#n); }) #define GET_FREG(n) ({ double _r; asm volatile("fcpyd %P0, d"#n : "=w"(_r) : :); _r;}) void foo() { SET_FREG(8, 8); SET_FREG(9, 9); SET_FREG(10, 10); SET_FREG(11, 11); SET_FREG(12, 12); SET_FREG(13, 13); USE(8.0, GET_FREG(8)); USE(9.0, GET_FREG(9)); USE(10.0, GET_FREG(10)); USE(11.0, GET_FREG(11)); USE(12.0, GET_FREG(12)); USE(13.0, GET_FREG(13)); } ``` Command: `clang++ test.cpp -c -target armv7a-linux-androideabi -march=armv8-a -O2 -S -o -` Output: ``` foo(): push {r11, lr} vpush {d8, d9, d10, d11, d12, d13, d14, d15} vmov.f64 d16, #8.000000e+00 vmov.f64 d8, d16 vmov.f64 d17, #1.300000e+01 vmov.f64 d14, #9.000000e+00 vmov.f64 d9, d14 vmov.f64 d18, #1.200000e+01 vmov.f64 d15, #1.000000e+01 vmov.f64 d10, d15 vmov.f64 d19, #1.100000e+01 vmov.f64 d11, d19 vmov.f64 d12, d18 vmov.f64 d13, d17 vmov.f64 d8, d17 <-- Redundant vmov vmov.f64 d17, d8 vmov r0, r1, d16 vmov r2, r3, d17 vmov.f64 d10, d19 <-- Redundant vmov vmov.f64 d9, d18 <-- Redundant vmov bl USE(double, double) vmov.f64 d16, d9 vmov r0, r1, d14 vmov r2, r3, d16 bl USE(double, double) vmov.f64 d16, d10 vmov r0, r1, d15 vmov r2, r3, d16 bl USE(double, double) vmov.f64 d16, d11 vmov r0, r1, d10 vmov r2, r3, d16 bl USE(double, double) vmov.f64 d16, d12 vmov r0, r1, d9 vmov r2, r3, d16 bl USE(double, double) vmov.f64 d16, d13 vmov r0, r1, d8 vmov r2, r3, d16 vpop {d8, d9, d10, d11, d12, d13, d14, d15} pop {r11, lr} b USE(double, double) ``` This issue has been there since at least LLVM 9.0.