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