ree.cc revision 1.1 1 1.1 mrg /* Redundant Extension Elimination pass for the GNU compiler.
2 1.1 mrg Copyright (C) 2010-2022 Free Software Foundation, Inc.
3 1.1 mrg Contributed by Ilya Enkovich (ilya.enkovich (at) intel.com)
4 1.1 mrg
5 1.1 mrg Based on the Redundant Zero-extension elimination pass contributed by
6 1.1 mrg Sriraman Tallam (tmsriram (at) google.com) and Silvius Rus (rus (at) google.com).
7 1.1 mrg
8 1.1 mrg This file is part of GCC.
9 1.1 mrg
10 1.1 mrg GCC is free software; you can redistribute it and/or modify it under
11 1.1 mrg the terms of the GNU General Public License as published by the Free
12 1.1 mrg Software Foundation; either version 3, or (at your option) any later
13 1.1 mrg version.
14 1.1 mrg
15 1.1 mrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16 1.1 mrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 1.1 mrg FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 1.1 mrg for more details.
19 1.1 mrg
20 1.1 mrg You should have received a copy of the GNU General Public License
21 1.1 mrg along with GCC; see the file COPYING3. If not see
22 1.1 mrg <http://www.gnu.org/licenses/>. */
23 1.1 mrg
24 1.1 mrg
25 1.1 mrg /* Problem Description :
26 1.1 mrg --------------------
27 1.1 mrg This pass is intended to remove redundant extension instructions.
28 1.1 mrg Such instructions appear for different reasons. We expect some of
29 1.1 mrg them due to implicit zero-extension in 64-bit registers after writing
30 1.1 mrg to their lower 32-bit half (e.g. for the x86-64 architecture).
31 1.1 mrg Another possible reason is a type cast which follows a load (for
32 1.1 mrg instance a register restore) and which can be combined into a single
33 1.1 mrg instruction, and for which earlier local passes, e.g. the combiner,
34 1.1 mrg weren't able to optimize.
35 1.1 mrg
36 1.1 mrg How does this pass work ?
37 1.1 mrg --------------------------
38 1.1 mrg
39 1.1 mrg This pass is run after register allocation. Hence, all registers that
40 1.1 mrg this pass deals with are hard registers. This pass first looks for an
41 1.1 mrg extension instruction that could possibly be redundant. Such extension
42 1.1 mrg instructions show up in RTL with the pattern :
43 1.1 mrg (set (reg:<SWI248> x) (any_extend:<SWI248> (reg:<SWI124> x))),
44 1.1 mrg where x can be any hard register.
45 1.1 mrg Now, this pass tries to eliminate this instruction by merging the
46 1.1 mrg extension with the definitions of register x. For instance, if
47 1.1 mrg one of the definitions of register x was :
48 1.1 mrg (set (reg:SI x) (plus:SI (reg:SI z1) (reg:SI z2))),
49 1.1 mrg followed by extension :
50 1.1 mrg (set (reg:DI x) (zero_extend:DI (reg:SI x)))
51 1.1 mrg then the combination converts this into :
52 1.1 mrg (set (reg:DI x) (zero_extend:DI (plus:SI (reg:SI z1) (reg:SI z2)))).
53 1.1 mrg If all the merged definitions are recognizable assembly instructions,
54 1.1 mrg the extension is effectively eliminated.
55 1.1 mrg
56 1.1 mrg For example, for the x86-64 architecture, implicit zero-extensions
57 1.1 mrg are captured with appropriate patterns in the i386.md file. Hence,
58 1.1 mrg these merged definition can be matched to a single assembly instruction.
59 1.1 mrg The original extension instruction is then deleted if all the
60 1.1 mrg definitions can be merged.
61 1.1 mrg
62 1.1 mrg However, there are cases where the definition instruction cannot be
63 1.1 mrg merged with an extension. Examples are CALL instructions. In such
64 1.1 mrg cases, the original extension is not redundant and this pass does
65 1.1 mrg not delete it.
66 1.1 mrg
67 1.1 mrg Handling conditional moves :
68 1.1 mrg ----------------------------
69 1.1 mrg
70 1.1 mrg Architectures like x86-64 support conditional moves whose semantics for
71 1.1 mrg extension differ from the other instructions. For instance, the
72 1.1 mrg instruction *cmov ebx, eax*
73 1.1 mrg zero-extends eax onto rax only when the move from ebx to eax happens.
74 1.1 mrg Otherwise, eax may not be zero-extended. Consider conditional moves as
75 1.1 mrg RTL instructions of the form
76 1.1 mrg (set (reg:SI x) (if_then_else (cond) (reg:SI y) (reg:SI z))).
77 1.1 mrg This pass tries to merge an extension with a conditional move by
78 1.1 mrg actually merging the definitions of y and z with an extension and then
79 1.1 mrg converting the conditional move into :
80 1.1 mrg (set (reg:DI x) (if_then_else (cond) (reg:DI y) (reg:DI z))).
81 1.1 mrg Since registers y and z are extended, register x will also be extended
82 1.1 mrg after the conditional move. Note that this step has to be done
83 1.1 mrg transitively since the definition of a conditional copy can be
84 1.1 mrg another conditional copy.
85 1.1 mrg
86 1.1 mrg Motivating Example I :
87 1.1 mrg ---------------------
88 1.1 mrg For this program :
89 1.1 mrg **********************************************
90 1.1 mrg bad_code.c
91 1.1 mrg
92 1.1 mrg int mask[1000];
93 1.1 mrg
94 1.1 mrg int foo(unsigned x)
95 1.1 mrg {
96 1.1 mrg if (x < 10)
97 1.1 mrg x = x * 45;
98 1.1 mrg else
99 1.1 mrg x = x * 78;
100 1.1 mrg return mask[x];
101 1.1 mrg }
102 1.1 mrg **********************************************
103 1.1 mrg
104 1.1 mrg $ gcc -O2 bad_code.c
105 1.1 mrg ........
106 1.1 mrg 400315: b8 4e 00 00 00 mov $0x4e,%eax
107 1.1 mrg 40031a: 0f af f8 imul %eax,%edi
108 1.1 mrg 40031d: 89 ff mov %edi,%edi - useless extension
109 1.1 mrg 40031f: 8b 04 bd 60 19 40 00 mov 0x401960(,%rdi,4),%eax
110 1.1 mrg 400326: c3 retq
111 1.1 mrg ......
112 1.1 mrg 400330: ba 2d 00 00 00 mov $0x2d,%edx
113 1.1 mrg 400335: 0f af fa imul %edx,%edi
114 1.1 mrg 400338: 89 ff mov %edi,%edi - useless extension
115 1.1 mrg 40033a: 8b 04 bd 60 19 40 00 mov 0x401960(,%rdi,4),%eax
116 1.1 mrg 400341: c3 retq
117 1.1 mrg
118 1.1 mrg $ gcc -O2 -free bad_code.c
119 1.1 mrg ......
120 1.1 mrg 400315: 6b ff 4e imul $0x4e,%edi,%edi
121 1.1 mrg 400318: 8b 04 bd 40 19 40 00 mov 0x401940(,%rdi,4),%eax
122 1.1 mrg 40031f: c3 retq
123 1.1 mrg 400320: 6b ff 2d imul $0x2d,%edi,%edi
124 1.1 mrg 400323: 8b 04 bd 40 19 40 00 mov 0x401940(,%rdi,4),%eax
125 1.1 mrg 40032a: c3 retq
126 1.1 mrg
127 1.1 mrg Motivating Example II :
128 1.1 mrg ---------------------
129 1.1 mrg
130 1.1 mrg Here is an example with a conditional move.
131 1.1 mrg
132 1.1 mrg For this program :
133 1.1 mrg **********************************************
134 1.1 mrg
135 1.1 mrg unsigned long long foo(unsigned x , unsigned y)
136 1.1 mrg {
137 1.1 mrg unsigned z;
138 1.1 mrg if (x > 100)
139 1.1 mrg z = x + y;
140 1.1 mrg else
141 1.1 mrg z = x - y;
142 1.1 mrg return (unsigned long long)(z);
143 1.1 mrg }
144 1.1 mrg
145 1.1 mrg $ gcc -O2 bad_code.c
146 1.1 mrg ............
147 1.1 mrg 400360: 8d 14 3e lea (%rsi,%rdi,1),%edx
148 1.1 mrg 400363: 89 f8 mov %edi,%eax
149 1.1 mrg 400365: 29 f0 sub %esi,%eax
150 1.1 mrg 400367: 83 ff 65 cmp $0x65,%edi
151 1.1 mrg 40036a: 0f 43 c2 cmovae %edx,%eax
152 1.1 mrg 40036d: 89 c0 mov %eax,%eax - useless extension
153 1.1 mrg 40036f: c3 retq
154 1.1 mrg
155 1.1 mrg $ gcc -O2 -free bad_code.c
156 1.1 mrg .............
157 1.1 mrg 400360: 89 fa mov %edi,%edx
158 1.1 mrg 400362: 8d 04 3e lea (%rsi,%rdi,1),%eax
159 1.1 mrg 400365: 29 f2 sub %esi,%edx
160 1.1 mrg 400367: 83 ff 65 cmp $0x65,%edi
161 1.1 mrg 40036a: 89 d6 mov %edx,%esi
162 1.1 mrg 40036c: 48 0f 42 c6 cmovb %rsi,%rax
163 1.1 mrg 400370: c3 retq
164 1.1 mrg
165 1.1 mrg Motivating Example III :
166 1.1 mrg ---------------------
167 1.1 mrg
168 1.1 mrg Here is an example with a type cast.
169 1.1 mrg
170 1.1 mrg For this program :
171 1.1 mrg **********************************************
172 1.1 mrg
173 1.1 mrg void test(int size, unsigned char *in, unsigned char *out)
174 1.1 mrg {
175 1.1 mrg int i;
176 1.1 mrg unsigned char xr, xg, xy=0;
177 1.1 mrg
178 1.1 mrg for (i = 0; i < size; i++) {
179 1.1 mrg xr = *in++;
180 1.1 mrg xg = *in++;
181 1.1 mrg xy = (unsigned char) ((19595*xr + 38470*xg) >> 16);
182 1.1 mrg *out++ = xy;
183 1.1 mrg }
184 1.1 mrg }
185 1.1 mrg
186 1.1 mrg $ gcc -O2 bad_code.c
187 1.1 mrg ............
188 1.1 mrg 10: 0f b6 0e movzbl (%rsi),%ecx
189 1.1 mrg 13: 0f b6 46 01 movzbl 0x1(%rsi),%eax
190 1.1 mrg 17: 48 83 c6 02 add $0x2,%rsi
191 1.1 mrg 1b: 0f b6 c9 movzbl %cl,%ecx - useless extension
192 1.1 mrg 1e: 0f b6 c0 movzbl %al,%eax - useless extension
193 1.1 mrg 21: 69 c9 8b 4c 00 00 imul $0x4c8b,%ecx,%ecx
194 1.1 mrg 27: 69 c0 46 96 00 00 imul $0x9646,%eax,%eax
195 1.1 mrg
196 1.1 mrg $ gcc -O2 -free bad_code.c
197 1.1 mrg .............
198 1.1 mrg 10: 0f b6 0e movzbl (%rsi),%ecx
199 1.1 mrg 13: 0f b6 46 01 movzbl 0x1(%rsi),%eax
200 1.1 mrg 17: 48 83 c6 02 add $0x2,%rsi
201 1.1 mrg 1b: 69 c9 8b 4c 00 00 imul $0x4c8b,%ecx,%ecx
202 1.1 mrg 21: 69 c0 46 96 00 00 imul $0x9646,%eax,%eax
203 1.1 mrg
204 1.1 mrg Usefulness :
205 1.1 mrg ----------
206 1.1 mrg
207 1.1 mrg The original redundant zero-extension elimination pass reported reduction
208 1.1 mrg of the dynamic instruction count of a compression benchmark by 2.8% and
209 1.1 mrg improvement of its run time by about 1%.
210 1.1 mrg
211 1.1 mrg The additional performance gain with the enhanced pass is mostly expected
212 1.1 mrg on in-order architectures where redundancy cannot be compensated by out of
213 1.1 mrg order execution. Measurements showed up to 10% performance gain (reduced
214 1.1 mrg run time) on EEMBC 2.0 benchmarks on Atom processor with geomean performance
215 1.1 mrg gain 1%. */
216 1.1 mrg
217 1.1 mrg
218 1.1 mrg #include "config.h"
219 1.1 mrg #include "system.h"
220 1.1 mrg #include "coretypes.h"
221 1.1 mrg #include "backend.h"
222 1.1 mrg #include "target.h"
223 1.1 mrg #include "rtl.h"
224 1.1 mrg #include "tree.h"
225 1.1 mrg #include "df.h"
226 1.1 mrg #include "memmodel.h"
227 1.1 mrg #include "tm_p.h"
228 1.1 mrg #include "optabs.h"
229 1.1 mrg #include "regs.h"
230 1.1 mrg #include "emit-rtl.h"
231 1.1 mrg #include "recog.h"
232 1.1 mrg #include "cfgrtl.h"
233 1.1 mrg #include "expr.h"
234 1.1 mrg #include "tree-pass.h"
235 1.1 mrg
236 1.1 mrg /* This structure represents a candidate for elimination. */
237 1.1 mrg
238 1.1 mrg struct ext_cand
239 1.1 mrg {
240 1.1 mrg /* The expression. */
241 1.1 mrg const_rtx expr;
242 1.1 mrg
243 1.1 mrg /* The kind of extension. */
244 1.1 mrg enum rtx_code code;
245 1.1 mrg
246 1.1 mrg /* The destination mode. */
247 1.1 mrg machine_mode mode;
248 1.1 mrg
249 1.1 mrg /* The instruction where it lives. */
250 1.1 mrg rtx_insn *insn;
251 1.1 mrg };
252 1.1 mrg
253 1.1 mrg
254 1.1 mrg static int max_insn_uid;
255 1.1 mrg
256 1.1 mrg /* Update or remove REG_EQUAL or REG_EQUIV notes for INSN. */
257 1.1 mrg
258 1.1 mrg static bool
259 1.1 mrg update_reg_equal_equiv_notes (rtx_insn *insn, machine_mode new_mode,
260 1.1 mrg machine_mode old_mode, enum rtx_code code)
261 1.1 mrg {
262 1.1 mrg rtx *loc = ®_NOTES (insn);
263 1.1 mrg while (*loc)
264 1.1 mrg {
265 1.1 mrg enum reg_note kind = REG_NOTE_KIND (*loc);
266 1.1 mrg if (kind == REG_EQUAL || kind == REG_EQUIV)
267 1.1 mrg {
268 1.1 mrg rtx orig_src = XEXP (*loc, 0);
269 1.1 mrg /* Update equivalency constants. Recall that RTL constants are
270 1.1 mrg sign-extended. */
271 1.1 mrg if (GET_CODE (orig_src) == CONST_INT
272 1.1 mrg && HWI_COMPUTABLE_MODE_P (new_mode))
273 1.1 mrg {
274 1.1 mrg if (INTVAL (orig_src) >= 0 || code == SIGN_EXTEND)
275 1.1 mrg /* Nothing needed. */;
276 1.1 mrg else
277 1.1 mrg {
278 1.1 mrg /* Zero-extend the negative constant by masking out the
279 1.1 mrg bits outside the source mode. */
280 1.1 mrg rtx new_const_int
281 1.1 mrg = gen_int_mode (INTVAL (orig_src)
282 1.1 mrg & GET_MODE_MASK (old_mode),
283 1.1 mrg new_mode);
284 1.1 mrg if (!validate_change (insn, &XEXP (*loc, 0),
285 1.1 mrg new_const_int, true))
286 1.1 mrg return false;
287 1.1 mrg }
288 1.1 mrg loc = &XEXP (*loc, 1);
289 1.1 mrg }
290 1.1 mrg /* Drop all other notes, they assume a wrong mode. */
291 1.1 mrg else if (!validate_change (insn, loc, XEXP (*loc, 1), true))
292 1.1 mrg return false;
293 1.1 mrg }
294 1.1 mrg else
295 1.1 mrg loc = &XEXP (*loc, 1);
296 1.1 mrg }
297 1.1 mrg return true;
298 1.1 mrg }
299 1.1 mrg
300 1.1 mrg /* Given a insn (CURR_INSN), an extension candidate for removal (CAND)
301 1.1 mrg and a pointer to the SET rtx (ORIG_SET) that needs to be modified,
302 1.1 mrg this code modifies the SET rtx to a new SET rtx that extends the
303 1.1 mrg right hand expression into a register on the left hand side. Note
304 1.1 mrg that multiple assumptions are made about the nature of the set that
305 1.1 mrg needs to be true for this to work and is called from merge_def_and_ext.
306 1.1 mrg
307 1.1 mrg Original :
308 1.1 mrg (set (reg a) (expression))
309 1.1 mrg
310 1.1 mrg Transform :
311 1.1 mrg (set (reg a) (any_extend (expression)))
312 1.1 mrg
313 1.1 mrg Special Cases :
314 1.1 mrg If the expression is a constant or another extension, then directly
315 1.1 mrg assign it to the register. */
316 1.1 mrg
317 1.1 mrg static bool
318 1.1 mrg combine_set_extension (ext_cand *cand, rtx_insn *curr_insn, rtx *orig_set)
319 1.1 mrg {
320 1.1 mrg rtx orig_src = SET_SRC (*orig_set);
321 1.1 mrg machine_mode orig_mode = GET_MODE (SET_DEST (*orig_set));
322 1.1 mrg rtx new_set;
323 1.1 mrg rtx cand_pat = single_set (cand->insn);
324 1.1 mrg
325 1.1 mrg /* If the extension's source/destination registers are not the same
326 1.1 mrg then we need to change the original load to reference the destination
327 1.1 mrg of the extension. Then we need to emit a copy from that destination
328 1.1 mrg to the original destination of the load. */
329 1.1 mrg rtx new_reg;
330 1.1 mrg bool copy_needed
331 1.1 mrg = (REGNO (SET_DEST (cand_pat)) != REGNO (XEXP (SET_SRC (cand_pat), 0)));
332 1.1 mrg if (copy_needed)
333 1.1 mrg new_reg = gen_rtx_REG (cand->mode, REGNO (SET_DEST (cand_pat)));
334 1.1 mrg else
335 1.1 mrg new_reg = gen_rtx_REG (cand->mode, REGNO (SET_DEST (*orig_set)));
336 1.1 mrg
337 1.1 mrg /* Merge constants by directly moving the constant into the register under
338 1.1 mrg some conditions. Recall that RTL constants are sign-extended. */
339 1.1 mrg if (GET_CODE (orig_src) == CONST_INT
340 1.1 mrg && HWI_COMPUTABLE_MODE_P (cand->mode))
341 1.1 mrg {
342 1.1 mrg if (INTVAL (orig_src) >= 0 || cand->code == SIGN_EXTEND)
343 1.1 mrg new_set = gen_rtx_SET (new_reg, orig_src);
344 1.1 mrg else
345 1.1 mrg {
346 1.1 mrg /* Zero-extend the negative constant by masking out the bits outside
347 1.1 mrg the source mode. */
348 1.1 mrg rtx new_const_int
349 1.1 mrg = gen_int_mode (INTVAL (orig_src) & GET_MODE_MASK (orig_mode),
350 1.1 mrg GET_MODE (new_reg));
351 1.1 mrg new_set = gen_rtx_SET (new_reg, new_const_int);
352 1.1 mrg }
353 1.1 mrg }
354 1.1 mrg else if (GET_MODE (orig_src) == VOIDmode)
355 1.1 mrg {
356 1.1 mrg /* This is mostly due to a call insn that should not be optimized. */
357 1.1 mrg return false;
358 1.1 mrg }
359 1.1 mrg else if (GET_CODE (orig_src) == cand->code)
360 1.1 mrg {
361 1.1 mrg /* Here is a sequence of two extensions. Try to merge them. */
362 1.1 mrg rtx temp_extension
363 1.1 mrg = gen_rtx_fmt_e (cand->code, cand->mode, XEXP (orig_src, 0));
364 1.1 mrg rtx simplified_temp_extension = simplify_rtx (temp_extension);
365 1.1 mrg if (simplified_temp_extension)
366 1.1 mrg temp_extension = simplified_temp_extension;
367 1.1 mrg new_set = gen_rtx_SET (new_reg, temp_extension);
368 1.1 mrg }
369 1.1 mrg else if (GET_CODE (orig_src) == IF_THEN_ELSE)
370 1.1 mrg {
371 1.1 mrg /* Only IF_THEN_ELSE of phi-type copies are combined. Otherwise,
372 1.1 mrg in general, IF_THEN_ELSE should not be combined. */
373 1.1 mrg return false;
374 1.1 mrg }
375 1.1 mrg else
376 1.1 mrg {
377 1.1 mrg /* This is the normal case. */
378 1.1 mrg rtx temp_extension
379 1.1 mrg = gen_rtx_fmt_e (cand->code, cand->mode, orig_src);
380 1.1 mrg rtx simplified_temp_extension = simplify_rtx (temp_extension);
381 1.1 mrg if (simplified_temp_extension)
382 1.1 mrg temp_extension = simplified_temp_extension;
383 1.1 mrg new_set = gen_rtx_SET (new_reg, temp_extension);
384 1.1 mrg }
385 1.1 mrg
386 1.1 mrg /* This change is a part of a group of changes. Hence,
387 1.1 mrg validate_change will not try to commit the change. */
388 1.1 mrg if (validate_change (curr_insn, orig_set, new_set, true)
389 1.1 mrg && update_reg_equal_equiv_notes (curr_insn, cand->mode, orig_mode,
390 1.1 mrg cand->code))
391 1.1 mrg {
392 1.1 mrg if (dump_file)
393 1.1 mrg {
394 1.1 mrg fprintf (dump_file,
395 1.1 mrg "Tentatively merged extension with definition %s:\n",
396 1.1 mrg (copy_needed) ? "(copy needed)" : "");
397 1.1 mrg print_rtl_single (dump_file, curr_insn);
398 1.1 mrg }
399 1.1 mrg return true;
400 1.1 mrg }
401 1.1 mrg
402 1.1 mrg return false;
403 1.1 mrg }
404 1.1 mrg
405 1.1 mrg /* Treat if_then_else insns, where the operands of both branches
406 1.1 mrg are registers, as copies. For instance,
407 1.1 mrg Original :
408 1.1 mrg (set (reg:SI a) (if_then_else (cond) (reg:SI b) (reg:SI c)))
409 1.1 mrg Transformed :
410 1.1 mrg (set (reg:DI a) (if_then_else (cond) (reg:DI b) (reg:DI c)))
411 1.1 mrg DEF_INSN is the if_then_else insn. */
412 1.1 mrg
413 1.1 mrg static bool
414 1.1 mrg transform_ifelse (ext_cand *cand, rtx_insn *def_insn)
415 1.1 mrg {
416 1.1 mrg rtx set_insn = PATTERN (def_insn);
417 1.1 mrg rtx srcreg, dstreg, srcreg2;
418 1.1 mrg rtx map_srcreg, map_dstreg, map_srcreg2;
419 1.1 mrg rtx ifexpr;
420 1.1 mrg rtx cond;
421 1.1 mrg rtx new_set;
422 1.1 mrg
423 1.1 mrg gcc_assert (GET_CODE (set_insn) == SET);
424 1.1 mrg
425 1.1 mrg cond = XEXP (SET_SRC (set_insn), 0);
426 1.1 mrg dstreg = SET_DEST (set_insn);
427 1.1 mrg srcreg = XEXP (SET_SRC (set_insn), 1);
428 1.1 mrg srcreg2 = XEXP (SET_SRC (set_insn), 2);
429 1.1 mrg /* If the conditional move already has the right or wider mode,
430 1.1 mrg there is nothing to do. */
431 1.1 mrg if (GET_MODE_UNIT_SIZE (GET_MODE (dstreg))
432 1.1 mrg >= GET_MODE_UNIT_SIZE (cand->mode))
433 1.1 mrg return true;
434 1.1 mrg
435 1.1 mrg map_srcreg = gen_rtx_REG (cand->mode, REGNO (srcreg));
436 1.1 mrg map_srcreg2 = gen_rtx_REG (cand->mode, REGNO (srcreg2));
437 1.1 mrg map_dstreg = gen_rtx_REG (cand->mode, REGNO (dstreg));
438 1.1 mrg ifexpr = gen_rtx_IF_THEN_ELSE (cand->mode, cond, map_srcreg, map_srcreg2);
439 1.1 mrg new_set = gen_rtx_SET (map_dstreg, ifexpr);
440 1.1 mrg
441 1.1 mrg if (validate_change (def_insn, &PATTERN (def_insn), new_set, true)
442 1.1 mrg && update_reg_equal_equiv_notes (def_insn, cand->mode, GET_MODE (dstreg),
443 1.1 mrg cand->code))
444 1.1 mrg {
445 1.1 mrg if (dump_file)
446 1.1 mrg {
447 1.1 mrg fprintf (dump_file,
448 1.1 mrg "Mode of conditional move instruction extended:\n");
449 1.1 mrg print_rtl_single (dump_file, def_insn);
450 1.1 mrg }
451 1.1 mrg return true;
452 1.1 mrg }
453 1.1 mrg
454 1.1 mrg return false;
455 1.1 mrg }
456 1.1 mrg
457 1.1 mrg /* Get all the reaching definitions of an instruction. The definitions are
458 1.1 mrg desired for REG used in INSN. Return the definition list or NULL if a
459 1.1 mrg definition is missing. If DEST is non-NULL, additionally push the INSN
460 1.1 mrg of the definitions onto DEST. */
461 1.1 mrg
462 1.1 mrg static struct df_link *
463 1.1 mrg get_defs (rtx_insn *insn, rtx reg, vec<rtx_insn *> *dest)
464 1.1 mrg {
465 1.1 mrg df_ref use;
466 1.1 mrg struct df_link *ref_chain, *ref_link;
467 1.1 mrg
468 1.1 mrg FOR_EACH_INSN_USE (use, insn)
469 1.1 mrg {
470 1.1 mrg if (GET_CODE (DF_REF_REG (use)) == SUBREG)
471 1.1 mrg return NULL;
472 1.1 mrg if (REGNO (DF_REF_REG (use)) == REGNO (reg))
473 1.1 mrg break;
474 1.1 mrg }
475 1.1 mrg
476 1.1 mrg gcc_assert (use != NULL);
477 1.1 mrg
478 1.1 mrg ref_chain = DF_REF_CHAIN (use);
479 1.1 mrg
480 1.1 mrg for (ref_link = ref_chain; ref_link; ref_link = ref_link->next)
481 1.1 mrg {
482 1.1 mrg /* Problem getting some definition for this instruction. */
483 1.1 mrg if (ref_link->ref == NULL)
484 1.1 mrg return NULL;
485 1.1 mrg if (DF_REF_INSN_INFO (ref_link->ref) == NULL)
486 1.1 mrg return NULL;
487 1.1 mrg /* As global regs are assumed to be defined at each function call
488 1.1 mrg dataflow can report a call_insn as being a definition of REG.
489 1.1 mrg But we can't do anything with that in this pass so proceed only
490 1.1 mrg if the instruction really sets REG in a way that can be deduced
491 1.1 mrg from the RTL structure. */
492 1.1 mrg if (global_regs[REGNO (reg)]
493 1.1 mrg && !set_of (reg, DF_REF_INSN (ref_link->ref)))
494 1.1 mrg return NULL;
495 1.1 mrg }
496 1.1 mrg
497 1.1 mrg if (dest)
498 1.1 mrg for (ref_link = ref_chain; ref_link; ref_link = ref_link->next)
499 1.1 mrg dest->safe_push (DF_REF_INSN (ref_link->ref));
500 1.1 mrg
501 1.1 mrg return ref_chain;
502 1.1 mrg }
503 1.1 mrg
504 1.1 mrg /* Get all the reaching uses of an instruction. The uses are desired for REG
505 1.1 mrg set in INSN. Return use list or NULL if a use is missing or irregular. */
506 1.1 mrg
507 1.1 mrg static struct df_link *
508 1.1 mrg get_uses (rtx_insn *insn, rtx reg)
509 1.1 mrg {
510 1.1 mrg df_ref def;
511 1.1 mrg struct df_link *ref_chain, *ref_link;
512 1.1 mrg
513 1.1 mrg FOR_EACH_INSN_DEF (def, insn)
514 1.1 mrg if (REGNO (DF_REF_REG (def)) == REGNO (reg))
515 1.1 mrg break;
516 1.1 mrg
517 1.1 mrg gcc_assert (def != NULL);
518 1.1 mrg
519 1.1 mrg ref_chain = DF_REF_CHAIN (def);
520 1.1 mrg
521 1.1 mrg for (ref_link = ref_chain; ref_link; ref_link = ref_link->next)
522 1.1 mrg {
523 1.1 mrg /* Problem getting some use for this instruction. */
524 1.1 mrg if (ref_link->ref == NULL)
525 1.1 mrg return NULL;
526 1.1 mrg if (DF_REF_CLASS (ref_link->ref) != DF_REF_REGULAR)
527 1.1 mrg return NULL;
528 1.1 mrg }
529 1.1 mrg
530 1.1 mrg return ref_chain;
531 1.1 mrg }
532 1.1 mrg
533 1.1 mrg /* Return true if INSN is
534 1.1 mrg (SET (reg REGNO (def_reg)) (if_then_else (cond) (REG x1) (REG x2)))
535 1.1 mrg and store x1 and x2 in REG_1 and REG_2. */
536 1.1 mrg
537 1.1 mrg static bool
538 1.1 mrg is_cond_copy_insn (rtx_insn *insn, rtx *reg1, rtx *reg2)
539 1.1 mrg {
540 1.1 mrg rtx expr = single_set (insn);
541 1.1 mrg
542 1.1 mrg if (expr != NULL_RTX
543 1.1 mrg && GET_CODE (expr) == SET
544 1.1 mrg && GET_CODE (SET_DEST (expr)) == REG
545 1.1 mrg && GET_CODE (SET_SRC (expr)) == IF_THEN_ELSE
546 1.1 mrg && GET_CODE (XEXP (SET_SRC (expr), 1)) == REG
547 1.1 mrg && GET_CODE (XEXP (SET_SRC (expr), 2)) == REG)
548 1.1 mrg {
549 1.1 mrg *reg1 = XEXP (SET_SRC (expr), 1);
550 1.1 mrg *reg2 = XEXP (SET_SRC (expr), 2);
551 1.1 mrg return true;
552 1.1 mrg }
553 1.1 mrg
554 1.1 mrg return false;
555 1.1 mrg }
556 1.1 mrg
557 1.1 mrg enum ext_modified_kind
558 1.1 mrg {
559 1.1 mrg /* The insn hasn't been modified by ree pass yet. */
560 1.1 mrg EXT_MODIFIED_NONE,
561 1.1 mrg /* Changed into zero extension. */
562 1.1 mrg EXT_MODIFIED_ZEXT,
563 1.1 mrg /* Changed into sign extension. */
564 1.1 mrg EXT_MODIFIED_SEXT
565 1.1 mrg };
566 1.1 mrg
567 1.1 mrg struct ATTRIBUTE_PACKED ext_modified
568 1.1 mrg {
569 1.1 mrg /* Mode from which ree has zero or sign extended the destination. */
570 1.1 mrg ENUM_BITFIELD(machine_mode) mode : 8;
571 1.1 mrg
572 1.1 mrg /* Kind of modification of the insn. */
573 1.1 mrg ENUM_BITFIELD(ext_modified_kind) kind : 2;
574 1.1 mrg
575 1.1 mrg unsigned int do_not_reextend : 1;
576 1.1 mrg
577 1.1 mrg /* True if the insn is scheduled to be deleted. */
578 1.1 mrg unsigned int deleted : 1;
579 1.1 mrg };
580 1.1 mrg
581 1.1 mrg /* Vectors used by combine_reaching_defs and its helpers. */
582 1.1 mrg class ext_state
583 1.1 mrg {
584 1.1 mrg public:
585 1.1 mrg /* In order to avoid constant alloc/free, we keep these
586 1.1 mrg 4 vectors live through the entire find_and_remove_re and just
587 1.1 mrg truncate them each time. */
588 1.1 mrg auto_vec<rtx_insn *> defs_list;
589 1.1 mrg auto_vec<rtx_insn *> copies_list;
590 1.1 mrg auto_vec<rtx_insn *> modified_list;
591 1.1 mrg auto_vec<rtx_insn *> work_list;
592 1.1 mrg
593 1.1 mrg /* For instructions that have been successfully modified, this is
594 1.1 mrg the original mode from which the insn is extending and
595 1.1 mrg kind of extension. */
596 1.1 mrg struct ext_modified *modified;
597 1.1 mrg };
598 1.1 mrg
599 1.1 mrg /* Reaching Definitions of the extended register could be conditional copies
600 1.1 mrg or regular definitions. This function separates the two types into two
601 1.1 mrg lists, STATE->DEFS_LIST and STATE->COPIES_LIST. This is necessary because,
602 1.1 mrg if a reaching definition is a conditional copy, merging the extension with
603 1.1 mrg this definition is wrong. Conditional copies are merged by transitively
604 1.1 mrg merging their definitions. The defs_list is populated with all the reaching
605 1.1 mrg definitions of the extension instruction (EXTEND_INSN) which must be merged
606 1.1 mrg with an extension. The copies_list contains all the conditional moves that
607 1.1 mrg will later be extended into a wider mode conditional move if all the merges
608 1.1 mrg are successful. The function returns false upon failure, true upon
609 1.1 mrg success. */
610 1.1 mrg
611 1.1 mrg static bool
612 1.1 mrg make_defs_and_copies_lists (rtx_insn *extend_insn, const_rtx set_pat,
613 1.1 mrg ext_state *state)
614 1.1 mrg {
615 1.1 mrg rtx src_reg = XEXP (SET_SRC (set_pat), 0);
616 1.1 mrg bool *is_insn_visited;
617 1.1 mrg bool ret = true;
618 1.1 mrg
619 1.1 mrg state->work_list.truncate (0);
620 1.1 mrg
621 1.1 mrg /* Initialize the work list. */
622 1.1 mrg if (!get_defs (extend_insn, src_reg, &state->work_list))
623 1.1 mrg return false;
624 1.1 mrg
625 1.1 mrg is_insn_visited = XCNEWVEC (bool, max_insn_uid);
626 1.1 mrg
627 1.1 mrg /* Perform transitive closure for conditional copies. */
628 1.1 mrg while (!state->work_list.is_empty ())
629 1.1 mrg {
630 1.1 mrg rtx_insn *def_insn = state->work_list.pop ();
631 1.1 mrg rtx reg1, reg2;
632 1.1 mrg
633 1.1 mrg gcc_assert (INSN_UID (def_insn) < max_insn_uid);
634 1.1 mrg
635 1.1 mrg if (is_insn_visited[INSN_UID (def_insn)])
636 1.1 mrg continue;
637 1.1 mrg is_insn_visited[INSN_UID (def_insn)] = true;
638 1.1 mrg
639 1.1 mrg if (is_cond_copy_insn (def_insn, ®1, ®2))
640 1.1 mrg {
641 1.1 mrg /* Push it onto the copy list first. */
642 1.1 mrg state->copies_list.safe_push (def_insn);
643 1.1 mrg
644 1.1 mrg /* Now perform the transitive closure. */
645 1.1 mrg if (!get_defs (def_insn, reg1, &state->work_list)
646 1.1 mrg || !get_defs (def_insn, reg2, &state->work_list))
647 1.1 mrg {
648 1.1 mrg ret = false;
649 1.1 mrg break;
650 1.1 mrg }
651 1.1 mrg }
652 1.1 mrg else
653 1.1 mrg state->defs_list.safe_push (def_insn);
654 1.1 mrg }
655 1.1 mrg
656 1.1 mrg XDELETEVEC (is_insn_visited);
657 1.1 mrg
658 1.1 mrg return ret;
659 1.1 mrg }
660 1.1 mrg
661 1.1 mrg /* If DEF_INSN has single SET expression with a register
662 1.1 mrg destination, possibly buried inside a PARALLEL, return
663 1.1 mrg the address of the SET expression, else return NULL.
664 1.1 mrg This is similar to single_set, except that single_set
665 1.1 mrg allows multiple SETs when all but one is dead. */
666 1.1 mrg static rtx *
667 1.1 mrg get_sub_rtx (rtx_insn *def_insn)
668 1.1 mrg {
669 1.1 mrg enum rtx_code code = GET_CODE (PATTERN (def_insn));
670 1.1 mrg rtx *sub_rtx = NULL;
671 1.1 mrg
672 1.1 mrg if (code == PARALLEL)
673 1.1 mrg {
674 1.1 mrg for (int i = 0; i < XVECLEN (PATTERN (def_insn), 0); i++)
675 1.1 mrg {
676 1.1 mrg rtx s_expr = XVECEXP (PATTERN (def_insn), 0, i);
677 1.1 mrg if (GET_CODE (s_expr) != SET)
678 1.1 mrg continue;
679 1.1 mrg if (!REG_P (SET_DEST (s_expr)))
680 1.1 mrg continue;
681 1.1 mrg
682 1.1 mrg if (sub_rtx == NULL)
683 1.1 mrg sub_rtx = &XVECEXP (PATTERN (def_insn), 0, i);
684 1.1 mrg else
685 1.1 mrg {
686 1.1 mrg /* PARALLEL with multiple SETs. */
687 1.1 mrg return NULL;
688 1.1 mrg }
689 1.1 mrg }
690 1.1 mrg }
691 1.1 mrg else if (code == SET)
692 1.1 mrg {
693 1.1 mrg rtx s_expr = PATTERN (def_insn);
694 1.1 mrg if (REG_P (SET_DEST (s_expr)))
695 1.1 mrg sub_rtx = &PATTERN (def_insn);
696 1.1 mrg }
697 1.1 mrg
698 1.1 mrg return sub_rtx;
699 1.1 mrg }
700 1.1 mrg
701 1.1 mrg /* Merge the DEF_INSN with an extension. Calls combine_set_extension
702 1.1 mrg on the SET pattern. */
703 1.1 mrg
704 1.1 mrg static bool
705 1.1 mrg merge_def_and_ext (ext_cand *cand, rtx_insn *def_insn, ext_state *state)
706 1.1 mrg {
707 1.1 mrg machine_mode ext_src_mode;
708 1.1 mrg rtx *sub_rtx;
709 1.1 mrg
710 1.1 mrg ext_src_mode = GET_MODE (XEXP (SET_SRC (cand->expr), 0));
711 1.1 mrg sub_rtx = get_sub_rtx (def_insn);
712 1.1 mrg
713 1.1 mrg if (sub_rtx == NULL)
714 1.1 mrg return false;
715 1.1 mrg
716 1.1 mrg if (GET_MODE (SET_DEST (*sub_rtx)) == ext_src_mode
717 1.1 mrg || ((state->modified[INSN_UID (def_insn)].kind
718 1.1 mrg == (cand->code == ZERO_EXTEND
719 1.1 mrg ? EXT_MODIFIED_ZEXT : EXT_MODIFIED_SEXT))
720 1.1 mrg && state->modified[INSN_UID (def_insn)].mode
721 1.1 mrg == ext_src_mode))
722 1.1 mrg {
723 1.1 mrg if (GET_MODE_UNIT_SIZE (GET_MODE (SET_DEST (*sub_rtx)))
724 1.1 mrg >= GET_MODE_UNIT_SIZE (cand->mode))
725 1.1 mrg return true;
726 1.1 mrg /* If def_insn is already scheduled to be deleted, don't attempt
727 1.1 mrg to modify it. */
728 1.1 mrg if (state->modified[INSN_UID (def_insn)].deleted)
729 1.1 mrg return false;
730 1.1 mrg if (combine_set_extension (cand, def_insn, sub_rtx))
731 1.1 mrg {
732 1.1 mrg if (state->modified[INSN_UID (def_insn)].kind == EXT_MODIFIED_NONE)
733 1.1 mrg state->modified[INSN_UID (def_insn)].mode = ext_src_mode;
734 1.1 mrg return true;
735 1.1 mrg }
736 1.1 mrg }
737 1.1 mrg
738 1.1 mrg return false;
739 1.1 mrg }
740 1.1 mrg
741 1.1 mrg /* Given SRC, which should be one or more extensions of a REG, strip
742 1.1 mrg away the extensions and return the REG. */
743 1.1 mrg
744 1.1 mrg static inline rtx
745 1.1 mrg get_extended_src_reg (rtx src)
746 1.1 mrg {
747 1.1 mrg while (GET_CODE (src) == SIGN_EXTEND || GET_CODE (src) == ZERO_EXTEND)
748 1.1 mrg src = XEXP (src, 0);
749 1.1 mrg gcc_assert (REG_P (src));
750 1.1 mrg return src;
751 1.1 mrg }
752 1.1 mrg
753 1.1 mrg /* This function goes through all reaching defs of the source
754 1.1 mrg of the candidate for elimination (CAND) and tries to combine
755 1.1 mrg the extension with the definition instruction. The changes
756 1.1 mrg are made as a group so that even if one definition cannot be
757 1.1 mrg merged, all reaching definitions end up not being merged.
758 1.1 mrg When a conditional copy is encountered, merging is attempted
759 1.1 mrg transitively on its definitions. It returns true upon success
760 1.1 mrg and false upon failure. */
761 1.1 mrg
762 1.1 mrg static bool
763 1.1 mrg combine_reaching_defs (ext_cand *cand, const_rtx set_pat, ext_state *state)
764 1.1 mrg {
765 1.1 mrg rtx_insn *def_insn;
766 1.1 mrg bool merge_successful = true;
767 1.1 mrg int i;
768 1.1 mrg int defs_ix;
769 1.1 mrg bool outcome;
770 1.1 mrg
771 1.1 mrg state->defs_list.truncate (0);
772 1.1 mrg state->copies_list.truncate (0);
773 1.1 mrg
774 1.1 mrg outcome = make_defs_and_copies_lists (cand->insn, set_pat, state);
775 1.1 mrg
776 1.1 mrg if (!outcome)
777 1.1 mrg return false;
778 1.1 mrg
779 1.1 mrg /* If the destination operand of the extension is a different
780 1.1 mrg register than the source operand, then additional restrictions
781 1.1 mrg are needed. Note we have to handle cases where we have nested
782 1.1 mrg extensions in the source operand.
783 1.1 mrg
784 1.1 mrg Candidate insns are known to be single_sets, via the test in
785 1.1 mrg find_removable_extensions. So we continue to use single_set here
786 1.1 mrg rather than get_sub_rtx. */
787 1.1 mrg rtx set = single_set (cand->insn);
788 1.1 mrg bool copy_needed
789 1.1 mrg = (REGNO (SET_DEST (set)) != REGNO (get_extended_src_reg (SET_SRC (set))));
790 1.1 mrg if (copy_needed)
791 1.1 mrg {
792 1.1 mrg /* Considering transformation of
793 1.1 mrg (set (reg1) (expression))
794 1.1 mrg ...
795 1.1 mrg (set (reg2) (any_extend (reg1)))
796 1.1 mrg
797 1.1 mrg into
798 1.1 mrg
799 1.1 mrg (set (reg2) (any_extend (expression)))
800 1.1 mrg (set (reg1) (reg2))
801 1.1 mrg ... */
802 1.1 mrg
803 1.1 mrg /* In theory we could handle more than one reaching def, it
804 1.1 mrg just makes the code to update the insn stream more complex. */
805 1.1 mrg if (state->defs_list.length () != 1)
806 1.1 mrg return false;
807 1.1 mrg
808 1.1 mrg /* We don't have the structure described above if there are
809 1.1 mrg conditional moves in between the def and the candidate,
810 1.1 mrg and we will not handle them correctly. See PR68194. */
811 1.1 mrg if (state->copies_list.length () > 0)
812 1.1 mrg return false;
813 1.1 mrg
814 1.1 mrg /* We require the candidate not already be modified. It may,
815 1.1 mrg for example have been changed from a (sign_extend (reg))
816 1.1 mrg into (zero_extend (sign_extend (reg))).
817 1.1 mrg
818 1.1 mrg Handling that case shouldn't be terribly difficult, but the code
819 1.1 mrg here and the code to emit copies would need auditing. Until
820 1.1 mrg we see a need, this is the safe thing to do. */
821 1.1 mrg if (state->modified[INSN_UID (cand->insn)].kind != EXT_MODIFIED_NONE)
822 1.1 mrg return false;
823 1.1 mrg
824 1.1 mrg machine_mode dst_mode = GET_MODE (SET_DEST (set));
825 1.1 mrg rtx src_reg = get_extended_src_reg (SET_SRC (set));
826 1.1 mrg
827 1.1 mrg /* Ensure we can use the src_reg in dst_mode (needed for
828 1.1 mrg the (set (reg1) (reg2)) insn mentioned above). */
829 1.1 mrg if (!targetm.hard_regno_mode_ok (REGNO (src_reg), dst_mode))
830 1.1 mrg return false;
831 1.1 mrg
832 1.1 mrg /* Ensure the number of hard registers of the copy match. */
833 1.1 mrg if (hard_regno_nregs (REGNO (src_reg), dst_mode) != REG_NREGS (src_reg))
834 1.1 mrg return false;
835 1.1 mrg
836 1.1 mrg /* There's only one reaching def. */
837 1.1 mrg rtx_insn *def_insn = state->defs_list[0];
838 1.1 mrg
839 1.1 mrg /* The defining statement must not have been modified either. */
840 1.1 mrg if (state->modified[INSN_UID (def_insn)].kind != EXT_MODIFIED_NONE)
841 1.1 mrg return false;
842 1.1 mrg
843 1.1 mrg /* The defining statement and candidate insn must be in the same block.
844 1.1 mrg This is merely to keep the test for safety and updating the insn
845 1.1 mrg stream simple. Also ensure that within the block the candidate
846 1.1 mrg follows the defining insn. */
847 1.1 mrg basic_block bb = BLOCK_FOR_INSN (cand->insn);
848 1.1 mrg if (bb != BLOCK_FOR_INSN (def_insn)
849 1.1 mrg || DF_INSN_LUID (def_insn) > DF_INSN_LUID (cand->insn))
850 1.1 mrg return false;
851 1.1 mrg
852 1.1 mrg /* If there is an overlap between the destination of DEF_INSN and
853 1.1 mrg CAND->insn, then this transformation is not safe. Note we have
854 1.1 mrg to test in the widened mode. */
855 1.1 mrg rtx *dest_sub_rtx = get_sub_rtx (def_insn);
856 1.1 mrg if (dest_sub_rtx == NULL)
857 1.1 mrg return false;
858 1.1 mrg
859 1.1 mrg rtx tmp_reg = gen_rtx_REG (GET_MODE (SET_DEST (set)),
860 1.1 mrg REGNO (SET_DEST (*dest_sub_rtx)));
861 1.1 mrg if (reg_overlap_mentioned_p (tmp_reg, SET_DEST (set)))
862 1.1 mrg return false;
863 1.1 mrg
864 1.1 mrg /* On RISC machines we must make sure that changing the mode of SRC_REG
865 1.1 mrg as destination register will not affect its reaching uses, which may
866 1.1 mrg read its value in a larger mode because DEF_INSN implicitly sets it
867 1.1 mrg in word mode. */
868 1.1 mrg poly_int64 prec
869 1.1 mrg = GET_MODE_PRECISION (GET_MODE (SET_DEST (*dest_sub_rtx)));
870 1.1 mrg if (WORD_REGISTER_OPERATIONS && known_lt (prec, BITS_PER_WORD))
871 1.1 mrg {
872 1.1 mrg struct df_link *uses = get_uses (def_insn, src_reg);
873 1.1 mrg if (!uses)
874 1.1 mrg return false;
875 1.1 mrg
876 1.1 mrg for (df_link *use = uses; use; use = use->next)
877 1.1 mrg if (paradoxical_subreg_p (GET_MODE (*DF_REF_LOC (use->ref)),
878 1.1 mrg GET_MODE (SET_DEST (*dest_sub_rtx)))
879 1.1 mrg && !DEBUG_INSN_P (DF_REF_INSN (use->ref)))
880 1.1 mrg return false;
881 1.1 mrg }
882 1.1 mrg
883 1.1 mrg /* The destination register of the extension insn must not be
884 1.1 mrg used or set between the def_insn and cand->insn exclusive. */
885 1.1 mrg if (reg_used_between_p (SET_DEST (set), def_insn, cand->insn)
886 1.1 mrg || reg_set_between_p (SET_DEST (set), def_insn, cand->insn))
887 1.1 mrg return false;
888 1.1 mrg
889 1.1 mrg /* We must be able to copy between the two registers. Generate,
890 1.1 mrg recognize and verify constraints of the copy. Also fail if this
891 1.1 mrg generated more than one insn.
892 1.1 mrg
893 1.1 mrg This generates garbage since we throw away the insn when we're
894 1.1 mrg done, only to recreate it later if this test was successful.
895 1.1 mrg
896 1.1 mrg Make sure to get the mode from the extension (cand->insn). This
897 1.1 mrg is different than in the code to emit the copy as we have not
898 1.1 mrg modified the defining insn yet. */
899 1.1 mrg start_sequence ();
900 1.1 mrg rtx new_dst = gen_rtx_REG (GET_MODE (SET_DEST (set)),
901 1.1 mrg REGNO (get_extended_src_reg (SET_SRC (set))));
902 1.1 mrg rtx new_src = gen_rtx_REG (GET_MODE (SET_DEST (set)),
903 1.1 mrg REGNO (SET_DEST (set)));
904 1.1 mrg emit_move_insn (new_dst, new_src);
905 1.1 mrg
906 1.1 mrg rtx_insn *insn = get_insns ();
907 1.1 mrg end_sequence ();
908 1.1 mrg if (NEXT_INSN (insn))
909 1.1 mrg return false;
910 1.1 mrg if (recog_memoized (insn) == -1)
911 1.1 mrg return false;
912 1.1 mrg extract_insn (insn);
913 1.1 mrg if (!constrain_operands (1, get_preferred_alternatives (insn, bb)))
914 1.1 mrg return false;
915 1.1 mrg
916 1.1 mrg while (REG_P (SET_SRC (*dest_sub_rtx))
917 1.1 mrg && (REGNO (SET_SRC (*dest_sub_rtx)) == REGNO (SET_DEST (set))))
918 1.1 mrg {
919 1.1 mrg /* Considering transformation of
920 1.1 mrg (set (reg2) (expression))
921 1.1 mrg ...
922 1.1 mrg (set (reg1) (reg2))
923 1.1 mrg ...
924 1.1 mrg (set (reg2) (any_extend (reg1)))
925 1.1 mrg
926 1.1 mrg into
927 1.1 mrg
928 1.1 mrg (set (reg2) (any_extend (expression)))
929 1.1 mrg (set (reg1) (reg2))
930 1.1 mrg ... */
931 1.1 mrg struct df_link *defs
932 1.1 mrg = get_defs (def_insn, SET_SRC (*dest_sub_rtx), NULL);
933 1.1 mrg if (defs == NULL || defs->next)
934 1.1 mrg break;
935 1.1 mrg
936 1.1 mrg /* There is only one reaching def. */
937 1.1 mrg rtx_insn *def_insn2 = DF_REF_INSN (defs->ref);
938 1.1 mrg
939 1.1 mrg /* The defining statement must not have been modified either. */
940 1.1 mrg if (state->modified[INSN_UID (def_insn2)].kind != EXT_MODIFIED_NONE)
941 1.1 mrg break;
942 1.1 mrg
943 1.1 mrg /* The def_insn2 and candidate insn must be in the same
944 1.1 mrg block and def_insn follows def_insn2. */
945 1.1 mrg if (bb != BLOCK_FOR_INSN (def_insn2)
946 1.1 mrg || DF_INSN_LUID (def_insn2) > DF_INSN_LUID (def_insn))
947 1.1 mrg break;
948 1.1 mrg
949 1.1 mrg rtx *dest_sub_rtx2 = get_sub_rtx (def_insn2);
950 1.1 mrg if (dest_sub_rtx2 == NULL)
951 1.1 mrg break;
952 1.1 mrg
953 1.1 mrg /* On RISC machines we must make sure that changing the mode of
954 1.1 mrg SRC_REG as destination register will not affect its reaching
955 1.1 mrg uses, which may read its value in a larger mode because DEF_INSN
956 1.1 mrg implicitly sets it in word mode. */
957 1.1 mrg if (WORD_REGISTER_OPERATIONS && known_lt (prec, BITS_PER_WORD))
958 1.1 mrg {
959 1.1 mrg struct df_link *uses = get_uses (def_insn2, SET_DEST (set));
960 1.1 mrg if (!uses)
961 1.1 mrg break;
962 1.1 mrg
963 1.1 mrg df_link *use;
964 1.1 mrg rtx dest2 = SET_DEST (*dest_sub_rtx2);
965 1.1 mrg for (use = uses; use; use = use->next)
966 1.1 mrg if (paradoxical_subreg_p (GET_MODE (*DF_REF_LOC (use->ref)),
967 1.1 mrg GET_MODE (dest2))
968 1.1 mrg && !DEBUG_INSN_P (DF_REF_INSN (use->ref)))
969 1.1 mrg break;
970 1.1 mrg if (use)
971 1.1 mrg break;
972 1.1 mrg }
973 1.1 mrg
974 1.1 mrg /* The destination register of the extension insn must not be
975 1.1 mrg used or set between the def_insn2 and def_insn exclusive.
976 1.1 mrg Likewise for the other reg, i.e. check both reg1 and reg2
977 1.1 mrg in the above comment. */
978 1.1 mrg if (reg_used_between_p (SET_DEST (set), def_insn2, def_insn)
979 1.1 mrg || reg_set_between_p (SET_DEST (set), def_insn2, def_insn)
980 1.1 mrg || reg_used_between_p (src_reg, def_insn2, def_insn)
981 1.1 mrg || reg_set_between_p (src_reg, def_insn2, def_insn))
982 1.1 mrg break;
983 1.1 mrg
984 1.1 mrg state->defs_list[0] = def_insn2;
985 1.1 mrg break;
986 1.1 mrg }
987 1.1 mrg }
988 1.1 mrg
989 1.1 mrg /* If cand->insn has been already modified, update cand->mode to a wider
990 1.1 mrg mode if possible, or punt. */
991 1.1 mrg if (state->modified[INSN_UID (cand->insn)].kind != EXT_MODIFIED_NONE)
992 1.1 mrg {
993 1.1 mrg machine_mode mode;
994 1.1 mrg
995 1.1 mrg if (state->modified[INSN_UID (cand->insn)].kind
996 1.1 mrg != (cand->code == ZERO_EXTEND
997 1.1 mrg ? EXT_MODIFIED_ZEXT : EXT_MODIFIED_SEXT)
998 1.1 mrg || state->modified[INSN_UID (cand->insn)].mode != cand->mode
999 1.1 mrg || (set == NULL_RTX))
1000 1.1 mrg return false;
1001 1.1 mrg mode = GET_MODE (SET_DEST (set));
1002 1.1 mrg gcc_assert (GET_MODE_UNIT_SIZE (mode)
1003 1.1 mrg >= GET_MODE_UNIT_SIZE (cand->mode));
1004 1.1 mrg cand->mode = mode;
1005 1.1 mrg }
1006 1.1 mrg
1007 1.1 mrg merge_successful = true;
1008 1.1 mrg
1009 1.1 mrg /* Go through the defs vector and try to merge all the definitions
1010 1.1 mrg in this vector. */
1011 1.1 mrg state->modified_list.truncate (0);
1012 1.1 mrg FOR_EACH_VEC_ELT (state->defs_list, defs_ix, def_insn)
1013 1.1 mrg {
1014 1.1 mrg if (merge_def_and_ext (cand, def_insn, state))
1015 1.1 mrg state->modified_list.safe_push (def_insn);
1016 1.1 mrg else
1017 1.1 mrg {
1018 1.1 mrg merge_successful = false;
1019 1.1 mrg break;
1020 1.1 mrg }
1021 1.1 mrg }
1022 1.1 mrg
1023 1.1 mrg /* Now go through the conditional copies vector and try to merge all
1024 1.1 mrg the copies in this vector. */
1025 1.1 mrg if (merge_successful)
1026 1.1 mrg {
1027 1.1 mrg FOR_EACH_VEC_ELT (state->copies_list, i, def_insn)
1028 1.1 mrg {
1029 1.1 mrg if (transform_ifelse (cand, def_insn))
1030 1.1 mrg state->modified_list.safe_push (def_insn);
1031 1.1 mrg else
1032 1.1 mrg {
1033 1.1 mrg merge_successful = false;
1034 1.1 mrg break;
1035 1.1 mrg }
1036 1.1 mrg }
1037 1.1 mrg }
1038 1.1 mrg
1039 1.1 mrg if (merge_successful)
1040 1.1 mrg {
1041 1.1 mrg /* Commit the changes here if possible
1042 1.1 mrg FIXME: It's an all-or-nothing scenario. Even if only one definition
1043 1.1 mrg cannot be merged, we entirely give up. In the future, we should allow
1044 1.1 mrg extensions to be partially eliminated along those paths where the
1045 1.1 mrg definitions could be merged. */
1046 1.1 mrg if (apply_change_group ())
1047 1.1 mrg {
1048 1.1 mrg if (dump_file)
1049 1.1 mrg fprintf (dump_file, "All merges were successful.\n");
1050 1.1 mrg
1051 1.1 mrg FOR_EACH_VEC_ELT (state->modified_list, i, def_insn)
1052 1.1 mrg {
1053 1.1 mrg ext_modified *modified = &state->modified[INSN_UID (def_insn)];
1054 1.1 mrg if (modified->kind == EXT_MODIFIED_NONE)
1055 1.1 mrg modified->kind = (cand->code == ZERO_EXTEND ? EXT_MODIFIED_ZEXT
1056 1.1 mrg : EXT_MODIFIED_SEXT);
1057 1.1 mrg
1058 1.1 mrg if (copy_needed)
1059 1.1 mrg modified->do_not_reextend = 1;
1060 1.1 mrg }
1061 1.1 mrg return true;
1062 1.1 mrg }
1063 1.1 mrg else
1064 1.1 mrg {
1065 1.1 mrg /* Changes need not be cancelled explicitly as apply_change_group
1066 1.1 mrg does it. Print list of definitions in the dump_file for debug
1067 1.1 mrg purposes. This extension cannot be deleted. */
1068 1.1 mrg if (dump_file)
1069 1.1 mrg {
1070 1.1 mrg fprintf (dump_file,
1071 1.1 mrg "Merge cancelled, non-mergeable definitions:\n");
1072 1.1 mrg FOR_EACH_VEC_ELT (state->modified_list, i, def_insn)
1073 1.1 mrg print_rtl_single (dump_file, def_insn);
1074 1.1 mrg }
1075 1.1 mrg }
1076 1.1 mrg }
1077 1.1 mrg else
1078 1.1 mrg {
1079 1.1 mrg /* Cancel any changes that have been made so far. */
1080 1.1 mrg cancel_changes (0);
1081 1.1 mrg }
1082 1.1 mrg
1083 1.1 mrg return false;
1084 1.1 mrg }
1085 1.1 mrg
1086 1.1 mrg /* Add an extension pattern that could be eliminated. */
1087 1.1 mrg
1088 1.1 mrg static void
1089 1.1 mrg add_removable_extension (const_rtx expr, rtx_insn *insn,
1090 1.1 mrg vec<ext_cand> *insn_list,
1091 1.1 mrg unsigned *def_map,
1092 1.1 mrg bitmap init_regs)
1093 1.1 mrg {
1094 1.1 mrg enum rtx_code code;
1095 1.1 mrg machine_mode mode;
1096 1.1 mrg unsigned int idx;
1097 1.1 mrg rtx src, dest;
1098 1.1 mrg
1099 1.1 mrg /* We are looking for SET (REG N) (ANY_EXTEND (REG N)). */
1100 1.1 mrg if (GET_CODE (expr) != SET)
1101 1.1 mrg return;
1102 1.1 mrg
1103 1.1 mrg src = SET_SRC (expr);
1104 1.1 mrg code = GET_CODE (src);
1105 1.1 mrg dest = SET_DEST (expr);
1106 1.1 mrg mode = GET_MODE (dest);
1107 1.1 mrg
1108 1.1 mrg if (REG_P (dest)
1109 1.1 mrg && (code == SIGN_EXTEND || code == ZERO_EXTEND)
1110 1.1 mrg && REG_P (XEXP (src, 0)))
1111 1.1 mrg {
1112 1.1 mrg rtx reg = XEXP (src, 0);
1113 1.1 mrg struct df_link *defs, *def;
1114 1.1 mrg ext_cand *cand;
1115 1.1 mrg
1116 1.1 mrg /* Zero-extension of an undefined value is partly defined (it's
1117 1.1 mrg completely undefined for sign-extension, though). So if there exists
1118 1.1 mrg a path from the entry to this zero-extension that leaves this register
1119 1.1 mrg uninitialized, removing the extension could change the behavior of
1120 1.1 mrg correct programs. So first, check it is not the case. */
1121 1.1 mrg if (code == ZERO_EXTEND && !bitmap_bit_p (init_regs, REGNO (reg)))
1122 1.1 mrg {
1123 1.1 mrg if (dump_file)
1124 1.1 mrg {
1125 1.1 mrg fprintf (dump_file, "Cannot eliminate extension:\n");
1126 1.1 mrg print_rtl_single (dump_file, insn);
1127 1.1 mrg fprintf (dump_file, " because it can operate on uninitialized"
1128 1.1 mrg " data\n");
1129 1.1 mrg }
1130 1.1 mrg return;
1131 1.1 mrg }
1132 1.1 mrg
1133 1.1 mrg /* Second, make sure we can get all the reaching definitions. */
1134 1.1 mrg defs = get_defs (insn, reg, NULL);
1135 1.1 mrg if (!defs)
1136 1.1 mrg {
1137 1.1 mrg if (dump_file)
1138 1.1 mrg {
1139 1.1 mrg fprintf (dump_file, "Cannot eliminate extension:\n");
1140 1.1 mrg print_rtl_single (dump_file, insn);
1141 1.1 mrg fprintf (dump_file, " because of missing definition(s)\n");
1142 1.1 mrg }
1143 1.1 mrg return;
1144 1.1 mrg }
1145 1.1 mrg
1146 1.1 mrg /* Third, make sure the reaching definitions don't feed another and
1147 1.1 mrg different extension. FIXME: this obviously can be improved. */
1148 1.1 mrg for (def = defs; def; def = def->next)
1149 1.1 mrg if ((idx = def_map[INSN_UID (DF_REF_INSN (def->ref))])
1150 1.1 mrg && idx != -1U
1151 1.1 mrg && (cand = &(*insn_list)[idx - 1])
1152 1.1 mrg && cand->code != code)
1153 1.1 mrg {
1154 1.1 mrg if (dump_file)
1155 1.1 mrg {
1156 1.1 mrg fprintf (dump_file, "Cannot eliminate extension:\n");
1157 1.1 mrg print_rtl_single (dump_file, insn);
1158 1.1 mrg fprintf (dump_file, " because of other extension\n");
1159 1.1 mrg }
1160 1.1 mrg return;
1161 1.1 mrg }
1162 1.1 mrg /* For vector mode extensions, ensure that all uses of the
1163 1.1 mrg XEXP (src, 0) register are in insn or debug insns, as unlike
1164 1.1 mrg integral extensions lowpart subreg of the sign/zero extended
1165 1.1 mrg register are not equal to the original register, so we have
1166 1.1 mrg to change all uses or none and the current code isn't able
1167 1.1 mrg to change them all at once in one transaction. */
1168 1.1 mrg else if (VECTOR_MODE_P (GET_MODE (XEXP (src, 0))))
1169 1.1 mrg {
1170 1.1 mrg struct df_link *ref_chain, *ref_link;
1171 1.1 mrg
1172 1.1 mrg ref_chain = DF_REF_CHAIN (def->ref);
1173 1.1 mrg for (ref_link = ref_chain; ref_link; ref_link = ref_link->next)
1174 1.1 mrg {
1175 1.1 mrg if (ref_link->ref == NULL
1176 1.1 mrg || DF_REF_INSN_INFO (ref_link->ref) == NULL)
1177 1.1 mrg {
1178 1.1 mrg idx = -1U;
1179 1.1 mrg break;
1180 1.1 mrg }
1181 1.1 mrg rtx_insn *use_insn = DF_REF_INSN (ref_link->ref);
1182 1.1 mrg if (use_insn != insn && !DEBUG_INSN_P (use_insn))
1183 1.1 mrg {
1184 1.1 mrg idx = -1U;
1185 1.1 mrg break;
1186 1.1 mrg }
1187 1.1 mrg }
1188 1.1 mrg
1189 1.1 mrg if (idx == -1U)
1190 1.1 mrg {
1191 1.1 mrg def_map[INSN_UID (DF_REF_INSN (def->ref))] = idx;
1192 1.1 mrg if (dump_file)
1193 1.1 mrg {
1194 1.1 mrg fprintf (dump_file, "Cannot eliminate extension:\n");
1195 1.1 mrg print_rtl_single (dump_file, insn);
1196 1.1 mrg fprintf (dump_file,
1197 1.1 mrg " because some vector uses aren't extension\n");
1198 1.1 mrg }
1199 1.1 mrg return;
1200 1.1 mrg }
1201 1.1 mrg }
1202 1.1 mrg
1203 1.1 mrg /* Fourth, if the extended version occupies more registers than the
1204 1.1 mrg original and the source of the extension is the same hard register
1205 1.1 mrg as the destination of the extension, then we cannot eliminate
1206 1.1 mrg the extension without deep analysis, so just punt.
1207 1.1 mrg
1208 1.1 mrg We allow this when the registers are different because the
1209 1.1 mrg code in combine_reaching_defs will handle that case correctly. */
1210 1.1 mrg if (hard_regno_nregs (REGNO (dest), mode) != REG_NREGS (reg)
1211 1.1 mrg && reg_overlap_mentioned_p (dest, reg))
1212 1.1 mrg return;
1213 1.1 mrg
1214 1.1 mrg /* Then add the candidate to the list and insert the reaching definitions
1215 1.1 mrg into the definition map. */
1216 1.1 mrg ext_cand e = {expr, code, mode, insn};
1217 1.1 mrg insn_list->safe_push (e);
1218 1.1 mrg idx = insn_list->length ();
1219 1.1 mrg
1220 1.1 mrg for (def = defs; def; def = def->next)
1221 1.1 mrg def_map[INSN_UID (DF_REF_INSN (def->ref))] = idx;
1222 1.1 mrg }
1223 1.1 mrg }
1224 1.1 mrg
1225 1.1 mrg /* Traverse the instruction stream looking for extensions and return the
1226 1.1 mrg list of candidates. */
1227 1.1 mrg
1228 1.1 mrg static vec<ext_cand>
1229 1.1 mrg find_removable_extensions (void)
1230 1.1 mrg {
1231 1.1 mrg vec<ext_cand> insn_list = vNULL;
1232 1.1 mrg basic_block bb;
1233 1.1 mrg rtx_insn *insn;
1234 1.1 mrg rtx set;
1235 1.1 mrg unsigned *def_map = XCNEWVEC (unsigned, max_insn_uid);
1236 1.1 mrg bitmap_head init, kill, gen, tmp;
1237 1.1 mrg
1238 1.1 mrg bitmap_initialize (&init, NULL);
1239 1.1 mrg bitmap_initialize (&kill, NULL);
1240 1.1 mrg bitmap_initialize (&gen, NULL);
1241 1.1 mrg bitmap_initialize (&tmp, NULL);
1242 1.1 mrg
1243 1.1 mrg FOR_EACH_BB_FN (bb, cfun)
1244 1.1 mrg {
1245 1.1 mrg bitmap_copy (&init, DF_MIR_IN (bb));
1246 1.1 mrg bitmap_clear (&kill);
1247 1.1 mrg bitmap_clear (&gen);
1248 1.1 mrg
1249 1.1 mrg FOR_BB_INSNS (bb, insn)
1250 1.1 mrg {
1251 1.1 mrg if (NONDEBUG_INSN_P (insn))
1252 1.1 mrg {
1253 1.1 mrg set = single_set (insn);
1254 1.1 mrg if (set != NULL_RTX)
1255 1.1 mrg add_removable_extension (set, insn, &insn_list, def_map,
1256 1.1 mrg &init);
1257 1.1 mrg df_mir_simulate_one_insn (bb, insn, &kill, &gen);
1258 1.1 mrg bitmap_ior_and_compl (&tmp, &gen, &init, &kill);
1259 1.1 mrg bitmap_copy (&init, &tmp);
1260 1.1 mrg }
1261 1.1 mrg }
1262 1.1 mrg }
1263 1.1 mrg
1264 1.1 mrg XDELETEVEC (def_map);
1265 1.1 mrg
1266 1.1 mrg return insn_list;
1267 1.1 mrg }
1268 1.1 mrg
1269 1.1 mrg /* This is the main function that checks the insn stream for redundant
1270 1.1 mrg extensions and tries to remove them if possible. */
1271 1.1 mrg
1272 1.1 mrg static void
1273 1.1 mrg find_and_remove_re (void)
1274 1.1 mrg {
1275 1.1 mrg ext_cand *curr_cand;
1276 1.1 mrg rtx_insn *curr_insn = NULL;
1277 1.1 mrg int num_re_opportunities = 0, num_realized = 0, i;
1278 1.1 mrg vec<ext_cand> reinsn_list;
1279 1.1 mrg auto_vec<rtx_insn *> reinsn_del_list;
1280 1.1 mrg auto_vec<rtx_insn *> reinsn_copy_list;
1281 1.1 mrg
1282 1.1 mrg /* Construct DU chain to get all reaching definitions of each
1283 1.1 mrg extension instruction. */
1284 1.1 mrg df_set_flags (DF_RD_PRUNE_DEAD_DEFS);
1285 1.1 mrg df_chain_add_problem (DF_UD_CHAIN + DF_DU_CHAIN);
1286 1.1 mrg df_mir_add_problem ();
1287 1.1 mrg df_analyze ();
1288 1.1 mrg df_set_flags (DF_DEFER_INSN_RESCAN);
1289 1.1 mrg
1290 1.1 mrg max_insn_uid = get_max_uid ();
1291 1.1 mrg reinsn_list = find_removable_extensions ();
1292 1.1 mrg
1293 1.1 mrg ext_state state;
1294 1.1 mrg if (reinsn_list.is_empty ())
1295 1.1 mrg state.modified = NULL;
1296 1.1 mrg else
1297 1.1 mrg state.modified = XCNEWVEC (struct ext_modified, max_insn_uid);
1298 1.1 mrg
1299 1.1 mrg FOR_EACH_VEC_ELT (reinsn_list, i, curr_cand)
1300 1.1 mrg {
1301 1.1 mrg num_re_opportunities++;
1302 1.1 mrg
1303 1.1 mrg /* Try to combine the extension with the definition. */
1304 1.1 mrg if (dump_file)
1305 1.1 mrg {
1306 1.1 mrg fprintf (dump_file, "Trying to eliminate extension:\n");
1307 1.1 mrg print_rtl_single (dump_file, curr_cand->insn);
1308 1.1 mrg }
1309 1.1 mrg
1310 1.1 mrg if (combine_reaching_defs (curr_cand, curr_cand->expr, &state))
1311 1.1 mrg {
1312 1.1 mrg if (dump_file)
1313 1.1 mrg fprintf (dump_file, "Eliminated the extension.\n");
1314 1.1 mrg num_realized++;
1315 1.1 mrg /* If the RHS of the current candidate is not (extend (reg)), then
1316 1.1 mrg we do not allow the optimization of extensions where
1317 1.1 mrg the source and destination registers do not match. Thus
1318 1.1 mrg checking REG_P here is correct. */
1319 1.1 mrg rtx set = single_set (curr_cand->insn);
1320 1.1 mrg if (REG_P (XEXP (SET_SRC (set), 0))
1321 1.1 mrg && (REGNO (SET_DEST (set)) != REGNO (XEXP (SET_SRC (set), 0))))
1322 1.1 mrg {
1323 1.1 mrg reinsn_copy_list.safe_push (curr_cand->insn);
1324 1.1 mrg reinsn_copy_list.safe_push (state.defs_list[0]);
1325 1.1 mrg }
1326 1.1 mrg reinsn_del_list.safe_push (curr_cand->insn);
1327 1.1 mrg state.modified[INSN_UID (curr_cand->insn)].deleted = 1;
1328 1.1 mrg }
1329 1.1 mrg }
1330 1.1 mrg
1331 1.1 mrg /* The copy list contains pairs of insns which describe copies we
1332 1.1 mrg need to insert into the INSN stream.
1333 1.1 mrg
1334 1.1 mrg The first insn in each pair is the extension insn, from which
1335 1.1 mrg we derive the source and destination of the copy.
1336 1.1 mrg
1337 1.1 mrg The second insn in each pair is the memory reference where the
1338 1.1 mrg extension will ultimately happen. We emit the new copy
1339 1.1 mrg immediately after this insn.
1340 1.1 mrg
1341 1.1 mrg It may first appear that the arguments for the copy are reversed.
1342 1.1 mrg Remember that the memory reference will be changed to refer to the
1343 1.1 mrg destination of the extention. So we're actually emitting a copy
1344 1.1 mrg from the new destination to the old destination. */
1345 1.1 mrg for (unsigned int i = 0; i < reinsn_copy_list.length (); i += 2)
1346 1.1 mrg {
1347 1.1 mrg rtx_insn *curr_insn = reinsn_copy_list[i];
1348 1.1 mrg rtx_insn *def_insn = reinsn_copy_list[i + 1];
1349 1.1 mrg
1350 1.1 mrg /* Use the mode of the destination of the defining insn
1351 1.1 mrg for the mode of the copy. This is necessary if the
1352 1.1 mrg defining insn was used to eliminate a second extension
1353 1.1 mrg that was wider than the first. */
1354 1.1 mrg rtx sub_rtx = *get_sub_rtx (def_insn);
1355 1.1 mrg rtx set = single_set (curr_insn);
1356 1.1 mrg rtx new_dst = gen_rtx_REG (GET_MODE (SET_DEST (sub_rtx)),
1357 1.1 mrg REGNO (XEXP (SET_SRC (set), 0)));
1358 1.1 mrg rtx new_src = gen_rtx_REG (GET_MODE (SET_DEST (sub_rtx)),
1359 1.1 mrg REGNO (SET_DEST (set)));
1360 1.1 mrg rtx new_set = gen_rtx_SET (new_dst, new_src);
1361 1.1 mrg emit_insn_after (new_set, def_insn);
1362 1.1 mrg }
1363 1.1 mrg
1364 1.1 mrg /* Delete all useless extensions here in one sweep. */
1365 1.1 mrg FOR_EACH_VEC_ELT (reinsn_del_list, i, curr_insn)
1366 1.1 mrg delete_insn (curr_insn);
1367 1.1 mrg
1368 1.1 mrg reinsn_list.release ();
1369 1.1 mrg XDELETEVEC (state.modified);
1370 1.1 mrg
1371 1.1 mrg if (dump_file && num_re_opportunities > 0)
1372 1.1 mrg fprintf (dump_file, "Elimination opportunities = %d realized = %d\n",
1373 1.1 mrg num_re_opportunities, num_realized);
1374 1.1 mrg }
1375 1.1 mrg
1376 1.1 mrg /* Find and remove redundant extensions. */
1377 1.1 mrg
1378 1.1 mrg static unsigned int
1379 1.1 mrg rest_of_handle_ree (void)
1380 1.1 mrg {
1381 1.1 mrg find_and_remove_re ();
1382 1.1 mrg return 0;
1383 1.1 mrg }
1384 1.1 mrg
1385 1.1 mrg namespace {
1386 1.1 mrg
1387 1.1 mrg const pass_data pass_data_ree =
1388 1.1 mrg {
1389 1.1 mrg RTL_PASS, /* type */
1390 1.1 mrg "ree", /* name */
1391 1.1 mrg OPTGROUP_NONE, /* optinfo_flags */
1392 1.1 mrg TV_REE, /* tv_id */
1393 1.1 mrg 0, /* properties_required */
1394 1.1 mrg 0, /* properties_provided */
1395 1.1 mrg 0, /* properties_destroyed */
1396 1.1 mrg 0, /* todo_flags_start */
1397 1.1 mrg TODO_df_finish, /* todo_flags_finish */
1398 1.1 mrg };
1399 1.1 mrg
1400 1.1 mrg class pass_ree : public rtl_opt_pass
1401 1.1 mrg {
1402 1.1 mrg public:
1403 1.1 mrg pass_ree (gcc::context *ctxt)
1404 1.1 mrg : rtl_opt_pass (pass_data_ree, ctxt)
1405 1.1 mrg {}
1406 1.1 mrg
1407 1.1 mrg /* opt_pass methods: */
1408 1.1 mrg virtual bool gate (function *) { return (optimize > 0 && flag_ree); }
1409 1.1 mrg virtual unsigned int execute (function *) { return rest_of_handle_ree (); }
1410 1.1 mrg
1411 1.1 mrg }; // class pass_ree
1412 1.1 mrg
1413 1.1 mrg } // anon namespace
1414 1.1 mrg
1415 1.1 mrg rtl_opt_pass *
1416 1.1 mrg make_pass_ree (gcc::context *ctxt)
1417 1.1 mrg {
1418 1.1 mrg return new pass_ree (ctxt);
1419 1.1 mrg }
1420