aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakayuki 'January June' Suwa <jjsuwa_sys3175@yahoo.co.jp>2022-06-10 13:19:32 +0900
committerMax Filippov <jcmvbkbc@gmail.com>2022-06-11 13:15:30 -0700
commitccd02e734e0f1742629403b46e5b1c650b00fd65 (patch)
tree132b6c5a54d45fb302361a7144a62e7ca6826e1f
parentfddf0e1057fe24eff0d894fbc2959b4086464a96 (diff)
downloadgcc-ccd02e734e0f1742629403b46e5b1c650b00fd65.zip
gcc-ccd02e734e0f1742629403b46e5b1c650b00fd65.tar.gz
gcc-ccd02e734e0f1742629403b46e5b1c650b00fd65.tar.bz2
xtensa: Improve instruction cost estimation and suggestion
This patch implements a new target-specific relative RTL insn cost function because of suboptimal cost estimation by default, and fixes several "length" insn attributes (related to the cost estimation). And also introduces a new machine-dependent option "-mextra-l32r-costs=" that tells implementation-specific InstRAM/ROM access penalty for L32R instruction to the compiler (in clock-cycle units, 0 by default). gcc/ChangeLog: * config/xtensa/xtensa.cc (xtensa_rtx_costs): Correct wrong case for ABS and NEG, add missing case for BSWAP and CLRSB, and double the costs for integer divisions using libfuncs if optimizing for speed, in order to take advantage of fast constant division by multiplication. (TARGET_INSN_COST): New macro definition. (xtensa_is_insn_L32R_p, xtensa_insn_cost): New functions for calculating relative costs of a RTL insns, for both of speed and size. * config/xtensa/xtensa.md (return, nop, trap): Correct values of the attribute "length" that depends on TARGET_DENSITY. (define_asm_attributes, blockage, frame_blockage): Add missing attributes. * config/xtensa/xtensa.opt (-mextra-l32r-costs=): New machine- dependent option, however, preparatory work for now.
-rw-r--r--gcc/config/xtensa/xtensa.cc116
-rw-r--r--gcc/config/xtensa/xtensa.md29
-rw-r--r--gcc/config/xtensa/xtensa.opt4
3 files changed, 134 insertions, 15 deletions
diff --git a/gcc/config/xtensa/xtensa.cc b/gcc/config/xtensa/xtensa.cc
index bc3330f..597a36e 100644
--- a/gcc/config/xtensa/xtensa.cc
+++ b/gcc/config/xtensa/xtensa.cc
@@ -55,6 +55,7 @@ along with GCC; see the file COPYING3. If not see
#include "dumpfile.h"
#include "hw-doloop.h"
#include "rtl-iter.h"
+#include "insn-attr.h"
/* This file should be included last. */
#include "target-def.h"
@@ -134,6 +135,7 @@ static unsigned int xtensa_multibss_section_type_flags (tree, const char *,
static section *xtensa_select_rtx_section (machine_mode, rtx,
unsigned HOST_WIDE_INT);
static bool xtensa_rtx_costs (rtx, machine_mode, int, int, int *, bool);
+static int xtensa_insn_cost (rtx_insn *, bool);
static int xtensa_register_move_cost (machine_mode, reg_class_t,
reg_class_t);
static int xtensa_memory_move_cost (machine_mode, reg_class_t, bool);
@@ -212,6 +214,8 @@ static rtx xtensa_delegitimize_address (rtx);
#define TARGET_MEMORY_MOVE_COST xtensa_memory_move_cost
#undef TARGET_RTX_COSTS
#define TARGET_RTX_COSTS xtensa_rtx_costs
+#undef TARGET_INSN_COST
+#define TARGET_INSN_COST xtensa_insn_cost
#undef TARGET_ADDRESS_COST
#define TARGET_ADDRESS_COST hook_int_rtx_mode_as_bool_0
@@ -3937,7 +3941,7 @@ xtensa_memory_move_cost (machine_mode mode ATTRIBUTE_UNUSED,
static bool
xtensa_rtx_costs (rtx x, machine_mode mode, int outer_code,
int opno ATTRIBUTE_UNUSED,
- int *total, bool speed ATTRIBUTE_UNUSED)
+ int *total, bool speed)
{
int code = GET_CODE (x);
@@ -4025,9 +4029,14 @@ xtensa_rtx_costs (rtx x, machine_mode mode, int outer_code,
return true;
case CLZ:
+ case CLRSB:
*total = COSTS_N_INSNS (TARGET_NSA ? 1 : 50);
return true;
+ case BSWAP:
+ *total = COSTS_N_INSNS (mode == HImode ? 3 : 5);
+ return true;
+
case NOT:
*total = COSTS_N_INSNS (mode == DImode ? 3 : 2);
return true;
@@ -4051,13 +4060,16 @@ xtensa_rtx_costs (rtx x, machine_mode mode, int outer_code,
return true;
case ABS:
+ case NEG:
{
if (mode == SFmode)
*total = COSTS_N_INSNS (TARGET_HARD_FLOAT ? 1 : 50);
else if (mode == DFmode)
*total = COSTS_N_INSNS (50);
- else
+ else if (mode == DImode)
*total = COSTS_N_INSNS (4);
+ else
+ *total = COSTS_N_INSNS (1);
return true;
}
@@ -4073,10 +4085,6 @@ xtensa_rtx_costs (rtx x, machine_mode mode, int outer_code,
return true;
}
- case NEG:
- *total = COSTS_N_INSNS (mode == DImode ? 4 : 2);
- return true;
-
case MULT:
{
if (mode == SFmode)
@@ -4116,11 +4124,11 @@ xtensa_rtx_costs (rtx x, machine_mode mode, int outer_code,
case UMOD:
{
if (mode == DImode)
- *total = COSTS_N_INSNS (50);
+ *total = COSTS_N_INSNS (speed ? 100 : 50);
else if (TARGET_DIV32)
*total = COSTS_N_INSNS (32);
else
- *total = COSTS_N_INSNS (50);
+ *total = COSTS_N_INSNS (speed ? 100 : 50);
return true;
}
@@ -4153,6 +4161,98 @@ xtensa_rtx_costs (rtx x, machine_mode mode, int outer_code,
}
}
+static bool
+xtensa_is_insn_L32R_p(const rtx_insn *insn)
+{
+ rtx x = PATTERN (insn);
+
+ if (GET_CODE (x) == SET)
+ {
+ x = XEXP (x, 1);
+ if (GET_CODE (x) == MEM)
+ {
+ x = XEXP (x, 0);
+ return (GET_CODE (x) == SYMBOL_REF || CONST_INT_P (x))
+ && CONSTANT_POOL_ADDRESS_P (x);
+ }
+ }
+
+ return false;
+}
+
+/* Compute a relative costs of RTL insns. This is necessary in order to
+ achieve better RTL insn splitting/combination result. */
+
+static int
+xtensa_insn_cost (rtx_insn *insn, bool speed)
+{
+ if (!(recog_memoized (insn) < 0))
+ {
+ int len = get_attr_length (insn), n = (len + 2) / 3;
+
+ if (len == 0)
+ return COSTS_N_INSNS (0);
+
+ if (speed) /* For speed cost. */
+ {
+ /* "L32R" may be particular slow (implementation-dependent). */
+ if (xtensa_is_insn_L32R_p (insn))
+ return COSTS_N_INSNS (1 + xtensa_extra_l32r_costs);
+
+ /* Cost based on the pipeline model. */
+ switch (get_attr_type (insn))
+ {
+ case TYPE_STORE:
+ case TYPE_MOVE:
+ case TYPE_ARITH:
+ case TYPE_MULTI:
+ case TYPE_NOP:
+ case TYPE_FSTORE:
+ return COSTS_N_INSNS (n);
+
+ case TYPE_LOAD:
+ return COSTS_N_INSNS (n - 1 + 2);
+
+ case TYPE_JUMP:
+ case TYPE_CALL:
+ return COSTS_N_INSNS (n - 1 + 3);
+
+ case TYPE_FCONV:
+ case TYPE_FLOAD:
+ case TYPE_MUL16:
+ case TYPE_MUL32:
+ case TYPE_RSR:
+ return COSTS_N_INSNS (n * 2);
+
+ case TYPE_FMADD:
+ return COSTS_N_INSNS (n * 4);
+
+ case TYPE_DIV32:
+ return COSTS_N_INSNS (n * 16);
+
+ default:
+ break;
+ }
+ }
+ else /* For size cost. */
+ {
+ /* Cost based on the instruction length. */
+ if (get_attr_type (insn) != TYPE_UNKNOWN)
+ {
+ /* "L32R" itself plus constant in litpool. */
+ if (xtensa_is_insn_L32R_p (insn))
+ return COSTS_N_INSNS (2) + 1;
+
+ /* Consider ".n" short instructions. */
+ return COSTS_N_INSNS (n) - (n * 3 - len);
+ }
+ }
+ }
+
+ /* Fall back. */
+ return pattern_cost (PATTERN (insn), speed);
+}
+
/* Worker function for TARGET_RETURN_IN_MEMORY. */
static bool
diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md
index 33cbd54..f6c6be4 100644
--- a/gcc/config/xtensa/xtensa.md
+++ b/gcc/config/xtensa/xtensa.md
@@ -98,7 +98,10 @@
;; Describe a user's asm statement.
(define_asm_attributes
- [(set_attr "type" "multi")])
+ [(set_attr "type" "multi")
+ (set_attr "mode" "none")
+ (set_attr "length" "3")]) ;; Should be the maximum possible length
+ ;; of a single machine instruction.
;; Pipeline model.
@@ -1879,7 +1882,10 @@
}
[(set_attr "type" "jump")
(set_attr "mode" "none")
- (set_attr "length" "2")])
+ (set (attr "length")
+ (if_then_else (match_test "TARGET_DENSITY")
+ (const_int 2)
+ (const_int 3)))])
;; Miscellaneous instructions.
@@ -1934,7 +1940,10 @@
}
[(set_attr "type" "nop")
(set_attr "mode" "none")
- (set_attr "length" "3")])
+ (set (attr "length")
+ (if_then_else (match_test "TARGET_DENSITY")
+ (const_int 2)
+ (const_int 3)))])
(define_expand "nonlocal_goto"
[(match_operand:SI 0 "general_operand" "")
@@ -1998,8 +2007,9 @@
[(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
""
""
- [(set_attr "length" "0")
- (set_attr "type" "nop")])
+ [(set_attr "type" "nop")
+ (set_attr "mode" "none")
+ (set_attr "length" "0")])
;; Do not schedule instructions accessing memory before this point.
@@ -2018,7 +2028,9 @@
(unspec:BLK [(match_operand:SI 1 "" "")] UNSPEC_FRAME_BLOCKAGE))]
""
""
- [(set_attr "length" "0")])
+ [(set_attr "type" "nop")
+ (set_attr "mode" "none")
+ (set_attr "length" "0")])
(define_insn "trap"
[(trap_if (const_int 1) (const_int 0))]
@@ -2031,7 +2043,10 @@
}
[(set_attr "type" "trap")
(set_attr "mode" "none")
- (set_attr "length" "3")])
+ (set (attr "length")
+ (if_then_else (match_test "!TARGET_DEBUG && TARGET_DENSITY")
+ (const_int 2)
+ (const_int 3)))])
;; Setting up a frame pointer is tricky for Xtensa because GCC doesn't
;; know if a frame pointer is required until the reload pass, and
diff --git a/gcc/config/xtensa/xtensa.opt b/gcc/config/xtensa/xtensa.opt
index 1fc68a3..08338e3 100644
--- a/gcc/config/xtensa/xtensa.opt
+++ b/gcc/config/xtensa/xtensa.opt
@@ -30,6 +30,10 @@ mlongcalls
Target Mask(LONGCALLS)
Use indirect CALLXn instructions for large programs.
+mextra-l32r-costs=
+Target RejectNegative Joined UInteger Var(xtensa_extra_l32r_costs) Init(0)
+Set extra memory access cost for L32R instruction, in clock-cycle units.
+
mtarget-align
Target
Automatically align branch targets to reduce branch penalties.