Previously, in 1eefa6e0c84e3008ed7ac44d08a8e5206038fb33 and a series of
subsequent commits, we added a target-specific optimization pass
'xt_largeconst' right after postreload to convert assignments of numeric
constants that don't fit into immediate fields to a more efficient
implementation than the standard one (references to literal pool entries),
if available.
However, the processes performed in this pass are a mixture of essential
and optional ones (such as optimizations), which is not good in terms of
structure or execution efficiency. Additionally, large numeric constant
assignments may be emitted after this pass, for example during stack frame
construction in function prologue.
To address these issues, this patch splits the processing in this pass
into two parts:
- places the mandatory processing (i.e., restoring delegitimized forms
of large numeric constant assignments to valid ones) immediately after
postreload, and
- places the rest, optional processing (i.e., optimizations) immediately
before regrename, which a reasonable location after pro_and_epilogue
and before sched2.
gcc/ChangeLog:
* config/xtensa/xtensa-passes.def (pass_xtensa_largeconst):
Rename to pass_xtensa_largeconst1.
(pass_xtensa_largeconst2): New target-specific pass.
* config/xtensa/xtensa-protos.h (make_pass_xtensa_largeconst):
Rename to make_pass_xtensa_largeconst1.
(make_pass_xtensa_largeconst2): New function prototype.
* config/xtensa/xtensa.cc (do_largeconst):
Rename it to do_largeconst1 and leave only the mandatory insn
transformation process.
(do_largeconst2): New function that inherits the optional insn
transformation processes from the old do_largeconst.
(rest_of_handle_largeconst):
Rename to rest_of_handle_largeconst1 and change to call
do_largeconst1.
(rest_of_handle_largeconst2): New function that calls
do_largeconst2.
(pass_data_xtensa_largeconst)
Rename to pass_data_xtensa_largeconst1.
(pass_xtensa_largeconst):
Rename to pass_xtensa_largeconst1 and change to call
rest_of_handle_largeconst1.
(pass_data_xtensa_largeconst2): New opt_pass data.
(pass_xtensa_largeconst2):
New rtl_opt_pass that runs rest_of_handle_largeconst2 when non-
debug optimizations are enabled.
(make_pass_xtensa_largeconst):
Rename to make_pass_xtensa_largeconst1.
(make_pass_xtensa_largeconst2): New function definition.
---
gcc/config/xtensa/xtensa-passes.def | 3 +-
gcc/config/xtensa/xtensa-protos.h | 3 +-
gcc/config/xtensa/xtensa.cc | 120 +++++++++++++++++++++-------
3 files changed, 94 insertions(+), 32 deletions(-)
diff --git a/gcc/config/xtensa/xtensa-passes.def
b/gcc/config/xtensa/xtensa-passes.def
index 65c719356f4..e1c636cc4a3 100644
--- a/gcc/config/xtensa/xtensa-passes.def
+++ b/gcc/config/xtensa/xtensa-passes.def
@@ -17,4 +17,5 @@ You should have received a copy of the GNU General Public
License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
-INSERT_PASS_AFTER (pass_postreload_cse, 1, pass_xtensa_largeconst);
+INSERT_PASS_AFTER (pass_postreload_cse, 1, pass_xtensa_largeconst1);
+INSERT_PASS_BEFORE (pass_regrename, 1, pass_xtensa_largeconst2);
diff --git a/gcc/config/xtensa/xtensa-protos.h
b/gcc/config/xtensa/xtensa-protos.h
index 53730d92b38..f41f32f18ac 100644
--- a/gcc/config/xtensa/xtensa-protos.h
+++ b/gcc/config/xtensa/xtensa-protos.h
@@ -80,6 +80,7 @@ extern void xtensa_adjust_reg_alloc_order (void);
extern enum reg_class xtensa_regno_to_class (int regno);
extern HOST_WIDE_INT xtensa_initial_elimination_offset (int from, int to);
extern const char **xtensa_get_config_strings (void);
-extern rtl_opt_pass *make_pass_xtensa_largeconst (gcc::context *);
+extern rtl_opt_pass *make_pass_xtensa_largeconst1 (gcc::context *);
+extern rtl_opt_pass *make_pass_xtensa_largeconst2 (gcc::context *);
#endif /* !__XTENSA_PROTOS_H__ */
diff --git a/gcc/config/xtensa/xtensa.cc b/gcc/config/xtensa/xtensa.cc
index d9420bb2cda..8a20c9eab58 100644
--- a/gcc/config/xtensa/xtensa.cc
+++ b/gcc/config/xtensa/xtensa.cc
@@ -6234,14 +6234,26 @@ litpool_set_src (rtx_insn *insn)
}
/* Replace all occurrences of large immediate values in assignment sources
- that were permitted for convenience with their legitimate forms, or
- more efficient representations if possible. */
+ that were permitted for convenience with their legitimate forms. */
static void
-do_largeconst (void)
+do_largeconst1 (void)
+{
+ rtx_insn *insn;
+
+ /* Replace the source of [SH]Imode allocation whose value does not fit
+ into signed 12 bits with a reference to litpool entry. */
+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ if (NONJUMP_INSN_P (insn))
+ litpool_set_src (insn);
+}
+
+/* Replace large immediate values in allocation sources with more efficient
+ representations if possible. */
+
+static void
+do_largeconst2 (void)
{
- bool replacing_required = !TARGET_CONST16 && !TARGET_AUTO_LITPOOLS;
- bool optimize_enabled = optimize && !optimize_debug;
rtx_insn *insn;
constantsynth_info cs_info;
@@ -6253,18 +6265,12 @@ do_largeconst (void)
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
if (NONJUMP_INSN_P (insn))
{
- /* Optimize assignment of negatively scaled (up to the minus
- 15th power of two) signed 12-bit immediate values to hardware
+ /* Optimize assignment of negatively scaled (up to the minus 15th
+ power of two) signed 12-bit immediate values to hardware
floating-point registers. */
- if (optimize_enabled
- && FPreg_neg_scaled_simm12b (insn))
+ if (FPreg_neg_scaled_simm12b (insn))
continue;
- /* Replace the source of [SH]Imode allocation whose value does not
- fit into signed 12 bits with a reference to litpool entry. */
- if (replacing_required)
- litpool_set_src (insn);
-
/* Split DI/SF/DFmode constant assignments into pairs of SImode
ones. This is also the pre-processing for constantsynth opti-
mization that follows immediately after. */
@@ -6272,22 +6278,20 @@ do_largeconst (void)
/* constantsynth pass 1.
Detect and record large constant assignments within a function. */
- if (optimize_enabled)
- constantsynth_pass1 (insn, cs_info);
+ constantsynth_pass1 (insn, cs_info);
}
/* constantsynth pass 2.
For each large constant value assignment collected in pass 1, try to
find a more efficient way to derive the value than referencing a literal
pool entry, and if found, replace the assignment with it. */
- if (optimize_enabled)
- constantsynth_pass2 (cs_info);
+ constantsynth_pass2 (cs_info);
}
/* Convert assignments for large constants. */
static unsigned int
-rest_of_handle_largeconst (void)
+rest_of_handle_largeconst1 (void)
{
/* Until this flag becomes true, all RTL expressions that assign integer
(not symbol nor floating-point) constants to [SH]Imode registers are
@@ -6321,23 +6325,67 @@ rest_of_handle_largeconst (void)
is no longer needed, so such assignments must now be all converted
back to references to literal pool entries (the original legitimate
form) if neither TARGET_CONST16 nor TARGET_AUTO_LITPOOLS is enabled.
- See the function do_largeconst() called below. */
+ See the function do_largeconst1() called below. */
cfun->machine->postreload_completed = true;
+ /* Do the process, only if the conditions are met. */
+ if (!TARGET_CONST16 && !TARGET_AUTO_LITPOOLS)
+ {
+ df_set_flags (DF_DEFER_INSN_RESCAN);
+
+ do_largeconst1 ();
+ }
+
+ return 0;
+}
+
+static unsigned int
+rest_of_handle_largeconst2 (void)
+{
df_set_flags (DF_DEFER_INSN_RESCAN);
+
+ /* The latest reg-notes are required later. */
df_note_add_problem ();
df_analyze ();
/* Do the process. */
- do_largeconst ();
+ do_largeconst2 ();
return 0;
}
-const pass_data pass_data_xtensa_largeconst =
+const pass_data pass_data_xtensa_largeconst1 =
+{
+ RTL_PASS, /* type */
+ "xt_largeconst1", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
+ TV_MACH_DEP, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ TODO_df_finish, /* todo_flags_finish */
+};
+
+class pass_xtensa_largeconst1 : public rtl_opt_pass
+{
+public:
+ pass_xtensa_largeconst1 (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_xtensa_largeconst1, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ unsigned int execute (function *) final override
+ {
+ return rest_of_handle_largeconst1 ();
+ }
+
+}; // class pass_xtensa_largeconst1
+
+const pass_data pass_data_xtensa_largeconst2 =
{
RTL_PASS, /* type */
- "xt_largeconst", /* name */
+ "xt_largeconst2", /* name */
OPTGROUP_NONE, /* optinfo_flags */
TV_MACH_DEP, /* tv_id */
0, /* properties_required */
@@ -6347,27 +6395,39 @@ const pass_data pass_data_xtensa_largeconst =
TODO_df_finish, /* todo_flags_finish */
};
-class pass_xtensa_largeconst : public rtl_opt_pass
+class pass_xtensa_largeconst2 : public rtl_opt_pass
{
public:
- pass_xtensa_largeconst (gcc::context *ctxt)
- : rtl_opt_pass (pass_data_xtensa_largeconst, ctxt)
+ pass_xtensa_largeconst2 (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_xtensa_largeconst2, ctxt)
{}
+ /* opt_pass methods: */
+ bool gate (function *) final override
+ {
+ return optimize && !optimize_debug;
+ }
+
/* opt_pass methods: */
unsigned int execute (function *) final override
{
- return rest_of_handle_largeconst ();
+ return rest_of_handle_largeconst2 ();
}
-}; // class pass_xtensa_largeconst
+}; // class pass_xtensa_largeconst2
} // anon namespace
rtl_opt_pass *
-make_pass_xtensa_largeconst (gcc::context *ctxt)
+make_pass_xtensa_largeconst1 (gcc::context *ctxt)
+{
+ return new pass_xtensa_largeconst1 (ctxt);
+}
+
+rtl_opt_pass *
+make_pass_xtensa_largeconst2 (gcc::context *ctxt)
{
- return new pass_xtensa_largeconst (ctxt);
+ return new pass_xtensa_largeconst2 (ctxt);
}
#include "gt-xtensa.h"
--
2.39.5