https://gcc.gnu.org/g:089e4fb29ffa2520c487db3724cb1beb0df0ce6b

commit r16-8105-g089e4fb29ffa2520c487db3724cb1beb0df0ce6b
Author: Takayuki 'January June' Suwa <[email protected]>
Date:   Sun Mar 15 18:32:48 2026 +0900

    xtensa: constantsynth: Add new 2-insns synthesis method
    
    This patch adds a new 2-instructions constant synthesis method:
    
      - A positive integer value that, despite left-shifting the leading 0 bits,
        becomes a negative number that still fits into a signed 12-bit
          => "MOVI(.N) Ax, simm12" + "SRLI Ax, Ax, 1...10"
    
         /* example */
         int test(void) {
           return 0x1FFFFF55;  /* 0b00011111111111111111111101010101 */
         }
    
         ;; before (-O1 -mextra-l32r-costs=1)
            .literal_position
            .literal .LC0, 536870741
         test:
            entry   sp, 32
            l32r    a2, .LC0
            retw.n
    
         ;; after (-O1 -mextra-l32r-costs=1)
         test:
            entry   sp, 32
            movi    a2, -0x558
            srli    a2, a2, 3
            retw.n
    
    gcc/ChangeLog:
    
            * config/xtensa/xtensa.cc
            (constantsynth_method_lshr_mi12b): New.
            (constantsynth_methods): Add constantsynth_method_lshr_mi12b.

Diff:
---
 gcc/config/xtensa/xtensa.cc | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/gcc/config/xtensa/xtensa.cc b/gcc/config/xtensa/xtensa.cc
index 9998d2ece822..4a9b156e0db7 100644
--- a/gcc/config/xtensa/xtensa.cc
+++ b/gcc/config/xtensa/xtensa.cc
@@ -5777,6 +5777,31 @@ constantsynth_method_lshr_m1 (rtx dest, HOST_WIDE_INT v)
   return end_sequence ();
 }
 
+/* A method that generates two machine instructions to logically right-
+   shift a negative signed 12-bit value a certain number of bits to
+   synthesize a positive number with a bit sequence of 1s on the MSB
+   side (eg., 0x1FFFFF55).  */
+
+static rtx_insn *
+constantsynth_method_lshr_mi12b (rtx dest, HOST_WIDE_INT v)
+{
+  int i;
+  HOST_WIDE_INT v0;
+
+  /* HOST_WIDE_INT should be always 64 bits (see gcc/hwint.h), while
+     asserts just in case.  */
+  gcc_assert (HOST_BITS_PER_WIDE_INT == 64);
+
+  if (! IN_RANGE (i = clz_hwi (v) - 32, 1, 10)
+      || ! IN_RANGE (v0 = (int32_t)(v << i), -2048, -2))
+    return NULL;
+
+  start_sequence ();
+  emit_insn (gen_rtx_SET (dest, GEN_INT (v0)));
+  emit_insn (gen_lshrsi3 (dest, dest, GEN_INT (i)));
+  return end_sequence ();
+}
+
 /* Split the specified value between -34816 and 34559 into the two
    immediates for the MOVI and ADDMI instruction.  */
 
@@ -5951,6 +5976,7 @@ struct constantsynth_method_info
 static const struct constantsynth_method_info constantsynth_methods[] =
 {
   { constantsynth_method_lshr_m1, "lshr_m1" },
+  { constantsynth_method_lshr_mi12b, "lshr_mi12b" },
   { constantsynth_method_16bits, "16bits" },
   { constantsynth_method_32bits, "32bits" },
   { constantsynth_method_square, "square" },

Reply via email to