Branch data Line data Source code
1 : : // Dependency fusion reordering pass.
2 : : // Copyright (C) 2025 Free Software Foundation, Inc.
3 : : //
4 : : // This file is part of GCC.
5 : : //
6 : : // GCC is free software; you can redistribute it and/or modify it under
7 : : // the terms of the GNU General Public License as published by the Free
8 : : // Software Foundation; either version 3, or (at your option) any later
9 : : // version.
10 : : //
11 : : // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 : : // WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 : : // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 : : // for more details.
15 : : //
16 : : // You should have received a copy of the GNU General Public License
17 : : // along with GCC; see the file COPYING3. If not see
18 : : // <http://www.gnu.org/licenses/>.
19 : : //
20 : : // This pass uses the RTL-SSA representation to detect def-use pairs that are
21 : : // macro-op-fusible in the current microarchitecture (using the
22 : : // macro_fusion_pair_p () target hook) and place them next to one another, if
23 : : // possible.
24 : :
25 : : #define INCLUDE_ALGORITHM
26 : : #define INCLUDE_FUNCTIONAL
27 : : #define INCLUDE_MEMORY
28 : : #define INCLUDE_ARRAY
29 : : #include "config.h"
30 : : #include "system.h"
31 : : #include "coretypes.h"
32 : : #include "backend.h"
33 : : #include "rtl.h"
34 : : #include "df.h"
35 : : #include "rtl-ssa.h"
36 : : #include "print-rtl.h"
37 : : #include "tree-pass.h"
38 : : #include "cfgcleanup.h"
39 : : #include "target.h"
40 : : #include "dbgcnt.h"
41 : :
42 : : namespace {
43 : : const pass_data pass_data_dep_fusion =
44 : : {
45 : : RTL_PASS, // type
46 : : "dep_fusion", // name
47 : : OPTGROUP_NONE, // optinfo_flags
48 : : TV_NONE, // tv_id
49 : : 0, // properties_required
50 : : 0, // properties_provided
51 : : 0, // properties_destroyed
52 : : 0, // todo_flags_start
53 : : TODO_df_finish, // todo_flags_finish
54 : : };
55 : :
56 : : class pass_dep_fusion : public rtl_opt_pass
57 : : {
58 : : public:
59 : 571378 : pass_dep_fusion (gcc::context *ctxt)
60 : 1142756 : : rtl_opt_pass (pass_data_dep_fusion, ctxt)
61 : : {}
62 : :
63 : : // opt_pass methods:
64 : 285689 : opt_pass *clone () final override { return new pass_dep_fusion (m_ctxt); }
65 : : bool gate (function *) final override;
66 : : unsigned int execute (function *) final override;
67 : : };
68 : :
69 : : bool
70 : 2962680 : pass_dep_fusion::gate (function *)
71 : : {
72 : 2962680 : return optimize > 0 && flag_dep_fusion;
73 : : }
74 : :
75 : : unsigned int
76 : 1932184 : pass_dep_fusion::execute (function *fn)
77 : : {
78 : : // If the target has no macro fusion, there is nothing to be done.
79 : 1932184 : if (!targetm.sched.macro_fusion_pair_p)
80 : : return 0;
81 : :
82 : : // Initialization.
83 : 1932184 : calculate_dominance_info (CDI_DOMINATORS);
84 : 1932184 : df_analyze ();
85 : 1932184 : crtl->ssa = new rtl_ssa::function_info (fn);
86 : :
87 : 1932184 : init_recog_no_volatile ();
88 : :
89 : 1932184 : for (rtl_ssa::insn_info *insn = *crtl->ssa->nondebug_insns ().begin ();
90 : 184130302 : insn;
91 : 182198118 : insn = insn->next_nondebug_insn ())
92 : : {
93 : 182198118 : if (!insn->can_be_optimized () || insn->num_defs () != 1)
94 : 174299870 : continue;
95 : :
96 : 75698940 : rtl_ssa::set_info *def = single_set_info (insn);
97 : 75698940 : if (!def)
98 : 20554 : continue;
99 : :
100 : 75678386 : rtl_ssa::use_info *use_insn = def->single_nondebug_insn_use ();
101 : 143361194 : if (!use_insn
102 : 53248049 : || !use_insn->insn ()->can_be_optimized ()
103 : 121790241 : || !targetm.sched.macro_fusion_pair_p (insn->rtl (),
104 : : use_insn->insn ()->rtl ()))
105 : 67682808 : continue;
106 : :
107 : 7995578 : auto attempt = crtl->ssa->new_change_attempt ();
108 : 7995578 : rtl_ssa::insn_change change (use_insn->insn ());
109 : :
110 : 7997076 : if (use_insn->insn () != insn->next_any_insn ())
111 : : {
112 : 97330 : if (!can_move_insn_p (use_insn->insn ()))
113 : 97330 : continue;
114 : :
115 : 0 : change.move_range = insn;
116 : 0 : if (!rtl_ssa::restrict_movement (change))
117 : 0 : continue;
118 : :
119 : 0 : if (dump_file && (dump_flags & TDF_DETAILS))
120 : : {
121 : 0 : fprintf (dump_file, "Moved a single-use instruction:\n");
122 : 0 : dump_insn_slim (dump_file, use_insn->insn ()->rtl ());
123 : 0 : fprintf (dump_file, "right after its definition:\n");
124 : 0 : dump_insn_slim (dump_file, insn->rtl ());
125 : : }
126 : : }
127 : :
128 : 7898248 : SCHED_GROUP_P (use_insn->insn ()->rtl ()) = 1;
129 : 7898248 : confirm_change_group ();
130 : 7898248 : crtl->ssa->change_insn (change);
131 : 7995578 : }
132 : :
133 : : // Finalization.
134 : 1932184 : if (crtl->ssa->perform_pending_updates ())
135 : 0 : cleanup_cfg (0);
136 : :
137 : 1932184 : delete crtl->ssa;
138 : :
139 : 1932184 : init_recog ();
140 : 1932184 : free_dominance_info (CDI_DOMINATORS);
141 : 1932184 : return 0;
142 : : }
143 : :
144 : : } // end namespace
145 : :
146 : : // Create a new dep fusion pass instance.
147 : :
148 : : rtl_opt_pass *
149 : 285689 : make_pass_dep_fusion (gcc::context *ctxt)
150 : : {
151 : 285689 : return new pass_dep_fusion (ctxt);
152 : : }
|