1 /* Redundant Zero-extension elimination for targets that implicitly
2 zero-extend writes to the lower 32-bit portion of 64-bit registers.
3 Copyright (C) 2010 Free Software Foundation, Inc.
4 Contributed by Sriraman Tallam (tmsriram@google.com) and
5 Silvius Rus (rus@google.com)
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 3, or (at your option) any later
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
24 /* Problem Description :
26 This pass is intended to be applicable only to targets that implicitly
27 zero-extend 64-bit registers after writing to their lower 32-bit half.
28 For instance, x86_64 zero-extends the upper bits of a register
29 implicitly whenever an instruction writes to its lower 32-bit half.
30 For example, the instruction *add edi,eax* also zero-extends the upper
31 32-bits of rax after doing the addition. These zero extensions come
32 for free and GCC does not always exploit this well. That is, it has
33 been observed that there are plenty of cases where GCC explicitly
34 zero-extends registers for x86_64 that are actually useless because
35 these registers were already implicitly zero-extended in a prior
36 instruction. This pass tries to eliminate such useless zero extension
39 How does this pass work ?
40 --------------------------
42 This pass is run after register allocation. Hence, all registers that
43 this pass deals with are hard registers. This pass first looks for a
44 zero-extension instruction that could possibly be redundant. Such zero
45 extension instructions show up in RTL with the pattern :
46 (set (reg:DI x) (zero_extend:DI (reg:SI x))).
47 where x can be any one of the 64-bit hard registers.
48 Now, this pass tries to eliminate this instruction by merging the
49 zero-extension with the definitions of register x. For instance, if
50 one of the definitions of register x was :
51 (set (reg:SI x) (plus:SI (reg:SI z1) (reg:SI z2))),
52 then the combination converts this into :
53 (set (reg:DI x) (zero_extend:DI (plus:SI (reg:SI z1) (reg:SI z2)))).
54 If all the merged definitions are recognizable assembly instructions,
55 the zero-extension is effectively eliminated. For example, in x86_64,
56 implicit zero-extensions are captured with appropriate patterns in the
57 i386.md file. Hence, these merged definition can be matched to a single
58 assembly instruction. The original zero-extension instruction is then
59 deleted if all the definitions can be merged.
61 However, there are cases where the definition instruction cannot be
62 merged with a zero-extend. Examples are CALL instructions. In such
63 cases, the original zero extension is not redundant and this pass does
66 Handling conditional moves :
67 ----------------------------
69 Architectures like x86_64 support conditional moves whose semantics for
70 zero-extension differ from the other instructions. For instance, the
71 instruction *cmov ebx, eax*
72 zero-extends eax onto rax only when the move from ebx to eax happens.
73 Otherwise, eax may not be zero-extended. Conditional moves appear as
74 RTL instructions of the form
75 (set (reg:SI x) (if_then_else (cond) (reg:SI y) (reg:SI z))).
76 This pass tries to merge a zero-extension with a conditional move by
77 actually merging the defintions of y and z with a zero-extend and then
78 converting the conditional move into :
79 (set (reg:DI x) (if_then_else (cond) (reg:DI y) (reg:DI z))).
80 Since registers y and z are zero-extended, register x will also be
81 zero-extended after the conditional move. Note that this step has to
82 be done transitively since the definition of a conditional copy can be
83 another conditional copy.
85 Motivating Example I :
88 **********************************************
101 **********************************************
103 $ gcc -O2 -fsee bad_code.c (Turned on existing sign-extension elimination.)
105 400315: b8 4e 00 00 00 mov $0x4e,%eax
106 40031a: 0f af f8 imul %eax,%edi
107 40031d: 89 ff mov %edi,%edi ---> Useless extend.
108 40031f: 8b 04 bd 60 19 40 00 mov 0x401960(,%rdi,4),%eax
111 400330: ba 2d 00 00 00 mov $0x2d,%edx
112 400335: 0f af fa imul %edx,%edi
113 400338: 89 ff mov %edi,%edi ---> Useless extend.
114 40033a: 8b 04 bd 60 19 40 00 mov 0x401960(,%rdi,4),%eax
117 $ gcc -O2 -fzee bad_code.c
119 400315: 6b ff 4e imul $0x4e,%edi,%edi
120 400318: 8b 04 bd 40 19 40 00 mov 0x401940(,%rdi,4),%eax
122 400320: 6b ff 2d imul $0x2d,%edi,%edi
123 400323: 8b 04 bd 40 19 40 00 mov 0x401940(,%rdi,4),%eax
126 Motivating Example II :
127 ---------------------
129 Here is an example with a conditional move.
132 **********************************************
134 unsigned long long foo(unsigned x , unsigned y)
141 return (unsigned long long)(z);
144 $ gcc -O2 -fsee bad_code.c (Turned on existing sign-extension elimination.)
146 400360: 8d 14 3e lea (%rsi,%rdi,1),%edx
147 400363: 89 f8 mov %edi,%eax
148 400365: 29 f0 sub %esi,%eax
149 400367: 83 ff 65 cmp $0x65,%edi
150 40036a: 0f 43 c2 cmovae %edx,%eax
151 40036d: 89 c0 mov %eax,%eax ---> Useless extend.
154 $ gcc -O2 -fzee bad_code.c
156 400360: 89 fa mov %edi,%edx
157 400362: 8d 04 3e lea (%rsi,%rdi,1),%eax
158 400365: 29 f2 sub %esi,%edx
159 400367: 83 ff 65 cmp $0x65,%edi
160 40036a: 89 d6 mov %edx,%esi
161 40036c: 48 0f 42 c6 cmovb %rsi,%rax
168 This pass reduces the dynamic instruction count of a compression benchmark by
169 2.8% and improves its run-time by about 1%. The compression benchmark had the
170 following code sequence in a very hot region of code before ZEE optimized it :
173 mov %edx, %edx --> Useless zero-extend.
182 #include "coretypes.h"
189 #include "hard-reg-set.h"
190 #include "basic-block.h"
191 #include "insn-config.h"
192 #include "function.h"
194 #include "insn-attr.h"
201 #include "insn-codes.h"
202 #include "rtlhooks-def.h"
203 /* Include output.h for dump_file. */
207 #include "tree-pass.h"
211 /* This says if a register is newly created for the purpose of
216 MERGE_NOT_ATTEMPTED = 0,
220 /* This says if a INSN UID or its definition has already been merged
221 with a zero-extend or not. */
223 static enum insn_merge_code *is_insn_merge_attempted;
224 static int max_insn_uid;
226 /* Returns the merge code status for INSN. */
228 static enum insn_merge_code
229 get_insn_status (rtx insn)
231 gcc_assert (INSN_UID (insn) < max_insn_uid);
232 return is_insn_merge_attempted[INSN_UID (insn)];
235 /* Sets the merge code status of INSN to CODE. */
238 set_insn_status (rtx insn, enum insn_merge_code code)
240 gcc_assert (INSN_UID (insn) < max_insn_uid);
241 is_insn_merge_attempted[INSN_UID (insn)] = code;
244 /* Check to see if this zero-extend matches a pattern
245 that could be eliminated. This is called via
246 for_each_rtx in function find_and_remove_ze. */
249 is_set_with_extension_DI (rtx *expr, void *data)
251 /* Looking only for patterns of the type :
252 SET (REG:DI X) (ZERO_EXTEND (REG:SI x))
255 if (GET_CODE (*expr) == SET
256 && GET_MODE (SET_DEST (*expr)) == DImode
257 && GET_CODE (SET_DEST (*expr)) == REG
258 && GET_CODE (SET_SRC (*expr)) == ZERO_EXTEND
259 && GET_CODE (XEXP (SET_SRC (*expr),0)) == REG
260 && GET_MODE (XEXP (SET_SRC (*expr),0)) == SImode
261 && REGNO (SET_DEST (*expr)) == REGNO (XEXP (SET_SRC (*expr),0)))
263 *(rtx **)(data) = expr;
269 /* Given a insn (CURR_INSN) and a pointer to the SET rtx (ORIG_SET)
270 that needs to be modified, this code modifies the SET rtx to a
271 new SET rtx that zero_extends the right hand expression into a DImode
272 register (NEWREG) on the left hand side. Note that multiple
273 assumptions are made about the nature of the set that needs
274 to be true for this to work and is called from merge_def_and_ze.
277 (set (reg:SI a) (expression))
280 (set (reg:DI a) (zero_extend (expression)))
283 If the expression is a constant or another zero_extend directly
284 assign it to the DI mode register. */
287 combine_set_zero_extend (rtx curr_insn, rtx *orig_set, rtx newreg)
289 rtx temp_extension, simplified_temp_extension, new_set, new_const_int;
292 unsigned int mask, delta_width;
294 /* Change the SET rtx and validate it. */
295 orig_src = SET_SRC (*orig_set);
298 /* The right hand side can also be VOIDmode. These cases have to be
299 handled differently. */
301 if (GET_MODE (orig_src) != SImode)
303 /* Merge constants by directly moving the constant into the
304 DImode register under some conditions. */
306 if (GET_CODE (orig_src) == CONST_INT
307 && HOST_BITS_PER_WIDE_INT >= GET_MODE_BITSIZE (SImode))
309 if (INTVAL (orig_src) >= 0)
310 new_set = gen_rtx_SET (VOIDmode, newreg, orig_src);
311 else if (INTVAL (orig_src) < 0)
313 /* Zero-extending a negative SImode integer into DImode
314 makes it a positive integer. Convert the given negative
315 integer into the appropriate integer when zero-extended. */
317 delta_width = HOST_BITS_PER_WIDE_INT - GET_MODE_BITSIZE (SImode);
318 mask = (~(unsigned HOST_WIDE_INT) 0) >> delta_width;
319 val = INTVAL (orig_src);
321 new_const_int = gen_rtx_CONST_INT (VOIDmode, val);
322 new_set = gen_rtx_SET (VOIDmode, newreg, new_const_int);
329 /* This is mostly due to a call insn that should not be
335 else if (GET_CODE (orig_src) == ZERO_EXTEND)
337 /* Here a zero-extend is used to get to SI. Why not make it
338 all the way till DI. */
340 temp_extension = gen_rtx_ZERO_EXTEND (DImode, XEXP (orig_src, 0));
341 simplified_temp_extension = simplify_rtx (temp_extension);
342 if (simplified_temp_extension)
343 temp_extension = simplified_temp_extension;
344 new_set = gen_rtx_SET (VOIDmode, newreg, temp_extension);
346 else if (GET_CODE (orig_src) == IF_THEN_ELSE)
348 /* Only IF_THEN_ELSE of phi-type copies are combined. Otherwise,
349 in general, IF_THEN_ELSE should not be combined. */
355 /* This is the normal case we expect. */
357 temp_extension = gen_rtx_ZERO_EXTEND (DImode, orig_src);
358 simplified_temp_extension = simplify_rtx (temp_extension);
359 if (simplified_temp_extension)
360 temp_extension = simplified_temp_extension;
361 new_set = gen_rtx_SET (VOIDmode, newreg, temp_extension);
364 gcc_assert (new_set != NULL_RTX);
366 /* This change is a part of a group of changes. Hence,
367 validate_change will not try to commit the change. */
369 if (validate_change (curr_insn, orig_set, new_set, true))
373 fprintf (dump_file, "Merged Instruction with ZERO_EXTEND:\n");
374 print_rtl_single (dump_file, curr_insn);
381 /* This returns the DI mode for the SI register REG_SI. */
384 get_reg_di (rtx reg_si)
388 newreg = gen_rtx_REG (DImode, REGNO (reg_si));
393 /* Treat if_then_else insns, where the operands of both branches
394 are registers, as copies. For instance,
396 (set (reg:SI a) (if_then_else (cond) (reg:SI b) (reg:SI c)))
398 (set (reg:DI a) (if_then_else (cond) (reg:DI b) (reg:DI c)))
399 DEF_INSN is the if_then_else insn. */
402 transform_ifelse (rtx def_insn)
404 rtx set_insn = PATTERN (def_insn);
405 rtx srcreg, dstreg, srcreg2;
406 rtx map_srcreg, map_dstreg, map_srcreg2;
411 gcc_assert (GET_CODE (set_insn) == SET);
412 cond = XEXP (SET_SRC (set_insn), 0);
413 dstreg = SET_DEST (set_insn);
414 srcreg = XEXP (SET_SRC (set_insn), 1);
415 srcreg2 = XEXP (SET_SRC (set_insn), 2);
416 map_srcreg = get_reg_di (srcreg);
417 map_srcreg2 = get_reg_di (srcreg2);
418 map_dstreg = get_reg_di (dstreg);
419 ifexpr = gen_rtx_IF_THEN_ELSE (DImode, cond, map_srcreg, map_srcreg2);
420 new_set = gen_rtx_SET (VOIDmode, map_dstreg, ifexpr);
422 if (validate_change (def_insn, &PATTERN (def_insn), new_set, true))
426 fprintf (dump_file, "Cond_Move Instruction's mode extended :\n");
427 print_rtl_single (dump_file, def_insn);
435 /* Function to get all the immediate definitions of an instruction.
436 The reaching definitions are desired for WHICH_REG used in
437 CURR_INSN. This function returns 0 if there was an error getting
438 a definition. Upon success, this function returns the number of
439 definitions and stores the definitions in DEST. */
442 get_defs (rtx curr_insn, rtx which_reg, VEC (rtx,heap) **dest)
444 df_ref reg_info, *defs;
445 struct df_link *def_chain;
448 defs = DF_INSN_USES (curr_insn);
454 if (GET_CODE (DF_REF_REG (reg_info)) == SUBREG)
456 if (REGNO (DF_REF_REG (reg_info)) == REGNO (which_reg))
461 gcc_assert (reg_info != NULL && defs != NULL);
462 def_chain = DF_REF_CHAIN (reg_info);
466 /* Problem getting some definition for this instruction. */
468 if (def_chain->ref == NULL)
470 if (DF_REF_INSN_INFO (def_chain->ref) == NULL)
472 def_chain = def_chain->next;
475 def_chain = DF_REF_CHAIN (reg_info);
482 VEC_safe_push (rtx, heap, *dest, DF_REF_INSN (def_chain->ref));
483 def_chain = def_chain->next;
489 /* rtx function to check if this SET insn, EXPR, is a conditional copy insn :
490 (set (reg:SI a ) (IF_THEN_ELSE (cond) (reg:SI b) (reg:SI c)))
491 Called from is_insn_cond_copy. DATA stores the two registers on each
492 side of the condition. */
495 is_this_a_cmove (rtx expr, void *data)
497 /* Check for conditional (if-then-else) copy. */
499 if (GET_CODE (expr) == SET
500 && GET_CODE (SET_DEST (expr)) == REG
501 && GET_MODE (SET_DEST (expr)) == SImode
502 && GET_CODE (SET_SRC (expr)) == IF_THEN_ELSE
503 && GET_CODE (XEXP (SET_SRC (expr), 1)) == REG
504 && GET_MODE (XEXP (SET_SRC (expr), 1)) == SImode
505 && GET_CODE (XEXP (SET_SRC (expr), 2)) == REG
506 && GET_MODE (XEXP (SET_SRC (expr), 2)) == SImode)
508 ((rtx *)data)[0] = XEXP (SET_SRC (expr), 1);
509 ((rtx *)data)[1] = XEXP (SET_SRC (expr), 2);
515 /* This returns 1 if it found
516 (SET (reg:SI REGNO (def_reg)) (if_then_else (cond) (REG:SI x1) (REG:SI x2)))
517 in the DEF_INSN pattern. It stores the x1 and x2 in COPY_REG_1
521 is_insn_cond_copy (rtx def_insn, rtx *copy_reg_1, rtx *copy_reg_2)
527 srcreg[0] = NULL_RTX;
528 srcreg[1] = NULL_RTX;
530 set_expr = single_set (def_insn);
532 if (set_expr == NULL_RTX)
535 type = is_this_a_cmove (set_expr, (void *) srcreg);
539 *copy_reg_1 = srcreg[0];
540 *copy_reg_2 = srcreg[1];
547 /* Reaching Definitions of the zero-extended register could be conditional
548 copies or regular definitions. This function separates the two types into
549 two lists, DEFS_LIST and COPIES_LIST. This is necessary because, if a
550 reaching definition is a conditional copy, combining the zero_extend with
551 this definition is wrong. Conditional copies are merged by transitively
552 merging its definitions. The defs_list is populated with all the reaching
553 definitions of the zero-extension instruction (ZERO_EXTEND_INSN) which must
554 be merged with a zero_extend. The copies_list contains all the conditional
555 moves that will later be extended into a DI mode conditonal move if all the
556 merges are successful. The function returns false when there is a failure
557 in getting some definitions, like that of parameters. It returns 1 upon
558 success, 0 upon failure and 2 when all definitions of the ZERO_EXTEND_INSN
559 were merged previously. */
562 make_defs_and_copies_lists (rtx zero_extend_insn, rtx set_pat,
563 VEC (rtx,heap) **defs_list,
564 VEC (rtx,heap) **copies_list)
566 bool *is_insn_visited;
567 VEC (rtx,heap) *work_list;
568 rtx srcreg, copy_reg_1, copy_reg_2;
575 srcreg = XEXP (SET_SRC (set_pat), 0);
576 work_list = VEC_alloc (rtx, heap, 8);
578 /* Initialize the Work List */
579 n_worklist = get_defs (zero_extend_insn, srcreg, &work_list);
583 VEC_free (rtx, heap, work_list);
584 /* The number of defs being equal to zero can only imply that all of its
585 definitions have been previously merged. */
589 is_insn_visited = XNEWVEC (bool, max_insn_uid);
591 for (i = 0; i < max_insn_uid; i++)
592 is_insn_visited[i] = false;
595 /* Perform transitive closure for conditional copies. */
596 while (n_worklist > vec_index)
598 def_insn = VEC_index (rtx, work_list, vec_index);
599 gcc_assert (INSN_UID (def_insn) < max_insn_uid);
601 if (is_insn_visited[INSN_UID (def_insn)])
607 is_insn_visited[INSN_UID (def_insn)] = true;
608 copy_reg_1 = copy_reg_2 = NULL_RTX;
609 is_copy = is_insn_cond_copy (def_insn, ©_reg_1, ©_reg_2);
612 gcc_assert (copy_reg_1 && copy_reg_2);
614 /* Push it into the copy list first. */
616 VEC_safe_push (rtx, heap, *copies_list, def_insn);
618 /* Perform transitive closure here */
620 n_defs = get_defs (def_insn, copy_reg_1, &work_list);
624 VEC_free (rtx, heap, work_list);
625 XDELETEVEC (is_insn_visited);
628 n_worklist += n_defs;
630 n_defs = get_defs (def_insn, copy_reg_2, &work_list);
633 VEC_free (rtx, heap, work_list);
634 XDELETEVEC (is_insn_visited);
637 n_worklist += n_defs;
641 VEC_safe_push (rtx, heap, *defs_list, def_insn);
646 VEC_free (rtx, heap, work_list);
647 XDELETEVEC (is_insn_visited);
651 /* Merge the DEF_INSN with a zero-extend. Calls combine_set_zero_extend
652 on the SET pattern. */
655 merge_def_and_ze (rtx def_insn)
663 code = GET_CODE (PATTERN (def_insn));
666 if (code == PARALLEL)
668 for (i = 0; i < XVECLEN (PATTERN (def_insn), 0); i++)
670 s_expr = XVECEXP (PATTERN (def_insn), 0, i);
671 if (GET_CODE (s_expr) != SET)
675 sub_rtx = &XVECEXP (PATTERN (def_insn), 0, i);
678 /* PARALLEL with multiple SETs. */
683 else if (code == SET)
684 sub_rtx = &PATTERN (def_insn);
687 /* It is not a PARALLEL or a SET, what could it be ? */
691 gcc_assert (sub_rtx != NULL);
693 if (GET_CODE (SET_DEST (*sub_rtx)) == REG
694 && GET_MODE (SET_DEST (*sub_rtx)) == SImode)
696 setreg = get_reg_di (SET_DEST (*sub_rtx));
697 return combine_set_zero_extend (def_insn, sub_rtx, setreg);
704 /* This function goes through all reaching defs of the source
705 of the zero extension instruction (ZERO_EXTEND_INSN) and
706 tries to combine the zero extension with the definition
707 instruction. The changes are made as a group so that even
708 if one definition cannot be merged, all reaching definitions
709 end up not being merged. When a conditional copy is encountered,
710 merging is attempted transitively on its definitions. It returns
711 true upon success and false upon failure. */
714 combine_reaching_defs (rtx zero_extend_insn, rtx set_pat)
717 bool merge_successful = true;
722 /* To store the definitions that have been merged. */
724 VEC (rtx, heap) *defs_list, *copies_list, *vec;
725 enum insn_merge_code merge_code;
727 defs_list = VEC_alloc (rtx, heap, 8);
728 copies_list = VEC_alloc (rtx, heap, 8);
730 outcome = make_defs_and_copies_lists (zero_extend_insn,
731 set_pat, &defs_list, &copies_list);
733 /* outcome == 2 implies that all the definitions for this zero_extend were
734 merged while previously when handling other zero_extends. */
738 VEC_free (rtx, heap, defs_list);
739 VEC_free (rtx, heap, copies_list);
741 fprintf (dump_file, "All definitions have been merged previously...\n");
747 VEC_free (rtx, heap, defs_list);
748 VEC_free (rtx, heap, copies_list);
752 merge_successful = true;
754 /* Go through the defs vector and try to merge all the definitions
757 vec = VEC_alloc (rtx, heap, 8);
758 for (defs_ix = 0; VEC_iterate (rtx, defs_list, defs_ix, def_insn); defs_ix++)
760 merge_code = get_insn_status (def_insn);
761 gcc_assert (merge_code == MERGE_NOT_ATTEMPTED);
763 if (merge_def_and_ze (def_insn))
764 VEC_safe_push (rtx, heap, vec, def_insn);
767 merge_successful = false;
772 /* Now go through the conditional copies vector and try to merge all
773 the copies in this vector. */
775 if (merge_successful)
777 for (i = 0; VEC_iterate (rtx, copies_list, i, def_insn); i++)
779 if (transform_ifelse (def_insn))
781 VEC_safe_push (rtx, heap, vec, def_insn);
785 merge_successful = false;
791 if (merge_successful)
793 /* Commit the changes here if possible */
794 /* XXX : Now, it is an all or nothing scenario. Even if one definition
795 cannot be merged we totally bail. In future, allow zero-extensions to
796 be partially eliminated along those paths where the definitions could
799 if (apply_change_group ())
802 fprintf (dump_file, "All merges were successful ....\n");
804 for (i = 0; VEC_iterate (rtx, vec, i, def_insn); i++)
806 set_insn_status (def_insn, MERGE_SUCCESS);
809 VEC_free (rtx, heap, vec);
810 VEC_free (rtx, heap, defs_list);
811 VEC_free (rtx, heap, copies_list);
816 /* Changes need not be cancelled explicitly as apply_change_group ()
817 does it. Print list of definitions in the dump_file for debug
818 purposes. This zero-extension cannot be deleted. */
822 for (i = 0; VEC_iterate (rtx, vec, i, def_insn); i++)
824 fprintf (dump_file, " Ummergable definitions : \n");
825 print_rtl_single (dump_file, def_insn);
832 /* Cancel any changes that have been made so far. */
836 VEC_free (rtx, heap, vec);
837 VEC_free (rtx, heap, defs_list);
838 VEC_free (rtx, heap, copies_list);
842 /* Goes through the instruction stream looking for zero-extends. If the zero
843 extension instruction has atleast one def it adds it to a list of possible
844 candidates for deletion. It returns the list of candidates. */
846 static VEC (rtx,heap)*
847 find_removable_zero_extends (void)
849 VEC (rtx, heap) *zeinsn_list;
850 basic_block curr_block;
857 zeinsn_list = VEC_alloc (rtx, heap, 8);
858 FOR_EACH_BB (curr_block)
860 FOR_BB_INSNS (curr_block, curr_insn)
862 if (!INSN_P (curr_insn))
865 type = for_each_rtx (&PATTERN (curr_insn),
866 is_set_with_extension_DI,
872 which_reg = XEXP (SET_SRC (*set_insn), 0);
873 has_defs = get_defs (curr_insn, which_reg, NULL);
875 VEC_safe_push (rtx, heap, zeinsn_list, curr_insn);
878 fprintf (dump_file, "Cannot eliminate zero extension : \n");
879 print_rtl_single (dump_file, curr_insn);
881 "This has no defs. Could be extending parameters.\n");
888 /* This is the main function that checks the insn stream for redundant
889 zero extensions and tries to remove them if possible. */
892 find_and_remove_ze (void)
894 rtx curr_insn = NULL_RTX;
897 long long num_realized = 0;
898 long long num_ze_opportunities = 0;
899 VEC (rtx, heap) *zeinsn_list;
900 VEC (rtx, heap) *zeinsn_del_list;
902 /* Construct DU chain to get all reaching definitions of each
903 zero-extension instruction. */
905 df_chain_add_problem (DF_UD_CHAIN + DF_DU_CHAIN);
908 max_insn_uid = get_max_uid ();
910 is_insn_merge_attempted = XNEWVEC (enum insn_merge_code,
911 sizeof (enum insn_merge_code)* max_insn_uid);
913 for (i = 0; i < max_insn_uid; i++)
915 is_insn_merge_attempted[i] = MERGE_NOT_ATTEMPTED;
918 num_ze_opportunities = num_realized = 0;
920 zeinsn_del_list = VEC_alloc (rtx, heap, 4);
922 zeinsn_list = find_removable_zero_extends ();
924 for (ix = 0; VEC_iterate (rtx, zeinsn_list, ix, curr_insn); ix++)
926 num_ze_opportunities++;
927 /* Try to combine the zero-extends with the definition here. */
931 fprintf (dump_file, "Trying to eliminate zero extension : \n");
932 print_rtl_single (dump_file, curr_insn);
935 if (combine_reaching_defs (curr_insn, PATTERN (curr_insn)))
938 fprintf (dump_file, "Eliminated the zero extension...\n");
940 VEC_safe_push (rtx, heap, zeinsn_del_list, curr_insn);
944 /* Delete all useless zero extensions here in one sweep. */
945 for (ix = 0; VEC_iterate (rtx, zeinsn_del_list, ix, curr_insn); ix++)
947 delete_insn (curr_insn);
950 free (is_insn_merge_attempted);
951 VEC_free (rtx, heap, zeinsn_list);
952 VEC_free (rtx, heap, zeinsn_del_list);
954 if (dump_file && num_ze_opportunities > 0)
955 fprintf (dump_file, "\n %s : num_zee_opportunities = %lld "
956 "num_realized = %lld \n",
957 current_function_name (),
958 num_ze_opportunities, num_realized);
960 df_finish_pass (false);
964 /* Find and remove redundant zero extensions. */
967 rest_of_handle_zee (void)
969 timevar_push (TV_ZEE);
970 find_and_remove_ze ();
971 timevar_pop (TV_ZEE);
975 /* Run zee pass when flag_zee is set at optimization level > 0. */
978 gate_handle_zee (void)
980 return (optimize > 0 && flag_zee);
983 struct rtl_opt_pass pass_implicit_zee =
988 gate_handle_zee, /* gate */
989 rest_of_handle_zee, /* execute */
992 0, /* static_pass_number */
994 0, /* properties_required */
995 0, /* properties_provided */
996 0, /* properties_destroyed */
997 0, /* todo_flags_start */
1000 TODO_verify_rtl_sharing, /* todo_flags_finish */