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.
---
 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 9998d2ece82..4a9b156e0db 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" },
--
2.39.5

Reply via email to