diff options
author | Dan Albert <danalbert@google.com> | 2015-06-17 11:09:54 -0700 |
---|---|---|
committer | Dan Albert <danalbert@google.com> | 2015-06-17 14:15:22 -0700 |
commit | f378ebf14df0952eae870c9865bab8326aa8f137 (patch) | |
tree | 31794503eb2a8c64ea5f313b93100f1163afcffb /gcc-4.4.3/gcc/implicit-zee.c | |
parent | 2c58169824949d3a597d9fa81931e001ef9b1bd0 (diff) | |
download | toolchain_gcc-f378ebf14df0952eae870c9865bab8326aa8f137.tar.gz toolchain_gcc-f378ebf14df0952eae870c9865bab8326aa8f137.tar.bz2 toolchain_gcc-f378ebf14df0952eae870c9865bab8326aa8f137.zip |
Delete old versions of GCC.
Change-Id: I710f125d905290e1024cbd67f48299861790c66c
Diffstat (limited to 'gcc-4.4.3/gcc/implicit-zee.c')
-rw-r--r-- | gcc-4.4.3/gcc/implicit-zee.c | 1028 |
1 files changed, 0 insertions, 1028 deletions
diff --git a/gcc-4.4.3/gcc/implicit-zee.c b/gcc-4.4.3/gcc/implicit-zee.c deleted file mode 100644 index 5631a6924..000000000 --- a/gcc-4.4.3/gcc/implicit-zee.c +++ /dev/null @@ -1,1028 +0,0 @@ -/* Redundant Zero-extension elimination for targets that implicitly - zero-extend writes to the lower 32-bit portion of 64-bit registers. - Copyright (C) 2009 Free Software Foundation, Inc. - Contributed by Sriraman Tallam (tmsriram@google.com) and - Silvius Rus (rus@google.com) - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 3, or (at your option) any later -version. - -GCC is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING3. If not see -<http://www.gnu.org/licenses/>. */ - - -/* Problem Description : - --------------------- - -This pass is intended to be applicable only to targets that implicitly -zero-extend 64-bit registers after writing to their lower 32-bit half. -For instance, x86_64 zero-extends the upper bits of a register -implicitly whenever an instruction writes to its lower 32-bit half. -For example, the instruction *add edi,eax* also zero-extends the upper -32-bits of rax after doing the addition. These zero extensions come -for free and GCC does not always exploit this well. That is, it has -been observed that there are plenty of cases where GCC explicitly -zero-extends registers for x86_64 that are actually useless because -these registers were already implicitly zero-extended in a prior -instruction. This pass tries to eliminate such useless zero extension -instructions. - -How does this pass work ? --------------------------- - -This pass is run after register allocation. Hence, all registers that -this pass deals with are hard registers. This pass first looks for a -zero-extension instruction that could possibly be redundant. Such zero -extension instructions show up in RTL with the pattern : -(set (reg:DI x) (zero_extend:DI (reg:SI x))). -where x can be any one of the 64-bit hard registers. -Now, this pass tries to eliminate this instruction by merging the -zero-extension with the definitions of register x. For instance, if -one of the definitions of register x was : -(set (reg:SI x) (plus:SI (reg:SI z1) (reg:SI z2))), -then the combination converts this into : -(set (reg:DI x) (zero_extend:DI (plus:SI (reg:SI z1) (reg:SI z2)))). -If all the merged definitions are recognizable assembly instructions, -the zero-extension is effectively eliminated. For example, in x86_64, -implicit zero-extensions are captured with appropriate patterns in the -i386.md file. Hence, these merged definition can be matched to a single -assembly instruction. The original zero-extension instruction is then -deleted if all the definitions can be merged. - -However, there are cases where the definition instruction cannot be -merged with a zero-extend. Examples are CALL instructions. In such -cases, the original zero extension is not redundant and this pass does -not delete it. - -Handling conditional moves : ----------------------------- - -Architectures like x86_64 support conditional moves whose semantics for -zero-extension differ from the other instructions. For instance, the -instruction *cmov ebx, eax* -zero-extends eax onto rax only when the move from ebx to eax happens. -Otherwise, eax may not be zero-extended. Conditional moves appear as -RTL instructions of the form -(set (reg:SI x) (if_then_else (cond) (reg:SI y) (reg:SI z))). -This pass tries to merge a zero-extension with a conditional move by -actually merging the defintions of y and z with a zero-extend and then -converting the conditional move into : -(set (reg:DI x) (if_then_else (cond) (reg:DI y) (reg:DI z))). -Since registers y and z are zero-extended, register x will also be -zero-extended after the conditional move. Note that this step has to -be done transitively since the definition of a conditional copy can be -another conditional copy. - -Motivating Example I : ---------------------- -For this program : -********************************************** -bad_code.c - -int mask[1000]; - -int foo(unsigned x) -{ - if (x < 10) - x = x * 45; - else - x = x * 78; - return mask[x]; -} -********************************************** - -$ gcc -O2 -fsee bad_code.c (Turned on existing sign-extension elimination.) - ........ - 400315: b8 4e 00 00 00 mov $0x4e,%eax - 40031a: 0f af f8 imul %eax,%edi - 40031d: 89 ff mov %edi,%edi ---> Useless extend. - 40031f: 8b 04 bd 60 19 40 00 mov 0x401960(,%rdi,4),%eax - 400326: c3 retq - ...... - 400330: ba 2d 00 00 00 mov $0x2d,%edx - 400335: 0f af fa imul %edx,%edi - 400338: 89 ff mov %edi,%edi ---> Useless extend. - 40033a: 8b 04 bd 60 19 40 00 mov 0x401960(,%rdi,4),%eax - 400341: c3 retq - -$ gcc -O2 -fzee bad_code.c - ...... - 400315: 6b ff 4e imul $0x4e,%edi,%edi - 400318: 8b 04 bd 40 19 40 00 mov 0x401940(,%rdi,4),%eax - 40031f: c3 retq - 400320: 6b ff 2d imul $0x2d,%edi,%edi - 400323: 8b 04 bd 40 19 40 00 mov 0x401940(,%rdi,4),%eax - 40032a: c3 retq - -Motivating Example II : ---------------------- - -Here is an example with a conditional move. - -For this program : -********************************************** - -unsigned long long foo(unsigned x , unsigned y) -{ - unsigned z; - if (x > 100) - z = x + y; - else - z = x - y; - return (unsigned long long)(z); -} - -$ gcc -O2 -fsee bad_code.c (Turned on existing sign-extension elimination.) - ............ - 400360: 8d 14 3e lea (%rsi,%rdi,1),%edx - 400363: 89 f8 mov %edi,%eax - 400365: 29 f0 sub %esi,%eax - 400367: 83 ff 65 cmp $0x65,%edi - 40036a: 0f 43 c2 cmovae %edx,%eax - 40036d: 89 c0 mov %eax,%eax ---> Useless extend. - 40036f: c3 retq - -$ gcc -O2 -fzee bad_code.c - ............. - 400360: 89 fa mov %edi,%edx - 400362: 8d 04 3e lea (%rsi,%rdi,1),%eax - 400365: 29 f2 sub %esi,%edx - 400367: 83 ff 65 cmp $0x65,%edi - 40036a: 89 d6 mov %edx,%esi - 40036c: 48 0f 42 c6 cmovb %rsi,%rax - 400370: c3 retq - - -Usefulness : ----------- - -This pass reduces the dynamic instruction count of a compression benchmark by -2.8% and improves it run-time by about 1%. The compression benchmark had the -following code sequence in a very hot region of code before ZEE optimized it : - -shr $0x5, %edx -mov %edx, %edx --> Useless zero-extend. - -How to turn on ? ----------------- --fzee -O2 - -*/ - -#include "config.h" -#include "system.h" -#include "coretypes.h" -#include "tm.h" -#include "rtl.h" -#include "tree.h" -#include "tm_p.h" -#include "flags.h" -#include "regs.h" -#include "hard-reg-set.h" -#include "basic-block.h" -#include "insn-config.h" -#include "function.h" -#include "expr.h" -#include "insn-attr.h" -#include "recog.h" -#include "real.h" -#include "toplev.h" -#include "target.h" -#include "timevar.h" -#include "optabs.h" -#include "insn-codes.h" -#include "rtlhooks-def.h" -/* Include output.h for dump_file. */ -#include "output.h" -#include "params.h" -#include "timevar.h" -#include "tree-pass.h" -#include "df.h" -#include "cgraph.h" - -/* This says if a register is newly created for the purpose of - zero-extension. */ - -enum insn_merge_code -{ - MERGE_NOT_ATTEMPTED = 0, - MERGE_SUCCESS -}; - -/* This says if a INSN UID or its definition has already been merged - with a zero-extend or not. */ - -static enum insn_merge_code *is_insn_merge_attempted; -static int max_insn_uid; - -/* Get and Set methods for is_insn_merge_attempted */ - -static enum insn_merge_code -get_insn_status (rtx insn) -{ - gcc_assert (INSN_UID (insn) < max_insn_uid); - return is_insn_merge_attempted[INSN_UID (insn)]; -} - -static void -set_insn_status (rtx insn, enum insn_merge_code code) -{ - gcc_assert (INSN_UID (insn) < max_insn_uid); - is_insn_merge_attempted[INSN_UID (insn)] = code; -} - -/* Check to see if this zero-extend matches a pattern - that could be eliminated. This is called via - for_each_rtx in function find_and_remove_ze. */ - -static int -is_set_with_extension_DI (rtx *expr, void *data) -{ - /* Looking only for patterns of the type : - SET (REG:DI X) (ZERO_EXTEND (REG:SI x)) - */ - - if (GET_CODE (*expr) == SET - && GET_MODE (SET_DEST (*expr)) == DImode - && GET_CODE (SET_DEST (*expr)) == REG) - { - if (GET_CODE (SET_SRC (*expr)) == ZERO_EXTEND - && GET_CODE (XEXP (SET_SRC (*expr),0)) == REG - && GET_MODE (XEXP (SET_SRC (*expr),0)) == SImode - && REGNO (SET_DEST (*expr)) == REGNO (XEXP (SET_SRC (*expr),0))) - { - *(rtx **)(data) = expr; - return 1; - } - } - return 0; -} - -/* Given a insn and a pointer to the SET rtx that needs to be - modified, this code modifies the SET rtx to a new SET rtx - that zero_extends the right hand expression into a DImode - register on the left hand side. Note that multiple - assumptions are made about the nature of the set that needs - to be true for this to work and is called from merge_def_and_ze. - - Original : - (set (reg:SI a) (expression)) - - Transform : - (set (reg:DI a) (zero_extend (expression))) - - Special Cases : - If the expression is a constant or another zero_extend directly - assign it to the 64-bit register. -*/ - -static bool -combine_set_zero_extend (rtx curr_insn, rtx *orig_set, rtx newreg) -{ - rtx temp_extension, simplified_temp_extension, new_set, new_const_int; - rtx orig_src,orig_dest; - HOST_WIDE_INT val; - - /* Change the SET rtx and validate it. */ - orig_src = SET_SRC (*orig_set); - orig_dest = SET_DEST (*orig_set); - new_set = NULL_RTX; - - /* The right hand side can also be VOIDmode. These cases have to be - handled differently. */ - - if (GET_MODE (orig_src) != SImode) - { - /* Merge constants by directly moving the constant into the - 64-bit register under some conditions. */ - - if (GET_CODE (orig_src) == CONST_INT) - { - if (INTVAL (orig_src) >= 0 && INTVAL (orig_src) <= 0x7fffffff) - { - new_set = gen_rtx_SET (VOIDmode, newreg, orig_src); - } - else if (INTVAL (orig_src) < 0) - { - val = INTVAL (orig_src); - - /* Zero-extending a negative 32-bit integer into 64-bits makes - it a positive integer. Convert the given negative integer - into the appropriate postive integer when zero-extended. */ - - val = 0xffffffff + val + 1; - gcc_assert (val > 0); - new_const_int = gen_rtx_CONST_INT (VOIDmode, val); - new_set = gen_rtx_SET (VOIDmode, newreg, new_const_int); - } - else - { - return false; - } - } - else - { - /* This is mostly due to a call insn that should not be - optimized. */ - - return false; - } - } - else if (GET_CODE (orig_src) == ZERO_EXTEND) - { - /* Here a zero-extend is used to get to SI. Why not make it - all the way till DI. */ - - temp_extension = gen_rtx_ZERO_EXTEND (DImode, XEXP (orig_src, 0)); - simplified_temp_extension = simplify_rtx (temp_extension); - if (simplified_temp_extension) - temp_extension = simplified_temp_extension; - new_set = gen_rtx_SET (VOIDmode, newreg, temp_extension); - } - else if (GET_CODE (orig_src) == IF_THEN_ELSE) - { - /* Only IF_THEN_ELSE of phi-type copies are combined. Otherwise, - in general, IF_THEN_ELSE should not be combined. */ - - return false; - } - else - { - /* This is the normal case we expect. */ - - temp_extension = gen_rtx_ZERO_EXTEND (DImode, orig_src); - simplified_temp_extension = simplify_rtx (temp_extension); - if (simplified_temp_extension) - temp_extension = simplified_temp_extension; - new_set = gen_rtx_SET (VOIDmode, newreg, temp_extension); - } - - gcc_assert (new_set != NULL_RTX); - - /* This change is a part of a group of changes. Hence, - validate_change will not try to commit the change. */ - - if (validate_change (curr_insn, orig_set, new_set, true)) - { - if (dump_file) - { - fprintf (dump_file, "Merged Instruction with ZERO_EXTEND:\n"); - print_rtl_single (dump_file, curr_insn); - } - return true; - } - return false; -} - -/* This returns the DI mode for the SI register. */ - -static rtx -get_reg_di (rtx reg_si) -{ - rtx newreg; - - newreg = gen_rtx_REG (DImode, REGNO (reg_si)); - gcc_assert (newreg); - return newreg; -} - -/* Treat if_then_else insns, where the operands of both branches - are registers, as copies. For instance, - Original : - (set (reg:SI a) (if_then_else (cond) (reg:SI b) (reg:SI c))) - Transformed : - (set (reg:DI a) (if_then_else (cond) (reg:DI b) (reg:DI c))) */ - -static bool -transform_ifelse (rtx def_insn) -{ - rtx set_insn = PATTERN (def_insn); - rtx srcreg, dstreg, srcreg2; - rtx map_srcreg, map_dstreg, map_srcreg2; - rtx ifexpr; - rtx cond; - rtx new_set; - - gcc_assert (GET_CODE (set_insn) == SET); - cond = XEXP (SET_SRC (set_insn), 0); - dstreg = SET_DEST (set_insn); - srcreg = XEXP (SET_SRC (set_insn), 1); - srcreg2 = XEXP (SET_SRC (set_insn), 2); - map_srcreg = get_reg_di (srcreg); - map_srcreg2 = get_reg_di (srcreg2); - map_dstreg = get_reg_di (dstreg); - ifexpr = gen_rtx_IF_THEN_ELSE (DImode, cond, map_srcreg, map_srcreg2); - new_set = gen_rtx_SET (VOIDmode, map_dstreg, ifexpr); - - if (validate_change (def_insn, &PATTERN (def_insn), new_set, true)) - { - if (dump_file) - { - fprintf (dump_file, "Cond_Move Instruction's mode extended :\n"); - print_rtl_single (dump_file, def_insn); - } - return true; - } - else - return false; -} - -/* Function to get all the immediate definitions of an instruction. - The reaching definitions are desired for which_reg used in - curr_insn. This function returns 0 if there was an error getting - a definition. Upon success, this function returns the number of - definitions. */ - -static int -get_defs (rtx curr_insn, rtx which_reg, VEC (rtx,heap) **dest) -{ - df_ref reg_info, *defs; - struct df_link *def_chain; - int n_refs = 0; - - defs = DF_INSN_USES (curr_insn); - reg_info = NULL; - - while (*defs) - { - reg_info = *defs; - if (GET_CODE (DF_REF_REG (reg_info)) == SUBREG) - { - return 0; - } - if (REGNO (DF_REF_REG (reg_info)) == REGNO (which_reg)) - { - break; - } - defs++; - } - - gcc_assert (reg_info != NULL && defs != NULL); - def_chain = DF_REF_CHAIN (reg_info); - - while (def_chain) - { - /* Problem getting some definition for this instruction */ - - if (def_chain->ref == NULL) - { - return 0; - } - if (DF_REF_INSN_INFO (def_chain->ref) == NULL) - { - return 0; - } - def_chain = def_chain->next; - } - - def_chain = DF_REF_CHAIN (reg_info); - - if (dest == NULL) - return 1; - - while (def_chain) - { - VEC_safe_push (rtx, heap, *dest, DF_REF_INSN (def_chain->ref)); - def_chain = def_chain->next; - n_refs++; - } - return n_refs; -} - -/* rtx function to check if this SET insn is a conditional copy insn : - (set (reg:SI a ) (IF_THEN_ELSE (cond) (reg:SI b) (reg:SI c))) - Called from is_insn_cond_copy */ - -static int -is_this_a_cmove (rtx expr, void *data) -{ - /* Check for conditional (if-then-else) copy. */ - - if (GET_CODE (expr) == SET - && GET_CODE (SET_DEST (expr)) == REG - && GET_MODE (SET_DEST (expr)) == SImode - && GET_CODE (SET_SRC (expr)) == IF_THEN_ELSE - && GET_CODE (XEXP (SET_SRC (expr), 1)) == REG - && GET_MODE (XEXP (SET_SRC (expr), 1)) == SImode - && GET_CODE (XEXP (SET_SRC (expr), 2)) == REG - && GET_MODE (XEXP (SET_SRC (expr), 2)) == SImode) - { - ((rtx *)data)[0] = XEXP (SET_SRC (expr), 1); - ((rtx *)data)[1] = XEXP (SET_SRC (expr), 2); - return 1; - } - return 0; -} - -/* This returns 1 if it found - (SET (reg:SI REGNO (def_reg)) (if_then_else (cond) (REG:SI x1) (REG:SI x2))) - in its pattern. It stores the x1 and x2 in copy_reg_1 and copy_reg_2. */ - -static int -is_insn_cond_copy (rtx def_insn, rtx *copy_reg_1, rtx *copy_reg_2) -{ - int type; - rtx set_expr; - rtx srcreg[2]; - - srcreg[0] = NULL_RTX; - srcreg[1] = NULL_RTX; - - set_expr = single_set (def_insn); - - if (set_expr == NULL_RTX) - return 0; - - type = is_this_a_cmove (set_expr, (void *) srcreg); - - if (type) - { - *copy_reg_1 = srcreg[0]; - *copy_reg_2 = srcreg[1]; - return type; - } - - return 0; -} - -/* Reaching Definitions of the zero-extended register could be conditional - copies or regular definitions. This function separates the two types into - two lists. This is necessary because, if a reaching definition is a - conditional copy, combining the zero_extend with this definition is wrong. - Conditional copies are merged by transitively merging its definitions. - The defs_list is populated with all the reaching definitions of the - zero-extension instruction (zero_extend_insn) which must be merged with - a zero_extend. The copies_list contains all the conditional moves that - will later be extended into a DI mode conditonal move if all the merges - are successful. The function returns false when there is a failure in - getting some definitions, like that of parameters. It returns 1 upon - success, 0 upon failure and 2 when all definitions of the zero_extend_insn - were merged previously. */ - -static int -make_defs_and_copies_lists (rtx zero_extend_insn, rtx set_pat, - VEC (rtx,heap) **defs_list, - VEC (rtx,heap) **copies_list) -{ - bool *is_insn_visited; - VEC (rtx,heap) *work_list; - rtx srcreg, copy_reg_1, copy_reg_2; - rtx def_insn; - int n_defs = 0; - int vec_index = 0; - int n_worklist = 0; - int i, is_copy; - - srcreg = XEXP (SET_SRC (set_pat), 0); - work_list = VEC_alloc (rtx, heap, 8); - - is_insn_visited = XNEWVEC (bool, max_insn_uid); - - for (i = 0; i < max_insn_uid; i++) - is_insn_visited[i] = false; - - /* Initialize the Work List */ - n_worklist = get_defs (zero_extend_insn, srcreg, &work_list); - - if (n_worklist == 0) - { - VEC_free (rtx, heap, work_list); - XDELETEVEC (is_insn_visited); - /* The number of defs being equal to zero can only imply that all of its - definitions have been previously merged. */ - return 2; - } - - /* Perform transitive closure for conditional copies. */ - while (n_worklist > vec_index) - { - def_insn = VEC_index (rtx, work_list, vec_index); - gcc_assert (INSN_UID (def_insn) < max_insn_uid); - - if (is_insn_visited[INSN_UID (def_insn)]) - { - vec_index++; - continue; - } - - is_insn_visited[INSN_UID (def_insn)] = true; - copy_reg_1 = copy_reg_2 = NULL_RTX; - is_copy = is_insn_cond_copy (def_insn, ©_reg_1, ©_reg_2); - if (is_copy) - { - gcc_assert (copy_reg_1 && copy_reg_2); - - /* Push it into the copy list first. */ - - VEC_safe_push (rtx, heap, *copies_list, def_insn); - - /* Perform transitive closure here */ - - n_defs = 0; - n_defs = get_defs (def_insn, copy_reg_1, &work_list); - - if (n_defs == 0) - { - VEC_free (rtx, heap, work_list); - XDELETEVEC (is_insn_visited); - return 0; - } - n_worklist += n_defs; - - n_defs = 0; - n_defs = get_defs (def_insn, copy_reg_2, &work_list); - if (n_defs == 0) - { - VEC_free (rtx, heap, work_list); - XDELETEVEC (is_insn_visited); - return 0; - } - n_worklist += n_defs; - } - else - { - VEC_safe_push (rtx, heap, *defs_list, def_insn); - } - vec_index++; - } - - VEC_free (rtx, heap, work_list); - XDELETEVEC (is_insn_visited); - return 1; -} - -/* Merge the definition with a zero-extend. Calls combine_set_zero_extend - on the SET pattern. */ - -static bool -merge_def_and_ze (rtx def_insn) -{ - enum rtx_code code; - rtx setreg; - rtx *sub_rtx; - rtx s_expr; - int i; - - code = GET_CODE (PATTERN (def_insn)); - sub_rtx = NULL; - - if (code == PARALLEL) - { - for (i = 0; i < XVECLEN (PATTERN (def_insn), 0); i++) - { - s_expr = XVECEXP (PATTERN (def_insn), 0, i); - if (GET_CODE (s_expr) != SET) - continue; - - if (sub_rtx == NULL) - sub_rtx = &XVECEXP (PATTERN (def_insn), 0, i); - else - { - /* PARALLEL with multiple SETs. */ - return false; - } - } - } - else if (code == SET) - { - sub_rtx = &PATTERN (def_insn); - } - else - { - /* It is not a PARALLEL or a SET, what could it be ? */ - return false; - } - - gcc_assert (sub_rtx != NULL); - - if (GET_CODE (SET_DEST (*sub_rtx)) == REG - && GET_MODE (SET_DEST (*sub_rtx)) == SImode) - { - setreg = get_reg_di (SET_DEST (*sub_rtx)); - if (!combine_set_zero_extend (def_insn, sub_rtx, setreg)) - { - return false; - } - else - { - return true; - } - } - else - { - return false; - } - return true; -} - -/* This function goes through all reaching defs of the source - of the zero extension instruction (zero_extend_insn) and - tries to combine the zero extension with the definition - instruction. The changes are made as a group so that even - if one definition cannot be merged, all reaching definitions - end up not being merged. When a conditional copy is encountered, - merging is attempted transitively on its definitions. It returns - true upon success and false upon failure. */ - -static bool -combine_reaching_defs (rtx zero_extend_insn, rtx set_pat) -{ - rtx newreg = NULL_RTX; - rtx srcreg, def_insn; - bool merge_successful = true; - int i; - int defs_ix; - int outcome; - - /* To store the definitions that have been merged. */ - - VEC (rtx, heap) *defs_list, *copies_list, *vec; - enum insn_merge_code merge_code; - - srcreg = XEXP (SET_SRC (set_pat), 0); - newreg = NULL_RTX; - - defs_list = VEC_alloc (rtx, heap, 8); - copies_list = VEC_alloc (rtx, heap, 8); - - outcome = make_defs_and_copies_lists (zero_extend_insn, - set_pat, &defs_list, &copies_list); - - /* outcome == 2 implies that all the definitions for this zero_extend were - merged while previously when handling other zero_extends. */ - - if (outcome == 2) - { - VEC_free (rtx, heap, defs_list); - VEC_free (rtx, heap, copies_list); - if (dump_file) - fprintf (dump_file, "All definitions have been merged previously...\n"); - return true; - } - - if (outcome == 0) - { - VEC_free (rtx, heap, defs_list); - VEC_free (rtx, heap, copies_list); - return false; - } - - newreg = get_reg_di (srcreg); - merge_successful = true; - - /* Go through the defs vector and try to merge all the definitions - in this vector. */ - - vec = VEC_alloc (rtx, heap, 8); - for (defs_ix = 0; VEC_iterate (rtx, defs_list, defs_ix, def_insn); defs_ix++) - { - merge_code = get_insn_status (def_insn); - gcc_assert (merge_code == MERGE_NOT_ATTEMPTED); - - if (merge_def_and_ze (def_insn)) - { - VEC_safe_push (rtx, heap, vec, def_insn); - } - else - { - merge_successful = false; - break; - } - } - - /* Now go through the conditional copies vector and try to merge all - the copies in this vector.*/ - - if (merge_successful) - { - for (i = 0; VEC_iterate (rtx, copies_list, i, def_insn); i++) - { - if (transform_ifelse (def_insn)) - { - VEC_safe_push (rtx, heap, vec, def_insn); - } - else - { - merge_successful = false; - break; - } - } - } - - if (merge_successful) - { - /* Commit the changes here if possible */ - /* XXX : Now, it is an all or nothing scenario. Even if one definition - cannot be merged we totally bail. In future, allow zero-extensions to - be partially eliminated along those paths where the definitions could - be merged. */ - - if (apply_change_group ()) - { - if (dump_file) - fprintf (dump_file, "All merges were successful ....\n"); - - for (i = 0; VEC_iterate (rtx, vec, i, def_insn); i++) - { - set_insn_status (def_insn, MERGE_SUCCESS); - } - - VEC_free (rtx, heap, vec); - VEC_free (rtx, heap, defs_list); - VEC_free (rtx, heap, copies_list); - return true; - } - else - { - /* Changes need not be cancelled explicitly as apply_change_group () - does it. Print list of definitions in the dump_file for debug - purposes. This zero-extension cannot be deleted. */ - - if (dump_file) - { - for (i = 0; VEC_iterate (rtx, vec, i, def_insn); i++) - { - fprintf (dump_file, " Ummergable definitions : \n"); - print_rtl_single (dump_file, def_insn); - } - } - } - } - else - { - /* Cancel any changes that have been made so far. */ - cancel_changes (0); - } - - VEC_free (rtx, heap, vec); - VEC_free (rtx, heap, defs_list); - VEC_free (rtx, heap, copies_list); - return false; -} - -/* Goes through the instruction stream looking for zero-extends. If the zero - extension instruction has atleast one def it adds it to a list of possible - candidates for deletion. It returns the list of candidates. */ -static VEC (rtx,heap)* -find_removable_zero_extends (void) -{ - VEC (rtx, heap) *zeinsn_list; - basic_block curr_block; - rtx curr_insn; - rtx *set_insn; - rtx which_reg; - int type ; - int has_defs; - - zeinsn_list = VEC_alloc (rtx, heap, 8); - FOR_EACH_BB (curr_block) - { - FOR_BB_INSNS (curr_block, curr_insn) - { - if (!INSN_P (curr_insn)) - continue; - - type = for_each_rtx (&PATTERN (curr_insn), - is_set_with_extension_DI, - (void *)&set_insn); - - if (!type) - continue; - - which_reg = XEXP (SET_SRC (*set_insn), 0); - has_defs = get_defs (curr_insn, which_reg, NULL); - if (has_defs) - { - VEC_safe_push (rtx, heap, zeinsn_list, curr_insn); - } - else if (dump_file) - { - fprintf (dump_file, "Cannot eliminate zero extension : \n"); - print_rtl_single (dump_file, curr_insn); - fprintf (dump_file, - "This has no defs. Could be extending parameters.\n"); - } - } - } - return zeinsn_list; -} - -static unsigned int -find_and_remove_ze (void) -{ - rtx curr_insn = NULL_RTX; - int i; - int ix; - long long num_realized = 0; - long long num_ze_opportunities = 0; - VEC (rtx, heap) *zeinsn_list; - VEC (rtx, heap) *zeinsn_del_list; - - /* Construct DU chain to get all reaching definitions of each - zero-extension instruction. */ - - df_chain_add_problem (DF_UD_CHAIN + DF_DU_CHAIN); - df_analyze (); - - max_insn_uid = get_max_uid (); - - is_insn_merge_attempted = XNEWVEC (enum insn_merge_code, - sizeof (enum insn_merge_code)* max_insn_uid); - - for (i = 0; i < max_insn_uid; i++) - { - is_insn_merge_attempted[i] = MERGE_NOT_ATTEMPTED; - } - - num_ze_opportunities = num_realized = 0; - - zeinsn_del_list = VEC_alloc (rtx, heap, 4); - - zeinsn_list = find_removable_zero_extends (); - - for (ix = 0; VEC_iterate (rtx, zeinsn_list, ix, curr_insn); ix++) - { - num_ze_opportunities++; - /* Try to combine the zero-extends with the definition here. */ - - if (dump_file) - { - fprintf (dump_file, "Trying to eliminate zero extension : \n"); - print_rtl_single (dump_file, curr_insn); - } - - if (combine_reaching_defs (curr_insn, PATTERN (curr_insn))) - { - if (dump_file) - fprintf (dump_file, "Eliminated the zero extension...\n"); - num_realized++; - VEC_safe_push (rtx, heap, zeinsn_del_list, curr_insn); - } - } - - /* Delete all useless zero extensions here in one sweep. */ - for (ix = 0; VEC_iterate (rtx, zeinsn_del_list, ix, curr_insn); ix++) - { - delete_insn (curr_insn); - } - - free (is_insn_merge_attempted); - VEC_free (rtx, heap, zeinsn_list); - VEC_free (rtx, heap, zeinsn_del_list); - - if (dump_file && num_ze_opportunities > 0) - fprintf (dump_file, "\n %s : num_zee_opportunities = %lld " - "num_realized = %lld \n", - current_function_name (), - num_ze_opportunities, num_realized); - - df_finish_pass (false); - return 0; -} - -static unsigned int -rest_of_handle_zee (void) -{ - timevar_push (TV_ZEE); - find_and_remove_ze (); - timevar_pop (TV_ZEE); - return 0; -} - -static bool -gate_handle_zee (void) -{ - return (optimize > 0 && flag_zee); -} - -struct rtl_opt_pass pass_implicit_zee = -{ - { - RTL_PASS, - "zee", /* name */ - gate_handle_zee, /* gate */ - rest_of_handle_zee, /* execute */ - NULL, /* sub */ - NULL, /* next */ - 0, /* static_pass_number */ - TV_ZEE, /* tv_id */ - 0, /* properties_required */ - 0, /* properties_provided */ - 0, /* properties_destroyed */ - 0, /* todo_flags_start */ - TODO_ggc_collect | - TODO_dump_func | - TODO_verify_rtl_sharing, /* todo_flags_finish */ - } -}; - |