Closed pulkitgupta1217 closed 3 weeks ago
Isn't at least part of your issue here that you are specifying --with-arch=rv32ima_zfinx
but your target doex not actually support the full M
extension? Aren't you effectively implementing a custom floating point extension that happens to be a subset of the ratified standard M
extension? And such a choice has implications that flow through into the toolchain support (including compiled support libraries/startup code/etc.) and required capabilities?
I'm supporting the full M
extension, just not the full ZFinx
extension. I believe in the past I have tested even without -ffp-contract=off
and thus allowed all float instructions to be used in compiled code, but that still uses soft-float in libmath. I can check this again.
I believe the reason for the issue I am seeing is that the ABI is the soft-float ABI despite Zfinx supporting float operations (because the register map for float now uses x-registers instead of f-registers). It seems to me that having the math library fit the soft-float abi is forcing everything to be soft-float, not any architecture restrictions that I am feeding the compiler. Since it is trying to make the library fit the ilp32 abi, it cannot use float instructions even though the isa string supports them. Using ilp32f doesn't work because there are no float registers, and that causes register collisions with zfinx hardware. I think this issue may require having a separate abi for zfinx/zdinx instead of trying to get it to fit into the standard ones.
I'm supporting the full
M
extension, just not the fullZFinx
extension.
Ok - but it's still effectively a custom extension that you're using because it's "some subset of" ZFinx
?
I believe the reason for the issue I am seeing is that the ABI is the soft-float ABI despite Zfinx supporting float operations (because the register map for float now uses x-registers instead of f-registers). It seems to me that having the math library fit the soft-float abi is forcing everything to be soft-float, not any architecture restrictions that I am feeding the compiler. Since it is trying to make the library fit the ilp32 abi, it cannot use float instructions even though the isa string supports them. Using ilp32f doesn't work because there are no float registers, and that causes register collisions with zfinx hardware. I think this issue may require having a separate abi for zfinx/zdinx instead of trying to get it to fit into the standard ones.
As far as I know using a float enabled arch
but an integer abi
should still allow hard float instructions to be generated but only integer registers will be used for passing floating point values. If the use of -mabi=ilp32
is preventing the generation of ZFinx
(subset) instructions when -march=rv32ima_zfinx
is also used then that does seem odd.
I'm confused...
However, it does not use any float instructions in library code, or for floating point comparisons in compiled code, and instead uses the soft-float libraries to accomplish these tasks.
I built the toolchain as follows:
git clone https://github.com/riscv-collab/riscv-gnu-toolchain
cd riscv-gnu-toolchain
./configure --prefix=`pwd`/installed-tools --with-arch=rv32ima_zfinx --with-abi=ilp32 --with-target-cflags="-ffp-contract=off" --with-target-cxxflags="-ffp-contract=off" --disable-gdb
make 2>&1 | tee build.log
./installed-tools/bin/riscv32-unknown-elf-gcc -v
Using built-in specs.
COLLECT_GCC=./installed-tools/bin/riscv32-unknown-elf-gcc
COLLECT_LTO_WRAPPER=/home/user/issue-1590/installed-tools/libexec/gcc/riscv32-unknown-elf/14.2.0/lto-wrapper
Target: riscv32-unknown-elf
Configured with: /home/user/issue-1590/gcc/configure --target=riscv32-unknown-elf --prefix=/home/user/issue-1590/installed-tools --disable-shared --disable-threads --enable-languages=c,c++ --with-pkgversion=g04696df0963 --with-system-zlib --enable-tls --with-newlib --with-sysroot=/home/user/issue-1590/installed-tools/riscv32-unknown-elf --with-native-system-header-dir=/include --disable-libmudflap --disable-libssp --disable-libquadmath --disable-libgomp --disable-nls --disable-tm-clone-registry --src=.././gcc --disable-multilib --with-abi=ilp32 --with-arch=rv32ima_zfinx --with-tune=rocket --with-isa-spec=20191213 'CFLAGS_FOR_TARGET=-Os -ffp-contract=off -mcmodel=medlow' 'CXXFLAGS_FOR_TARGET=-Os -ffp-contract=off -mcmodel=medlow'
Thread model: single
Supported LTO compression algorithms: zlib
gcc version 14.2.0 (g04696df0963)
And when I disassemble libm.a
I see floating point instructions:
cd installed-tools//riscv32-unknown-elf/lib
../../bin/riscv32-unknown-elf-objdump -d libm.a | grep fadd
1f0: 00c7f553 fadd.s a0,a5,a2
350: 00e67653 fadd.s a2,a2,a4
3ac: 00c87853 fadd.s a6,a6,a2
60c: 00e57553 fadd.s a0,a0,a4
...
../../bin/riscv32-unknown-elf-objdump -d libm.a | grep fsub
1ec: 08e57753 fsub.s a4,a0,a4
230: 08a67653 fsub.s a2,a2,a0
23c: 08a67653 fsub.s a2,a2,a0
478: 08c57653 fsub.s a2,a0,a2
...
../../bin/riscv32-unknown-elf-objdump -d libm.a | grep feq
284: a0a62553 feq.s a0,a2,a0
4ac: a0a62553 feq.s a0,a2,a0
260: a0aa2553 feq.s a0,s4,a0
2a4: a17a27d3 feq.s a5,s4,s7
...
../../bin/riscv32-unknown-elf-objdump -d libm.a | grep flt
54: a0f697d3 flt.s a5,a3,a5
8c: a0f697d3 flt.s a5,a3,a5
204: a0e51753 flt.s a4,a0,a4
78: a0d617d3 flt.s a5,a2,a3
...
../../bin/riscv32-unknown-elf-objdump -d libm.a | grep fle
3e4: a0c78553 fle.s a0,a5,a2
4fc: a0a58653 fle.s a2,a1,a0
78: a0ab87d3 fle.s a5,s7,a0
700: a0f807d3 fle.s a5,a6,a5
...
As Tommy showed, I think when using Zfinx/Zdinx, the behavior should be consistent with the F/D extension (it just replaces the registers for floating point instructions). Which seems to conflict with soft floating point, but this is what Zfinx/Zdinx is designed for ,please check https://github.com/riscvarchive/riscv-zfinx/blob/main/Zfinx_spec.adoc#16-rationale-why-implement-zfinx.
This is interesting that disassembling libm is using the float operations for you. When I try compiling code that calls the sin and cos functions, I am seeing that there are explicit calls to softfloat routines. I'm going to try building everything from scratch again and see if I can tell what is going on.
One difference I see is that you did make
where I do make linux
because I need certain features that were not there in the elf build. Could this be causing the difference?
One difference I see is that you did
make
where I domake linux
because I need certain features that were not there in the elf build. Could this be causing the difference?
I have since built the Linux toolchain and see the same sort of floating point instructions in installed-tools/sysroot/usr/lib/libm*
, for example. So I still can't seem to reproduce this issue with either the bare-metal or Linux toolchains:
However, it does not use any float instructions in library code, or for floating point comparisons in compiled code, and instead uses the soft-float libraries to accomplish these tasks.
Any update @pulkitgupta1217? As shown above I can't seem to reproduce the issue that you originally reported.
Cannot reproduce the original problem so closing this issue.
I am working on a custom 32-bit risc-v based architecture with the following configure command for building the toolchain:
my architecture supports floating point instructions, but does not support fma-type instructions, and as risc-v gcc target does not support
-mno-fused-madd
like MIPS and other targets do, I found that setting-ffpcontract=off
was the only easy way to get the toolchain to build without fma operations.Per the RISC-V ABI spec, I find that the supported abi for my needs would be
ilp32
, I believe this is a causing a problem for me. The ilp32 abi uses the soft-float calling convention. This is expected for the most part, and still allows floating point operations to exist in the compiled code but not in the standard libraries.However, it does not use any float instructions in library code, or for floating point comparisons in compiled code, and instead uses the soft-float libraries to accomplish these tasks. I have found that by passing
-fno-math-errno
I am able to get float comparisons in compiled code I write to use float compare instructions as I would expect. However, adding -fno-math-errno to the configure command cflags and cxxflags does not appear to remove soft-float arithmetic or compares performed in libmath functions like sin and cos.Is this expected behavior? I would expect that Zfinx, Zdinx, etc. should not be restricted to only float instructions in compiled code. I understand that the comparison is likely done in soft-float because of the fcsr changes due to zfinx. I am not sure why subtraction and addition within math library functions would use soft-float. If this is not expected behavior, is there a configuration change that could fix this?