X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Femit-rtl.c;h=803f740168228ea921ac10cb6a64289437ce55a1;hb=06f0b99c264712365d4142ee12ae9e8133b2f4c0;hp=afd3a401a25f7502a5af19172f8b220627b27e19;hpb=ad4583d978292a368c345f43dc85ede2c0e0e498;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c index afd3a401a25..803f7401682 100644 --- a/gcc/emit-rtl.c +++ b/gcc/emit-rtl.c @@ -7,7 +7,7 @@ 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 2, or (at your option) any later +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 @@ -16,9 +16,8 @@ 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 COPYING. If not, write to the Free -Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301, USA. */ +along with GCC; see the file COPYING3. If not see +. */ /* Middle-to-low level generation of rtx code and insns. @@ -51,12 +50,14 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "insn-config.h" #include "recog.h" #include "real.h" +#include "fixed-value.h" #include "bitmap.h" #include "basic-block.h" #include "ggc.h" #include "debug.h" #include "langhooks.h" #include "tree-pass.h" +#include "df.h" /* Commonly used modes. */ @@ -108,6 +109,10 @@ REAL_VALUE_TYPE dconstthird; REAL_VALUE_TYPE dconstsqrt2; REAL_VALUE_TYPE dconste; +/* Record fixed-point constant 0 and 1. */ +FIXED_VALUE_TYPE fconst0[MAX_FCONST0]; +FIXED_VALUE_TYPE fconst1[MAX_FCONST1]; + /* All references to the following fixed hard registers go through these unique rtl objects. On machines where the frame-pointer and arg-pointer are the same register, they use the same unique object. @@ -167,7 +172,7 @@ static GTY ((if_marked ("ggc_marked_p"), param_is (struct rtx_def))) static rtx make_call_insn_raw (rtx); static rtx change_address_1 (rtx, enum machine_mode, rtx, int); -static void reset_used_decls (tree); +static void set_used_decls (tree); static void mark_label_nuses (rtx); static hashval_t const_int_htab_hash (const void *); static int const_int_htab_eq (const void *, const void *); @@ -194,7 +199,7 @@ int split_branch_probability = -1; static hashval_t const_int_htab_hash (const void *x) { - return (hashval_t) INTVAL ((rtx) x); + return (hashval_t) INTVAL ((const_rtx) x); } /* Returns nonzero if the value represented by X (which is really a @@ -204,14 +209,14 @@ const_int_htab_hash (const void *x) static int const_int_htab_eq (const void *x, const void *y) { - return (INTVAL ((rtx) x) == *((const HOST_WIDE_INT *) y)); + return (INTVAL ((const_rtx) x) == *((const HOST_WIDE_INT *) y)); } /* Returns a hash code for X (which is really a CONST_DOUBLE). */ static hashval_t const_double_htab_hash (const void *x) { - rtx value = (rtx) x; + const_rtx const value = (const_rtx) x; hashval_t h; if (GET_MODE (value) == VOIDmode) @@ -230,7 +235,7 @@ const_double_htab_hash (const void *x) static int const_double_htab_eq (const void *x, const void *y) { - rtx a = (rtx)x, b = (rtx)y; + const_rtx const a = (const_rtx)x, b = (const_rtx)y; if (GET_MODE (a) != GET_MODE (b)) return 0; @@ -247,7 +252,7 @@ const_double_htab_eq (const void *x, const void *y) static hashval_t mem_attrs_htab_hash (const void *x) { - mem_attrs *p = (mem_attrs *) x; + const mem_attrs *const p = (const mem_attrs *) x; return (p->alias ^ (p->align * 1000) ^ ((p->offset ? INTVAL (p->offset) : 0) * 50000) @@ -262,8 +267,8 @@ mem_attrs_htab_hash (const void *x) static int mem_attrs_htab_eq (const void *x, const void *y) { - mem_attrs *p = (mem_attrs *) x; - mem_attrs *q = (mem_attrs *) y; + const mem_attrs *const p = (const mem_attrs *) x; + const mem_attrs *const q = (const mem_attrs *) y; return (p->alias == q->alias && p->offset == q->offset && p->size == q->size && p->align == q->align @@ -314,7 +319,7 @@ get_mem_attrs (HOST_WIDE_INT alias, tree expr, rtx offset, rtx size, static hashval_t reg_attrs_htab_hash (const void *x) { - reg_attrs *p = (reg_attrs *) x; + const reg_attrs *const p = (const reg_attrs *) x; return ((p->offset * 1000) ^ (long) p->decl); } @@ -326,8 +331,8 @@ reg_attrs_htab_hash (const void *x) static int reg_attrs_htab_eq (const void *x, const void *y) { - reg_attrs *p = (reg_attrs *) x; - reg_attrs *q = (reg_attrs *) y; + const reg_attrs *const p = (const reg_attrs *) x; + const reg_attrs *const q = (const reg_attrs *) y; return (p->decl == q->decl && p->offset == q->offset); } @@ -358,6 +363,21 @@ get_reg_attrs (tree decl, int offset) return *slot; } + +#if !HAVE_blockage +/* Generate an empty ASM_INPUT, which is used to block attempts to schedule + across this insn. */ + +rtx +gen_blockage (void) +{ + rtx x = gen_rtx_ASM_INPUT (VOIDmode, ""); + MEM_VOLATILE_P (x) = true; + return x; +} +#endif + + /* Generate a new REG rtx. Make sure ORIGINAL_REGNO is set properly, and don't attempt to share with the various global pieces of rtl (such as frame_pointer_rtx). */ @@ -764,9 +784,7 @@ gen_reg_rtx (enum machine_mode mode) struct function *f = cfun; rtx val; - /* Don't let anything called after initial flow analysis create new - registers. */ - gcc_assert (!no_new_pseudos); + gcc_assert (can_create_pseudo_p ()); if (generating_concat_p && (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT @@ -1270,7 +1288,7 @@ subreg_highpart_offset (enum machine_mode outermode, enum machine_mode innermode If X is not a SUBREG, always return 1 (it is its own low part!). */ int -subreg_lowpart_p (rtx x) +subreg_lowpart_p (const_rtx x) { if (GET_CODE (x) != SUBREG) return 1; @@ -1412,7 +1430,7 @@ component_ref_for_mem_expr (tree ref) and 0 otherwise. */ int -mem_expr_equal_p (tree expr1, tree expr2) +mem_expr_equal_p (const_tree expr1, const_tree expr2) { if (expr1 == expr2) return 1; @@ -2144,15 +2162,14 @@ unshare_all_rtl_again (rtx insn) { reset_used_flags (PATTERN (p)); reset_used_flags (REG_NOTES (p)); - reset_used_flags (LOG_LINKS (p)); } /* Make sure that virtual stack slots are not shared. */ - reset_used_decls (DECL_INITIAL (cfun->decl)); + set_used_decls (DECL_INITIAL (cfun->decl)); /* Make sure that virtual parameters are not shared. */ for (decl = DECL_ARGUMENTS (cfun->decl); decl; decl = TREE_CHAIN (decl)) - reset_used_flags (DECL_RTL (decl)); + set_used_flags (DECL_RTL (decl)); reset_used_flags (stack_slot_list); @@ -2222,11 +2239,7 @@ verify_rtx_sharing (rtx orig, rtx insn) break; case CONST: - /* CONST can be shared if it contains a SYMBOL_REF. If it contains - a LABEL_REF, it isn't sharable. */ - if (GET_CODE (XEXP (x, 0)) == PLUS - && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF - && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT) + if (shared_const_p (orig)) return; break; @@ -2307,7 +2320,6 @@ 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; @@ -2319,7 +2331,6 @@ verify_rtl_sharing (void) gcc_assert (INSN_P (q)); reset_used_flags (PATTERN (q)); reset_used_flags (REG_NOTES (q)); - reset_used_flags (LOG_LINKS (q)); } } } @@ -2329,7 +2340,6 @@ verify_rtl_sharing (void) { verify_rtx_sharing (PATTERN (p), p); verify_rtx_sharing (REG_NOTES (p), p); - verify_rtx_sharing (LOG_LINKS (p), p); } } @@ -2344,25 +2354,32 @@ unshare_all_rtl_in_chain (rtx insn) { PATTERN (insn) = copy_rtx_if_shared (PATTERN (insn)); REG_NOTES (insn) = copy_rtx_if_shared (REG_NOTES (insn)); - LOG_LINKS (insn) = copy_rtx_if_shared (LOG_LINKS (insn)); } } /* Go through all virtual stack slots of a function and mark them as - not shared. */ + shared. We never replace the DECL_RTLs themselves with a copy, + but expressions mentioned into a DECL_RTL cannot be shared with + expressions in the instruction stream. + + Note that reload may convert pseudo registers into memories in-place. + Pseudo registers are always shared, but MEMs never are. Thus if we + reset the used flags on MEMs in the instruction stream, we must set + them again on MEMs that appear in DECL_RTLs. */ + static void -reset_used_decls (tree blk) +set_used_decls (tree blk) { tree t; /* Mark decls. */ for (t = BLOCK_VARS (blk); t; t = TREE_CHAIN (t)) if (DECL_RTL_SET_P (t)) - reset_used_flags (DECL_RTL (t)); + set_used_flags (DECL_RTL (t)); /* Now process sub-blocks. */ for (t = BLOCK_SUBBLOCKS (blk); t; t = TREE_CHAIN (t)) - reset_used_decls (t); + set_used_decls (t); } /* Mark ORIG as in use, and return a copy of it if it was already in use. @@ -2421,11 +2438,7 @@ repeat: break; case CONST: - /* CONST can be shared if it contains a SYMBOL_REF. If it contains - a LABEL_REF, it isn't sharable. */ - if (GET_CODE (XEXP (x, 0)) == PLUS - && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF - && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT) + if (shared_const_p (x)) return; break; @@ -2904,7 +2917,7 @@ last_call_insn (void) same as next_real_insn. */ int -active_insn_p (rtx insn) +active_insn_p (const_rtx insn) { return (CALL_P (insn) || JUMP_P (insn) || (NONJUMP_INSN_P (insn) @@ -3160,6 +3173,10 @@ try_split (rtx pat, rtx trial, int last) insn_last = NEXT_INSN (insn_last); } + /* We will be adding the new sequence to the function. The splitters + may have introduced invalid RTL sharing, so unshare the sequence now. */ + unshare_all_rtl_in_chain (seq); + /* Mark labels. */ for (insn = insn_last; insn ; insn = PREV_INSN (insn)) { @@ -3307,7 +3324,6 @@ make_insn_raw (rtx pattern) INSN_UID (insn) = cur_insn_uid++; PATTERN (insn) = pattern; INSN_CODE (insn) = -1; - LOG_LINKS (insn) = NULL; REG_NOTES (insn) = NULL; INSN_LOCATOR (insn) = curr_insn_locator (); BLOCK_FOR_INSN (insn) = NULL; @@ -3339,7 +3355,6 @@ make_jump_insn_raw (rtx pattern) PATTERN (insn) = pattern; INSN_CODE (insn) = -1; - LOG_LINKS (insn) = NULL; REG_NOTES (insn) = NULL; JUMP_LABEL (insn) = NULL; INSN_LOCATOR (insn) = curr_insn_locator (); @@ -3360,7 +3375,6 @@ make_call_insn_raw (rtx pattern) PATTERN (insn) = pattern; INSN_CODE (insn) = -1; - LOG_LINKS (insn) = NULL; REG_NOTES (insn) = NULL; CALL_INSN_FUNCTION_USAGE (insn) = NULL; INSN_LOCATOR (insn) = curr_insn_locator (); @@ -3393,10 +3407,9 @@ add_insn (rtx insn) SEQUENCE. */ void -add_insn_after (rtx insn, rtx after) +add_insn_after (rtx insn, rtx after, basic_block bb) { rtx next = NEXT_INSN (after); - basic_block bb; gcc_assert (!optimize || !INSN_DELETED_P (after)); @@ -3431,7 +3444,7 @@ add_insn_after (rtx insn, rtx after) { set_block_for_insn (insn, bb); if (INSN_P (insn)) - bb->flags |= BB_DIRTY; + df_insn_rescan (insn); /* Should not happen as first in the BB is always either NOTE or LABEL. */ if (BB_END (bb) == after @@ -3450,15 +3463,15 @@ add_insn_after (rtx insn, rtx after) } /* Add INSN into the doubly-linked list before insn BEFORE. This and - the previous should be the only functions called to insert an insn once - delay slots have been filled since only they know how to update a - SEQUENCE. */ + the previous should be the only functions called to insert an insn + once delay slots have been filled since only they know how to + update a SEQUENCE. If BB is NULL, an attempt is made to infer the + bb from before. */ void -add_insn_before (rtx insn, rtx before) +add_insn_before (rtx insn, rtx before, basic_block bb) { rtx prev = PREV_INSN (before); - basic_block bb; gcc_assert (!optimize || !INSN_DELETED_P (before)); @@ -3490,13 +3503,16 @@ add_insn_before (rtx insn, rtx before) gcc_assert (stack); } - if (!BARRIER_P (before) - && !BARRIER_P (insn) - && (bb = BLOCK_FOR_INSN (before))) + if (!bb + && !BARRIER_P (before) + && !BARRIER_P (insn)) + bb = BLOCK_FOR_INSN (before); + + if (bb) { set_block_for_insn (insn, bb); if (INSN_P (insn)) - bb->flags |= BB_DIRTY; + df_insn_rescan (insn); /* Should not happen as first in the BB is always either NOTE or LABEL. */ gcc_assert (BB_HEAD (bb) != insn @@ -3510,6 +3526,17 @@ add_insn_before (rtx insn, rtx before) PREV_INSN (XVECEXP (PATTERN (before), 0, 0)) = insn; } + +/* Replace insn with an deleted instruction note. */ + +void set_insn_deleted (rtx insn) +{ + df_insn_delete (BLOCK_FOR_INSN (insn), INSN_UID (insn)); + PUT_CODE (insn, NOTE); + NOTE_KIND (insn) = NOTE_INSN_DELETED; +} + + /* Remove an insn from its doubly-linked list. This function knows how to handle sequences. */ void @@ -3519,6 +3546,9 @@ remove_insn (rtx insn) rtx prev = PREV_INSN (insn); basic_block bb; + /* Later in the code, the block will be marked dirty. */ + df_insn_delete (NULL, INSN_UID (insn)); + if (prev) { NEXT_INSN (prev) = next; @@ -3569,7 +3599,7 @@ remove_insn (rtx insn) && (bb = BLOCK_FOR_INSN (insn))) { if (INSN_P (insn)) - bb->flags |= BB_DIRTY; + df_set_bb_dirty (bb); if (BB_HEAD (bb) == insn) { /* Never ever delete the basic block note without deleting whole @@ -3665,14 +3695,14 @@ reorder_insns (rtx from, rtx to, rtx after) && (bb = BLOCK_FOR_INSN (after))) { rtx x; - bb->flags |= BB_DIRTY; + df_set_bb_dirty (bb); if (!BARRIER_P (from) && (bb2 = BLOCK_FOR_INSN (from))) { if (BB_END (bb2) == to) BB_END (bb2) = prev; - bb2->flags |= BB_DIRTY; + df_set_bb_dirty (bb2); } if (BB_END (bb) == after) @@ -3680,7 +3710,10 @@ reorder_insns (rtx from, rtx to, rtx after) for (x = from; x != NEXT_INSN (to); x = NEXT_INSN (x)) if (!BARRIER_P (x)) - set_block_for_insn (x, bb); + { + set_block_for_insn (x, bb); + df_insn_change_bb (x); + } } } @@ -3713,7 +3746,7 @@ reorder_insns (rtx from, rtx to, rtx after) /* Make X be output before the instruction BEFORE. */ rtx -emit_insn_before_noloc (rtx x, rtx before) +emit_insn_before_noloc (rtx x, rtx before, basic_block bb) { rtx last = before; rtx insn; @@ -3735,7 +3768,7 @@ emit_insn_before_noloc (rtx x, rtx before) while (insn) { rtx next = NEXT_INSN (insn); - add_insn_before (insn, before); + add_insn_before (insn, before, bb); last = insn; insn = next; } @@ -3749,7 +3782,7 @@ emit_insn_before_noloc (rtx x, rtx before) default: last = make_insn_raw (x); - add_insn_before (last, before); + add_insn_before (last, before, bb); break; } @@ -3778,7 +3811,7 @@ emit_jump_insn_before_noloc (rtx x, rtx before) while (insn) { rtx next = NEXT_INSN (insn); - add_insn_before (insn, before); + add_insn_before (insn, before, NULL); last = insn; insn = next; } @@ -3792,7 +3825,7 @@ emit_jump_insn_before_noloc (rtx x, rtx before) default: last = make_jump_insn_raw (x); - add_insn_before (last, before); + add_insn_before (last, before, NULL); break; } @@ -3821,7 +3854,7 @@ emit_call_insn_before_noloc (rtx x, rtx before) while (insn) { rtx next = NEXT_INSN (insn); - add_insn_before (insn, before); + add_insn_before (insn, before, NULL); last = insn; insn = next; } @@ -3835,7 +3868,7 @@ emit_call_insn_before_noloc (rtx x, rtx before) default: last = make_call_insn_raw (x); - add_insn_before (last, before); + add_insn_before (last, before, NULL); break; } @@ -3852,7 +3885,7 @@ emit_barrier_before (rtx before) INSN_UID (insn) = cur_insn_uid++; - add_insn_before (insn, before); + add_insn_before (insn, before, NULL); return insn; } @@ -3866,7 +3899,7 @@ emit_label_before (rtx label, rtx before) if (INSN_UID (label) == 0) { INSN_UID (label) = cur_insn_uid++; - add_insn_before (label, before); + add_insn_before (label, before, NULL); } return label; @@ -3881,32 +3914,37 @@ emit_note_before (enum insn_note subtype, rtx before) INSN_UID (note) = cur_insn_uid++; NOTE_KIND (note) = subtype; BLOCK_FOR_INSN (note) = NULL; + memset (&NOTE_DATA (note), 0, sizeof (NOTE_DATA (note))); - add_insn_before (note, before); + add_insn_before (note, before, NULL); return note; } /* Helper for emit_insn_after, handles lists of instructions efficiently. */ -static rtx emit_insn_after_1 (rtx, rtx); - static rtx -emit_insn_after_1 (rtx first, rtx after) +emit_insn_after_1 (rtx first, rtx after, basic_block bb) { rtx last; rtx after_after; - basic_block bb; + if (!bb && !BARRIER_P (after)) + bb = BLOCK_FOR_INSN (after); - if (!BARRIER_P (after) - && (bb = BLOCK_FOR_INSN (after))) + if (bb) { - bb->flags |= BB_DIRTY; + df_set_bb_dirty (bb); for (last = first; NEXT_INSN (last); last = NEXT_INSN (last)) if (!BARRIER_P (last)) - set_block_for_insn (last, bb); + { + set_block_for_insn (last, bb); + df_insn_rescan (last); + } if (!BARRIER_P (last)) - set_block_for_insn (last, bb); + { + set_block_for_insn (last, bb); + df_insn_rescan (last); + } if (BB_END (bb) == after) BB_END (bb) = last; } @@ -3927,10 +3965,11 @@ emit_insn_after_1 (rtx first, rtx after) return last; } -/* Make X be output after the insn AFTER. */ +/* Make X be output after the insn AFTER and set the BB of insn. If + BB is NULL, an attempt is made to infer the BB from AFTER. */ rtx -emit_insn_after_noloc (rtx x, rtx after) +emit_insn_after_noloc (rtx x, rtx after, basic_block bb) { rtx last = after; @@ -3947,7 +3986,7 @@ emit_insn_after_noloc (rtx x, rtx after) case CODE_LABEL: case BARRIER: case NOTE: - last = emit_insn_after_1 (x, after); + last = emit_insn_after_1 (x, after, bb); break; #ifdef ENABLE_RTL_CHECKING @@ -3958,7 +3997,7 @@ emit_insn_after_noloc (rtx x, rtx after) default: last = make_insn_raw (x); - add_insn_after (last, after); + add_insn_after (last, after, bb); break; } @@ -3984,7 +4023,7 @@ emit_jump_insn_after_noloc (rtx x, rtx after) case CODE_LABEL: case BARRIER: case NOTE: - last = emit_insn_after_1 (x, after); + last = emit_insn_after_1 (x, after, NULL); break; #ifdef ENABLE_RTL_CHECKING @@ -3995,7 +4034,7 @@ emit_jump_insn_after_noloc (rtx x, rtx after) default: last = make_jump_insn_raw (x); - add_insn_after (last, after); + add_insn_after (last, after, NULL); break; } @@ -4020,7 +4059,7 @@ emit_call_insn_after_noloc (rtx x, rtx after) case CODE_LABEL: case BARRIER: case NOTE: - last = emit_insn_after_1 (x, after); + last = emit_insn_after_1 (x, after, NULL); break; #ifdef ENABLE_RTL_CHECKING @@ -4031,7 +4070,7 @@ emit_call_insn_after_noloc (rtx x, rtx after) default: last = make_call_insn_raw (x); - add_insn_after (last, after); + add_insn_after (last, after, NULL); break; } @@ -4048,7 +4087,7 @@ emit_barrier_after (rtx after) INSN_UID (insn) = cur_insn_uid++; - add_insn_after (insn, after); + add_insn_after (insn, after, NULL); return insn; } @@ -4063,7 +4102,7 @@ emit_label_after (rtx label, rtx after) if (INSN_UID (label) == 0) { INSN_UID (label) = cur_insn_uid++; - add_insn_after (label, after); + add_insn_after (label, after, NULL); } return label; @@ -4078,7 +4117,8 @@ emit_note_after (enum insn_note subtype, rtx after) INSN_UID (note) = cur_insn_uid++; NOTE_KIND (note) = subtype; BLOCK_FOR_INSN (note) = NULL; - add_insn_after (note, after); + memset (&NOTE_DATA (note), 0, sizeof (NOTE_DATA (note))); + add_insn_after (note, after, NULL); return note; } @@ -4086,7 +4126,7 @@ emit_note_after (enum insn_note subtype, rtx after) rtx emit_insn_after_setloc (rtx pattern, rtx after, int loc) { - rtx last = emit_insn_after_noloc (pattern, after); + rtx last = emit_insn_after_noloc (pattern, after, NULL); if (pattern == NULL_RTX || !loc) return last; @@ -4110,7 +4150,7 @@ emit_insn_after (rtx pattern, rtx after) if (INSN_P (after)) return emit_insn_after_setloc (pattern, after, INSN_LOCATOR (after)); else - return emit_insn_after_noloc (pattern, after); + return emit_insn_after_noloc (pattern, after, NULL); } /* Like emit_jump_insn_after_noloc, but set INSN_LOCATOR according to SCOPE. */ @@ -4180,7 +4220,7 @@ rtx emit_insn_before_setloc (rtx pattern, rtx before, int loc) { rtx first = PREV_INSN (before); - rtx last = emit_insn_before_noloc (pattern, before); + rtx last = emit_insn_before_noloc (pattern, before, NULL); if (pattern == NULL_RTX || !loc) return last; @@ -4207,7 +4247,7 @@ emit_insn_before (rtx pattern, rtx before) if (INSN_P (before)) return emit_insn_before_setloc (pattern, before, INSN_LOCATOR (before)); else - return emit_insn_before_noloc (pattern, before); + return emit_insn_before_noloc (pattern, before, NULL); } /* like emit_insn_before_noloc, but set insn_locator according to scope. */ @@ -4480,6 +4520,7 @@ rtx set_unique_reg_note (rtx insn, enum reg_note kind, rtx datum) { rtx note = find_reg_note (insn, kind, NULL_RTX); + rtx new_note = NULL; switch (kind) { @@ -4499,19 +4540,37 @@ set_unique_reg_note (rtx insn, enum reg_note kind, rtx datum) It serves no useful purpose and breaks eliminate_regs. */ if (GET_CODE (datum) == ASM_OPERANDS) return NULL_RTX; + + if (note) + { + XEXP (note, 0) = datum; + df_notes_rescan (insn); + return note; + } break; default: + if (note) + { + XEXP (note, 0) = datum; + return note; + } break; } - if (note) + new_note = gen_rtx_EXPR_LIST (kind, datum, REG_NOTES (insn)); + REG_NOTES (insn) = new_note; + + switch (kind) { - XEXP (note, 0) = datum; - return note; + case REG_EQUAL: + case REG_EQUIV: + df_notes_rescan (insn); + break; + default: + break; } - REG_NOTES (insn) = gen_rtx_EXPR_LIST (kind, datum, REG_NOTES (insn)); return REG_NOTES (insn); } @@ -4630,6 +4689,18 @@ push_to_sequence (rtx first) last_insn = last; } +/* Like push_to_sequence, but take the last insn as an argument to avoid + looping through the list. */ + +void +push_to_sequence2 (rtx first, rtx last) +{ + start_sequence (); + + first_insn = first; + last_insn = last; +} + /* Set up the outer-level insn chain as the current sequence, saving the previously current one. */ @@ -4773,11 +4844,7 @@ copy_insn_1 (rtx orig) break; case CONST: - /* CONST can be shared if it contains a SYMBOL_REF. If it contains - a LABEL_REF, it isn't sharable. */ - if (GET_CODE (XEXP (orig, 0)) == PLUS - && GET_CODE (XEXP (XEXP (orig, 0), 0)) == SYMBOL_REF - && GET_CODE (XEXP (XEXP (orig, 0), 1)) == CONST_INT) + if (shared_const_p (orig)) return orig; break; @@ -5162,6 +5229,22 @@ init_emit_once (int line_numbers) const_tiny_rtx[i][(int) mode] = GEN_INT (i); } + for (mode = GET_CLASS_NARROWEST_MODE (MODE_COMPLEX_INT); + mode != VOIDmode; + mode = GET_MODE_WIDER_MODE (mode)) + { + rtx inner = const_tiny_rtx[0][(int)GET_MODE_INNER (mode)]; + const_tiny_rtx[0][(int) mode] = gen_rtx_CONCAT (mode, inner, inner); + } + + for (mode = GET_CLASS_NARROWEST_MODE (MODE_COMPLEX_FLOAT); + mode != VOIDmode; + mode = GET_MODE_WIDER_MODE (mode)) + { + rtx inner = const_tiny_rtx[0][(int)GET_MODE_INNER (mode)]; + const_tiny_rtx[0][(int) mode] = gen_rtx_CONCAT (mode, inner, inner); + } + for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_INT); mode != VOIDmode; mode = GET_MODE_WIDER_MODE (mode)) @@ -5178,6 +5261,62 @@ init_emit_once (int line_numbers) const_tiny_rtx[1][(int) mode] = gen_const_vector (mode, 1); } + for (mode = GET_CLASS_NARROWEST_MODE (MODE_FRACT); + mode != VOIDmode; + mode = GET_MODE_WIDER_MODE (mode)) + { + FCONST0(mode).data.high = 0; + FCONST0(mode).data.low = 0; + FCONST0(mode).mode = mode; + } + + for (mode = GET_CLASS_NARROWEST_MODE (MODE_UFRACT); + mode != VOIDmode; + mode = GET_MODE_WIDER_MODE (mode)) + { + FCONST0(mode).data.high = 0; + FCONST0(mode).data.low = 0; + FCONST0(mode).mode = mode; + } + + for (mode = GET_CLASS_NARROWEST_MODE (MODE_ACCUM); + mode != VOIDmode; + mode = GET_MODE_WIDER_MODE (mode)) + { + FCONST0(mode).data.high = 0; + FCONST0(mode).data.low = 0; + FCONST0(mode).mode = mode; + + /* We store the value 1. */ + FCONST1(mode).data.high = 0; + FCONST1(mode).data.low = 0; + FCONST1(mode).mode = mode; + lshift_double (1, 0, GET_MODE_FBIT (mode), + 2 * HOST_BITS_PER_WIDE_INT, + &FCONST1(mode).data.low, + &FCONST1(mode).data.high, + SIGNED_FIXED_POINT_MODE_P (mode)); + } + + for (mode = GET_CLASS_NARROWEST_MODE (MODE_UACCUM); + mode != VOIDmode; + mode = GET_MODE_WIDER_MODE (mode)) + { + FCONST0(mode).data.high = 0; + FCONST0(mode).data.low = 0; + FCONST0(mode).mode = mode; + + /* We store the value 1. */ + FCONST1(mode).data.high = 0; + FCONST1(mode).data.low = 0; + FCONST1(mode).mode = mode; + lshift_double (1, 0, GET_MODE_FBIT (mode), + 2 * HOST_BITS_PER_WIDE_INT, + &FCONST1(mode).data.low, + &FCONST1(mode).data.high, + SIGNED_FIXED_POINT_MODE_P (mode)); + } + for (i = (int) CCmode; i < (int) MAX_MACHINE_MODE; ++i) if (GET_MODE_CLASS ((enum machine_mode) i) == MODE_CC) const_tiny_rtx[0][i] = const0_rtx;