X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Femit-rtl.c;h=6e1f9490614e3c3069f7acafbd5fb863dc0eca3d;hb=149405350be50c105b4b0e97a57f745006318f76;hp=5b42f4a87786e3c0f405760c7212cbb5f4236865;hpb=3a4438438e8c85036b3cf79cbbf030f0d726db88;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c index 5b42f4a8778..6e1f9490614 100644 --- a/gcc/emit-rtl.c +++ b/gcc/emit-rtl.c @@ -58,6 +58,8 @@ along with GCC; see the file COPYING3. If not see #include "langhooks.h" #include "tree-pass.h" #include "df.h" +#include "params.h" +#include "target.h" /* Commonly used modes. */ @@ -71,7 +73,7 @@ enum machine_mode ptr_mode; /* Mode whose width is POINTER_SIZE. */ struct rtl_data x_rtl; /* Indexed by pseudo register number, gives the rtx for that pseudo. - Allocated in parallel with regno_pointer_align. + Allocated in parallel with regno_pointer_align. FIXME: We could put it into emit_status struct, but gengtype is not able to deal with length attribute nested in top level structures. */ @@ -82,10 +84,6 @@ rtx * regno_reg_rtx; static GTY(()) int label_num = 1; -/* Nonzero means do not generate NOTEs for source line numbers. */ - -static int no_line_numbers; - /* Commonly used rtx's, so that we only need space for one copy. These are initialized once for the entire compilation. All of these are unique; no other rtx-object will be equal to any @@ -135,8 +133,6 @@ FIXED_VALUE_TYPE fconst1[MAX_FCONST1]; In an inline procedure, the stack and frame pointer rtxs may not be used for anything else. */ -rtx static_chain_rtx; /* (REG:Pmode STATIC_CHAIN_REGNUM) */ -rtx static_chain_incoming_rtx; /* (REG:Pmode STATIC_CHAIN_INCOMING_REGNUM) */ rtx pic_offset_table_rtx; /* (REG:Pmode PIC_OFFSET_TABLE_REGNUM) */ /* This is used to implement __builtin_return_address for some machines. @@ -175,6 +171,7 @@ static GTY ((if_marked ("ggc_marked_p"), param_is (struct rtx_def))) #define first_insn (crtl->emit.x_first_insn) #define last_insn (crtl->emit.x_last_insn) #define cur_insn_uid (crtl->emit.x_cur_insn_uid) +#define cur_debug_insn_uid (crtl->emit.x_cur_debug_insn_uid) #define last_location (crtl->emit.x_last_location) #define first_label_num (crtl->emit.x_first_label_num) @@ -193,7 +190,7 @@ static rtx lookup_const_fixed (rtx); static hashval_t mem_attrs_htab_hash (const void *); static int mem_attrs_htab_eq (const void *, const void *); static mem_attrs *get_mem_attrs (alias_set_type, tree, rtx, rtx, unsigned int, - enum machine_mode); + addr_space_t, enum machine_mode); static hashval_t reg_attrs_htab_hash (const void *); static int reg_attrs_htab_eq (const void *, const void *); static reg_attrs *get_reg_attrs (tree, int); @@ -292,6 +289,7 @@ mem_attrs_htab_hash (const void *x) const mem_attrs *const p = (const mem_attrs *) x; return (p->alias ^ (p->align * 1000) + ^ (p->addrspace * 4000) ^ ((p->offset ? INTVAL (p->offset) : 0) * 50000) ^ ((p->size ? INTVAL (p->size) : 0) * 2500000) ^ (size_t) iterative_hash_expr (p->expr, 0)); @@ -309,6 +307,7 @@ mem_attrs_htab_eq (const void *x, const void *y) return (p->alias == q->alias && p->offset == q->offset && p->size == q->size && p->align == q->align + && p->addrspace == q->addrspace && (p->expr == q->expr || (p->expr != NULL_TREE && q->expr != NULL_TREE && operand_equal_p (p->expr, q->expr, 0)))); @@ -320,7 +319,7 @@ mem_attrs_htab_eq (const void *x, const void *y) static mem_attrs * get_mem_attrs (alias_set_type alias, tree expr, rtx offset, rtx size, - unsigned int align, enum machine_mode mode) + unsigned int align, addr_space_t addrspace, enum machine_mode mode) { mem_attrs attrs; void **slot; @@ -328,7 +327,7 @@ get_mem_attrs (alias_set_type alias, tree expr, rtx offset, rtx size, /* If everything is the default, we can just return zero. This must match what the corresponding MEM_* macros return when the field is not present. */ - if (alias == 0 && expr == 0 && offset == 0 + if (alias == 0 && expr == 0 && offset == 0 && addrspace == 0 && (size == 0 || (mode != BLKmode && GET_MODE_SIZE (mode) == INTVAL (size))) && (STRICT_ALIGNMENT && mode != BLKmode @@ -340,6 +339,7 @@ get_mem_attrs (alias_set_type alias, tree expr, rtx offset, rtx size, attrs.offset = offset; attrs.size = size; attrs.align = align; + attrs.addrspace = addrspace; slot = htab_find_slot (mem_attrs_htab, &attrs, INSERT); if (*slot == 0) @@ -535,7 +535,7 @@ immed_double_const (HOST_WIDE_INT i0, HOST_WIDE_INT i1, enum machine_mode mode) 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 + 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) @@ -865,7 +865,7 @@ gen_reg_rtx (enum machine_mode mode) /* If a virtual register with bigger mode alignment is generated, increase stack alignment estimation because it might be spilled to stack later. */ - if (SUPPORTS_STACK_ALIGNMENT + if (SUPPORTS_STACK_ALIGNMENT && crtl->stack_alignment_estimated < align && !crtl->stack_realign_processed) { @@ -1189,7 +1189,7 @@ gen_lowpart_common (enum machine_mode mode, rtx x) innermode = mode_for_size (HOST_BITS_PER_WIDE_INT, MODE_INT, 0); else if (innermode == VOIDmode) innermode = mode_for_size (HOST_BITS_PER_WIDE_INT * 2, MODE_INT, 0); - + xsize = GET_MODE_SIZE (innermode); gcc_assert (innermode != VOIDmode && innermode != BLKmode); @@ -1250,7 +1250,7 @@ gen_highpart (enum machine_mode mode, rtx x) result = simplify_gen_subreg (mode, x, GET_MODE (x), subreg_highpart_offset (mode, GET_MODE (x))); gcc_assert (result); - + /* simplify_gen_subreg is not guaranteed to return a valid operand for the target if we have a MEM. gen_highpart must return a valid operand, emitting code if necessary to do so. */ @@ -1259,7 +1259,7 @@ gen_highpart (enum machine_mode mode, rtx x) result = validize_mem (result); gcc_assert (result); } - + return result; } @@ -1386,7 +1386,9 @@ operand_subword (rtx op, unsigned int offset, int validate_address, enum machine else if (reload_completed) { - if (! strict_memory_address_p (word_mode, XEXP (new_rtx, 0))) + if (! strict_memory_address_addr_space_p (word_mode, + XEXP (new_rtx, 0), + MEM_ADDR_SPACE (op))) return 0; } else @@ -1581,11 +1583,11 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp, /* We can set the alignment from the type if we are making an object, this is an INDIRECT_REF, or if TYPE_ALIGN_OK. */ - if (objectp || TREE_CODE (t) == INDIRECT_REF - || TREE_CODE (t) == ALIGN_INDIRECT_REF + if (objectp || TREE_CODE (t) == INDIRECT_REF + || TREE_CODE (t) == ALIGN_INDIRECT_REF || TYPE_ALIGN_OK (type)) align = MAX (align, TYPE_ALIGN (type)); - else + else if (TREE_CODE (t) == MISALIGNED_INDIRECT_REF) { if (integer_zerop (TREE_OPERAND (t, 1))) @@ -1795,7 +1797,8 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp, /* Now set the attributes we computed above. */ MEM_ATTRS (ref) - = get_mem_attrs (alias, expr, offset, size, align, GET_MODE (ref)); + = get_mem_attrs (alias, expr, offset, size, align, + TYPE_ADDR_SPACE (type), GET_MODE (ref)); /* If this is already known to be a scalar or aggregate, we are done. */ if (MEM_IN_STRUCT_P (ref) || MEM_SCALAR_P (ref)) @@ -1827,7 +1830,17 @@ set_mem_alias_set (rtx mem, alias_set_type set) MEM_ATTRS (mem) = get_mem_attrs (set, MEM_EXPR (mem), MEM_OFFSET (mem), MEM_SIZE (mem), MEM_ALIGN (mem), - GET_MODE (mem)); + MEM_ADDR_SPACE (mem), GET_MODE (mem)); +} + +/* Set the address space of MEM to ADDRSPACE (target-defined). */ + +void +set_mem_addr_space (rtx mem, addr_space_t addrspace) +{ + MEM_ATTRS (mem) = get_mem_attrs (MEM_ALIAS_SET (mem), MEM_EXPR (mem), + MEM_OFFSET (mem), MEM_SIZE (mem), + MEM_ALIGN (mem), addrspace, GET_MODE (mem)); } /* Set the alignment of MEM to ALIGN bits. */ @@ -1837,7 +1850,7 @@ set_mem_align (rtx mem, unsigned int align) { MEM_ATTRS (mem) = get_mem_attrs (MEM_ALIAS_SET (mem), MEM_EXPR (mem), MEM_OFFSET (mem), MEM_SIZE (mem), align, - GET_MODE (mem)); + MEM_ADDR_SPACE (mem), GET_MODE (mem)); } /* Set the expr for MEM to EXPR. */ @@ -1847,7 +1860,8 @@ set_mem_expr (rtx mem, tree expr) { MEM_ATTRS (mem) = get_mem_attrs (MEM_ALIAS_SET (mem), expr, MEM_OFFSET (mem), - MEM_SIZE (mem), MEM_ALIGN (mem), GET_MODE (mem)); + MEM_SIZE (mem), MEM_ALIGN (mem), + MEM_ADDR_SPACE (mem), GET_MODE (mem)); } /* Set the offset of MEM to OFFSET. */ @@ -1857,7 +1871,7 @@ set_mem_offset (rtx mem, rtx offset) { MEM_ATTRS (mem) = get_mem_attrs (MEM_ALIAS_SET (mem), MEM_EXPR (mem), offset, MEM_SIZE (mem), MEM_ALIGN (mem), - GET_MODE (mem)); + MEM_ADDR_SPACE (mem), GET_MODE (mem)); } /* Set the size of MEM to SIZE. */ @@ -1867,7 +1881,7 @@ set_mem_size (rtx mem, rtx size) { MEM_ATTRS (mem) = get_mem_attrs (MEM_ALIAS_SET (mem), MEM_EXPR (mem), MEM_OFFSET (mem), size, MEM_ALIGN (mem), - GET_MODE (mem)); + MEM_ADDR_SPACE (mem), GET_MODE (mem)); } /* Return a memory reference like MEMREF, but with its mode changed to MODE @@ -1879,23 +1893,25 @@ set_mem_size (rtx mem, rtx size) static rtx change_address_1 (rtx memref, enum machine_mode mode, rtx addr, int validate) { + addr_space_t as; rtx new_rtx; gcc_assert (MEM_P (memref)); + as = MEM_ADDR_SPACE (memref); if (mode == VOIDmode) mode = GET_MODE (memref); if (addr == 0) addr = XEXP (memref, 0); if (mode == GET_MODE (memref) && addr == XEXP (memref, 0) - && (!validate || memory_address_p (mode, addr))) + && (!validate || memory_address_addr_space_p (mode, addr, as))) return memref; if (validate) { if (reload_in_progress || reload_completed) - gcc_assert (memory_address_p (mode, addr)); + gcc_assert (memory_address_addr_space_p (mode, addr, as)); else - addr = memory_address (mode, addr); + addr = memory_address_addr_space (mode, addr, as); } if (rtx_equal_p (addr, XEXP (memref, 0)) && mode == GET_MODE (memref)) @@ -1934,7 +1950,8 @@ change_address (rtx memref, enum machine_mode mode, rtx addr) } MEM_ATTRS (new_rtx) - = get_mem_attrs (MEM_ALIAS_SET (memref), 0, 0, size, align, mmode); + = get_mem_attrs (MEM_ALIAS_SET (memref), 0, 0, size, align, + MEM_ADDR_SPACE (memref), mmode); return new_rtx; } @@ -1954,11 +1971,13 @@ adjust_address_1 (rtx memref, enum machine_mode mode, HOST_WIDE_INT offset, rtx memoffset = MEM_OFFSET (memref); rtx size = 0; unsigned int memalign = MEM_ALIGN (memref); + addr_space_t as = MEM_ADDR_SPACE (memref); + enum machine_mode address_mode = targetm.addr_space.address_mode (as); int pbits; /* If there are no changes, just return the original memory reference. */ if (mode == GET_MODE (memref) && !offset - && (!validate || memory_address_p (mode, addr))) + && (!validate || memory_address_addr_space_p (mode, addr, as))) return memref; /* ??? Prefer to create garbage instead of creating shared rtl. @@ -1968,7 +1987,7 @@ adjust_address_1 (rtx memref, enum machine_mode mode, HOST_WIDE_INT offset, /* Convert a possibly large offset to a signed value within the range of the target address space. */ - pbits = GET_MODE_BITSIZE (Pmode); + pbits = GET_MODE_BITSIZE (address_mode); if (HOST_BITS_PER_WIDE_INT > pbits) { int shift = HOST_BITS_PER_WIDE_INT - pbits; @@ -1984,7 +2003,7 @@ adjust_address_1 (rtx memref, enum machine_mode mode, HOST_WIDE_INT offset, && offset >= 0 && (unsigned HOST_WIDE_INT) offset < GET_MODE_ALIGNMENT (GET_MODE (memref)) / BITS_PER_UNIT) - addr = gen_rtx_LO_SUM (Pmode, XEXP (addr, 0), + addr = gen_rtx_LO_SUM (address_mode, XEXP (addr, 0), plus_constant (XEXP (addr, 1), offset)); else addr = plus_constant (addr, offset); @@ -2017,7 +2036,8 @@ adjust_address_1 (rtx memref, enum machine_mode mode, HOST_WIDE_INT offset, size = plus_constant (MEM_SIZE (memref), -offset); MEM_ATTRS (new_rtx) = get_mem_attrs (MEM_ALIAS_SET (memref), MEM_EXPR (memref), - memoffset, size, memalign, GET_MODE (new_rtx)); + memoffset, size, memalign, as, + GET_MODE (new_rtx)); /* At some point, we should validate that this offset is within the object, if all the appropriate values are known. */ @@ -2045,8 +2065,10 @@ rtx offset_address (rtx memref, rtx offset, unsigned HOST_WIDE_INT pow2) { rtx new_rtx, addr = XEXP (memref, 0); + addr_space_t as = MEM_ADDR_SPACE (memref); + enum machine_mode address_mode = targetm.addr_space.address_mode (as); - new_rtx = simplify_gen_binary (PLUS, Pmode, addr, offset); + new_rtx = simplify_gen_binary (PLUS, address_mode, addr, offset); /* At this point we don't know _why_ the address is invalid. It could have secondary memory references, multiplies or anything. @@ -2055,12 +2077,12 @@ offset_address (rtx memref, rtx offset, unsigned HOST_WIDE_INT pow2) being able to recognize the magic around pic_offset_table_rtx. This stuff is fragile, and is yet another example of why it is bad to expose PIC machinery too early. */ - if (! memory_address_p (GET_MODE (memref), new_rtx) + if (! memory_address_addr_space_p (GET_MODE (memref), new_rtx, as) && GET_CODE (addr) == PLUS && XEXP (addr, 0) == pic_offset_table_rtx) { addr = force_reg (GET_MODE (addr), addr); - new_rtx = simplify_gen_binary (PLUS, Pmode, addr, offset); + new_rtx = simplify_gen_binary (PLUS, address_mode, addr, offset); } update_temp_slot_address (XEXP (memref, 0), new_rtx); @@ -2075,7 +2097,7 @@ offset_address (rtx memref, rtx offset, unsigned HOST_WIDE_INT pow2) MEM_ATTRS (new_rtx) = get_mem_attrs (MEM_ALIAS_SET (memref), MEM_EXPR (memref), 0, 0, MIN (MEM_ALIGN (memref), pow2 * BITS_PER_UNIT), - GET_MODE (new_rtx)); + as, GET_MODE (new_rtx)); return new_rtx; } @@ -2179,7 +2201,8 @@ widen_memory_access (rtx memref, enum machine_mode mode, HOST_WIDE_INT offset) /* ??? Maybe use get_alias_set on any remaining expression. */ MEM_ATTRS (new_rtx) = get_mem_attrs (0, expr, memoffset, GEN_INT (size), - MEM_ALIGN (new_rtx), mode); + MEM_ALIGN (new_rtx), + MEM_ADDR_SPACE (new_rtx), mode); return new_rtx; } @@ -2207,7 +2230,7 @@ get_spill_slot_decl (bool force_build_p) rd = gen_rtx_MEM (BLKmode, frame_pointer_rtx); MEM_NOTRAP_P (rd) = 1; MEM_ATTRS (rd) = get_mem_attrs (new_alias_set (), d, const0_rtx, - NULL_RTX, 0, BLKmode); + NULL_RTX, 0, ADDR_SPACE_GENERIC, BLKmode); SET_DECL_RTL (d, rd); return d; @@ -2240,7 +2263,7 @@ set_mem_attrs_for_spill (rtx mem) MEM_ATTRS (mem) = get_mem_attrs (alias, expr, offset, MEM_SIZE (mem), MEM_ALIGN (mem), - GET_MODE (mem)); + ADDR_SPACE_GENERIC, GET_MODE (mem)); MEM_NOTRAP_P (mem) = 1; } @@ -2268,8 +2291,31 @@ set_new_first_and_last_insn (rtx first, rtx last) last_insn = last; cur_insn_uid = 0; - for (insn = first; insn; insn = NEXT_INSN (insn)) - cur_insn_uid = MAX (cur_insn_uid, INSN_UID (insn)); + if (MIN_NONDEBUG_INSN_UID || MAY_HAVE_DEBUG_INSNS) + { + int debug_count = 0; + + cur_insn_uid = MIN_NONDEBUG_INSN_UID - 1; + cur_debug_insn_uid = 0; + + for (insn = first; insn; insn = NEXT_INSN (insn)) + if (INSN_UID (insn) < MIN_NONDEBUG_INSN_UID) + cur_debug_insn_uid = MAX (cur_debug_insn_uid, INSN_UID (insn)); + else + { + cur_insn_uid = MAX (cur_insn_uid, INSN_UID (insn)); + if (DEBUG_INSN_P (insn)) + debug_count++; + } + + if (debug_count) + cur_debug_insn_uid = MIN_NONDEBUG_INSN_UID + debug_count; + else + cur_debug_insn_uid++; + } + else + for (insn = first; insn; insn = NEXT_INSN (insn)) + cur_insn_uid = MAX (cur_insn_uid, INSN_UID (insn)); cur_insn_uid++; } @@ -2370,6 +2416,8 @@ verify_rtx_sharing (rtx orig, rtx insn) switch (code) { case REG: + case DEBUG_EXPR: + case VALUE: case CONST_INT: case CONST_DOUBLE: case CONST_FIXED: @@ -2417,7 +2465,7 @@ verify_rtx_sharing (rtx orig, rtx insn) } #endif gcc_assert (!RTX_FLAG (x, used)); - + RTX_FLAG (x, used) = 1; /* Now scan the subexpressions recursively. */ @@ -2570,6 +2618,8 @@ repeat: switch (code) { case REG: + case DEBUG_EXPR: + case VALUE: case CONST_INT: case CONST_DOUBLE: case CONST_FIXED: @@ -2592,6 +2642,7 @@ repeat: return; break; + case DEBUG_INSN: case INSN: case JUMP_INSN: case CALL_INSN: @@ -2622,7 +2673,7 @@ repeat: format_ptr = GET_RTX_FORMAT (code); length = GET_RTX_LENGTH (code); last_ptr = NULL; - + for (i = 0; i < length; i++) { switch (*format_ptr++) @@ -2638,12 +2689,12 @@ repeat: { int j; int len = XVECLEN (x, i); - + /* Copy the vector iff I copied the rtx and the length is nonzero. */ if (copied && len > 0) XVEC (x, i) = gen_rtvec_v (len, XVEC (x, i)->elem); - + /* Call recursively on all inside the vector. */ for (j = 0; j < len; j++) { @@ -2688,6 +2739,8 @@ repeat: switch (code) { case REG: + case DEBUG_EXPR: + case VALUE: case CONST_INT: case CONST_DOUBLE: case CONST_FIXED: @@ -2698,6 +2751,7 @@ repeat: case CC0: return; + case DEBUG_INSN: case INSN: case JUMP_INSN: case CALL_INSN: @@ -2715,7 +2769,7 @@ repeat: format_ptr = GET_RTX_FORMAT (code); length = GET_RTX_LENGTH (code); - + for (i = 0; i < length; i++) { switch (*format_ptr++) @@ -2758,6 +2812,8 @@ set_used_flags (rtx x) switch (code) { case REG: + case DEBUG_EXPR: + case VALUE: case CONST_INT: case CONST_DOUBLE: case CONST_FIXED: @@ -2768,6 +2824,7 @@ set_used_flags (rtx x) case CC0: return; + case DEBUG_INSN: case INSN: case JUMP_INSN: case CALL_INSN: @@ -2947,6 +3004,27 @@ get_max_uid (void) { return cur_insn_uid; } + +/* Return the number of actual (non-debug) insns emitted in this + function. */ + +int +get_max_insn_count (void) +{ + int n = cur_insn_uid; + + /* The table size must be stable across -g, to avoid codegen + differences due to debug insns, and not be affected by + -fmin-insn-uid, to avoid excessive table size and to simplify + debugging of -fcompare-debug failures. */ + if (cur_debug_insn_uid > MIN_NONDEBUG_INSN_UID) + n -= cur_debug_insn_uid; + else + n -= MIN_NONDEBUG_INSN_UID; + + return n; +} + /* Return the next insn. If it is a SEQUENCE, return the first insn of the sequence. */ @@ -2998,6 +3076,25 @@ next_nonnote_insn (rtx insn) return insn; } +/* Return the next insn after INSN that is not a NOTE, but stop the + search before we enter another basic block. This routine does not + look inside SEQUENCEs. */ + +rtx +next_nonnote_insn_bb (rtx insn) +{ + while (insn) + { + insn = NEXT_INSN (insn); + if (insn == 0 || !NOTE_P (insn)) + break; + if (NOTE_INSN_BASIC_BLOCK_P (insn)) + return NULL_RTX; + } + + return insn; +} + /* Return the previous insn before INSN that is not a NOTE. This routine does not look inside SEQUENCEs. */ @@ -3014,6 +3111,57 @@ prev_nonnote_insn (rtx insn) return insn; } +/* Return the previous insn before INSN that is not a NOTE, but stop + the search before we enter another basic block. This routine does + not look inside SEQUENCEs. */ + +rtx +prev_nonnote_insn_bb (rtx insn) +{ + while (insn) + { + insn = PREV_INSN (insn); + if (insn == 0 || !NOTE_P (insn)) + break; + if (NOTE_INSN_BASIC_BLOCK_P (insn)) + return NULL_RTX; + } + + return insn; +} + +/* Return the next insn after INSN that is not a DEBUG_INSN. This + routine does not look inside SEQUENCEs. */ + +rtx +next_nondebug_insn (rtx insn) +{ + while (insn) + { + insn = NEXT_INSN (insn); + if (insn == 0 || !DEBUG_INSN_P (insn)) + break; + } + + return insn; +} + +/* Return the previous insn before INSN that is not a DEBUG_INSN. + This routine does not look inside SEQUENCEs. */ + +rtx +prev_nondebug_insn (rtx insn) +{ + while (insn) + { + insn = PREV_INSN (insn); + if (insn == 0 || !DEBUG_INSN_P (insn)) + break; + } + + return insn; +} + /* Return the next INSN, CALL_INSN or JUMP_INSN after INSN; or 0, if there is none. This routine does not look inside SEQUENCEs. */ @@ -3065,8 +3213,8 @@ last_call_insn (void) } /* Find the next insn after INSN that really does something. This routine - does not look inside SEQUENCEs. Until reload has completed, this is the - same as next_real_insn. */ + does not look inside SEQUENCEs. After reload this also skips over + standalone USE and CLOBBER insn. */ int active_insn_p (const_rtx insn) @@ -3092,8 +3240,8 @@ next_active_insn (rtx insn) } /* Find the last insn before INSN that really does something. This routine - does not look inside SEQUENCEs. Until reload has completed, this is the - same as prev_real_insn. */ + does not look inside SEQUENCEs. After reload this also skips over + standalone USE and CLOBBER insn. */ rtx prev_active_insn (rtx insn) @@ -3364,6 +3512,10 @@ try_split (rtx pat, rtx trial, int last) p = &XEXP (*p, 1); *p = CALL_INSN_FUNCTION_USAGE (trial); SIBLING_CALL_P (insn) = SIBLING_CALL_P (trial); + + /* Update the debug information for the CALL_INSN. */ + if (flag_enable_icf_debug) + (*debug_hooks->copy_call_info) (trial, insn); } } @@ -3373,13 +3525,7 @@ try_split (rtx pat, rtx trial, int last) switch (REG_NOTE_KIND (note)) { case REG_EH_REGION: - for (insn = insn_last; insn != NULL_RTX; insn = PREV_INSN (insn)) - { - if (CALL_P (insn) - || (flag_non_call_exceptions && INSN_P (insn) - && may_trap_p (PATTERN (insn)))) - add_reg_note (insn, REG_EH_REGION, XEXP (note, 0)); - } + copy_reg_eh_region_note_backward (note, insn_last, NULL); break; case REG_NORETURN: @@ -3485,6 +3631,27 @@ make_insn_raw (rtx pattern) return insn; } +/* Like `make_insn_raw' but make a DEBUG_INSN instead of an insn. */ + +rtx +make_debug_insn_raw (rtx pattern) +{ + rtx insn; + + insn = rtx_alloc (DEBUG_INSN); + INSN_UID (insn) = cur_debug_insn_uid++; + if (cur_debug_insn_uid > MIN_NONDEBUG_INSN_UID) + INSN_UID (insn) = cur_insn_uid++; + + PATTERN (insn) = pattern; + INSN_CODE (insn) = -1; + REG_NOTES (insn) = NULL; + INSN_LOCATOR (insn) = curr_insn_locator (); + BLOCK_FOR_INSN (insn) = NULL; + + return insn; +} + /* Like `make_insn_raw' but make a JUMP_INSN instead of an insn. */ rtx @@ -3645,7 +3812,7 @@ add_insn_before (rtx insn, rtx before, basic_block bb) gcc_assert (stack); } - if (!bb + if (!bb && !BARRIER_P (before) && !BARRIER_P (insn)) bb = BLOCK_FOR_INSN (before); @@ -3898,6 +4065,7 @@ emit_insn_before_noloc (rtx x, rtx before, basic_block bb) switch (GET_CODE (x)) { + case DEBUG_INSN: case INSN: case JUMP_INSN: case CALL_INSN: @@ -3941,6 +4109,7 @@ emit_jump_insn_before_noloc (rtx x, rtx before) switch (GET_CODE (x)) { + case DEBUG_INSN: case INSN: case JUMP_INSN: case CALL_INSN: @@ -3984,6 +4153,7 @@ emit_call_insn_before_noloc (rtx x, rtx before) switch (GET_CODE (x)) { + case DEBUG_INSN: case INSN: case JUMP_INSN: case CALL_INSN: @@ -4015,6 +4185,50 @@ emit_call_insn_before_noloc (rtx x, rtx before) return last; } +/* Make an instruction with body X and code DEBUG_INSN + and output it before the instruction BEFORE. */ + +rtx +emit_debug_insn_before_noloc (rtx x, rtx before) +{ + rtx last = NULL_RTX, insn; + + gcc_assert (before); + + switch (GET_CODE (x)) + { + case DEBUG_INSN: + case INSN: + case JUMP_INSN: + case CALL_INSN: + case CODE_LABEL: + case BARRIER: + case NOTE: + insn = x; + while (insn) + { + rtx next = NEXT_INSN (insn); + add_insn_before (insn, before, NULL); + last = insn; + insn = next; + } + break; + +#ifdef ENABLE_RTL_CHECKING + case SEQUENCE: + gcc_unreachable (); + break; +#endif + + default: + last = make_debug_insn_raw (x); + add_insn_before (last, before, NULL); + break; + } + + return last; +} + /* Make an insn of code BARRIER and output it before the insn BEFORE. */ @@ -4121,6 +4335,7 @@ emit_insn_after_noloc (rtx x, rtx after, basic_block bb) switch (GET_CODE (x)) { + case DEBUG_INSN: case INSN: case JUMP_INSN: case CALL_INSN: @@ -4158,6 +4373,7 @@ emit_jump_insn_after_noloc (rtx x, rtx after) switch (GET_CODE (x)) { + case DEBUG_INSN: case INSN: case JUMP_INSN: case CALL_INSN: @@ -4194,6 +4410,7 @@ emit_call_insn_after_noloc (rtx x, rtx after) switch (GET_CODE (x)) { + case DEBUG_INSN: case INSN: case JUMP_INSN: case CALL_INSN: @@ -4218,6 +4435,43 @@ emit_call_insn_after_noloc (rtx x, rtx after) return last; } +/* Make an instruction with body X and code CALL_INSN + and output it after the instruction AFTER. */ + +rtx +emit_debug_insn_after_noloc (rtx x, rtx after) +{ + rtx last; + + gcc_assert (after); + + switch (GET_CODE (x)) + { + case DEBUG_INSN: + case INSN: + case JUMP_INSN: + case CALL_INSN: + case CODE_LABEL: + case BARRIER: + case NOTE: + last = emit_insn_after_1 (x, after, NULL); + break; + +#ifdef ENABLE_RTL_CHECKING + case SEQUENCE: + gcc_unreachable (); + break; +#endif + + default: + last = make_debug_insn_raw (x); + add_insn_after (last, after, NULL); + break; + } + + return last; +} + /* Make an insn of code BARRIER and output it after the insn AFTER. */ @@ -4288,8 +4542,13 @@ emit_insn_after_setloc (rtx pattern, rtx after, int loc) rtx emit_insn_after (rtx pattern, rtx after) { - if (INSN_P (after)) - return emit_insn_after_setloc (pattern, after, INSN_LOCATOR (after)); + rtx prev = after; + + while (DEBUG_INSN_P (prev)) + prev = PREV_INSN (prev); + + if (INSN_P (prev)) + return emit_insn_after_setloc (pattern, after, INSN_LOCATOR (prev)); else return emit_insn_after_noloc (pattern, after, NULL); } @@ -4319,8 +4578,13 @@ emit_jump_insn_after_setloc (rtx pattern, rtx after, int loc) rtx emit_jump_insn_after (rtx pattern, rtx after) { - if (INSN_P (after)) - return emit_jump_insn_after_setloc (pattern, after, INSN_LOCATOR (after)); + rtx prev = after; + + while (DEBUG_INSN_P (prev)) + prev = PREV_INSN (prev); + + if (INSN_P (prev)) + return emit_jump_insn_after_setloc (pattern, after, INSN_LOCATOR (prev)); else return emit_jump_insn_after_noloc (pattern, after); } @@ -4350,12 +4614,48 @@ emit_call_insn_after_setloc (rtx pattern, rtx after, int loc) rtx emit_call_insn_after (rtx pattern, rtx after) { - if (INSN_P (after)) - return emit_call_insn_after_setloc (pattern, after, INSN_LOCATOR (after)); + rtx prev = after; + + while (DEBUG_INSN_P (prev)) + prev = PREV_INSN (prev); + + if (INSN_P (prev)) + return emit_call_insn_after_setloc (pattern, after, INSN_LOCATOR (prev)); else return emit_call_insn_after_noloc (pattern, after); } +/* Like emit_debug_insn_after_noloc, but set INSN_LOCATOR according to SCOPE. */ +rtx +emit_debug_insn_after_setloc (rtx pattern, rtx after, int loc) +{ + rtx last = emit_debug_insn_after_noloc (pattern, after); + + if (pattern == NULL_RTX || !loc) + return last; + + after = NEXT_INSN (after); + while (1) + { + if (active_insn_p (after) && !INSN_LOCATOR (after)) + INSN_LOCATOR (after) = loc; + if (after == last) + break; + after = NEXT_INSN (after); + } + return last; +} + +/* Like emit_debug_insn_after_noloc, but set INSN_LOCATOR according to AFTER. */ +rtx +emit_debug_insn_after (rtx pattern, rtx after) +{ + if (INSN_P (after)) + return emit_debug_insn_after_setloc (pattern, after, INSN_LOCATOR (after)); + else + return emit_debug_insn_after_noloc (pattern, after); +} + /* Like emit_insn_before_noloc, but set INSN_LOCATOR according to SCOPE. */ rtx emit_insn_before_setloc (rtx pattern, rtx before, int loc) @@ -4385,8 +4685,13 @@ emit_insn_before_setloc (rtx pattern, rtx before, int loc) rtx emit_insn_before (rtx pattern, rtx before) { - if (INSN_P (before)) - return emit_insn_before_setloc (pattern, before, INSN_LOCATOR (before)); + rtx next = before; + + while (DEBUG_INSN_P (next)) + next = PREV_INSN (next); + + if (INSN_P (next)) + return emit_insn_before_setloc (pattern, before, INSN_LOCATOR (next)); else return emit_insn_before_noloc (pattern, before, NULL); } @@ -4417,8 +4722,13 @@ emit_jump_insn_before_setloc (rtx pattern, rtx before, int loc) rtx emit_jump_insn_before (rtx pattern, rtx before) { - if (INSN_P (before)) - return emit_jump_insn_before_setloc (pattern, before, INSN_LOCATOR (before)); + rtx next = before; + + while (DEBUG_INSN_P (next)) + next = PREV_INSN (next); + + if (INSN_P (next)) + return emit_jump_insn_before_setloc (pattern, before, INSN_LOCATOR (next)); else return emit_jump_insn_before_noloc (pattern, before); } @@ -4450,11 +4760,49 @@ emit_call_insn_before_setloc (rtx pattern, rtx before, int loc) rtx emit_call_insn_before (rtx pattern, rtx before) { - if (INSN_P (before)) - return emit_call_insn_before_setloc (pattern, before, INSN_LOCATOR (before)); + rtx next = before; + + while (DEBUG_INSN_P (next)) + next = PREV_INSN (next); + + if (INSN_P (next)) + return emit_call_insn_before_setloc (pattern, before, INSN_LOCATOR (next)); else return emit_call_insn_before_noloc (pattern, before); } + +/* like emit_insn_before_noloc, but set insn_locator according to scope. */ +rtx +emit_debug_insn_before_setloc (rtx pattern, rtx before, int loc) +{ + rtx first = PREV_INSN (before); + rtx last = emit_debug_insn_before_noloc (pattern, before); + + if (pattern == NULL_RTX) + return last; + + first = NEXT_INSN (first); + while (1) + { + if (active_insn_p (first) && !INSN_LOCATOR (first)) + INSN_LOCATOR (first) = loc; + if (first == last) + break; + first = NEXT_INSN (first); + } + return last; +} + +/* like emit_debug_insn_before_noloc, + but set insn_locator according to before. */ +rtx +emit_debug_insn_before (rtx pattern, rtx before) +{ + if (INSN_P (before)) + return emit_debug_insn_before_setloc (pattern, before, INSN_LOCATOR (before)); + else + return emit_debug_insn_before_noloc (pattern, before); +} /* Take X and emit it at the end of the doubly-linked INSN list. @@ -4472,6 +4820,7 @@ emit_insn (rtx x) switch (GET_CODE (x)) { + case DEBUG_INSN: case INSN: case JUMP_INSN: case CALL_INSN: @@ -4503,6 +4852,52 @@ emit_insn (rtx x) return last; } +/* Make an insn of code DEBUG_INSN with pattern X + and add it to the end of the doubly-linked list. */ + +rtx +emit_debug_insn (rtx x) +{ + rtx last = last_insn; + rtx insn; + + if (x == NULL_RTX) + return last; + + switch (GET_CODE (x)) + { + case DEBUG_INSN: + case INSN: + case JUMP_INSN: + case CALL_INSN: + case CODE_LABEL: + case BARRIER: + case NOTE: + insn = x; + while (insn) + { + rtx next = NEXT_INSN (insn); + add_insn (insn); + last = insn; + insn = next; + } + break; + +#ifdef ENABLE_RTL_CHECKING + case SEQUENCE: + gcc_unreachable (); + break; +#endif + + default: + last = make_debug_insn_raw (x); + add_insn (last); + break; + } + + return last; +} + /* Make an insn of code JUMP_INSN with pattern X and add it to the end of the doubly-linked list. */ @@ -4513,6 +4908,7 @@ emit_jump_insn (rtx x) switch (GET_CODE (x)) { + case DEBUG_INSN: case INSN: case JUMP_INSN: case CALL_INSN: @@ -4554,6 +4950,7 @@ emit_call_insn (rtx x) switch (GET_CODE (x)) { + case DEBUG_INSN: case INSN: case JUMP_INSN: case CALL_INSN: @@ -4612,15 +5009,15 @@ rtx emit_note_copy (rtx orig) { rtx note; - + note = rtx_alloc (NOTE); - + INSN_UID (note) = cur_insn_uid++; NOTE_DATA (note) = NOTE_DATA (orig); NOTE_KIND (note) = NOTE_KIND (orig); BLOCK_FOR_INSN (note) = NULL; add_insn (note); - + return note; } @@ -4825,6 +5222,8 @@ emit (rtx x) } case CALL_INSN: return emit_call_insn (x); + case DEBUG_INSN: + return emit_debug_insn (x); default: gcc_unreachable (); } @@ -5149,7 +5548,11 @@ init_emit (void) { first_insn = NULL; last_insn = NULL; - cur_insn_uid = 1; + if (MIN_NONDEBUG_INSN_UID) + cur_insn_uid = MIN_NONDEBUG_INSN_UID; + else + cur_insn_uid = 1; + cur_debug_insn_uid = 1; reg_rtx_no = LAST_VIRTUAL_REGISTER + 1; last_location = UNKNOWN_LOCATION; first_label_num = label_num; @@ -5301,39 +5704,16 @@ init_emit_regs (void) = gen_raw_REG (Pmode, RETURN_ADDRESS_POINTER_REGNUM); #endif -#ifdef STATIC_CHAIN_REGNUM - static_chain_rtx = gen_rtx_REG (Pmode, STATIC_CHAIN_REGNUM); - -#ifdef STATIC_CHAIN_INCOMING_REGNUM - if (STATIC_CHAIN_INCOMING_REGNUM != STATIC_CHAIN_REGNUM) - static_chain_incoming_rtx - = gen_rtx_REG (Pmode, STATIC_CHAIN_INCOMING_REGNUM); - else -#endif - static_chain_incoming_rtx = static_chain_rtx; -#endif - -#ifdef STATIC_CHAIN - static_chain_rtx = STATIC_CHAIN; - -#ifdef STATIC_CHAIN_INCOMING - static_chain_incoming_rtx = STATIC_CHAIN_INCOMING; -#else - static_chain_incoming_rtx = static_chain_rtx; -#endif -#endif - if ((unsigned) PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM) pic_offset_table_rtx = gen_raw_REG (Pmode, PIC_OFFSET_TABLE_REGNUM); else pic_offset_table_rtx = NULL_RTX; } -/* Create some permanent unique rtl objects shared between all functions. - LINE_NUMBERS is nonzero if line numbers are to be generated. */ +/* Create some permanent unique rtl objects shared between all functions. */ void -init_emit_once (int line_numbers) +init_emit_once (void) { int i; enum machine_mode mode; @@ -5355,8 +5735,6 @@ init_emit_once (int line_numbers) reg_attrs_htab = htab_create_ggc (37, reg_attrs_htab_hash, reg_attrs_htab_eq, NULL); - no_line_numbers = ! line_numbers; - /* Compute the word and byte modes. */ byte_mode = VOIDmode; @@ -5606,6 +5984,10 @@ emit_copy_of_insn_after (rtx insn, rtx after) new_rtx = emit_jump_insn_after (copy_insn (PATTERN (insn)), after); break; + case DEBUG_INSN: + new_rtx = emit_debug_insn_after (copy_insn (PATTERN (insn)), after); + break; + case CALL_INSN: new_rtx = emit_call_insn_after (copy_insn (PATTERN (insn)), after); if (CALL_INSN_FUNCTION_USAGE (insn)) @@ -5614,7 +5996,7 @@ emit_copy_of_insn_after (rtx insn, rtx after) SIBLING_CALL_P (new_rtx) = SIBLING_CALL_P (insn); RTL_CONST_CALL_P (new_rtx) = RTL_CONST_CALL_P (insn); RTL_PURE_CALL_P (new_rtx) = RTL_PURE_CALL_P (insn); - RTL_LOOPING_CONST_OR_PURE_CALL_P (new_rtx) + RTL_LOOPING_CONST_OR_PURE_CALL_P (new_rtx) = RTL_LOOPING_CONST_OR_PURE_CALL_P (insn); break;