Line data Source code
1 : // Dependency fusion reordering pass.
2 : // Copyright (C) 2025-2026 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 571444 : pass_dep_fusion (gcc::context *ctxt)
60 1142888 : : rtl_opt_pass (pass_data_dep_fusion, ctxt)
61 : {}
62 :
63 : // opt_pass methods:
64 285722 : 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 2942740 : pass_dep_fusion::gate (function *)
71 : {
72 2942740 : return optimize > 0 && flag_dep_fusion;
73 : }
74 :
75 : unsigned int
76 1927962 : pass_dep_fusion::execute (function *fn)
77 : {
78 : // If the target has no macro fusion, there is nothing to be done.
79 1927962 : if (!targetm.sched.macro_fusion_pair_p)
80 : return 0;
81 :
82 : // Initialization.
83 1927962 : calculate_dominance_info (CDI_DOMINATORS);
84 1927962 : df_analyze ();
85 1927962 : crtl->ssa = new rtl_ssa::function_info (fn);
86 :
87 1927962 : init_recog_no_volatile ();
88 :
89 1927962 : for (rtl_ssa::insn_info *insn = *crtl->ssa->nondebug_insns ().begin ();
90 182035910 : insn;
91 180107948 : insn = insn->next_nondebug_insn ())
92 : {
93 180107948 : if (!insn->can_be_optimized () || insn->num_defs () != 1)
94 172240432 : continue;
95 :
96 74807784 : rtl_ssa::set_info *def = single_set_info (insn);
97 74807784 : if (!def)
98 21189 : continue;
99 :
100 74786595 : rtl_ssa::use_info *use_insn = def->single_nondebug_insn_use ();
101 141608105 : if (!use_insn
102 52306399 : || !use_insn->insn ()->can_be_optimized ()
103 120120932 : || !targetm.sched.macro_fusion_pair_p (insn->rtl (),
104 : use_insn->insn ()->rtl ()))
105 66821510 : continue;
106 :
107 7965085 : auto attempt = crtl->ssa->new_change_attempt ();
108 7965085 : rtl_ssa::insn_change change (use_insn->insn ());
109 :
110 7966294 : if (use_insn->insn () != insn->next_any_insn ())
111 : {
112 97569 : if (!can_move_insn_p (use_insn->insn ()))
113 97569 : 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 7867516 : SCHED_GROUP_P (use_insn->insn ()->rtl ()) = 1;
129 7867516 : confirm_change_group ();
130 7867516 : crtl->ssa->change_insn (change);
131 7965085 : }
132 :
133 : // Finalization.
134 1927962 : if (crtl->ssa->perform_pending_updates ())
135 0 : cleanup_cfg (0);
136 :
137 1927962 : delete crtl->ssa;
138 :
139 1927962 : init_recog ();
140 1927962 : free_dominance_info (CDI_DOMINATORS);
141 1927962 : return 0;
142 : }
143 :
144 : } // end namespace
145 :
146 : // Create a new dep fusion pass instance.
147 :
148 : rtl_opt_pass *
149 285722 : make_pass_dep_fusion (gcc::context *ctxt)
150 : {
151 285722 : return new pass_dep_fusion (ctxt);
152 : }
|