Until now, in Xtensa ISA, the CONST16 machine instruction (which shifts a
specified register left by half a word and stores a 16-bit constant value
in the low halfword of the register) has always been used in pairs and
only for full-word constant value assignments.

This patch provides a new insn definition for using CONST16 alone, and
also adds a constantsynth method that saves one byte for constant assign-
ments within a certain range when TARGET_DENSITY is also enabled.

gcc/ChangeLog:

        * config/xtensa/xtensa.cc
        (constantsynth_method_const16): New.
        (constantsynth_methods): Append constantsynth_method_const16().
        (constantsynth_info): Add cost calculation for full-word constant
        assignment when TARGET_CONST16 is enabled.
        (constantsynth_pass1): Change it so that it works regardless of
        TARGET_CONST16.
        * config/xtensa/xtensa.md (*xtensa_const16): New.
---
 gcc/config/xtensa/xtensa.cc | 47 ++++++++++++++++++++++++++++++-------
 gcc/config/xtensa/xtensa.md | 12 ++++++++++
 2 files changed, 50 insertions(+), 9 deletions(-)

diff --git a/gcc/config/xtensa/xtensa.cc b/gcc/config/xtensa/xtensa.cc
index 4ece2cacb38..f09123d5c33 100644
--- a/gcc/config/xtensa/xtensa.cc
+++ b/gcc/config/xtensa/xtensa.cc
@@ -5954,6 +5954,29 @@ constantsynth_method_square (rtx dest, HOST_WIDE_INT v)
   return end_sequence ();
 }
+/* A method that generates two machine instructions for assigning a value
+   between -32 and 95, followed by a CONST16 instruction to synthesize a
+   value in the range -2097151 to 6291455.  This method only works when
+   TARGET_CONST16 is enabled.  */
+
+static rtx_insn *
+constantsynth_method_const16 (rtx dest, HOST_WIDE_INT v)
+{
+  rtx x;
+
+  if (!TARGET_CONST16
+      || ! IN_RANGE (v >> 16, -32, 95)
+      || ! IN_RANGE (v & 65535, 1, 65535))
+    return NULL;
+
+  start_sequence ();
+  emit_insn (gen_rtx_SET (dest, GEN_INT (v >> 16)));
+  x = gen_rtx_ASHIFT (SImode, dest, GEN_INT (16));
+  x = gen_rtx_IOR (SImode, x, GEN_INT (v & 65535));
+  emit_insn (gen_rtx_SET (dest, x));
+  return end_sequence ();
+}
+
 /* List of all available synthesis methods.  */
struct constantsynth_method_info
@@ -5968,6 +5991,7 @@ static const struct constantsynth_method_info 
constantsynth_methods[] =
   { constantsynth_method_16bits, "16bits" },
   { constantsynth_method_32bits, "32bits" },
   { constantsynth_method_square, "square" },
+  { constantsynth_method_const16, "const16" },
 };
/* Information that mediates between synthesis pass 1 and 2. */
@@ -5979,13 +6003,19 @@ struct constantsynth_info
   hash_map<rtx, int> usage;
   constantsynth_info ()
   {
-    /* To avoid wasting literal pool entries, we use fake references to
-       estimate the costs of an L32R instruction.  */
-    rtx x = gen_rtx_SYMBOL_REF (Pmode, "*.LC-1");
-    SYMBOL_REF_FLAGS (x) |= SYMBOL_FLAG_LOCAL;
-    CONSTANT_POOL_ADDRESS_P (x) = 1;
-    x = gen_const_mem (SImode, x);
-    gcc_assert (constantpool_mem_p (x));
+    rtx x;
+    if (TARGET_CONST16)
+      x = GEN_INT (0x5A5A5A5A);
+    else
+      {
+       /* To avoid wasting literal pool entries, we use fake references
+          to estimate the costs of an L32R instruction.  */
+       x = gen_rtx_SYMBOL_REF (Pmode, "*.LC-1");
+       SYMBOL_REF_FLAGS (x) |= SYMBOL_FLAG_LOCAL;
+       CONSTANT_POOL_ADDRESS_P (x) = 1;
+       x = gen_const_mem (SImode, x);
+       gcc_assert (constantpool_mem_p (x));
+      }
     costs += make_insn_raw (gen_rtx_SET (gen_rtx_REG (SImode, A9_REG),
                                         x));
   }
@@ -6005,8 +6035,7 @@ constantsynth_pass1 (rtx_insn *insn, constantsynth_info 
&info)
      number of occurrences of the constant if optimizing for size.  If the
      constant fits in the immediate field, update the insn to re-assign the
      constant.  */
-  if (TARGET_CONST16
-      || GET_CODE (pat = PATTERN (insn)) != SET
+  if (GET_CODE (pat = PATTERN (insn)) != SET
       || ! REG_P (dest = SET_DEST (pat)) || ! GP_REG_P (REGNO (dest))
       || GET_MODE (dest) != SImode
       || ! CONST_INT_P (src = avoid_constant_pool_reference (SET_SRC (pat))))
diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md
index cb047b0f655..950c33f859f 100644
--- a/gcc/config/xtensa/xtensa.md
+++ b/gcc/config/xtensa/xtensa.md
@@ -1281,6 +1281,18 @@
   }
   [(set_attr "mode" "SI")])
+(define_insn "*xtensa_const16"
+  [(set (match_operand:SI 0 "register_operand" "=a")
+       (match_operator:SI 3 "xtensa_bit_join_operator"
+               [(ashift:SI (match_operand:SI 1 "register_operand" "0")
+                           (const_int 16))
+                (match_operand:SI 2 "const_int_operand" "")]))]
+  "TARGET_CONST16 && IN_RANGE (INTVAL (operands[2]), 1, 65535)"
+  "const16\t%0, %2"
+  [(set_attr "type"  "move")
+   (set_attr "mode"  "SI")
+   (set_attr "length"        "3")])
+
 ;; 16-bit Integer moves
(define_expand "movhi"
--
2.39.5

Reply via email to