X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fcse.c;h=d729cb29a1afa4dddacd067fe51e6541a24df68d;hb=20f0a040ddc6a91c13ce35a4cb42facfb61200c8;hp=72a1ff63c3d200826ec3e7a4d2272bef4a0ea5a4;hpb=53d90e4e720a6b3529dec3b13b5012f544d2572f;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/cse.c b/gcc/cse.c index 72a1ff63c3d..d729cb29a1a 100644 --- a/gcc/cse.c +++ b/gcc/cse.c @@ -25,16 +25,19 @@ Boston, MA 02111-1307, USA. */ #include #include "rtl.h" +#include "tm_p.h" #include "regs.h" #include "hard-reg-set.h" #include "flags.h" #include "real.h" #include "insn-config.h" #include "recog.h" +#include "function.h" #include "expr.h" #include "toplev.h" #include "output.h" -#include "splay-tree.h" +#include "hashtab.h" +#include "ggc.h" /* The basic idea of common subexpression elimination is to go through the code, keeping a record of expressions that would @@ -42,12 +45,14 @@ Boston, MA 02111-1307, USA. */ expressions encountered with the cheapest equivalent expression. It is too complicated to keep track of the different possibilities - when control paths merge; so, at each label, we forget all that is - known and start fresh. This can be described as processing each - basic block separately. Note, however, that these are not quite - the same as the basic blocks found by a later pass and used for - data flow analysis and register packing. We do not need to start fresh - after a conditional jump instruction if there is no label there. + when control paths merge in this code; so, at each label, we forget all + that is known and start fresh. This can be described as processing each + extended basic block separately. We have a separate pass to perform + global CSE. + + Note CSE can turn a conditional or computed jump into a nop or + an unconditional jump. When this occurs we arrange to run the jump + optimizer after CSE to delete the unreachable code. We use two data structures to record the equivalent expressions: a hash table for most expressions, and several vectors together @@ -287,14 +292,12 @@ static int *reg_next_eqv; static int *reg_prev_eqv; struct cse_reg_info { - union { - /* The number of times the register has been altered in the current - basic block. */ - int reg_tick; - - /* The next cse_reg_info structure in the free list. */ - struct cse_reg_info* next; - } variant; + /* The number of times the register has been altered in the current + basic block. */ + int reg_tick; + + /* The next cse_reg_info structure in the free or used list. */ + struct cse_reg_info* next; /* The REG_TICK value at which rtx's containing this register are valid in the hash table. If this does not equal the current @@ -304,13 +307,20 @@ struct cse_reg_info { /* The quantity number of the register's current contents. */ int reg_qty; + + /* Search key */ + int regno; }; /* A free list of cse_reg_info entries. */ static struct cse_reg_info *cse_reg_info_free_list; +/* A used list of cse_reg_info entries. */ +static struct cse_reg_info *cse_reg_info_used_list; +static struct cse_reg_info *cse_reg_info_used_list_end; + /* A mapping from registers to cse_reg_info data structures. */ -static splay_tree cse_reg_info_tree; +static hash_table_t cse_reg_info_tree; /* The last lookup we did into the cse_reg_info_tree. This allows us to cache repeated lookups. */ @@ -506,7 +516,7 @@ struct table_elt /* Get the number of times this register has been updated in this basic block. */ -#define REG_TICK(N) ((GET_CSE_REG_INFO (N))->variant.reg_tick) +#define REG_TICK(N) ((GET_CSE_REG_INFO (N))->reg_tick) /* Get the point at which REG was recorded in the table. */ @@ -594,13 +604,14 @@ struct cse_basic_block_data { #define FIXED_BASE_PLUS_P(X) \ ((X) == frame_pointer_rtx || (X) == hard_frame_pointer_rtx \ - || (X) == arg_pointer_rtx \ + || ((X) == arg_pointer_rtx && fixed_regs[ARG_POINTER_REGNUM])\ || (X) == virtual_stack_vars_rtx \ || (X) == virtual_incoming_args_rtx \ || (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 1)) == CONST_INT \ && (XEXP (X, 0) == frame_pointer_rtx \ || XEXP (X, 0) == hard_frame_pointer_rtx \ - || XEXP (X, 0) == arg_pointer_rtx \ + || ((X) == arg_pointer_rtx \ + && fixed_regs[ARG_POINTER_REGNUM]) \ || XEXP (X, 0) == virtual_stack_vars_rtx \ || XEXP (X, 0) == virtual_incoming_args_rtx)) \ || GET_CODE (X) == ADDRESSOF) @@ -618,7 +629,8 @@ struct cse_basic_block_data { || (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 1)) == CONST_INT \ && (XEXP (X, 0) == frame_pointer_rtx \ || XEXP (X, 0) == hard_frame_pointer_rtx \ - || XEXP (X, 0) == arg_pointer_rtx \ + || ((X) == arg_pointer_rtx \ + && fixed_regs[ARG_POINTER_REGNUM]) \ || XEXP (X, 0) == virtual_stack_vars_rtx \ || XEXP (X, 0) == virtual_incoming_args_rtx)) \ || (X) == stack_pointer_rtx \ @@ -690,10 +702,11 @@ static void count_reg_usage PROTO((rtx, int *, rtx, int)); extern void dump_class PROTO((struct table_elt*)); static void check_fold_consts PROTO((PTR)); static struct cse_reg_info* get_cse_reg_info PROTO((int)); -static void free_cse_reg_info PROTO((splay_tree_value)); -static void flush_hash_table PROTO((void)); +static unsigned int hash_cse_reg_info PROTO((hash_table_entry_t)); +static int cse_reg_info_equal_p PROTO((hash_table_entry_t, + hash_table_entry_t)); -extern int rtx_equal_function_value_matters; +static void flush_hash_table PROTO((void)); /* Dump the expressions in the equivalence class indicated by CLASSP. This function is used only for debugging. */ @@ -754,7 +767,7 @@ rtx_cost (x, outer_code) { register int i, j; register enum rtx_code code; - register char *fmt; + register const char *fmt; register int total; if (x == 0) @@ -840,32 +853,38 @@ get_cse_reg_info (regno) int regno; { struct cse_reg_info *cri; - splay_tree_node n; + struct cse_reg_info **entry; + struct cse_reg_info temp; /* See if we already have this entry. */ - n = splay_tree_lookup (cse_reg_info_tree, - (splay_tree_key) regno); - if (n) - cri = (struct cse_reg_info *) (n->value); + temp.regno = regno; + entry = (struct cse_reg_info **) find_hash_table_entry (cse_reg_info_tree, + &temp, TRUE); + + if (*entry) + cri = *entry; else { /* Get a new cse_reg_info structure. */ if (cse_reg_info_free_list) { cri = cse_reg_info_free_list; - cse_reg_info_free_list = cri->variant.next; + cse_reg_info_free_list = cri->next; } else cri = (struct cse_reg_info *) xmalloc (sizeof (struct cse_reg_info)); /* Initialize it. */ - cri->variant.reg_tick = 0; + cri->reg_tick = 0; cri->reg_in_table = -1; cri->reg_qty = regno; - - splay_tree_insert (cse_reg_info_tree, - (splay_tree_key) regno, - (splay_tree_value) cri); + cri->regno = regno; + cri->next = cse_reg_info_used_list; + cse_reg_info_used_list = cri; + if (!cse_reg_info_used_list_end) + cse_reg_info_used_list_end = cri; + + *entry = cri; } /* Cache this lookup; we tend to be looking up information about the @@ -876,14 +895,20 @@ get_cse_reg_info (regno) return cri; } -static void -free_cse_reg_info (v) - splay_tree_value v; +static unsigned int +hash_cse_reg_info (el_ptr) + hash_table_entry_t el_ptr; { - struct cse_reg_info *cri = (struct cse_reg_info *) v; - - cri->variant.next = cse_reg_info_free_list; - cse_reg_info_free_list = cri; + return ((const struct cse_reg_info *) el_ptr)->regno; +} + +static int +cse_reg_info_equal_p (el_ptr1, el_ptr2) + hash_table_entry_t el_ptr1; + hash_table_entry_t el_ptr2; +{ + return (((const struct cse_reg_info *) el_ptr1)->regno + == ((const struct cse_reg_info *) el_ptr2)->regno); } /* Clear the hash table and initialize each register with its own quantity, @@ -898,12 +923,18 @@ new_basic_block () if (cse_reg_info_tree) { - splay_tree_delete (cse_reg_info_tree); + delete_hash_table (cse_reg_info_tree); + if (cse_reg_info_used_list) + { + cse_reg_info_used_list_end->next = cse_reg_info_free_list; + cse_reg_info_free_list = cse_reg_info_used_list; + cse_reg_info_used_list = cse_reg_info_used_list_end = 0; + } cached_cse_reg_info = 0; } - cse_reg_info_tree = splay_tree_new (splay_tree_compare_ints, 0, - free_cse_reg_info); + cse_reg_info_tree = create_hash_table (0, hash_cse_reg_info, + cse_reg_info_equal_p); CLEAR_HARD_REG_SET (hard_regs_in_table); @@ -1058,7 +1089,7 @@ mention_regs (x) { register enum rtx_code code; register int i, j; - register char *fmt; + register const char *fmt; register int changed = 0; if (x == 0) @@ -1978,12 +2009,6 @@ invalidate_for_call () { next = p->next_same_hash; - if (p->in_memory) - { - remove_from_table (p, hash); - continue; - } - if (GET_CODE (p->exp) != REG || REGNO (p->exp) >= FIRST_PSEUDO_REGISTER) continue; @@ -2098,7 +2123,7 @@ canon_hash (x, mode) register int i, j; register unsigned hash = 0; register enum rtx_code code; - register char *fmt; + register const char *fmt; /* repeat is used to turn tail-recursion into iteration. */ repeat: @@ -2167,7 +2192,7 @@ canon_hash (x, mode) if (GET_MODE (x) != VOIDmode) for (i = 2; i < GET_RTX_LENGTH (CONST_DOUBLE); i++) { - unsigned tem = XINT (x, i); + unsigned HOST_WIDE_INT tem = XWINT (x, i); hash += tem; } else @@ -2260,7 +2285,7 @@ canon_hash (x, mode) register unsigned tem = XINT (x, i); hash += tem; } - else if (fmt[i] == '0') + else if (fmt[i] == '0' || fmt[i] == 't') /* unused */; else abort (); @@ -2308,7 +2333,7 @@ exp_equiv_p (x, y, validate, equal_values) { register int i, j; register enum rtx_code code; - register char *fmt; + register const char *fmt; /* Note: it is incorrect to assume an expression is equivalent to itself if VALIDATE is nonzero. */ @@ -2443,6 +2468,7 @@ exp_equiv_p (x, y, validate, equal_values) break; case '0': + case 't': break; default: @@ -2463,7 +2489,7 @@ refers_to_p (x, y) { register int i; register enum rtx_code code; - register char *fmt; + register const char *fmt; repeat: if (x == y) @@ -2723,7 +2749,7 @@ canon_reg (x, insn) { register int i; register enum rtx_code code; - register char *fmt; + register const char *fmt; if (x == 0) return x; @@ -2782,7 +2808,7 @@ canon_reg (x, insn) && (((REGNO (new) < FIRST_PSEUDO_REGISTER) != (REGNO (XEXP (x, i)) < FIRST_PSEUDO_REGISTER)) || (insn_code = recog_memoized (insn)) < 0 - || insn_n_dups[insn_code] > 0)) + || insn_data[insn_code].n_dups > 0)) validate_change (insn, &XEXP (x, i), new, 1); else XEXP (x, i) = new; @@ -3364,27 +3390,7 @@ simplify_unary_operation (code, mode, op, op_mode) abort (); } - /* Clear the bits that don't belong in our mode, - unless they and our sign bit are all one. - So we get either a reasonable negative value or a reasonable - unsigned value for this mode. */ - if (width < HOST_BITS_PER_WIDE_INT - && ((val & ((HOST_WIDE_INT) (-1) << (width - 1))) - != ((HOST_WIDE_INT) (-1) << (width - 1)))) - val &= ((HOST_WIDE_INT) 1 << width) - 1; - - /* If this would be an entire word for the target, but is not for - the host, then sign-extend on the host so that the number will look - the same way on the host that it would on the target. - - For example, when building a 64 bit alpha hosted 32 bit sparc - targeted compiler, then we want the 32 bit unsigned value -1 to be - represented as a 64 bit value -1, and not as 0x00000000ffffffff. - The later confuses the sparc backend. */ - - if (BITS_PER_WORD < HOST_BITS_PER_WIDE_INT && BITS_PER_WORD == width - && (val & ((HOST_WIDE_INT) 1 << (width - 1)))) - val |= ((HOST_WIDE_INT) (-1) << width); + val = trunc_int_for_mode (val, mode); return GEN_INT (val); } @@ -3556,27 +3562,7 @@ simplify_unary_operation (code, mode, op, op_mode) set_float_handler (NULL_PTR); - /* Clear the bits that don't belong in our mode, - unless they and our sign bit are all one. - So we get either a reasonable negative value or a reasonable - unsigned value for this mode. */ - if (width < HOST_BITS_PER_WIDE_INT - && ((val & ((HOST_WIDE_INT) (-1) << (width - 1))) - != ((HOST_WIDE_INT) (-1) << (width - 1)))) - val &= ((HOST_WIDE_INT) 1 << width) - 1; - - /* If this would be an entire word for the target, but is not for - the host, then sign-extend on the host so that the number will look - the same way on the host that it would on the target. - - For example, when building a 64 bit alpha hosted 32 bit sparc - targeted compiler, then we want the 32 bit unsigned value -1 to be - represented as a 64 bit value -1, and not as 0x00000000ffffffff. - The later confuses the sparc backend. */ - - if (BITS_PER_WORD < HOST_BITS_PER_WIDE_INT && BITS_PER_WORD == width - && (val & ((HOST_WIDE_INT) 1 << (width - 1)))) - val |= ((HOST_WIDE_INT) (-1) << width); + val = trunc_int_for_mode (val, mode); return GEN_INT (val); } @@ -4065,9 +4051,11 @@ simplify_binary_operation (code, mode, op0, op1) if (GET_CODE (op1) == AND) { if (rtx_equal_p (op0, XEXP (op1, 0))) - return cse_gen_binary (AND, mode, op0, gen_rtx_NOT (mode, XEXP (op1, 1))); + return cse_gen_binary (AND, mode, op0, + gen_rtx_NOT (mode, XEXP (op1, 1))); if (rtx_equal_p (op0, XEXP (op1, 1))) - return cse_gen_binary (AND, mode, op0, gen_rtx_NOT (mode, XEXP (op1, 0))); + return cse_gen_binary (AND, mode, op0, + gen_rtx_NOT (mode, XEXP (op1, 0))); } break; @@ -4212,8 +4200,9 @@ simplify_binary_operation (code, mode, op0, op1) return gen_rtx_MULT (mode, op0, CONST_DOUBLE_FROM_REAL_VALUE (d, mode)); #else - return gen_rtx_MULT (mode, op0, - CONST_DOUBLE_FROM_REAL_VALUE (1./d, mode)); + return + gen_rtx_MULT (mode, op0, + CONST_DOUBLE_FROM_REAL_VALUE (1./d, mode)); #endif } } @@ -4238,7 +4227,7 @@ simplify_binary_operation (code, mode, op0, op1) case ROTATE: /* Rotating ~0 always results in ~0. */ if (GET_CODE (op0) == CONST_INT && width <= HOST_BITS_PER_WIDE_INT - && INTVAL (op0) == GET_MODE_MASK (mode) + && (unsigned HOST_WIDE_INT) INTVAL (op0) == GET_MODE_MASK (mode) && ! side_effects_p (op1)) return op0; @@ -4264,7 +4253,7 @@ simplify_binary_operation (code, mode, op0, op1) case SMAX: if (width <= HOST_BITS_PER_WIDE_INT && GET_CODE (op1) == CONST_INT - && (INTVAL (op1) + && ((unsigned HOST_WIDE_INT) INTVAL (op1) == (unsigned HOST_WIDE_INT) GET_MODE_MASK (mode) >> 1) && ! side_effects_p (op0)) return op1; @@ -4458,26 +4447,7 @@ simplify_binary_operation (code, mode, op0, op1) abort (); } - /* Clear the bits that don't belong in our mode, unless they and our sign - bit are all one. So we get either a reasonable negative value or a - reasonable unsigned value for this mode. */ - if (width < HOST_BITS_PER_WIDE_INT - && ((val & ((HOST_WIDE_INT) (-1) << (width - 1))) - != ((HOST_WIDE_INT) (-1) << (width - 1)))) - val &= ((HOST_WIDE_INT) 1 << width) - 1; - - /* If this would be an entire word for the target, but is not for - the host, then sign-extend on the host so that the number will look - the same way on the host that it would on the target. - - For example, when building a 64 bit alpha hosted 32 bit sparc - targeted compiler, then we want the 32 bit unsigned value -1 to be - represented as a 64 bit value -1, and not as 0x00000000ffffffff. - The later confuses the sparc backend. */ - - if (BITS_PER_WORD < HOST_BITS_PER_WIDE_INT && BITS_PER_WORD == width - && (val & ((HOST_WIDE_INT) 1 << (width - 1)))) - val |= ((HOST_WIDE_INT) (-1) << width); + val = trunc_int_for_mode (val, mode); return GEN_INT (val); } @@ -4898,14 +4868,14 @@ simplify_relational_operation (code, mode, op0, op1) /* Unsigned values are never greater than the largest unsigned value. */ if (GET_CODE (op1) == CONST_INT - && INTVAL (op1) == GET_MODE_MASK (mode) + && (unsigned HOST_WIDE_INT) INTVAL (op1) == GET_MODE_MASK (mode) && INTEGRAL_MODE_P (mode)) return const_true_rtx; break; case GTU: if (GET_CODE (op1) == CONST_INT - && INTVAL (op1) == GET_MODE_MASK (mode) + && (unsigned HOST_WIDE_INT) INTVAL (op1) == GET_MODE_MASK (mode) && INTEGRAL_MODE_P (mode)) return const0_rtx; break; @@ -5057,7 +5027,7 @@ fold_rtx (x, insn) { register enum rtx_code code; register enum machine_mode mode; - register char *fmt; + register const char *fmt; register int i; rtx new = 0; int copied = 0; @@ -5861,7 +5831,15 @@ fold_rtx (x, insn) hence not save anything) or be incorrect. */ if (const_arg1 != 0 && GET_CODE (const_arg1) == CONST_INT && INTVAL (const_arg1) < 0 - && - INTVAL (const_arg1) >= 0 + /* This used to test + + - INTVAL (const_arg1) >= 0 + + But The Sun V5.0 compilers mis-compiled that test. So + instead we test for the problematic value in a more direct + manner and hope the Sun compilers get it correct. */ + && INTVAL (const_arg1) != + ((HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1)) && GET_CODE (folded_arg1) == REG) { rtx new_const = GEN_INT (- INTVAL (const_arg1)); @@ -6399,8 +6377,6 @@ struct set unsigned dest_hash; /* The SET_DEST, with SUBREG, etc., stripped. */ rtx inner_dest; - /* Place where the pointer to the INNER_DEST was found. */ - rtx *inner_dest_loc; /* Nonzero if the SET_SRC is in memory. */ char src_in_memory; /* Nonzero if the SET_SRC is in a structure. */ @@ -6436,12 +6412,12 @@ cse_insn (insn, libcall_insn) rtx src_eqv = 0; struct table_elt *src_eqv_elt = 0; - int src_eqv_volatile; - int src_eqv_in_memory; - int src_eqv_in_struct; - unsigned src_eqv_hash; + int src_eqv_volatile = 0; + int src_eqv_in_memory = 0; + int src_eqv_in_struct = 0; + unsigned src_eqv_hash = 0; - struct set *sets; + struct set *sets = NULL_PTR; this_insn = insn; @@ -6615,7 +6591,7 @@ cse_insn (insn, libcall_insn) && ((REGNO (new) < FIRST_PSEUDO_REGISTER) != (REGNO (src) < FIRST_PSEUDO_REGISTER))) || (insn_code = recog_memoized (insn)) < 0 - || insn_n_dups[insn_code] > 0) + || insn_data[insn_code].n_dups > 0) validate_change (insn, &SET_SRC (sets[i].rtl), new, 1); else SET_SRC (sets[i].rtl) = new; @@ -7263,9 +7239,10 @@ cse_insn (insn, libcall_insn) && qty_first_reg[REG_QTY (REGNO (dest))] != REGNO (dest) && GET_CODE (src) == REG && REGNO (src) == REGNO (dest) /* Don't do this if the original insn had a hard reg as - SET_SRC. */ + SET_SRC or SET_DEST. */ && (GET_CODE (sets[i].src) != REG - || REGNO (sets[i].src) >= FIRST_PSEUDO_REGISTER)) + || REGNO (sets[i].src) >= FIRST_PSEUDO_REGISTER) + && (GET_CODE (dest) != REG || REGNO (dest) >= FIRST_PSEUDO_REGISTER)) /* We can't call canon_reg here because it won't do anything if SRC is a hard register. */ { @@ -7323,6 +7300,9 @@ cse_insn (insn, libcall_insn) { tem = find_reg_note (insn, REG_EQUAL, NULL_RTX); + /* Make sure that the rtx is not shared with any other insn. */ + src_const = copy_rtx (src_const); + /* Record the actual constant value in a REG_EQUAL note, making a new one if one does not already exist. */ if (tem) @@ -7355,16 +7335,15 @@ cse_insn (insn, libcall_insn) if (note) XEXP (note, 0) = const_insn; else - REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_WAS_0, - const_insn, - REG_NOTES (insn)); + REG_NOTES (insn) + = gen_rtx_INSN_LIST (REG_WAS_0, const_insn, + REG_NOTES (insn)); } } } /* Now deal with the destination. */ do_not_record = 0; - sets[i].inner_dest_loc = &SET_DEST (sets[0].rtl); /* Look within any SIGN_EXTRACT or ZERO_EXTRACT to the MEM or REG within it. */ @@ -7372,10 +7351,7 @@ cse_insn (insn, libcall_insn) || GET_CODE (dest) == ZERO_EXTRACT || GET_CODE (dest) == SUBREG || GET_CODE (dest) == STRICT_LOW_PART) - { - sets[i].inner_dest_loc = &XEXP (dest, 0); - dest = XEXP (dest, 0); - } + dest = XEXP (dest, 0); sets[i].inner_dest = dest; @@ -7432,13 +7408,13 @@ cse_insn (insn, libcall_insn) the insn. */ else if (n_sets == 1 && dest == pc_rtx && src == pc_rtx) { + /* One less use of the label this insn used to jump to. */ + if (JUMP_LABEL (insn) != 0) + --LABEL_NUSES (JUMP_LABEL (insn)); PUT_CODE (insn, NOTE); NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED; NOTE_SOURCE_FILE (insn) = 0; cse_jumps_altered = 1; - /* One less use of the label this insn used to jump to. */ - if (JUMP_LABEL (insn) != 0) - --LABEL_NUSES (JUMP_LABEL (insn)); /* No more processing for this set. */ sets[i].rtl = 0; } @@ -7448,8 +7424,6 @@ cse_insn (insn, libcall_insn) it. If it was a computed branch, delete it and re-emit. */ else if (dest == pc_rtx && GET_CODE (src) == LABEL_REF) { - rtx p; - /* If this is not in the format for a simple branch and we are the only SET in it, re-emit it. */ if (! simplejump_p (insn) && n_sets == 1) @@ -7457,7 +7431,6 @@ cse_insn (insn, libcall_insn) rtx new = emit_jump_insn_before (gen_jump (XEXP (src, 0)), insn); JUMP_LABEL (new) = XEXP (src, 0); LABEL_NUSES (XEXP (src, 0))++; - delete_insn (insn); insn = new; } else @@ -7468,39 +7441,13 @@ cse_insn (insn, libcall_insn) Until the right place is found, might as well do this here. */ INSN_CODE (insn) = -1; - /* Now that we've converted this jump to an unconditional jump, - there is dead code after it. Delete the dead code until we - reach a BARRIER, the end of the function, or a label. Do - not delete NOTEs except for NOTE_INSN_DELETED since later - phases assume these notes are retained. */ + never_reached_warning (insn); - p = insn; - - while (NEXT_INSN (p) != 0 - && GET_CODE (NEXT_INSN (p)) != BARRIER - && GET_CODE (NEXT_INSN (p)) != CODE_LABEL) - { - if (GET_CODE (NEXT_INSN (p)) != NOTE - || NOTE_LINE_NUMBER (NEXT_INSN (p)) == NOTE_INSN_DELETED) - delete_insn (NEXT_INSN (p)); - else - p = NEXT_INSN (p); - } - - /* If we don't have a BARRIER immediately after INSN, put one there. - Much code assumes that there are no NOTEs between a JUMP_INSN and - BARRIER. */ - - if (NEXT_INSN (insn) == 0 - || GET_CODE (NEXT_INSN (insn)) != BARRIER) - emit_barrier_before (NEXT_INSN (insn)); - - /* We might have two BARRIERs separated by notes. Delete the second - one if so. */ - - if (p != insn && NEXT_INSN (p) != 0 - && GET_CODE (NEXT_INSN (p)) == BARRIER) - delete_insn (NEXT_INSN (p)); + /* Now emit a BARRIER after the unconditional jump. Do not bother + deleting any unreachable code, let jump/flow do that. */ + if (NEXT_INSN (insn) != 0 + && GET_CODE (NEXT_INSN (insn)) != BARRIER) + emit_barrier_after (insn); cse_jumps_altered = 1; sets[i].rtl = 0; @@ -7604,7 +7551,12 @@ cse_insn (insn, libcall_insn) enum machine_mode mode = GET_MODE (src) == VOIDmode ? GET_MODE (dest) : GET_MODE (src); - if (sets[i].src_elt == 0) + /* Don't put a hard register source into the table if this is + the last insn of a libcall. */ + if (sets[i].src_elt == 0 + && (GET_CODE (src) != REG + || REGNO (src) >= FIRST_PSEUDO_REGISTER + || ! find_reg_note (insn, REG_RETVAL, NULL_RTX))) { register struct table_elt *elt; @@ -8097,7 +8049,7 @@ cse_process_notes (x, object) rtx object; { enum rtx_code code = GET_CODE (x); - char *fmt = GET_RTX_FORMAT (code); + const char *fmt = GET_RTX_FORMAT (code); int i; switch (code) @@ -8490,6 +8442,15 @@ cse_end_of_basic_block (insn, data, follow_jumps, after_loop, skip_blocks) path_size--; } + /* If the first instruction is marked with QImode, that means we've + already processed this block. Our caller will look at DATA->LAST + to figure out where to go next. We want to return the next block + in the instruction stream, not some branched-to block somewhere + else. We accomplish this by pretending our called forbid us to + follow jumps, or skip blocks. */ + if (GET_MODE (insn) == QImode) + follow_jumps = skip_blocks = 0; + /* Scan to end of this basic block. */ while (p && GET_CODE (p) != CODE_LABEL) { @@ -8764,6 +8725,9 @@ cse_main (f, nregs, after_loop, file) || global_regs[i]) SET_HARD_REG_BIT (regs_invalidated_by_call, i); + if (ggc_p) + ggc_push_context (); + /* Loop over basic blocks. Compute the maximum number of qty's needed for each basic block (which is 2 for each SET). */ @@ -8820,11 +8784,17 @@ cse_main (f, nregs, after_loop, file) cse_jumps_altered |= old_cse_jumps_altered; } + if (ggc_p) + ggc_collect (); + #ifdef USE_C_ALLOCA alloca (0); #endif } + if (ggc_p) + ggc_pop_context (); + /* Tell refers_to_mem_p that qty_const info is not available. */ qty_const = 0; @@ -8858,7 +8828,8 @@ cse_basic_block (from, to, next_branch, around_loop) qty_first_reg = (int *) alloca ((max_qty - max_reg) * sizeof (int)); qty_last_reg = (int *) alloca ((max_qty - max_reg) * sizeof (int)); - qty_mode= (enum machine_mode *) alloca ((max_qty - max_reg) * sizeof (enum machine_mode)); + qty_mode = (enum machine_mode *) alloca ((max_qty - max_reg) + * sizeof (enum machine_mode)); qty_const = (rtx *) alloca ((max_qty - max_reg) * sizeof (rtx)); qty_const_insn = (rtx *) alloca ((max_qty - max_reg) * sizeof (rtx)); qty_comparison_code @@ -8988,9 +8959,6 @@ cse_basic_block (from, to, next_branch, around_loop) insn = NEXT_INSN (to); - if (LABEL_NUSES (to) == 0) - insn = delete_insn (to); - /* If TO was the last insn in the function, we are done. */ if (insn == 0) return 0; @@ -9063,7 +9031,7 @@ count_reg_usage (x, counts, dest, incr) int incr; { enum rtx_code code; - char *fmt; + const char *fmt; int i, j; if (x == 0) @@ -9173,8 +9141,16 @@ delete_trivially_dead_insns (insns, nreg) /* Go from the last insn to the first and delete insns that only set unused registers or copy a register to itself. As we delete an insn, remove - usage counts for registers it uses. */ - for (insn = prev_real_insn (get_last_insn ()); insn; insn = prev) + usage counts for registers it uses. + + The first jump optimization pass may leave a real insn as the last + insn in the function. We must not skip that insn or we may end + up deleting code that is not really dead. */ + insn = get_last_insn (); + if (GET_RTX_CLASS (GET_CODE (insn)) != 'i') + insn = prev_real_insn (insn); + + for ( ; insn; insn = prev) { int live_insn = 0; rtx note; @@ -9229,7 +9205,13 @@ delete_trivially_dead_insns (insns, nreg) else if (GET_CODE (SET_DEST (PATTERN (insn))) != REG || REGNO (SET_DEST (PATTERN (insn))) < FIRST_PSEUDO_REGISTER || counts[REGNO (SET_DEST (PATTERN (insn)))] != 0 - || side_effects_p (SET_SRC (PATTERN (insn)))) + || side_effects_p (SET_SRC (PATTERN (insn))) + /* An ADDRESSOF expression can turn into a use of the + internal arg pointer, so always consider the + internal arg pointer live. If it is truly dead, + flow will delete the initializing insn. */ + || (SET_DEST (PATTERN (insn)) + == current_function_internal_arg_pointer)) live_insn = 1; } else if (GET_CODE (PATTERN (insn)) == PARALLEL) @@ -9254,7 +9236,13 @@ delete_trivially_dead_insns (insns, nreg) else if (GET_CODE (SET_DEST (elt)) != REG || REGNO (SET_DEST (elt)) < FIRST_PSEUDO_REGISTER || counts[REGNO (SET_DEST (elt))] != 0 - || side_effects_p (SET_SRC (elt))) + || side_effects_p (SET_SRC (elt)) + /* An ADDRESSOF expression can turn into a use of the + internal arg pointer, so always consider the + internal arg pointer live. If it is truly dead, + flow will delete the initializing insn. */ + || (SET_DEST (elt) + == current_function_internal_arg_pointer)) live_insn = 1; } else if (GET_CODE (elt) != CLOBBER && GET_CODE (elt) != USE)