X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Femit-rtl.c;h=17f8c2d8446b45c7b91690ab18671a3338dc1e2c;hb=60ad3b0ebe854dee275302eb74126ceaa8ce9b16;hp=ba3ae57dcbab36ecdf68eda04c917e03f831e528;hpb=6c799a83c8fba7edb02964d6925bef201217f8a8;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c index ba3ae57dcba..17f8c2d8446 100644 --- a/gcc/emit-rtl.c +++ b/gcc/emit-rtl.c @@ -1,6 +1,7 @@ /* Emit RTL for the GCC expander. Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 + Free Software Foundation, Inc. This file is part of GCC. @@ -104,7 +105,7 @@ REAL_VALUE_TYPE dconstm1; REAL_VALUE_TYPE dconstm2; REAL_VALUE_TYPE dconsthalf; REAL_VALUE_TYPE dconstthird; -REAL_VALUE_TYPE dconstpi; +REAL_VALUE_TYPE dconstsqrt2; REAL_VALUE_TYPE dconste; /* All references to the following fixed hard registers go through @@ -164,11 +165,8 @@ static GTY ((if_marked ("ggc_marked_p"), param_is (struct rtx_def))) #define last_location (cfun->emit->x_last_location) #define first_label_num (cfun->emit->x_first_label_num) -static rtx make_jump_insn_raw (rtx); static rtx make_call_insn_raw (rtx); -static rtx find_line_note (rtx); static rtx change_address_1 (rtx, enum machine_mode, rtx, int); -static void unshare_all_decls (tree); static void reset_used_decls (tree); static void mark_label_nuses (rtx); static hashval_t const_int_htab_hash (const void *); @@ -254,7 +252,7 @@ mem_attrs_htab_hash (const void *x) return (p->alias ^ (p->align * 1000) ^ ((p->offset ? INTVAL (p->offset) : 0) * 50000) ^ ((p->size ? INTVAL (p->size) : 0) * 2500000) - ^ (size_t) p->expr); + ^ (size_t) iterative_hash_expr (p->expr, 0)); } /* Returns nonzero if the value represented by X (which is really a @@ -267,8 +265,11 @@ mem_attrs_htab_eq (const void *x, const void *y) mem_attrs *p = (mem_attrs *) x; mem_attrs *q = (mem_attrs *) y; - return (p->alias == q->alias && p->expr == q->expr && p->offset == q->offset - && p->size == q->size && p->align == q->align); + return (p->alias == q->alias && p->offset == q->offset + && p->size == q->size && p->align == q->align + && (p->expr == q->expr + || (p->expr != NULL_TREE && q->expr != NULL_TREE + && operand_equal_p (p->expr, q->expr, 0)))); } /* Allocate a new mem_attrs structure and insert it into the hash table if @@ -426,7 +427,7 @@ const_double_from_real_value (REAL_VALUE_TYPE value, enum machine_mode mode) rtx real = rtx_alloc (CONST_DOUBLE); PUT_MODE (real, mode); - memcpy (&CONST_DOUBLE_LOW (real), &value, sizeof (REAL_VALUE_TYPE)); + real->u.rv = value; return lookup_const_double (real); } @@ -442,64 +443,28 @@ immed_double_const (HOST_WIDE_INT i0, HOST_WIDE_INT i1, enum machine_mode mode) rtx value; unsigned int i; + /* There are the following cases (note that there are no modes with + HOST_BITS_PER_WIDE_INT < GET_MODE_BITSIZE (mode) < 2 * HOST_BITS_PER_WIDE_INT): + + 1) If GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT, then we use + gen_int_mode. + 2) GET_MODE_BITSIZE (mode) == 2 * HOST_BITS_PER_WIDE_INT, but the value of + the integer fits into HOST_WIDE_INT anyway (i.e., i1 consists only + from copies of the sign bit, and sign of i0 and i1 are the same), then + we return a CONST_INT for i0. + 3) Otherwise, we create a CONST_DOUBLE for i0 and i1. */ if (mode != VOIDmode) { - int width; - gcc_assert (GET_MODE_CLASS (mode) == MODE_INT || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT /* We can get a 0 for an error mark. */ || GET_MODE_CLASS (mode) == MODE_VECTOR_INT || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT); - /* We clear out all bits that don't belong in 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. */ - width = GET_MODE_BITSIZE (mode); - if (width < HOST_BITS_PER_WIDE_INT - && ((i0 & ((HOST_WIDE_INT) (-1) << (width - 1))) - != ((HOST_WIDE_INT) (-1) << (width - 1)))) - i0 &= ((HOST_WIDE_INT) 1 << width) - 1, i1 = 0; - else if (width == HOST_BITS_PER_WIDE_INT - && ! (i1 == ~0 && i0 < 0)) - i1 = 0; - else - /* We should be able to represent this value as a constant. */ - gcc_assert (width <= 2 * HOST_BITS_PER_WIDE_INT); - - /* 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 latter confuses the sparc backend. */ - - if (width < HOST_BITS_PER_WIDE_INT - && (i0 & ((HOST_WIDE_INT) 1 << (width - 1)))) - i0 |= ((HOST_WIDE_INT) (-1) << width); - - /* If MODE fits within HOST_BITS_PER_WIDE_INT, always use a - CONST_INT. - - ??? Strictly speaking, this is wrong if we create a CONST_INT for - a large unsigned constant with the size of MODE being - HOST_BITS_PER_WIDE_INT and later try to interpret that constant - in a wider mode. In that case we will mis-interpret it as a - negative number. - - Unfortunately, the only alternative is to make a CONST_DOUBLE for - any constant in any mode if it is an unsigned constant larger - than the maximum signed integer in an int on the host. However, - doing this will break everyone that always expects to see a - CONST_INT for SImode and smaller. - - We have always been making CONST_INTs in this case, so nothing - new is being broken. */ - - if (width <= HOST_BITS_PER_WIDE_INT) - i1 = (i0 < 0) ? ~(HOST_WIDE_INT) 0 : 0; + if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT) + return gen_int_mode (i0, mode); + + gcc_assert (GET_MODE_BITSIZE (mode) == 2 * HOST_BITS_PER_WIDE_INT); } /* If this integer fits in one word, return a CONST_INT. */ @@ -607,6 +572,31 @@ gen_const_mem (enum machine_mode mode, rtx addr) return mem; } +/* Generate a MEM referring to fixed portions of the frame, e.g., register + save areas. */ + +rtx +gen_frame_mem (enum machine_mode mode, rtx addr) +{ + rtx mem = gen_rtx_MEM (mode, addr); + MEM_NOTRAP_P (mem) = 1; + set_mem_alias_set (mem, get_frame_alias_set ()); + return mem; +} + +/* Generate a MEM referring to a temporary use of the stack, not part + of the fixed stack frame. For example, something which is pushed + by a target splitter. */ +rtx +gen_tmp_stack_mem (enum machine_mode mode, rtx addr) +{ + rtx mem = gen_rtx_MEM (mode, addr); + MEM_NOTRAP_P (mem) = 1; + if (!current_function_calls_alloca) + set_mem_alias_set (mem, get_frame_alias_set ()); + return mem; +} + /* We want to create (subreg:OMODE (obj:IMODE) OFFSET). Return true if this construct would be valid, and false otherwise. */ @@ -821,13 +811,12 @@ gen_reg_rtx (enum machine_mode mode) return val; } -/* Generate a register with same attributes as REG, but offsetted by OFFSET. +/* Update NEW with the same attributes as REG, but offsetted by OFFSET. Do the big endian correction if needed. */ -rtx -gen_rtx_REG_offset (rtx reg, enum machine_mode mode, unsigned int regno, int offset) +static void +update_reg_offset (rtx new, rtx reg, int offset) { - rtx new = gen_rtx_REG (mode, regno); tree decl; HOST_WIDE_INT var_size; @@ -869,7 +858,7 @@ gen_rtx_REG_offset (rtx reg, enum machine_mode mode, unsigned int regno, int off if ((BYTES_BIG_ENDIAN || WORDS_BIG_ENDIAN) && decl != NULL && offset > 0 - && GET_MODE_SIZE (GET_MODE (reg)) > GET_MODE_SIZE (mode) + && GET_MODE_SIZE (GET_MODE (reg)) > GET_MODE_SIZE (GET_MODE (new)) && ((var_size = int_size_in_bytes (TREE_TYPE (decl))) > 0 && var_size < GET_MODE_SIZE (GET_MODE (reg)))) { @@ -913,6 +902,30 @@ gen_rtx_REG_offset (rtx reg, enum machine_mode mode, unsigned int regno, int off REG_ATTRS (new) = get_reg_attrs (REG_EXPR (reg), REG_OFFSET (reg) + offset); +} + +/* Generate a register with same attributes as REG, but offsetted by + OFFSET. */ + +rtx +gen_rtx_REG_offset (rtx reg, enum machine_mode mode, unsigned int regno, + int offset) +{ + rtx new = gen_rtx_REG (mode, regno); + + update_reg_offset (new, reg, offset); + return new; +} + +/* Generate a new pseudo-register with the same attributes as REG, but + offsetted by OFFSET. */ + +rtx +gen_reg_rtx_offset (rtx reg, enum machine_mode mode, int offset) +{ + rtx new = gen_reg_rtx (mode); + + update_reg_offset (new, reg, offset); return new; } @@ -1137,7 +1150,7 @@ gen_lowpart_common (enum machine_mode mode, rtx x) return 0; /* Don't allow generating paradoxical FLOAT_MODE subregs. */ - if (GET_MODE_CLASS (mode) == MODE_FLOAT && msize > xsize) + if (SCALAR_FLOAT_MODE_P (mode) && msize > xsize) return 0; offset = subreg_lowpart_offset (mode, innermode); @@ -1467,13 +1480,15 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp, alias = get_alias_set (t); MEM_VOLATILE_P (ref) |= TYPE_VOLATILE (type); - MEM_IN_STRUCT_P (ref) = AGGREGATE_TYPE_P (type); + MEM_IN_STRUCT_P (ref) + = AGGREGATE_TYPE_P (type) || TREE_CODE (type) == COMPLEX_TYPE; MEM_POINTER (ref) = POINTER_TYPE_P (type); - MEM_NOTRAP_P (ref) = TREE_THIS_NOTRAP (t); /* If we are making an object of this type, or if this is a DECL, we know that it is a scalar if the type is not an aggregate. */ - if ((objectp || DECL_P (t)) && ! AGGREGATE_TYPE_P (type)) + if ((objectp || DECL_P (t)) + && ! AGGREGATE_TYPE_P (type) + && TREE_CODE (type) != COMPLEX_TYPE) MEM_SCALAR_P (ref) = 1; /* We can set the alignment from the type if we are making an object, @@ -1500,16 +1515,7 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp, the expression. */ if (! TYPE_P (t)) { - tree base = get_base_address (t); - if (base && DECL_P (base) - && TREE_READONLY (base) - && (TREE_STATIC (base) || DECL_EXTERNAL (base))) - { - tree base_type = TREE_TYPE (base); - gcc_assert (!(base_type && TYPE_NEEDS_CONSTRUCTING (base_type)) - || DECL_ARTIFICIAL (base)); - MEM_READONLY_P (ref) = 1; - } + tree base; if (TREE_THIS_VOLATILE (t)) MEM_VOLATILE_P (ref) = 1; @@ -1522,6 +1528,36 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp, || TREE_CODE (t) == SAVE_EXPR) t = TREE_OPERAND (t, 0); + /* We may look through structure-like accesses for the purposes of + examining TREE_THIS_NOTRAP, but not array-like accesses. */ + base = t; + while (TREE_CODE (base) == COMPONENT_REF + || TREE_CODE (base) == REALPART_EXPR + || TREE_CODE (base) == IMAGPART_EXPR + || TREE_CODE (base) == BIT_FIELD_REF) + base = TREE_OPERAND (base, 0); + + if (DECL_P (base)) + { + if (CODE_CONTAINS_STRUCT (TREE_CODE (base), TS_DECL_WITH_VIS)) + MEM_NOTRAP_P (ref) = !DECL_WEAK (base); + else + MEM_NOTRAP_P (ref) = 1; + } + else + MEM_NOTRAP_P (ref) = TREE_THIS_NOTRAP (base); + + base = get_base_address (base); + if (base && DECL_P (base) + && TREE_READONLY (base) + && (TREE_STATIC (base) || DECL_EXTERNAL (base))) + { + tree base_type = TREE_TYPE (base); + gcc_assert (!(base_type && TYPE_NEEDS_CONSTRUCTING (base_type)) + || DECL_ARTIFICIAL (base)); + MEM_READONLY_P (ref) = 1; + } + /* If this expression uses it's parent's alias set, mark it such that we won't change it. */ if (component_uses_parent_alias_set (t)) @@ -1585,8 +1621,9 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp, index, low_bound); off_tree = size_binop (PLUS_EXPR, - size_binop (MULT_EXPR, convert (sizetype, - index), + size_binop (MULT_EXPR, + fold_convert (sizetype, + index), unit_size), off_tree); t2 = TREE_OPERAND (t2, 0); @@ -2077,17 +2114,8 @@ set_new_first_and_last_insn (rtx first, rtx last) structure. This routine should only be called once. */ static void -unshare_all_rtl_1 (tree fndecl, rtx insn) +unshare_all_rtl_1 (rtx insn) { - tree decl; - - /* Make sure that virtual parameters are not shared. */ - for (decl = DECL_ARGUMENTS (fndecl); decl; decl = TREE_CHAIN (decl)) - SET_DECL_RTL (decl, copy_rtx_if_shared (DECL_RTL (decl))); - - /* Make sure that virtual stack slots are not shared. */ - unshare_all_decls (DECL_INITIAL (fndecl)); - /* Unshare just about everything else. */ unshare_all_rtl_in_chain (insn); @@ -2128,18 +2156,19 @@ unshare_all_rtl_again (rtx insn) reset_used_flags (stack_slot_list); - unshare_all_rtl_1 (cfun->decl, insn); + unshare_all_rtl_1 (insn); } -void +unsigned int unshare_all_rtl (void) { - unshare_all_rtl_1 (current_function_decl, get_insns ()); + unshare_all_rtl_1 (get_insns ()); + return 0; } struct tree_opt_pass pass_unshare_all_rtl = { - NULL, /* name */ + "unshare", /* name */ NULL, /* gate */ unshare_all_rtl, /* execute */ NULL, /* sub */ @@ -2150,7 +2179,7 @@ struct tree_opt_pass pass_unshare_all_rtl = 0, /* properties_provided */ 0, /* properties_destroyed */ 0, /* todo_flags_start */ - 0, /* todo_flags_finish */ + TODO_dump_func, /* todo_flags_finish */ 0 /* letter */ }; @@ -2279,6 +2308,20 @@ verify_rtl_sharing (void) reset_used_flags (PATTERN (p)); reset_used_flags (REG_NOTES (p)); reset_used_flags (LOG_LINKS (p)); + if (GET_CODE (PATTERN (p)) == SEQUENCE) + { + int i; + rtx q, sequence = PATTERN (p); + + for (i = 0; i < XVECLEN (sequence, 0); i++) + { + q = XVECEXP (sequence, 0, i); + gcc_assert (INSN_P (q)); + reset_used_flags (PATTERN (q)); + reset_used_flags (REG_NOTES (q)); + reset_used_flags (LOG_LINKS (q)); + } + } } for (p = get_insns (); p; p = NEXT_INSN (p)) @@ -2305,23 +2348,6 @@ unshare_all_rtl_in_chain (rtx insn) } } -/* Go through all virtual stack slots of a function and copy any - shared structure. */ -static void -unshare_all_decls (tree blk) -{ - tree t; - - /* Copy shared decls. */ - for (t = BLOCK_VARS (blk); t; t = TREE_CHAIN (t)) - if (DECL_RTL_SET_P (t)) - SET_DECL_RTL (t, copy_rtx_if_shared (DECL_RTL (t))); - - /* Now process sub-blocks. */ - for (t = BLOCK_SUBBLOCKS (blk); t; t = TREE_CHAIN (t)) - unshare_all_decls (t); -} - /* Go through all virtual stack slots of a function and mark them as not shared. */ static void @@ -2420,11 +2446,7 @@ repeat: if (RTX_FLAG (x, used)) { - rtx copy; - - copy = rtx_alloc (code); - memcpy (copy, x, RTX_SIZE (code)); - x = copy; + x = shallow_copy_rtx (x); copied = 1; } RTX_FLAG (x, used) = 1; @@ -2760,33 +2782,6 @@ get_max_uid (void) { return cur_insn_uid; } - -/* Renumber instructions so that no instruction UIDs are wasted. */ - -void -renumber_insns (FILE *stream) -{ - rtx insn; - - /* If we're not supposed to renumber instructions, don't. */ - if (!flag_renumber_insns) - return; - - /* If there aren't that many instructions, then it's not really - worth renumbering them. */ - if (flag_renumber_insns == 1 && get_max_uid () < 25000) - return; - - cur_insn_uid = 1; - - for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) - { - if (stream) - fprintf (stream, "Renumbering insn %d to %d\n", - INSN_UID (insn), cur_insn_uid); - INSN_UID (insn) = cur_insn_uid++; - } -} /* Return the next insn. If it is a SEQUENCE, return the first insn of the sequence. */ @@ -3055,6 +3050,37 @@ prev_cc0_setter (rtx insn) } #endif +#ifdef AUTO_INC_DEC +/* Find a RTX_AUTOINC class rtx which matches DATA. */ + +static int +find_auto_inc (rtx *xp, void *data) +{ + rtx x = *xp; + rtx reg = data; + + if (GET_RTX_CLASS (GET_CODE (x)) != RTX_AUTOINC) + return 0; + + switch (GET_CODE (x)) + { + case PRE_DEC: + case PRE_INC: + case POST_DEC: + case POST_INC: + case PRE_MODIFY: + case POST_MODIFY: + if (rtx_equal_p (reg, XEXP (x, 0))) + return 1; + break; + + default: + gcc_unreachable (); + } + return -1; +} +#endif + /* Increment the label uses for all labels present in rtx. */ static void @@ -3179,8 +3205,7 @@ try_split (rtx pat, rtx trial, int last) switch (REG_NOTE_KIND (note)) { case REG_EH_REGION: - insn = insn_last; - while (insn != NULL_RTX) + for (insn = insn_last; insn != NULL_RTX; insn = PREV_INSN (insn)) { if (CALL_P (insn) || (flag_non_call_exceptions && INSN_P (insn) @@ -3189,37 +3214,45 @@ try_split (rtx pat, rtx trial, int last) = gen_rtx_EXPR_LIST (REG_EH_REGION, XEXP (note, 0), REG_NOTES (insn)); - insn = PREV_INSN (insn); } break; case REG_NORETURN: case REG_SETJMP: - insn = insn_last; - while (insn != NULL_RTX) + for (insn = insn_last; insn != NULL_RTX; insn = PREV_INSN (insn)) { if (CALL_P (insn)) REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_NOTE_KIND (note), XEXP (note, 0), REG_NOTES (insn)); - insn = PREV_INSN (insn); } break; case REG_NON_LOCAL_GOTO: - insn = insn_last; - while (insn != NULL_RTX) + for (insn = insn_last; insn != NULL_RTX; insn = PREV_INSN (insn)) { if (JUMP_P (insn)) REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_NOTE_KIND (note), XEXP (note, 0), REG_NOTES (insn)); - insn = PREV_INSN (insn); } break; +#ifdef AUTO_INC_DEC + case REG_INC: + for (insn = insn_last; insn != NULL_RTX; insn = PREV_INSN (insn)) + { + rtx reg = XEXP (note, 0); + if (!FIND_REG_INC_NOTE (insn, reg) + && for_each_rtx (&PATTERN (insn), find_auto_inc, reg) > 0) + REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, reg, + REG_NOTES (insn)); + } + break; +#endif + default: break; } @@ -3276,7 +3309,7 @@ make_insn_raw (rtx pattern) INSN_CODE (insn) = -1; LOG_LINKS (insn) = NULL; REG_NOTES (insn) = NULL; - INSN_LOCATOR (insn) = 0; + INSN_LOCATOR (insn) = curr_insn_locator (); BLOCK_FOR_INSN (insn) = NULL; #ifdef ENABLE_RTL_CHECKING @@ -3296,7 +3329,7 @@ make_insn_raw (rtx pattern) /* Like `make_insn_raw' but make a JUMP_INSN instead of an insn. */ -static rtx +rtx make_jump_insn_raw (rtx pattern) { rtx insn; @@ -3309,7 +3342,7 @@ make_jump_insn_raw (rtx pattern) LOG_LINKS (insn) = NULL; REG_NOTES (insn) = NULL; JUMP_LABEL (insn) = NULL; - INSN_LOCATOR (insn) = 0; + INSN_LOCATOR (insn) = curr_insn_locator (); BLOCK_FOR_INSN (insn) = NULL; return insn; @@ -3330,7 +3363,7 @@ make_call_insn_raw (rtx pattern) LOG_LINKS (insn) = NULL; REG_NOTES (insn) = NULL; CALL_INSN_FUNCTION_USAGE (insn) = NULL; - INSN_LOCATOR (insn) = 0; + INSN_LOCATOR (insn) = curr_insn_locator (); BLOCK_FOR_INSN (insn) = NULL; return insn; @@ -3404,8 +3437,7 @@ add_insn_after (rtx insn, rtx after) if (BB_END (bb) == after /* Avoid clobbering of structure when creating new BB. */ && !BARRIER_P (insn) - && (!NOTE_P (insn) - || NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK)) + && !NOTE_INSN_BASIC_BLOCK_P (insn)) BB_END (bb) = insn; } @@ -3470,8 +3502,7 @@ add_insn_before (rtx insn, rtx before) gcc_assert (BB_HEAD (bb) != insn /* Avoid clobbering of structure when creating new BB. */ || BARRIER_P (insn) - || (NOTE_P (insn) - && NOTE_LINE_NUMBER (insn) == NOTE_INSN_BASIC_BLOCK)); + || NOTE_INSN_BASIC_BLOCK_P (insn)); } PREV_INSN (before) = insn; @@ -3653,95 +3684,6 @@ reorder_insns (rtx from, rtx to, rtx after) } } -/* Return the line note insn preceding INSN. */ - -static rtx -find_line_note (rtx insn) -{ - if (no_line_numbers) - return 0; - - for (; insn; insn = PREV_INSN (insn)) - if (NOTE_P (insn) - && NOTE_LINE_NUMBER (insn) >= 0) - break; - - return insn; -} - -/* Remove unnecessary notes from the instruction stream. */ - -void -remove_unnecessary_notes (void) -{ - rtx eh_stack = NULL_RTX; - rtx insn; - rtx next; - rtx tmp; - - /* We must not remove the first instruction in the function because - the compiler depends on the first instruction being a note. */ - for (insn = NEXT_INSN (get_insns ()); insn; insn = next) - { - /* Remember what's next. */ - next = NEXT_INSN (insn); - - /* We're only interested in notes. */ - if (!NOTE_P (insn)) - continue; - - switch (NOTE_LINE_NUMBER (insn)) - { - case NOTE_INSN_DELETED: - remove_insn (insn); - break; - - case NOTE_INSN_EH_REGION_BEG: - eh_stack = alloc_INSN_LIST (insn, eh_stack); - break; - - case NOTE_INSN_EH_REGION_END: - /* Too many end notes. */ - gcc_assert (eh_stack); - /* Mismatched nesting. */ - gcc_assert (NOTE_EH_HANDLER (XEXP (eh_stack, 0)) - == NOTE_EH_HANDLER (insn)); - tmp = eh_stack; - eh_stack = XEXP (eh_stack, 1); - free_INSN_LIST_node (tmp); - break; - - case NOTE_INSN_BLOCK_BEG: - case NOTE_INSN_BLOCK_END: - /* BLOCK_END and BLOCK_BEG notes only exist in the `final' pass. */ - gcc_unreachable (); - - default: - break; - } - } - - /* Too many EH_REGION_BEG notes. */ - gcc_assert (!eh_stack); -} - -struct tree_opt_pass pass_remove_unnecessary_notes = -{ - NULL, /* name */ - NULL, /* gate */ - remove_unnecessary_notes, /* execute */ - NULL, /* sub */ - NULL, /* next */ - 0, /* static_pass_number */ - 0, /* tv_id */ - 0, /* properties_required */ - 0, /* properties_provided */ - 0, /* properties_destroyed */ - 0, /* todo_flags_start */ - 0, /* todo_flags_finish */ - 0 /* letter */ -}; - /* Emit insn(s) of given code and pattern at a specified place within the doubly-linked list. @@ -3933,15 +3875,13 @@ emit_label_before (rtx label, rtx before) /* Emit a note of subtype SUBTYPE before the insn BEFORE. */ rtx -emit_note_before (int subtype, rtx before) +emit_note_before (enum insn_note subtype, rtx before) { rtx note = rtx_alloc (NOTE); INSN_UID (note) = cur_insn_uid++; -#ifndef USE_MAPPED_LOCATION - NOTE_SOURCE_FILE (note) = 0; -#endif - NOTE_LINE_NUMBER (note) = subtype; + NOTE_KIND (note) = subtype; BLOCK_FOR_INSN (note) = NULL; + memset (&NOTE_DATA (note), 0, sizeof (NOTE_DATA (note))); add_insn_before (note, before); return note; @@ -4026,22 +3966,6 @@ emit_insn_after_noloc (rtx x, rtx after) return last; } -/* Similar to emit_insn_after, except that line notes are to be inserted so - as to act as if this insn were at FROM. */ - -void -emit_insn_after_with_line_notes (rtx x, rtx after, rtx from) -{ - rtx from_line = find_line_note (from); - rtx after_line = find_line_note (after); - rtx insn = emit_insn_after (x, after); - - if (from_line) - emit_note_copy_after (from_line, after); - - if (after_line) - emit_note_copy_after (after_line, insn); -} /* Make an insn of code JUMP_INSN with body X and output it after the insn AFTER. */ @@ -4149,37 +4073,13 @@ emit_label_after (rtx label, rtx after) /* Emit a note of subtype SUBTYPE after the insn AFTER. */ rtx -emit_note_after (int subtype, rtx after) +emit_note_after (enum insn_note subtype, rtx after) { rtx note = rtx_alloc (NOTE); INSN_UID (note) = cur_insn_uid++; -#ifndef USE_MAPPED_LOCATION - NOTE_SOURCE_FILE (note) = 0; -#endif - NOTE_LINE_NUMBER (note) = subtype; - BLOCK_FOR_INSN (note) = NULL; - add_insn_after (note, after); - return note; -} - -/* Emit a copy of note ORIG after the insn AFTER. */ - -rtx -emit_note_copy_after (rtx orig, rtx after) -{ - rtx note; - - if (NOTE_LINE_NUMBER (orig) >= 0 && no_line_numbers) - { - cur_insn_uid++; - return 0; - } - - note = rtx_alloc (NOTE); - INSN_UID (note) = cur_insn_uid++; - NOTE_LINE_NUMBER (note) = NOTE_LINE_NUMBER (orig); - NOTE_DATA (note) = NOTE_DATA (orig); + NOTE_KIND (note) = subtype; BLOCK_FOR_INSN (note) = NULL; + memset (&NOTE_DATA (note), 0, sizeof (NOTE_DATA (note))); add_insn_after (note, after); return note; } @@ -4287,7 +4187,10 @@ emit_insn_before_setloc (rtx pattern, rtx before, int loc) if (pattern == NULL_RTX || !loc) return last; - first = NEXT_INSN (first); + if (!first) + first = get_insns (); + else + first = NEXT_INSN (first); while (1) { if (active_insn_p (first) && !INSN_LOCATOR (first)) @@ -4524,42 +4427,6 @@ emit_barrier (void) return barrier; } -/* Make line numbering NOTE insn for LOCATION add it to the end - of the doubly-linked list, but only if line-numbers are desired for - debugging info and it doesn't match the previous one. */ - -rtx -emit_line_note (location_t location) -{ - rtx note; - -#ifdef USE_MAPPED_LOCATION - if (location == last_location) - return NULL_RTX; -#else - if (location.file && last_location.file - && !strcmp (location.file, last_location.file) - && location.line == last_location.line) - return NULL_RTX; -#endif - last_location = location; - - if (no_line_numbers) - { - cur_insn_uid++; - return NULL_RTX; - } - -#ifdef USE_MAPPED_LOCATION - note = emit_note ((int) location); -#else - note = emit_note (location.line); - NOTE_SOURCE_FILE (note) = location.file; -#endif - - return note; -} - /* Emit a copy of note ORIG. */ rtx @@ -4567,17 +4434,11 @@ emit_note_copy (rtx orig) { rtx note; - if (NOTE_LINE_NUMBER (orig) >= 0 && no_line_numbers) - { - cur_insn_uid++; - return NULL_RTX; - } - note = rtx_alloc (NOTE); INSN_UID (note) = cur_insn_uid++; NOTE_DATA (note) = NOTE_DATA (orig); - NOTE_LINE_NUMBER (note) = NOTE_LINE_NUMBER (orig); + NOTE_KIND (note) = NOTE_KIND (orig); BLOCK_FOR_INSN (note) = NULL; add_insn (note); @@ -4588,13 +4449,13 @@ emit_note_copy (rtx orig) and add it to the end of the doubly-linked list. */ rtx -emit_note (int note_no) +emit_note (enum insn_note kind) { rtx note; note = rtx_alloc (NOTE); INSN_UID (note) = cur_insn_uid++; - NOTE_LINE_NUMBER (note) = note_no; + NOTE_KIND (note) = kind; memset (&NOTE_DATA (note), 0, sizeof (NOTE_DATA (note))); BLOCK_FOR_INSN (note) = NULL; add_insn (note); @@ -4842,7 +4703,7 @@ in_sequence_p (void) /* Put the various virtual registers into REGNO_REG_RTX. */ -void +static void init_virtual_regs (struct emit_status *es) { rtx *ptr = es->x_regno_reg_rtx; @@ -4931,13 +4792,11 @@ copy_insn_1 (rtx orig) break; } - copy = rtx_alloc (code); - - /* Copy the various flags, and other information. We assume that - all fields need copying, and then clear the fields that should + /* Copy the various flags, fields, and other information. We assume + that all fields need copying, and then clear the fields that should not be copied. That is the sensible default behavior, and forces us to explicitly document why we are *not* copying a flag. */ - memcpy (copy, orig, RTX_HDR_SIZE); + copy = shallow_copy_rtx (orig); /* We do not copy the USED flag, which is used as a mark bit during walks over the RTL. */ @@ -4954,43 +4813,40 @@ copy_insn_1 (rtx orig) format_ptr = GET_RTX_FORMAT (GET_CODE (copy)); for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++) - { - copy->u.fld[i] = orig->u.fld[i]; - switch (*format_ptr++) - { - case 'e': - if (XEXP (orig, i) != NULL) - XEXP (copy, i) = copy_insn_1 (XEXP (orig, i)); - break; + switch (*format_ptr++) + { + case 'e': + if (XEXP (orig, i) != NULL) + XEXP (copy, i) = copy_insn_1 (XEXP (orig, i)); + break; - case 'E': - case 'V': - if (XVEC (orig, i) == orig_asm_constraints_vector) - XVEC (copy, i) = copy_asm_constraints_vector; - else if (XVEC (orig, i) == orig_asm_operands_vector) - XVEC (copy, i) = copy_asm_operands_vector; - else if (XVEC (orig, i) != NULL) - { - XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i)); - for (j = 0; j < XVECLEN (copy, i); j++) - XVECEXP (copy, i, j) = copy_insn_1 (XVECEXP (orig, i, j)); - } - break; + case 'E': + case 'V': + if (XVEC (orig, i) == orig_asm_constraints_vector) + XVEC (copy, i) = copy_asm_constraints_vector; + else if (XVEC (orig, i) == orig_asm_operands_vector) + XVEC (copy, i) = copy_asm_operands_vector; + else if (XVEC (orig, i) != NULL) + { + XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i)); + for (j = 0; j < XVECLEN (copy, i); j++) + XVECEXP (copy, i, j) = copy_insn_1 (XVECEXP (orig, i, j)); + } + break; - case 't': - case 'w': - case 'i': - case 's': - case 'S': - case 'u': - case '0': - /* These are left unchanged. */ - break; + case 't': + case 'w': + case 'i': + case 's': + case 'S': + case 'u': + case '0': + /* These are left unchanged. */ + break; - default: - gcc_unreachable (); - } - } + default: + gcc_unreachable (); + } if (code == SCRATCH) { @@ -5106,6 +4962,8 @@ gen_const_vector (enum machine_mode mode, int constant) units = GET_MODE_NUNITS (mode); inner = GET_MODE_INNER (mode); + gcc_assert (!DECIMAL_FLOAT_MODE_P (inner)); + v = rtvec_alloc (units); /* We need to call this function after we set the scalar const_tiny_rtx @@ -5182,7 +5040,8 @@ init_emit_once (int line_numbers) word_mode = VOIDmode; double_mode = VOIDmode; - for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode; + for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); + mode != VOIDmode; mode = GET_MODE_WIDER_MODE (mode)) { if (GET_MODE_BITSIZE (mode) == BITS_PER_UNIT @@ -5194,7 +5053,8 @@ init_emit_once (int line_numbers) word_mode = mode; } - for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); mode != VOIDmode; + for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); + mode != VOIDmode; mode = GET_MODE_WIDER_MODE (mode)) { if (GET_MODE_BITSIZE (mode) == DOUBLE_TYPE_SIZE @@ -5269,8 +5129,8 @@ init_emit_once (int line_numbers) /* Initialize mathematical constants for constant folding builtins. These constants need to be given to at least 160 bits precision. */ - real_from_string (&dconstpi, - "3.1415926535897932384626433832795028841971693993751058209749445923078"); + real_from_string (&dconstsqrt2, + "1.4142135623730950488016887242096980785696718753769480731766797379907"); real_from_string (&dconste, "2.7182818284590452353602874713526624977572470936999595749669676277241"); @@ -5279,14 +5139,22 @@ init_emit_once (int line_numbers) REAL_VALUE_TYPE *r = (i == 0 ? &dconst0 : i == 1 ? &dconst1 : &dconst2); - for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); mode != VOIDmode; + for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); + mode != VOIDmode; + mode = GET_MODE_WIDER_MODE (mode)) + const_tiny_rtx[i][(int) mode] = + CONST_DOUBLE_FROM_REAL_VALUE (*r, mode); + + for (mode = GET_CLASS_NARROWEST_MODE (MODE_DECIMAL_FLOAT); + mode != VOIDmode; mode = GET_MODE_WIDER_MODE (mode)) const_tiny_rtx[i][(int) mode] = CONST_DOUBLE_FROM_REAL_VALUE (*r, mode); const_tiny_rtx[i][(int) VOIDmode] = GEN_INT (i); - for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode; + for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); + mode != VOIDmode; mode = GET_MODE_WIDER_MODE (mode)) const_tiny_rtx[i][(int) mode] = GEN_INT (i); @@ -5400,14 +5268,12 @@ emit_copy_of_insn_after (rtx insn, rtx after) { if (GET_CODE (link) == EXPR_LIST) REG_NOTES (new) - = copy_insn_1 (gen_rtx_EXPR_LIST (REG_NOTE_KIND (link), - XEXP (link, 0), - REG_NOTES (new))); + = gen_rtx_EXPR_LIST (REG_NOTE_KIND (link), + copy_insn_1 (XEXP (link, 0)), REG_NOTES (new)); else REG_NOTES (new) - = copy_insn_1 (gen_rtx_INSN_LIST (REG_NOTE_KIND (link), - XEXP (link, 0), - REG_NOTES (new))); + = gen_rtx_INSN_LIST (REG_NOTE_KIND (link), + XEXP (link, 0), REG_NOTES (new)); } /* Fix the libcall sequences. */