]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
xtensa: Make individual use of CONST16 instruction
authorTakayuki 'January June' Suwa <jjsuwa_sys3175@yahoo.co.jp>
Thu, 9 Oct 2025 21:29:16 +0000 (06:29 +0900)
committerMax Filippov <jcmvbkbc@gmail.com>
Mon, 20 Oct 2025 16:34:38 +0000 (09:34 -0700)
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
gcc/config/xtensa/xtensa.md

index 4ece2cacb38b353fd6b4e8ea5bf60f1374d1cd3f..f09123d5c330ad9147014021e477dc487e72a276 100644 (file)
@@ -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))))
index cb047b0f65573555823ffce6445ce844573aecea..950c33f859f11dcdf9efdfe9d269b631ea4ba2aa 100644 (file)
   }
   [(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"