Branch data Line data Source code
1 : : /* Shared code for before and after reload gcse implementations.
2 : : Copyright (C) 1997-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 : : It is expected that more hunks of gcse.cc and postreload-gcse.cc should
21 : : migrate into this file. */
22 : :
23 : : #include "config.h"
24 : : #include "system.h"
25 : : #include "coretypes.h"
26 : : #include "backend.h"
27 : : #include "rtl.h"
28 : : #include "df.h"
29 : : #include "gcse-common.h"
30 : : #include "regs.h"
31 : : #include "function-abi.h"
32 : :
33 : : /* Record all of the canonicalized MEMs of record_last_mem_set_info's insn.
34 : : Note we store a pair of elements in the list, so they have to be
35 : : taken off pairwise. */
36 : :
37 : : void
38 : 7277834 : canon_list_insert (rtx dest, const_rtx x ATTRIBUTE_UNUSED, void *data)
39 : : {
40 : 7277834 : rtx dest_addr;
41 : 7277834 : int bb;
42 : 7277834 : modify_pair pair;
43 : :
44 : 7277834 : while (GET_CODE (dest) == SUBREG
45 : 7277834 : || GET_CODE (dest) == ZERO_EXTRACT
46 : 14555668 : || GET_CODE (dest) == STRICT_LOW_PART)
47 : 0 : dest = XEXP (dest, 0);
48 : :
49 : : /* If DEST is not a MEM, then it will not conflict with a load. Note
50 : : that function calls are assumed to clobber memory, but are handled
51 : : elsewhere. */
52 : :
53 : 7277834 : if (! MEM_P (dest))
54 : 284077 : return;
55 : :
56 : 6993757 : dest_addr = get_addr (XEXP (dest, 0));
57 : 6993757 : dest_addr = canon_rtx (dest_addr);
58 : 6993757 : rtx_insn *insn = ((struct gcse_note_stores_info *)data)->insn;
59 : 6993757 : bb = BLOCK_FOR_INSN (insn)->index;
60 : :
61 : 6993757 : pair.dest = dest;
62 : 6993757 : pair.dest_addr = dest_addr;
63 : 6993757 : vec<modify_pair> *canon_mem_list
64 : : = ((struct gcse_note_stores_info *)data)->canon_mem_list;
65 : 6993757 : canon_mem_list[bb].safe_push (pair);
66 : : }
67 : :
68 : : /* Record memory modification information for INSN. We do not actually care
69 : : about the memory location(s) that are set, or even how they are set (consider
70 : : a CALL_INSN). We merely need to record which insns modify memory. */
71 : :
72 : : void
73 : 10922070 : record_last_mem_set_info_common (rtx_insn *insn,
74 : : vec<rtx_insn *> *modify_mem_list,
75 : : vec<modify_pair> *canon_modify_mem_list,
76 : : bitmap modify_mem_list_set,
77 : : bitmap blocks_with_calls)
78 : :
79 : : {
80 : 10922070 : int bb;
81 : :
82 : 10922070 : bb = BLOCK_FOR_INSN (insn)->index;
83 : 10922070 : modify_mem_list[bb].safe_push (insn);
84 : 10922070 : bitmap_set_bit (modify_mem_list_set, bb);
85 : :
86 : 10922070 : if (CALL_P (insn))
87 : 3929219 : bitmap_set_bit (blocks_with_calls, bb);
88 : : else
89 : : {
90 : 6992851 : struct gcse_note_stores_info data;
91 : 6992851 : data.insn = insn;
92 : 6992851 : data.canon_mem_list = canon_modify_mem_list;
93 : 6992851 : note_stores (insn, canon_list_insert, (void*) &data);
94 : : }
95 : 10922070 : }
96 : :
97 : :
98 : : /* For each block, compute whether X is transparent. X is either an
99 : : expression or an assignment [though we don't care which, for this context
100 : : an assignment is treated as an expression]. For each block where an
101 : : element of X is modified, reset the INDX bit in BMAP.
102 : :
103 : : BLOCKS_WITH_CALLS indicates which blocks contain CALL_INSNs which kill
104 : : memory.
105 : :
106 : : MODIFY_MEM_LIST_SET indicates which blocks have memory stores which might
107 : : kill a particular memory location.
108 : :
109 : : CANON_MODIFY_MEM_LIST is the canonicalized list of memory locations modified
110 : : for each block. */
111 : :
112 : : void
113 : 20081621 : compute_transp (const_rtx x, int indx, sbitmap *bmap,
114 : : bitmap blocks_with_calls,
115 : : bitmap modify_mem_list_set,
116 : : vec<modify_pair> *canon_modify_mem_list)
117 : : {
118 : 34936694 : int i, j;
119 : 34936694 : enum rtx_code code;
120 : 34936694 : const char *fmt;
121 : :
122 : : /* repeat is used to turn tail-recursion into iteration since GCC
123 : : can't do it when there's no return value. */
124 : 34936694 : repeat:
125 : :
126 : 34936694 : if (x == 0)
127 : : return;
128 : :
129 : 34936694 : code = GET_CODE (x);
130 : 34936694 : switch (code)
131 : : {
132 : 11903403 : case REG:
133 : 11903403 : {
134 : 11903403 : df_ref def;
135 : 11903403 : for (def = DF_REG_DEF_CHAIN (REGNO (x));
136 : 77810074 : def;
137 : 65906671 : def = DF_REF_NEXT_REG (def))
138 : 65906671 : bitmap_clear_bit (bmap[DF_REF_BB (def)->index], indx);
139 : :
140 : : /* Check for hard registers that are partially clobbered (but not
141 : : fully clobbered) by calls. Such partial clobbers do not have
142 : : an associated definition or use in the DF representation,
143 : : but they do prevent the register from being transparent.
144 : :
145 : : ??? The check here is fairly crude. We could instead maintain
146 : : separate blocks_with_calls bitmaps for each ABI. */
147 : 11903403 : if (HARD_REGISTER_P (x))
148 : 23293341 : for (unsigned int i = 0; i < NUM_ABI_IDS; ++i)
149 : : {
150 : 20705192 : const predefined_function_abi &abi = function_abis[i];
151 : 20705192 : if (abi.initialized_p ()
152 : 23316496 : && overlaps_hard_reg_set_p (abi.only_partial_reg_clobbers (),
153 : 2611304 : GET_MODE (x), REGNO (x)))
154 : : {
155 : 0 : bitmap_iterator bi;
156 : 0 : unsigned bb_index;
157 : 0 : EXECUTE_IF_SET_IN_BITMAP (blocks_with_calls, 0, bb_index, bi)
158 : 0 : bitmap_clear_bit (bmap[bb_index], indx);
159 : 0 : break;
160 : : }
161 : : }
162 : : }
163 : :
164 : : return;
165 : :
166 : 4708922 : case MEM:
167 : 4708922 : if (! MEM_READONLY_P (x))
168 : : {
169 : 4343107 : bitmap_iterator bi;
170 : 4343107 : unsigned bb_index;
171 : 4343107 : rtx x_addr;
172 : :
173 : 4343107 : x_addr = get_addr (XEXP (x, 0));
174 : 4343107 : x_addr = canon_rtx (x_addr);
175 : :
176 : : /* First handle all the blocks with calls. We don't need to
177 : : do any list walking for them. */
178 : 159967922 : EXECUTE_IF_SET_IN_BITMAP (blocks_with_calls, 0, bb_index, bi)
179 : : {
180 : 155624815 : bitmap_clear_bit (bmap[bb_index], indx);
181 : : }
182 : :
183 : : /* Now iterate over the blocks which have memory modifications
184 : : but which do not have any calls. */
185 : 102508650 : EXECUTE_IF_AND_COMPL_IN_BITMAP (modify_mem_list_set,
186 : : blocks_with_calls,
187 : : 0, bb_index, bi)
188 : : {
189 : 98165543 : vec<modify_pair> list
190 : 98165543 : = canon_modify_mem_list[bb_index];
191 : 98165543 : modify_pair *pair;
192 : 98165543 : unsigned ix;
193 : :
194 : 437517843 : FOR_EACH_VEC_ELT_REVERSE (list, ix, pair)
195 : : {
196 : 180447862 : rtx dest = pair->dest;
197 : 180447862 : rtx dest_addr = pair->dest_addr;
198 : :
199 : 180447862 : if (canon_true_dependence (dest, GET_MODE (dest),
200 : : dest_addr, x, x_addr))
201 : : {
202 : 37426648 : bitmap_clear_bit (bmap[bb_index], indx);
203 : 37426648 : break;
204 : : }
205 : : }
206 : : }
207 : : }
208 : :
209 : 4708922 : x = XEXP (x, 0);
210 : 4708922 : goto repeat;
211 : :
212 : : case PC:
213 : : case CONST:
214 : : CASE_CONST_ANY:
215 : : case SYMBOL_REF:
216 : : case LABEL_REF:
217 : : case ADDR_VEC:
218 : : case ADDR_DIFF_VEC:
219 : : return;
220 : :
221 : 10385721 : default:
222 : 10385721 : break;
223 : : }
224 : :
225 : 19851219 : for (i = GET_RTX_LENGTH (code) - 1, fmt = GET_RTX_FORMAT (code); i >= 0; i--)
226 : : {
227 : 19611649 : if (fmt[i] == 'e')
228 : : {
229 : : /* If we are about to do the last recursive call
230 : : needed at this level, change it into iteration.
231 : : This function is called enough to be worth it. */
232 : 19039270 : if (i == 0)
233 : : {
234 : 10146151 : x = XEXP (x, i);
235 : 10146151 : goto repeat;
236 : : }
237 : :
238 : 8893119 : compute_transp (XEXP (x, i), indx, bmap, blocks_with_calls,
239 : : modify_mem_list_set, canon_modify_mem_list);
240 : : }
241 : 572379 : else if (fmt[i] == 'E')
242 : 1058745 : for (j = 0; j < XVECLEN (x, i); j++)
243 : 819175 : compute_transp (XVECEXP (x, i, j), indx, bmap, blocks_with_calls,
244 : : modify_mem_list_set, canon_modify_mem_list);
245 : : }
246 : : }
|