Ran into a minor snafu in const splitting code when playing with test case from an old PR/23813.
long long f(void) { return 0xF0F0F0F0F0F0F0F0ull; } This currently generates li a5,-252645376 addi a5,a5,241 li a0,-252645376 slli a5,a5,32 addi a0,a0,240 add a0,a5,a0 ret The signed math in hival extraction introduces an additional bit, causing loval == hival check to fail. | riscv_split_integer (val=-1085102592571150096, mode=E_DImode) at ../gcc/config/riscv/riscv.cc:702 | 702 unsigned HOST_WIDE_INT loval = sext_hwi (val, 32); | (gdb)n | 703 unsigned HOST_WIDE_INT hival = sext_hwi ((val - loval) >> 32, 32); | (gdb) | 704 rtx hi = gen_reg_rtx (mode), lo = gen_reg_rtx (mode); | (gdb) p/x val | $2 = 0xf0f0f0f0f0f0f0f0 | (gdb) p/x loval | $3 = 0xfffffffff0f0f0f0 | (gdb) p/x hival | $4 = 0xfffffffff0f0f0f1 ^^^ Fix that by eliding the subtraction in shift. With patch: li a5,-252645376 addi a5,a5,240 slli a0,a5,32 add a0,a0,a5 ret gcc/ChangeLog: * config/riscv/riscv.cc (riscv_split_integer): hival computation do elide subtraction of loval. * (riscv_split_integer_cost): Ditto. * (riscv_build_integer): Ditto Signed-off-by: Vineet Gupta <vine...@rivosinc.com> --- I wasn't planning to do any more work on large const stuff, but just ran into it this on a random BZ entry when trying search for redundant constant stuff. The test seemed too good to pass :-) --- gcc/config/riscv/riscv.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index 5ac187c1b1b4..377d3aac794b 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -643,7 +643,7 @@ riscv_build_integer (struct riscv_integer_op *codes, HOST_WIDE_INT value, && (value > INT32_MAX || value < INT32_MIN)) { unsigned HOST_WIDE_INT loval = sext_hwi (value, 32); - unsigned HOST_WIDE_INT hival = sext_hwi ((value - loval) >> 32, 32); + unsigned HOST_WIDE_INT hival = sext_hwi (value >> 32, 32); struct riscv_integer_op alt_codes[RISCV_MAX_INTEGER_OPS]; struct riscv_integer_op hicode[RISCV_MAX_INTEGER_OPS]; int hi_cost, lo_cost; @@ -674,7 +674,7 @@ riscv_split_integer_cost (HOST_WIDE_INT val) { int cost; unsigned HOST_WIDE_INT loval = sext_hwi (val, 32); - unsigned HOST_WIDE_INT hival = sext_hwi ((val - loval) >> 32, 32); + unsigned HOST_WIDE_INT hival = sext_hwi (val >> 32, 32); struct riscv_integer_op codes[RISCV_MAX_INTEGER_OPS]; cost = 2 + riscv_build_integer (codes, loval, VOIDmode); @@ -700,7 +700,7 @@ static rtx riscv_split_integer (HOST_WIDE_INT val, machine_mode mode) { unsigned HOST_WIDE_INT loval = sext_hwi (val, 32); - unsigned HOST_WIDE_INT hival = sext_hwi ((val - loval) >> 32, 32); + unsigned HOST_WIDE_INT hival = sext_hwi (val >> 32, 32); rtx hi = gen_reg_rtx (mode), lo = gen_reg_rtx (mode); riscv_move_integer (lo, lo, loval, mode); -- 2.34.1