Thinking about -march= and -mfloat-abi=
I see that float support can currently be distinguished from GCC preprocessor macros however the macros are different to the march flags, and there is also no expansion of extensions from the -march flags so we don’t know the value of -march at compile time (use case is library code versus internal access for compiler optimisation)
I wonder whether creating macros for each extension in the -march flag is a good idea? e.g. -march=IMAFDN would result in something like this:
Not sure if this is a good idea?
I was looking to see what other platforms define for -mfloat-abi but I couldn’t find anything definitive. Something like this perhaps?
#define _RISCV_RVABI_HARD 1
#define _RISCV_RVABI_SOFT 1
#define _RISCV_RVABI_SOFTFP 1
The other thought was that once these macros are added, we won’t really be able to change them easily without breaking things. The preprocessor macros become part of the ABI glue at the compiler level, and they will likely be used by optimisations in math, crypto and multimedia libraries. So the question is we have to freeze __riscv_soft_float and __riscv_hard_float so we can depend on these in base libraries for presence of hard float? or is it still okay to break things at the preprocessor level? I know the Base ISA is frozen, but it seems there isn’t any official documentation for RVABI interfaces or compiler macros. So even if we add new macros to further distinguish RVABI and the various extensions we should also keep __riscv_soft_float and __riscv_hard_float
There also needs to be an RVABI header (assuming its called RVABI) that includes the soft float and integer ops for 64-bit on RV32, and potentially even 128-bit on RV64 and RV32. There is no reason why we couldn’t provide optimised intrinsics for 128-bit ops on RV32 and RV64 in RVABI, so that 128-bit integer and QP arithmetic work on all RISC-V targets (perhaps at some later date).
Q. Are the 64-bit ops on RV32 in compiler_rt and libgcc or is this part of some kind of RVABI? I think if we define an RVABI early on then a big compatibility mess of many different ABIs could be avoided. i.e. the first decade of ARM.
This example header is just RISC-V FD, and is just a starting point. I imagine we would need to standardise the ABI for integer ‘M’ and ‘A’ as well as the 64-bit fill in functions for 64-bit arithmetic on RV32:
Is there a page somewhere that lists the matrix of what headers are defined depending on which ABI is selected and what hardware extensions are present. It could be quite useful for a manual.
Model specific tuning will also become important e.g. we want to know if whether mul and shifts are constant time for use in optimisation (strength reductions). Ideally RISC-V library code can detect the -mtune flags via preprocessor headers so not only the compiler can perform these optimisations, but libraries can modify their code based on extension and model. e.g.
-mtune=constant-time-shift
-mtune=constant-time-mul
#define _RISCV_SHIFT_O1 1
-mtune=non-constant-time-shift
-mtune=non-constant-time-mul
#undef _RISCV_MUL_O1
#undef _RISCV_SHIFT_O1
Crypto code is definitely going to want to enact different strategies depending on whether mul or shift is constant time.
I was actually looking at disassembly of loop induction variables and noticed that gcc currently emits mul in structure offset calculations for array of structure loops (versus emitting adds). It might be something wrong with the cost model. gcc on x86 emits adds for array of structure loop induction variables. Overflow semantics are the same for add or mul so it doesn’t matter whether the loop bounds check is constant or dynamic. I also notice the mul got strength reduced to shift (mul strength reduced to shift with -O3, mul with -Os versus add on x86).
Perhaps I can put up an (unofficial) rvabi.md file that documents the current macros and interfaces. I think it might require some more reverse engineering.
Michael.
mclark@minty:~/src/riscv-tools$ riscv32-unknown-elf-gcc --version
riscv32-unknown-elf-gcc (GCC) 6.1.0
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
mclark@minty:~/src/riscv-tools$ riscv64-unknown-elf-gcc --version
riscv64-unknown-elf-gcc (GCC) 6.1.0
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
mclark@minty:~/src/riscv-tools$ riscv32-unknown-elf-gcc -dM -E -march=IMAFD -msoft-float - < /dev/null | grep -i RISCV
#define __riscv 1
#define __riscv_atomic 1
#define __RISCVEL 1
#define RISCVEL 1
#define _RISCV_SZPTR 32
#define _RISCV_SZINT 32
#define __riscv_muldiv 1
#define __riscv32 1
#define _RISCV_SZLONG 32
#define __RISCVEL__ 1
#define _RISCV_SIM _ABI32
#define __riscv__ 1
#define _riscv 1
#define __riscv_soft_float 1
mclark@minty:~/src/riscv-tools$ riscv32-unknown-elf-gcc -dM -E -march=IMA -mhard-float - < /dev/null | grep -i RISCV
#define __riscv 1
#define __riscv_hard_float 1
#define __riscv_atomic 1
#define __RISCVEL 1
#define RISCVEL 1
#define __riscv_fdiv 1
#define _RISCV_SZPTR 32
#define _RISCV_SZINT 32
#define __riscv_muldiv 1
#define __riscv32 1
#define _RISCV_SZLONG 32
#define __riscv_fsqrt 1
#define __RISCVEL__ 1
#define _RISCV_SIM _ABI32
#define __riscv__ 1
#define _riscv 1
mclark@minty:~/src/riscv-tools$ riscv32-unknown-elf-gcc -dM -E -march=I -mhard-float - < /dev/null | grep -i RISCV
#define __riscv 1
#define __riscv_hard_float 1
#define __RISCVEL 1
#define RISCVEL 1
#define __riscv_fdiv 1
#define _RISCV_SZPTR 32
#define _RISCV_SZINT 32
#define __riscv32 1
#define _RISCV_SZLONG 32
#define __riscv_fsqrt 1
#define __RISCVEL__ 1
#define _RISCV_SIM _ABI32
#define __riscv__ 1
#define _riscv 1