On RV32IMFD, when a double value returned by a function call needs to be copied to an export register, wrong code is generated.
The return value is being exported to two i32 registers and the second one is not being previously allocated, which causes multiple virtual registers definitions in most cases. Besides that, code following the call is expecting the return value to be present in a f64 register and not in an i32 pair, which also causes invalid code to be generated.
Any code that generates a PHI node whose values are doubles returned by function calls seems to reproduce the issue.
Example:
double func(double a) {
if (a > 10)
a = sin(a);
else
a = cos(a);
return a + 35;
}
I'm using clang --target=riscv32 -O1 -emit-llvm -c and then llc -O1 -march=riscv32 -mattr=-a,-c,+m,+f,+d to generate RV32 assembly code.
On RV32IMFD, when a double value returned by a function call needs to be copied to an export register, wrong code is generated.
The return value is being exported to two i32 registers and the second one is not being previously allocated, which causes multiple virtual registers definitions in most cases. Besides that, code following the call is expecting the return value to be present in a f64 register and not in an i32 pair, which also causes invalid code to be generated.
Any code that generates a PHI node whose values are doubles returned by function calls seems to reproduce the issue.
Example:
I'm using
clang --target=riscv32 -O1 -emit-llvm -c
and thenllc -O1 -march=riscv32 -mattr=-a,-c,+m,+f,+d
to generate RV32 assembly code.