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

Reply via email to