So I was trying to untangle our define_insn_and_split situation for zero-extensions and stumbled over some code we need to adjust & simplify in the RISC-V backend. I probably should have caught this earlier.

riscv_extend_to_xmode_reg is just a poor implementation of convert_modes; we can replace the whole thing will a call to convert_modes + force_reg.

Why is this important beyond code hygene?

convert_modes works with the expansion code wheres extend_to_xmode_reg makes assumptions about the kinds of insns the target directly supports. This shows up if you try to untangle the zero-extension support where the base ISA doesn't support zero extensions and should be going through an expander rather than using a define_insn_and_split.

The define_insn_and_split for the reg->reg case isn't split until after reload. Naturally this inhibits some optimizations and forces further work in this space that should be simple define_splits into also needing to be define_insn_and_splits.

Anyway, without going further into the zero-extend rathole, this removes the assumption that the target is providing a single insn zero/sign extension thus allowing me to continue to untangle that mess.

Bootstrapped and regression tested on the Pioneer (which thoroughly exercises this code as it does not have the B extension. I don't think the BPI has picked up this one yet. Also built and regression tested riscv32-elf and riscv64-elf.

Waiting on pre-commit CI before moving forward.
jeff

        * config/riscv/riscv.cc (riscv_extend_to_xmode_reg): Simplify
        by using convert_modes + force_reg.

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 7d723fc4d695..2b2fada592f0 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -14144,84 +14144,14 @@ riscv_get_raw_result_mode (int regno)
   return default_get_reg_raw_mode (regno);
 }
 
-/* Generate a REG rtx of Xmode from the given rtx and mode.
-   The rtx x can be REG (QI/HI/SI/DI) or const_int.
-   The machine_mode mode is the original mode from define pattern.
-   The rtx_code can be ZERO_EXTEND or SIGN_EXTEND.
-
-   If rtx is REG:
-
-   1.  If rtx Xmode, the RTX x will be returned directly.
-   2.  If rtx non-Xmode, the value extended into a new REG of Xmode will be
-       returned.
-
-   The scalar ALU like add don't support non-Xmode like QI/HI.  Then the
-   gen_lowpart will have problem here.  For example, when we would like
-   to add -1 (0xff if QImode) and 2 (0x2 if QImode).  The 0xff and 0x2 will
-   be loaded to register for adding.  Aka:
-
-   0xff + 0x2 = 0x101 instead of -1 + 2 = 1.
-
-   Thus we need to sign extend 0xff to 0xffffffffffffffff if Xmode is DImode
-   for correctness.  Similar the unsigned also need zero extend.
-
-   If rtx is const_int:
-
-   1.  A new REG rtx will be created to hold the value of const_int.
-
-   According to the gccint doc, the constants generated for modes with fewer
-   bits than in HOST_WIDE_INT must be sign extended to full width.  Thus there
-   will be two cases here, take QImode as example.
-
-   For .SAT_SUB (127, y) in QImode, we have (const_int 127) and one simple
-   mov from const_int to the new REG rtx is good enough here.
-
-   For .SAT_SUB (254, y) in QImode, we have (const_int -2) after define_expand.
-   Aka 0xfffffffffffffffe in Xmode of RV64 but we actually need 0xfe in Xmode
-   of RV64.  So we need to cleanup the highest 56 bits of the new REG rtx moved
-   from the (const_int -2).
-
-   Then the underlying expanding can perform the code generation based on
-   the REG rtx of Xmode, instead of taking care of these in expand func.  */
-
+/* Force X into an Xmode register.  */
 static rtx
 riscv_extend_to_xmode_reg (rtx x, machine_mode mode, enum rtx_code rcode)
 {
   gcc_assert (rcode == ZERO_EXTEND || rcode == SIGN_EXTEND);
 
-  rtx xmode_reg = gen_reg_rtx (Xmode);
-
-  if (CONST_INT_P (x))
-    {
-      if (mode == Xmode)
-       emit_move_insn (xmode_reg, x);
-      else if (rcode == ZERO_EXTEND)
-       {
-         /* Combine deliberately does not simplify extensions of constants
-            (long story).  So try to generate the zero extended constant
-            efficiently.
-
-            First extract the constant and mask off all the bits not in
-            MODE.  */
-         HOST_WIDE_INT val = INTVAL (x);
-         val &= GET_MODE_MASK (mode);
-
-         /* X may need synthesis, so do not blindly copy it.  */
-         xmode_reg = force_reg (Xmode, gen_int_mode (val, Xmode));
-       }
-      else /* SIGN_EXTEND.  */
-       {
-         rtx x_reg = gen_reg_rtx (mode);
-         emit_move_insn (x_reg, x);
-         riscv_emit_unary (rcode, xmode_reg, x_reg);
-       }
-    }
-  else if (mode == Xmode)
-    return x;
-  else
-    riscv_emit_unary (rcode, xmode_reg, x);
-
-  return xmode_reg;
+  rtx t = convert_modes (Xmode, mode, x, rcode == ZERO_EXTEND);
+  return force_reg (Xmode, t);
 }
 
 /* Implements the unsigned saturation add standard name usadd for int mode.

Reply via email to