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