https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82106
Bug ID: 82106 Summary: [RISCV] Misaligned loads generated when doubles are split between stack and registers Product: gcc Version: 8.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: asb at lowrisc dot org Target Milestone: --- Created attachment 42127 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=42127&action=edit Simple program to reproduce this problem When targeting RISC-V, GCC will allocate space on the stack for values which are split between argument registers and the stack. If the type has alignment larger than xlen, it is possible for misaligned loads to be generated. This can be observed when passing a double in the attached example. The below is generated using GCC r251714. $ cat call.c typedef long long int int64_t; struct large_struct { int64_t h1; int64_t h2; }; void fun_float(float); void fun_double(double); void fun_int64(int64_t); void callee(float fa0, float fa1, float fa2, float fa3, float fa4, float fa5, float fa6, float fa7, int a0, int a1, int a2, int a3, int a4, int a5, int a6, double a7_s0, int64_t s1, float s2, struct large_struct s3) { fun_double(a7_s0); fun_int64(s1); fun_float(s2); fun_int64(s3.h1); fun_int64(s3.h2); return; } /riscv32-unknown-elf-gcc -v -c call.c -march=rv32ifd -mabi=ilp32d -O1 -fno-omit-frame-pointer -S -o -Using built-in specs. COLLECT_GCC=./riscv32-unknown-elf-gcc Target: riscv32-unknown-elf Configured with: ../configure --target=riscv32-unknown-elf --enable-languages=c --disable-shared --disable-threads --disable-multilib --disable-gdb --disable-libssp --with-newlib --with-arch=rv32ima --with-abi=ilp32 --prefix=/home/asb/work/2017_09_05_gcc_build/combined/build/built Thread model: single gcc version 8.0.0 20170905 (experimental) (GCC) COLLECT_GCC_OPTIONS='-v' '-c' '-march=rv32ifd' '-mabi=ilp32d' '-O1' '-fno-omit-frame-pointer' '-S' '-o' '-' /home/asb/work/2017_09_05_gcc_build/combined/build/built/libexec/gcc/riscv32-unknown-elf/8.0.0/cc1 -quiet -v call.c -quiet -dumpbase call.c -march=rv32ifd -mabi=ilp32d -auxbase-strip - -O1 -version -fno-omit-frame-pointer -o - GNU C11 (GCC) version 8.0.0 20170905 (experimental) (riscv32-unknown-elf) compiled by GNU C version 7.1.1 20170630, GMP version 6.1.2, MPFR version 3.1.5-p2, MPC version 1.0.3, isl version none GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096 ignoring nonexistent directory "/home/asb/work/2017_09_05_gcc_build/combined/build/built/lib/gcc/riscv32-unknown-elf/8.0.0/../../../../riscv32-unknown-elf/sys-include" #include "..." search starts here: #include <...> search starts here: /home/asb/work/2017_09_05_gcc_build/combined/build/built/lib/gcc/riscv32-unknown-elf/8.0.0/include /home/asb/work/2017_09_05_gcc_build/combined/build/built/lib/gcc/riscv32-unknown-elf/8.0.0/include-fixed /home/asb/work/2017_09_05_gcc_build/combined/build/built/lib/gcc/riscv32-unknown-elf/8.0.0/../../../../riscv32-unknown-elf/include End of search list. GNU C11 (GCC) version 8.0.0 20170905 (experimental) (riscv32-unknown-elf) compiled by GNU C version 7.1.1 20170630, GMP version 6.1.2, MPFR version 3.1.5-p2, MPC version 1.0.3, isl version none GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096 Compiler executable checksum: 82d1950b419a8e1b72499dc8b233dd66 .file "call.c" .option nopic .text .align 2 .globl callee .type callee, @function callee: add sp,sp,-32 sw ra,12(sp) sw s0,8(sp) sw s1,4(sp) add s0,sp,16 sw a7,12(s0) lw s1,36(s0) fld fa0,12(s0) call fun_double lw a0,24(s0) lw a1,28(s0) call fun_int64 flw fa0,32(s0) call fun_float lw a0,0(s1) lw a1,4(s1) call fun_int64 lw a0,8(s1) lw a1,12(s1) call fun_int64 lw ra,12(sp) lw s0,8(sp) lw s1,4(sp) add sp,sp,32 jr ra .size callee, .-callee .ident "GCC: (GNU) 8.0.0 20170905 (experimental)" COMPILER_PATH=/home/asb/work/2017_09_05_gcc_build/combined/build/built/libexec/gcc/riscv32-unknown-elf/8.0.0/:/home/asb/work/2017_09_05_gcc_build/combined/build/built/libexec/gcc/riscv32-unknown-elf/8.0.0/:/home/asb/work/2017_09_05_gcc_build/combined/build/built/libexec/gcc/riscv32-unknown-elf/:/home/asb/work/2017_09_05_gcc_build/combined/build/built/lib/gcc/riscv32-unknown-elf/8.0.0/:/home/asb/work/2017_09_05_gcc_build/combined/build/built/lib/gcc/riscv32-unknown-elf/:/home/asb/work/2017_09_05_gcc_build/combined/build/built/lib/gcc/riscv32-unknown-elf/8.0.0/../../../../riscv32-unknown-elf/bin/ LIBRARY_PATH=/home/asb/work/2017_09_05_gcc_build/combined/build/built/lib/gcc/riscv32-unknown-elf/8.0.0/:/home/asb/work/2017_09_05_gcc_build/combined/build/built/lib/gcc/riscv32-unknown-elf/8.0.0/../../../../riscv32-unknown-elf/lib/:/lib/:/usr/lib/ COLLECT_GCC_OPTIONS='-v' '-c' '-march=rv32ifd' '-mabi=ilp32d' '-O1' '-fno-omit-frame-pointer' '-S' '-o' '-' `fld fa0,12(s0)` is using a misaligned stack address. Although this should work, the compiler should avoid generating misaligned accesses where possible as they may be trigger an exception and an emulation routine.