GCC Middle and Back End API Reference
pair-fusion.h
Go to the documentation of this file.
1// Pass to fuse adjacent loads/stores into paired memory accesses.
2//
3// This file contains the definition of the virtual base class which is
4// overriden by targets that make use of the pass.
5//
6// Copyright (C) 2023-2024 Free Software Foundation, Inc.
7//
8// This file is part of GCC.
9//
10// GCC is free software; you can redistribute it and/or modify it
11// under the terms of the GNU General Public License as published by
12// the Free Software Foundation; either version 3, or (at your option)
13// any later version.
14//
15// GCC is distributed in the hope that it will be useful, but
16// WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18// General Public License for more details.
19//
20// You should have received a copy of the GNU General Public License
21// along with GCC; see the file COPYING3. If not see
22// <http://www.gnu.org/licenses/>.
23
24namespace rtl_ssa {
25 class def_info;
26 class insn_info;
27 class insn_range_info;
28 class bb_info;
29}
30
31// Information about a potential base candidate, used in try_fuse_pair.
32// There may be zero, one, or two viable RTL bases for a given pair.
34{
35 // DEF is the def of the base register to be used by the pair.
36 rtl_ssa::def_info *def;
37
38 // FROM_INSN is -1 if the base candidate is already shared by both
39 // candidate insns. Otherwise it holds the index of the insn from
40 // which the base originated.
41 //
42 // In the case that the base is shared, either DEF is already used
43 // by both candidate accesses, or both accesses see different versions
44 // of the same regno, in which case DEF is the def consumed by the
45 // first candidate access.
47
48 // To form a pair, we do so by moving the first access down and the second
49 // access up. To determine where to form the pair, and whether or not
50 // it is safe to form the pair, we track instructions which cannot be
51 // re-ordered past due to either dataflow or alias hazards.
52 //
53 // Since we allow changing the base used by an access, the choice of
54 // base can change which instructions act as re-ordering hazards for
55 // this pair (due to different dataflow). We store the initial
56 // dataflow hazards for this choice of base candidate in HAZARDS.
57 //
58 // These hazards act as re-ordering barriers to each candidate insn
59 // respectively, in program order.
60 //
61 // Later on, when we take alias analysis into account, we narrow
62 // HAZARDS accordingly.
63 rtl_ssa::insn_info *hazards[2];
64
65 base_cand (rtl_ssa::def_info *def, int insn)
66 : def (def), from_insn (insn), hazards {nullptr, nullptr} {}
67
68 base_cand (rtl_ssa::def_info *def) : base_cand (def, -1) {}
69
70 // Test if this base candidate is viable according to HAZARDS.
71 bool viable () const;
72};
73
74struct alias_walker;
75
76// When querying should_handle_writeback, this enum is used to
77// qualify which opportunities we are asking about.
78enum class writeback_type {
79 // Only those writeback opportunities that arise from existing
80 // auto-increment accesses.
82
83 // All writeback opportunities, including those that involve folding
84 // base register updates into a non-writeback pair.
85 ALL
86};
87
88// This class can be overriden by targets to give a pass that fuses
89// adjacent loads and stores into load/store pair instructions.
90//
91// The target can override the various virtual functions to customize
92// the behaviour of the pass as appropriate for the target.
94 pair_fusion ();
95
96 // Given:
97 // - an rtx REG_OP, the non-memory operand in a load/store insn,
98 // - a machine_mode MEM_MODE, the mode of the MEM in that insn, and
99 // - a boolean LOAD_P (true iff the insn is a load), then:
100 // return true if the access should be considered an FP/SIMD access.
101 // Such accesses are segregated from GPR accesses, since we only want
102 // to form pairs for accesses that use the same register file.
103 virtual bool fpsimd_op_p (rtx, machine_mode, bool)
104 {
105 return false;
106 }
107
108 // Return true if we should consider forming pairs from memory
109 // accesses with operand mode MODE at this stage in compilation.
110 virtual bool pair_operand_mode_ok_p (machine_mode mode) = 0;
111
112 // Return true iff REG_OP is a suitable register operand for a paired
113 // memory access, where LOAD_P is true if we're asking about loads and
114 // false for stores. MODE gives the mode of the operand.
115 virtual bool pair_reg_operand_ok_p (bool load_p, rtx reg_op,
116 machine_mode mode) = 0;
117
118 // Return alias check limit.
119 // This is needed to avoid unbounded quadratic behaviour when
120 // performing alias analysis.
121 virtual int pair_mem_alias_check_limit () = 0;
122
123 // Return true if we should try to handle writeback opportunities.
124 // WHICH determines the kinds of writeback opportunities the caller
125 // is asking about.
126 virtual bool should_handle_writeback (writeback_type which) = 0;
127
128 // Given BASE_MEM, the mem from the lower candidate access for a pair,
129 // and LOAD_P (true if the access is a load), check if we should proceed
130 // to form the pair given the target's code generation policy on
131 // paired accesses.
132 virtual bool pair_mem_ok_with_policy (rtx base_mem, bool load_p) = 0;
133
134 // Generate the pattern for a paired access. PATS gives the patterns
135 // for the individual memory accesses (which by this point must share a
136 // common base register). If WRITEBACK is non-NULL, then this rtx
137 // describes the update to the base register that should be performed by
138 // the resulting insn. LOAD_P is true iff the accesses are loads.
139 virtual rtx gen_pair (rtx *pats, rtx writeback, bool load_p) = 0;
140
141 // Return true if INSN is a paired memory access. If so, set LOAD_P to
142 // true iff INSN is a load pair.
143 virtual bool pair_mem_insn_p (rtx_insn *insn, bool &load_p) = 0;
144
145 // Return true if we should track loads.
146 virtual bool track_loads_p ()
147 {
148 return true;
149 }
150
151 // Return true if we should track stores.
152 virtual bool track_stores_p ()
153 {
154 return true;
155 }
156
157 // Return true if OFFSET is in range for a paired memory access.
158 virtual bool pair_mem_in_range_p (HOST_WIDE_INT offset) = 0;
159
160 // Given a load/store pair insn in PATTERN, unpack the insn, storing
161 // the register operands in REGS, and returning the mem. LOAD_P is
162 // true for loads and false for stores.
163 virtual rtx destructure_pair (rtx regs[2], rtx pattern, bool load_p) = 0;
164
165 // Given a pair mem in MEM, register operands in REGS, and an rtx
166 // representing the effect of writeback on the base register in WB_EFFECT,
167 // return an insn representing a writeback variant of this pair.
168 // LOAD_P is true iff the pair is a load.
169 // This is used when promoting existing non-writeback pairs to writeback
170 // variants.
171 virtual rtx gen_promote_writeback_pair (rtx wb_effect, rtx mem,
172 rtx regs[2], bool load_p) = 0;
173
174 void process_block (rtl_ssa::bb_info *bb);
175 rtl_ssa::insn_info *find_trailing_add (rtl_ssa::insn_info *insns[2],
176 const rtl_ssa::insn_range_info
177 &pair_range,
178 int initial_writeback,
179 rtx *writeback_effect,
180 rtl_ssa::def_info **add_def,
181 rtl_ssa::def_info *base_def,
182 poly_int64 initial_offset,
183 unsigned access_size);
184 int get_viable_bases (rtl_ssa::insn_info *insns[2],
185 vec<base_cand> &base_cands,
186 rtx cand_mems[2],
187 unsigned access_size,
188 bool reversed);
189 void do_alias_analysis (rtl_ssa::insn_info *alias_hazards[4],
190 alias_walker *walkers[4],
191 bool load_p);
192 void try_promote_writeback (rtl_ssa::insn_info *insn, bool load_p);
193 void run ();
194 ~pair_fusion ();
195};
static hash_table< insn_hasher > * insns
Definition gentarget-def.cc:53
Definition emit-rtl.h:26
writeback_type
Definition pair-fusion.h:78
rtx offset
Definition postreload.cc:691
Definition pair-fusion.cc:99
Definition pair-fusion.h:34
base_cand(rtl_ssa::def_info *def, int insn)
Definition pair-fusion.h:65
int from_insn
Definition pair-fusion.h:46
base_cand(rtl_ssa::def_info *def)
Definition pair-fusion.h:68
bool viable() const
Definition pair-fusion.cc:84
rtl_ssa::def_info * def
Definition pair-fusion.h:36
rtl_ssa::insn_info * hazards[2]
Definition pair-fusion.h:63
Definition loop-invariant.cc:88
Definition pair-fusion.h:93
rtl_ssa::insn_info * find_trailing_add(rtl_ssa::insn_info *insns[2], const rtl_ssa::insn_range_info &pair_range, int initial_writeback, rtx *writeback_effect, rtl_ssa::def_info **add_def, rtl_ssa::def_info *base_def, poly_int64 initial_offset, unsigned access_size)
Definition pair-fusion.cc:1151
pair_fusion()
Definition pair-fusion.cc:107
void process_block(rtl_ssa::bb_info *bb)
Definition pair-fusion.cc:3080
int get_viable_bases(rtl_ssa::insn_info *insns[2], vec< base_cand > &base_cands, rtx cand_mems[2], unsigned access_size, bool reversed)
Definition pair-fusion.cc:2350
virtual bool track_stores_p()
Definition pair-fusion.h:152
void do_alias_analysis(rtl_ssa::insn_info *alias_hazards[4], alias_walker *walkers[4], bool load_p)
Definition pair-fusion.cc:2259
virtual bool should_handle_writeback(writeback_type which)=0
virtual rtx gen_promote_writeback_pair(rtx wb_effect, rtx mem, rtx regs[2], bool load_p)=0
virtual bool fpsimd_op_p(rtx, machine_mode, bool)
Definition pair-fusion.h:103
void run()
Definition pair-fusion.cc:127
virtual bool track_loads_p()
Definition pair-fusion.h:146
virtual bool pair_mem_in_range_p(HOST_WIDE_INT offset)=0
virtual bool pair_operand_mode_ok_p(machine_mode mode)=0
virtual rtx destructure_pair(rtx regs[2], rtx pattern, bool load_p)=0
virtual bool pair_mem_insn_p(rtx_insn *insn, bool &load_p)=0
virtual bool pair_reg_operand_ok_p(bool load_p, rtx reg_op, machine_mode mode)=0
virtual int pair_mem_alias_check_limit()=0
virtual bool pair_mem_ok_with_policy(rtx base_mem, bool load_p)=0
void try_promote_writeback(rtl_ssa::insn_info *insn, bool load_p)
Definition pair-fusion.cc:2990
~pair_fusion()
Definition pair-fusion.cc:114
virtual rtx gen_pair(rtx *pats, rtx writeback, bool load_p)=0
Definition rtl.h:312
Definition rtl.h:546
Definition vec.h:450