aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2001-10-20 12:04:00 +0200
committerJan Hubicka <hubicka@gcc.gnu.org>2001-10-20 10:04:00 +0000
commitb932f770f70d60b1d6c89d6ef1fe8dc88bdecda1 (patch)
tree8b850e82487dad7507a2357d498b653cbeb1d71e /gcc
parent870628131ce6ff529817509e256c7ee035d37bfd (diff)
downloadgcc-b932f770f70d60b1d6c89d6ef1fe8dc88bdecda1.zip
gcc-b932f770f70d60b1d6c89d6ef1fe8dc88bdecda1.tar.gz
gcc-b932f770f70d60b1d6c89d6ef1fe8dc88bdecda1.tar.bz2
basic-block.h (find_sub_basic_blocks): Use sbitmap parameter.
* basic-block.h (find_sub_basic_blocks): Use sbitmap parameter. * cfgbuild.c (find_bb_boundaries, compute_outgoing_frequencies): Break out from ... (find_sub_basic_blocks): ... here; (find_many_sub_basic_blocks): New. * recog.c (split_all_insns): Update find_sub_basic_blocks call. * i386.h (ASM_PREFERRED_EH_DATA_FORMAT): Define sdata4. * i386.c (ix86_va_arg): Kill indirect_p handling; fix aliasing issues.: * i386.c (split_di, split_ti): Revamp to use simplify_subreg. * timevar.def (TV_LIFE, TV_LIFE_UPDATE, TV_MODE_SWITCH): new. * flow.c (update_life_info): Measure time. * c-decl.c: Include timevar.h (c_expand_body): Measure time. * toplev.c (rest_of_compilation): Measure time of mode switching separately. * Makefile.in (c-decl.o, cfgcleanup.o): Add dependancy. * toplev.c (flag_asynchronous_unwind_tables): New global variable. (lang_independent_options): Add asynchronous-unwind-tables (toplev_main): flag_asynchronous_unwind_tables implies flag_unwind_tables. * flags.h (flag_asynchronous_unwind_tables): Declare. * dwarf2out.c (dwarf2out_stack_adjust): Take into account flag_asynchronous_unwind_tables. (output_call_frame_info): Likewise. * invoke.texi (-fasynchronous-unwind-tables): Document. * i386.c (optimization_options): Enable flag_asynchronous_unwind_tables. * i386.c (ix86_expand_setcc): Always expect target to be QImode. * i386.md (s* expanders): Destination is QImode. * toplev.c (rest_of_compilation): Do not call clear_log_links. * rtl.h (clear_log_links): Kill. * flow.c (clear_log_links): Make static; accept blocks parameter; do no clear life info. (update_life_info): Call clear_log_links. * cfganal.c (forwarder_block_p): Avoid active_insn_p calls. From-SVN: r46374
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog46
-rw-r--r--gcc/Makefile.in4
-rw-r--r--gcc/basic-block.h1
-rw-r--r--gcc/c-decl.c4
-rw-r--r--gcc/cfganal.c7
-rw-r--r--gcc/cfgbuild.c170
-rw-r--r--gcc/config/i386/i386.c133
-rw-r--r--gcc/config/i386/i386.h3
-rw-r--r--gcc/config/i386/i386.md72
-rw-r--r--gcc/doc/invoke.texi8
-rw-r--r--gcc/dwarf2out.c7
-rw-r--r--gcc/flags.h4
-rw-r--r--gcc/flow.c52
-rw-r--r--gcc/recog.c3
-rw-r--r--gcc/rtl.h1
-rw-r--r--gcc/timevar.def4
-rw-r--r--gcc/toplev.c19
17 files changed, 322 insertions, 216 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 834268d..8b6793b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,49 @@
+Sat Oct 20 12:01:07 CEST 2001 Jan Hubicka <jh@suse.cz>
+
+ * basic-block.h (find_sub_basic_blocks): Use sbitmap parameter.
+ * cfgbuild.c (find_bb_boundaries, compute_outgoing_frequencies):
+ Break out from ...
+ (find_sub_basic_blocks): ... here;
+ (find_many_sub_basic_blocks): New.
+ * recog.c (split_all_insns): Update find_sub_basic_blocks call.
+
+ * i386.h (ASM_PREFERRED_EH_DATA_FORMAT): Define sdata4.
+
+ * i386.c (ix86_va_arg): Kill indirect_p handling; fix aliasing issues.:
+
+ * i386.c (split_di, split_ti): Revamp to use simplify_subreg.
+
+ * timevar.def (TV_LIFE, TV_LIFE_UPDATE, TV_MODE_SWITCH): new.
+ * flow.c (update_life_info): Measure time.
+ * c-decl.c: Include timevar.h
+ (c_expand_body): Measure time.
+ * toplev.c (rest_of_compilation): Measure time of mode switching
+ separately.
+ * Makefile.in (c-decl.o, cfgcleanup.o): Add dependancy.
+
+ * toplev.c (flag_asynchronous_unwind_tables): New global variable.
+ (lang_independent_options): Add asynchronous-unwind-tables
+ (toplev_main): flag_asynchronous_unwind_tables implies
+ flag_unwind_tables.
+ * flags.h (flag_asynchronous_unwind_tables): Declare.
+ * dwarf2out.c (dwarf2out_stack_adjust): Take into account
+ flag_asynchronous_unwind_tables.
+ (output_call_frame_info): Likewise.
+ * invoke.texi (-fasynchronous-unwind-tables): Document.
+ * i386.c (optimization_options): Enable
+ flag_asynchronous_unwind_tables.
+
+ * i386.c (ix86_expand_setcc): Always expect target to be QImode.
+ * i386.md (s* expanders): Destination is QImode.
+
+ * toplev.c (rest_of_compilation): Do not call clear_log_links.
+ * rtl.h (clear_log_links): Kill.
+ * flow.c (clear_log_links): Make static; accept blocks parameter;
+ do no clear life info.
+ (update_life_info): Call clear_log_links.
+
+ * cfganal.c (forwarder_block_p): Avoid active_insn_p calls.
+
2001-10-20 Neil Booth <neil@daikokuya.demon.co.uk>
* cpplex.c (handle_newline, skip_escaped_newlines,
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index c930972..00577e1 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1168,7 +1168,7 @@ $(srcdir)/c-parse.y: c-parse.in
c-decl.o : c-decl.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(RTL_H) $(C_TREE_H) \
$(GGC_H) $(TARGET_H) c-lex.h flags.h function.h output.h $(EXPR_H) \
- debug.h toplev.h intl.h $(TM_P_H) tree-inline.h
+ debug.h toplev.h intl.h $(TM_P_H) tree-inline.h $(TIMEVAR_H)
c-typeck.o : c-typeck.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(C_TREE_H) \
$(TARGET_H) flags.h intl.h output.h $(EXPR_H) $(RTL_H) toplev.h $(TM_P_H)
c-lang.o : c-lang.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(C_TREE_H) \
@@ -1512,7 +1512,7 @@ cfganal.o : cfganal.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) \
cfgbuild.o : cfgbuild.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) flags.h insn-config.h \
$(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h output.h toplev.h $(RECOG_H) \
function.h except.h $(GGC_H)
-cfgcleanup.o : cfgcleanup.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) \
+cfgcleanup.o : cfgcleanup.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TIMEVAR_H)\
$(BASIC_BLOCK_H) hard-reg-set.h output.h flags.h $(RECOG_H) toplev.h $(GGC_H)
cfgloop.o : cfgloop.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) \
$(BASIC_BLOCK_H) hard-reg-set.h
diff --git a/gcc/basic-block.h b/gcc/basic-block.h
index c56ea77..1a0cab6 100644
--- a/gcc/basic-block.h
+++ b/gcc/basic-block.h
@@ -640,6 +640,7 @@ extern bool forwarder_block_p PARAMS ((basic_block));
extern bool purge_all_dead_edges PARAMS ((void));
extern bool purge_dead_edges PARAMS ((basic_block));
extern void find_sub_basic_blocks PARAMS ((basic_block));
+extern void find_many_sub_basic_blocks PARAMS ((sbitmap));
extern bool can_fallthru PARAMS ((basic_block, basic_block));
extern void flow_nodes_print PARAMS ((const char *, const sbitmap,
FILE *));
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index de553b1..45b923a 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -44,6 +44,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "cpplib.h"
#include "target.h"
#include "debug.h"
+#include "timevar.h"
/* In grokdeclarator, distinguish syntactic contexts of declarators. */
enum decl_context
@@ -6802,6 +6803,8 @@ c_expand_body (fndecl, nested_p)
if (flag_syntax_only)
return;
+ timevar_push (TV_EXPAND);
+
if (flag_inline_trees)
{
/* First, cache whether the current function is inlinable. Some
@@ -6952,6 +6955,7 @@ c_expand_body (fndecl, nested_p)
if (nested_p)
/* Return to the enclosing function. */
pop_function_context ();
+ timevar_pop (TV_EXPAND);
}
/* Check the declarations given in a for-loop for satisfying the C99
diff --git a/gcc/cfganal.c b/gcc/cfganal.c
index 5ad1a10..8615a14 100644
--- a/gcc/cfganal.c
+++ b/gcc/cfganal.c
@@ -67,12 +67,13 @@ forwarder_block_p (bb)
while (insn != bb->end)
{
- if (active_insn_p (insn))
+ if (INSN_P (insn) && active_insn_p (insn))
return false;
insn = NEXT_INSN (insn);
}
- return (!active_insn_p (insn)
- || (GET_CODE (insn) == JUMP_INSN && onlyjump_p (insn)));
+ return (!INSN_P (insn)
+ || (GET_CODE (insn) == JUMP_INSN && simplejump_p (insn))
+ || !active_insn_p (insn));
}
/* Return nonzero if we can reach target from src by falling trought. */
diff --git a/gcc/cfgbuild.c b/gcc/cfgbuild.c
index b27c239..ef86939 100644
--- a/gcc/cfgbuild.c
+++ b/gcc/cfgbuild.c
@@ -55,6 +55,8 @@ static void make_edges PARAMS ((rtx, int, int, int));
static void make_label_edge PARAMS ((sbitmap *, basic_block,
rtx, int));
static void make_eh_edge PARAMS ((sbitmap *, basic_block, rtx));
+static void find_bb_boundaries PARAMS ((basic_block));
+static void compute_outgoing_frequencies PARAMS ((basic_block));
/* Count the basic blocks of the function. */
@@ -246,7 +248,8 @@ make_edges (label_value_list, min, max, update_p)
}
/* By nature of the way these get numbered, block 0 is always the entry. */
- cached_make_edge (edge_cache, ENTRY_BLOCK_PTR, BASIC_BLOCK (0), EDGE_FALLTHRU);
+ if (min == 0)
+ cached_make_edge (edge_cache, ENTRY_BLOCK_PTR, BASIC_BLOCK (0), EDGE_FALLTHRU);
for (i = min; i <= max; ++i)
{
@@ -663,18 +666,27 @@ find_basic_blocks (f, nregs, file)
timevar_pop (TV_CFG);
}
-/* Assume that someone emitted code with control flow instructions to the
- basic block. Update the data structure. */
-void
-find_sub_basic_blocks (bb)
+/* State of basic block as seen by find_sub_basic_blocks. */
+enum state
+ {
+ BLOCK_NEW = 0,
+ BLOCK_ORIGINAL,
+ BLOCK_TO_SPLIT
+ };
+#define STATE(bb) (enum state)(size_t)(bb)->aux
+#define SET_STATE(bb, state) (bb)->aux = (void *)(state)
+
+/* Scan basic block BB for possible BB boundaries inside the block
+ and create new basic blocks in the progress. */
+
+static void
+find_bb_boundaries (bb)
basic_block bb;
{
rtx insn = bb->head;
rtx end = bb->end;
rtx flow_transfer_insn = NULL_RTX;
edge fallthru = NULL;
- basic_block first_bb = bb;
- int i;
if (insn == bb->end)
return;
@@ -694,7 +706,7 @@ find_sub_basic_blocks (bb)
abort ();
break;
- /* On code label, split current basic block. */
+ /* On code label, split current basic block. */
case CODE_LABEL:
fallthru = split_block (bb, PREV_INSN (insn));
if (flow_transfer_insn)
@@ -725,7 +737,7 @@ find_sub_basic_blocks (bb)
{
if (GET_CODE (PATTERN (insn)) == ADDR_VEC
|| GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
- abort();
+ abort ();
flow_transfer_insn = insn;
}
else if (code == CALL_INSN)
@@ -764,18 +776,87 @@ find_sub_basic_blocks (bb)
followed by cleanup at fallthru edge, so the outgoing edges may
be dead. */
purge_dead_edges (bb);
+}
+
+/* Assume that frequency of basic block B is known. Compute frequencies
+ and probabilities of outgoing edges. */
+
+static void
+compute_outgoing_frequencies (b)
+ basic_block b;
+{
+ edge e, f;
+ if (b->succ && b->succ->succ_next && !b->succ->succ_next->succ_next)
+ {
+ rtx note = find_reg_note (b->end, REG_BR_PROB, NULL);
+ int probability;
+
+ if (!note)
+ return;
+ probability = INTVAL (XEXP (find_reg_note (b->end,
+ REG_BR_PROB, NULL), 0));
+ e = BRANCH_EDGE (b);
+ e->probability = probability;
+ e->count = ((b->count * probability + REG_BR_PROB_BASE / 2)
+ / REG_BR_PROB_BASE);
+ f = FALLTHRU_EDGE (b);
+ f->probability = REG_BR_PROB_BASE - probability;
+ f->count = b->count - e->count;
+ }
+ if (b->succ && !b->succ->succ_next)
+ {
+ e = b->succ;
+ e->probability = REG_BR_PROB_BASE;
+ e->count = b->count;
+ }
+}
+
+/* Assume that someone emitted code with control flow instructions to the
+ basic block. Update the data structure. */
+
+void
+find_many_sub_basic_blocks (blocks)
+ sbitmap blocks;
+{
+ int i;
+ int min, max;
+
+ for (i = 0; i < n_basic_blocks; i++)
+ {
+ SET_STATE (BASIC_BLOCK (i),
+ TEST_BIT (blocks, i)
+ ? BLOCK_TO_SPLIT : BLOCK_ORIGINAL);
+ }
+
+ for (i = 0; i < n_basic_blocks; i++)
+ {
+ basic_block bb = BASIC_BLOCK (i);
+ if (STATE (bb) == BLOCK_TO_SPLIT)
+ find_bb_boundaries (bb);
+ }
+
+ for (i = 0; i < n_basic_blocks; i++)
+ if (STATE (BASIC_BLOCK (i)) != BLOCK_ORIGINAL)
+ break;
+ min = max = i;
+ for (; i < n_basic_blocks; i++)
+ if (STATE (BASIC_BLOCK (i)) != BLOCK_ORIGINAL)
+ max = i;
/* Now re-scan and wire in all edges. This expect simple (conditional)
jumps at the end of each new basic blocks. */
- make_edges (NULL, first_bb->index, bb->index, 1);
+ make_edges (NULL, min, max, 1);
/* Update branch probabilities. Expect only (un)conditional jumps
to be created with only the forward edges. */
- for (i = first_bb->index; i <= bb->index; i++)
+ for (i = min; i <= max; i++)
{
- edge e,f;
+ edge e;
basic_block b = BASIC_BLOCK (i);
- if (b != first_bb)
+
+ if (STATE (b) == BLOCK_ORIGINAL)
+ continue;
+ if (STATE (b) == BLOCK_NEW)
{
b->count = 0;
b->frequency = 0;
@@ -785,29 +866,48 @@ find_sub_basic_blocks (bb)
b->frequency += EDGE_FREQUENCY (e);
}
}
- if (b->succ && b->succ->succ_next && !b->succ->succ_next->succ_next)
- {
- rtx note = find_reg_note (b->end, REG_BR_PROB, NULL);
- int probability;
-
- if (!note)
- continue;
- probability = INTVAL (XEXP (find_reg_note (b->end,
- REG_BR_PROB,
- NULL), 0));
- e = BRANCH_EDGE (b);
- e->probability = probability;
- e->count = ((b->count * probability + REG_BR_PROB_BASE / 2)
- / REG_BR_PROB_BASE);
- f = FALLTHRU_EDGE (b);
- f->probability = REG_BR_PROB_BASE - probability;
- f->count = b->count - e->count;
- }
- if (b->succ && !b->succ->succ_next)
+ compute_outgoing_frequencies (b);
+ }
+ for (i = 0; i < n_basic_blocks; i++)
+ SET_STATE (BASIC_BLOCK (i), 0);
+}
+
+/* Like above but for single basic block only. */
+
+void
+find_sub_basic_blocks (bb)
+ basic_block bb;
+{
+ int i;
+ int min, max;
+ basic_block next = (bb->index == n_basic_blocks - 1
+ ? NULL : BASIC_BLOCK (bb->index + 1));
+
+ min = bb->index;
+ find_bb_boundaries (bb);
+ max = (next ? next->index : n_basic_blocks) - 1;
+
+ /* Now re-scan and wire in all edges. This expect simple (conditional)
+ jumps at the end of each new basic blocks. */
+ make_edges (NULL, min, max, 1);
+
+ /* Update branch probabilities. Expect only (un)conditional jumps
+ to be created with only the forward edges. */
+ for (i = min; i <= max; i++)
+ {
+ edge e;
+ basic_block b = BASIC_BLOCK (i);
+
+ if (i != min)
{
- e = b->succ;
- e->probability = REG_BR_PROB_BASE;
- e->count = b->count;
+ b->count = 0;
+ b->frequency = 0;
+ for (e = b->pred; e; e=e->pred_next)
+ {
+ b->count += e->count;
+ b->frequency += EDGE_FREQUENCY (e);
+ }
}
+ compute_outgoing_frequencies (b);
}
}
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 6be389c..b9f1470 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -1061,7 +1061,10 @@ optimization_options (level, size)
if (TARGET_64BIT && optimize >= 1)
flag_omit_frame_pointer = 1;
if (TARGET_64BIT)
- flag_pcc_struct_return = 0;
+ {
+ flag_pcc_struct_return = 0;
+ flag_asynchronous_unwind_tables = 1;
+ }
}
/* Table of valid machine attributes. */
@@ -2331,7 +2334,7 @@ ix86_va_arg (valist, type)
static int intreg[6] = { 0, 1, 2, 3, 4, 5 };
tree f_gpr, f_fpr, f_ovf, f_sav;
tree gpr, fpr, ovf, sav, t;
- int indirect_p = 0, size, rsize;
+ int size, rsize;
rtx lab_false, lab_over = NULL_RTX;
rtx addr_rtx, r;
rtx container;
@@ -2459,9 +2462,11 @@ ix86_va_arg (valist, type)
int i;
rtx mem;
- mem = assign_temp (type, 0, 1, 0);
+ /* Never use the memory itself, as it has the alias set. */
+ addr_rtx = XEXP (assign_temp (type, 0, 1, 0), 0);
+ mem = gen_rtx_MEM (BLKmode, addr_rtx);
set_mem_alias_set (mem, get_varargs_alias_set ());
- addr_rtx = XEXP (mem, 0);
+
for (i = 0; i < XVECLEN (container, 0); i++)
{
rtx slot = XVECEXP (container, 0, i);
@@ -2487,7 +2492,6 @@ ix86_va_arg (valist, type)
src_mem = adjust_address (src_mem, mode, src_offset);
dest_mem = adjust_address (mem, mode, INTVAL (XEXP (slot, 1)));
PUT_MODE (dest_mem, mode);
- /* ??? Break out TImode moves from integer registers? */
emit_move_insn (dest_mem, src_mem);
}
}
@@ -2543,14 +2547,6 @@ ix86_va_arg (valist, type)
if (container)
emit_label (lab_over);
- if (indirect_p)
- {
- abort ();
- r = gen_rtx_MEM (Pmode, addr_rtx);
- set_mem_alias_set (r, get_varargs_alias_set ());
- emit_move_insn (addr_rtx, r);
- }
-
return addr_rtx;
}
@@ -5931,27 +5927,19 @@ split_di (operands, num, lo_half, hi_half)
while (num--)
{
rtx op = operands[num];
- if (CONSTANT_P (op))
- split_double (op, &lo_half[num], &hi_half[num]);
- else if (! reload_completed)
- {
- lo_half[num] = gen_lowpart (SImode, op);
- hi_half[num] = gen_highpart (SImode, op);
- }
- else if (GET_CODE (op) == REG)
- {
- if (TARGET_64BIT)
- abort();
- lo_half[num] = gen_rtx_REG (SImode, REGNO (op));
- hi_half[num] = gen_rtx_REG (SImode, REGNO (op) + 1);
- }
- else if (offsettable_memref_p (op))
+
+ /* simplify_subreg refuse to split volatile memory addresses,
+ but we still have to handle it. */
+ if (GET_CODE (op) == MEM)
{
lo_half[num] = adjust_address (op, SImode, 0);
hi_half[num] = adjust_address (op, SImode, 4);
}
else
- abort ();
+ {
+ lo_half[num] = simplify_gen_subreg (SImode, op, DImode, 0);
+ hi_half[num] = simplify_gen_subreg (SImode, op, DImode, 4);
+ }
}
}
/* Split one or more TImode RTL references into pairs of SImode
@@ -5969,40 +5957,19 @@ split_ti (operands, num, lo_half, hi_half)
while (num--)
{
rtx op = operands[num];
- if (CONSTANT_P (op))
- {
- if (GET_CODE (op) == CONST_INT)
- {
- lo_half[num] = GEN_INT (trunc_int_for_mode (INTVAL (op), SImode));
- hi_half[num] = (1 << (HOST_BITS_PER_WIDE_INT -1)) != 0 ? constm1_rtx : const0_rtx;
- }
- else if (GET_CODE (op) == CONST_DOUBLE && HOST_BITS_PER_WIDE_INT == 64)
- {
- lo_half[num] = GEN_INT (trunc_int_for_mode (CONST_DOUBLE_LOW (op), SImode));
- hi_half[num] = GEN_INT (trunc_int_for_mode (CONST_DOUBLE_HIGH (op), SImode));
- }
- else
- abort ();
- }
- else if (! reload_completed)
- {
- lo_half[num] = gen_lowpart (DImode, op);
- hi_half[num] = gen_highpart (DImode, op);
- }
- else if (GET_CODE (op) == REG)
- {
- if (TARGET_64BIT)
- abort();
- lo_half[num] = gen_rtx_REG (DImode, REGNO (op));
- hi_half[num] = gen_rtx_REG (DImode, REGNO (op) + 1);
- }
- else if (offsettable_memref_p (op))
+
+ /* simplify_subreg refuse to split volatile memory addresses, but we
+ still have to handle it. */
+ if (GET_CODE (op) == MEM)
{
lo_half[num] = adjust_address (op, DImode, 0);
hi_half[num] = adjust_address (op, DImode, 8);
}
else
- abort ();
+ {
+ lo_half[num] = simplify_gen_subreg (DImode, op, TImode, 0);
+ hi_half[num] = simplify_gen_subreg (DImode, op, TImode, 8);
+ }
}
}
@@ -7860,54 +7827,19 @@ ix86_expand_setcc (code, dest)
{
rtx ret, tmp, tmpreg;
rtx second_test, bypass_test;
- int type;
if (GET_MODE (ix86_compare_op0) == DImode
&& !TARGET_64BIT)
return 0; /* FAIL */
- /* Three modes of generation:
- 0 -- destination does not overlap compare sources:
- clear dest first, emit strict_low_part setcc.
- 1 -- destination does overlap compare sources:
- emit subreg setcc, zero extend.
- 2 -- destination is in QImode:
- emit setcc only.
-
- We don't use mode 0 early in compilation because it confuses CSE.
- There are peepholes to turn mode 1 into mode 0 if things work out
- nicely after reload. */
-
- type = cse_not_expected ? 0 : 1;
-
- if (GET_MODE (dest) == QImode)
- type = 2;
- else if (reg_overlap_mentioned_p (dest, ix86_compare_op0)
- || reg_overlap_mentioned_p (dest, ix86_compare_op1))
- type = 1;
-
- if (type == 0)
- emit_move_insn (dest, const0_rtx);
+ if (GET_MODE (dest) != QImode)
+ abort ();
ret = ix86_expand_compare (code, &second_test, &bypass_test);
PUT_MODE (ret, QImode);
tmp = dest;
tmpreg = dest;
- if (type == 0)
- {
- tmp = gen_lowpart (QImode, dest);
- tmpreg = tmp;
- tmp = gen_rtx_STRICT_LOW_PART (VOIDmode, tmp);
- }
- else if (type == 1)
- {
- if (!cse_not_expected)
- tmp = gen_reg_rtx (QImode);
- else
- tmp = gen_lowpart (QImode, dest);
- tmpreg = tmp;
- }
emit_insn (gen_rtx_SET (VOIDmode, tmp, ret));
if (bypass_test || second_test)
@@ -7932,17 +7864,6 @@ ix86_expand_setcc (code, dest)
emit_insn (gen_iorqi3 (tmp, tmpreg, tmp2));
}
- if (type == 1)
- {
- rtx clob;
-
- tmp = gen_rtx_ZERO_EXTEND (GET_MODE (dest), tmp);
- tmp = gen_rtx_SET (VOIDmode, dest, tmp);
- clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
- tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, tmp, clob));
- emit_insn (tmp);
- }
-
return 1; /* DONE */
}
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 49c1b27..da093be 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -2885,7 +2885,8 @@ extern int const svr4_dbx_register_map[FIRST_PSEUDO_REGISTER];
Whether or not a particular assembler allows us to enter such, I
guess we'll have to see. */
#define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL) \
- (flag_pic ? (GLOBAL ? DW_EH_PE_indirect : 0) | DW_EH_PE_pcrel \
+ (flag_pic \
+ ? (GLOBAL ? DW_EH_PE_indirect : 0) | DW_EH_PE_pcrel | DW_EH_PE_sdata4\
: DW_EH_PE_absptr)
/* This is how to output the definition of a user-level label named NAME,
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index e12c4bd..efede44 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -12423,110 +12423,110 @@
;; way, which can later delete the movzx if only QImode is needed.
(define_expand "seq"
- [(set (match_operand:SI 0 "register_operand" "")
- (eq:SI (reg:CC 17) (const_int 0)))]
+ [(set (match_operand:QI 0 "register_operand" "")
+ (eq:QI (reg:CC 17) (const_int 0)))]
""
"if (ix86_expand_setcc (EQ, operands[0])) DONE; else FAIL;")
(define_expand "sne"
- [(set (match_operand:SI 0 "register_operand" "")
- (ne:SI (reg:CC 17) (const_int 0)))]
+ [(set (match_operand:QI 0 "register_operand" "")
+ (ne:QI (reg:CC 17) (const_int 0)))]
""
"if (ix86_expand_setcc (NE, operands[0])) DONE; else FAIL;")
(define_expand "sgt"
- [(set (match_operand:SI 0 "register_operand" "")
- (gt:SI (reg:CC 17) (const_int 0)))]
+ [(set (match_operand:QI 0 "register_operand" "")
+ (gt:QI (reg:CC 17) (const_int 0)))]
""
"if (ix86_expand_setcc (GT, operands[0])) DONE; else FAIL;")
(define_expand "sgtu"
- [(set (match_operand:SI 0 "register_operand" "")
- (gtu:SI (reg:CC 17) (const_int 0)))]
+ [(set (match_operand:QI 0 "register_operand" "")
+ (gtu:QI (reg:CC 17) (const_int 0)))]
""
"if (ix86_expand_setcc (GTU, operands[0])) DONE; else FAIL;")
(define_expand "slt"
- [(set (match_operand:SI 0 "register_operand" "")
- (lt:SI (reg:CC 17) (const_int 0)))]
+ [(set (match_operand:QI 0 "register_operand" "")
+ (lt:QI (reg:CC 17) (const_int 0)))]
""
"if (ix86_expand_setcc (LT, operands[0])) DONE; else FAIL;")
(define_expand "sltu"
- [(set (match_operand:SI 0 "register_operand" "")
- (ltu:SI (reg:CC 17) (const_int 0)))]
+ [(set (match_operand:QI 0 "register_operand" "")
+ (ltu:QI (reg:CC 17) (const_int 0)))]
""
"if (ix86_expand_setcc (LTU, operands[0])) DONE; else FAIL;")
(define_expand "sge"
- [(set (match_operand:SI 0 "register_operand" "")
- (ge:SI (reg:CC 17) (const_int 0)))]
+ [(set (match_operand:QI 0 "register_operand" "")
+ (ge:QI (reg:CC 17) (const_int 0)))]
""
"if (ix86_expand_setcc (GE, operands[0])) DONE; else FAIL;")
(define_expand "sgeu"
- [(set (match_operand:SI 0 "register_operand" "")
- (geu:SI (reg:CC 17) (const_int 0)))]
+ [(set (match_operand:QI 0 "register_operand" "")
+ (geu:QI (reg:CC 17) (const_int 0)))]
""
"if (ix86_expand_setcc (GEU, operands[0])) DONE; else FAIL;")
(define_expand "sle"
- [(set (match_operand:SI 0 "register_operand" "")
- (le:SI (reg:CC 17) (const_int 0)))]
+ [(set (match_operand:QI 0 "register_operand" "")
+ (le:QI (reg:CC 17) (const_int 0)))]
""
"if (ix86_expand_setcc (LE, operands[0])) DONE; else FAIL;")
(define_expand "sleu"
- [(set (match_operand:SI 0 "register_operand" "")
- (leu:SI (reg:CC 17) (const_int 0)))]
+ [(set (match_operand:QI 0 "register_operand" "")
+ (leu:QI (reg:CC 17) (const_int 0)))]
""
"if (ix86_expand_setcc (LEU, operands[0])) DONE; else FAIL;")
(define_expand "sunordered"
- [(set (match_operand:SI 0 "register_operand" "")
- (unordered:SI (reg:CC 17) (const_int 0)))]
+ [(set (match_operand:QI 0 "register_operand" "")
+ (unordered:QI (reg:CC 17) (const_int 0)))]
"TARGET_80387 || TARGET_SSE"
"if (ix86_expand_setcc (UNORDERED, operands[0])) DONE; else FAIL;")
(define_expand "sordered"
- [(set (match_operand:SI 0 "register_operand" "")
- (ordered:SI (reg:CC 17) (const_int 0)))]
+ [(set (match_operand:QI 0 "register_operand" "")
+ (ordered:QI (reg:CC 17) (const_int 0)))]
"TARGET_80387"
"if (ix86_expand_setcc (ORDERED, operands[0])) DONE; else FAIL;")
(define_expand "suneq"
- [(set (match_operand:SI 0 "register_operand" "")
- (uneq:SI (reg:CC 17) (const_int 0)))]
+ [(set (match_operand:QI 0 "register_operand" "")
+ (uneq:QI (reg:CC 17) (const_int 0)))]
"TARGET_80387 || TARGET_SSE"
"if (ix86_expand_setcc (UNEQ, operands[0])) DONE; else FAIL;")
(define_expand "sunge"
- [(set (match_operand:SI 0 "register_operand" "")
- (unge:SI (reg:CC 17) (const_int 0)))]
+ [(set (match_operand:QI 0 "register_operand" "")
+ (unge:QI (reg:CC 17) (const_int 0)))]
"TARGET_80387 || TARGET_SSE"
"if (ix86_expand_setcc (UNGE, operands[0])) DONE; else FAIL;")
(define_expand "sungt"
- [(set (match_operand:SI 0 "register_operand" "")
- (ungt:SI (reg:CC 17) (const_int 0)))]
+ [(set (match_operand:QI 0 "register_operand" "")
+ (ungt:QI (reg:CC 17) (const_int 0)))]
"TARGET_80387 || TARGET_SSE"
"if (ix86_expand_setcc (UNGT, operands[0])) DONE; else FAIL;")
(define_expand "sunle"
- [(set (match_operand:SI 0 "register_operand" "")
- (unle:SI (reg:CC 17) (const_int 0)))]
+ [(set (match_operand:QI 0 "register_operand" "")
+ (unle:QI (reg:CC 17) (const_int 0)))]
"TARGET_80387 || TARGET_SSE"
"if (ix86_expand_setcc (UNLE, operands[0])) DONE; else FAIL;")
(define_expand "sunlt"
- [(set (match_operand:SI 0 "register_operand" "")
- (unlt:SI (reg:CC 17) (const_int 0)))]
+ [(set (match_operand:QI 0 "register_operand" "")
+ (unlt:QI (reg:CC 17) (const_int 0)))]
"TARGET_80387 || TARGET_SSE"
"if (ix86_expand_setcc (UNLT, operands[0])) DONE; else FAIL;")
(define_expand "sltgt"
- [(set (match_operand:SI 0 "register_operand" "")
- (ltgt:SI (reg:CC 17) (const_int 0)))]
+ [(set (match_operand:QI 0 "register_operand" "")
+ (ltgt:QI (reg:CC 17) (const_int 0)))]
"TARGET_80387 || TARGET_SSE"
"if (ix86_expand_setcc (LTGT, operands[0])) DONE; else FAIL;")
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 89ee913..d8887d8 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -602,7 +602,7 @@ in the following sections.
@gccoptlist{
-fcall-saved-@var{reg} -fcall-used-@var{reg} @gol
-ffixed-@var{reg} -fexceptions @gol
--fnon-call-exceptions -funwind-tables @gol
+-fnon-call-exceptions -funwind-tables -fasynchronous-unwind-tables @gol
-finhibit-size-directive -finstrument-functions @gol
-fcheck-memory-usage -fprefix-function-name @gol
-fno-common -fno-ident -fno-gnu-linker @gol
@@ -9658,6 +9658,12 @@ static data, but will not affect the generated code in any other way.
You will normally not enable this option; instead, a language processor
that needs this handling would enable it on your behalf.
+@item -fasynchronous-unwind-tables
+@opindex funwind-tables
+Generate unwind table in dwarf2 format, if supported by target machine. The
+table is exact at each instruction boundary, so it can be used for stack
+unwinding from asynchronous events (such as debugger or garbage collector).
+
@item -fpcc-struct-return
@opindex fpcc-struct-return
Return ``short'' @code{struct} and @code{union} values in memory like
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 1d245b7..486c7a2 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -943,7 +943,8 @@ dwarf2out_stack_adjust (insn)
long offset;
const char *label;
- if (! flag_non_call_exceptions && GET_CODE (insn) == CALL_INSN)
+ if (!flag_asynchronous_unwind_tables
+ && GET_CODE (insn) == CALL_INSN)
{
/* Extract the size of the args from the CALL rtx itself. */
@@ -960,7 +961,7 @@ dwarf2out_stack_adjust (insn)
/* If only calls can throw, and we have a frame pointer,
save up adjustments until we see the CALL_INSN. */
- else if (! flag_non_call_exceptions
+ else if (!flag_asynchronous_unwind_tables
&& cfa.reg != STACK_POINTER_REGNUM)
return;
@@ -1721,7 +1722,7 @@ output_call_frame_info (for_eh)
emit any EH unwind information. */
if (for_eh)
{
- int any_eh_needed = 0;
+ int any_eh_needed = flag_asynchronous_unwind_tables;
for (i = 0; i < fde_table_in_use; ++i)
if (fde_table[i].uses_eh_lsda)
any_eh_needed = any_lsda_needed = 1;
diff --git a/gcc/flags.h b/gcc/flags.h
index bf9e2af..04c3ed9 100644
--- a/gcc/flags.h
+++ b/gcc/flags.h
@@ -451,6 +451,10 @@ extern int flag_exceptions;
extern int flag_unwind_tables;
+/* Nonzero means generate frame unwind info table exact at each insn boundary */
+
+extern int flag_asynchronous_unwind_tables;
+
/* Nonzero means don't place uninitialized global data in common storage
by default. */
diff --git a/gcc/flow.c b/gcc/flow.c
index 030a233..58bf257 100644
--- a/gcc/flow.c
+++ b/gcc/flow.c
@@ -344,6 +344,7 @@ static void invalidate_mems_from_autoinc PARAMS ((struct propagate_block_info *,
static void invalidate_mems_from_set PARAMS ((struct propagate_block_info *,
rtx));
static void delete_dead_jumptables PARAMS ((void));
+static void clear_log_links PARAMS ((sbitmap));
void
@@ -628,12 +629,19 @@ update_life_info (blocks, extent, prop_flags)
tmp = INITIALIZE_REG_SET (tmp_head);
+ timevar_push ((extent == UPDATE_LIFE_LOCAL || blocks)
+ ? TV_LIFE_UPDATE : TV_LIFE);
+
/* Changes to the CFG are only allowed when
doing a global update for the entire CFG. */
if ((prop_flags & PROP_ALLOW_CFG_CHANGES)
&& (extent == UPDATE_LIFE_LOCAL || blocks))
abort ();
+ /* Clear log links in case we are asked to (re)compute them. */
+ if (prop_flags & PROP_LOG_LINKS)
+ clear_log_links (blocks);
+
/* For a global update, we go through the relaxation process again. */
if (extent != UPDATE_LIFE_LOCAL)
{
@@ -727,6 +735,8 @@ update_life_info (blocks, extent, prop_flags)
}
});
}
+ timevar_pop ((extent == UPDATE_LIFE_LOCAL || blocks)
+ ? TV_LIFE_UPDATE : TV_LIFE);
}
/* Free the variables allocated by find_basic_blocks.
@@ -4088,31 +4098,33 @@ count_or_remove_death_notes (blocks, kill)
return count;
}
-/* Clear LOG_LINKS fields of insns in a chain.
- Also clear the global_live_at_{start,end} fields of the basic block
- structures. */
+/* Clear LOG_LINKS fields of insns in a selected blocks or whole chain
+ if blocks is NULL. */
-void
-clear_log_links (insns)
- rtx insns;
+static void
+clear_log_links (blocks)
+ sbitmap blocks;
{
- rtx i;
- int b;
-
- for (i = insns; i; i = NEXT_INSN (i))
- if (INSN_P (i))
- LOG_LINKS (i) = 0;
+ rtx insn;
+ int i;
- for (b = 0; b < n_basic_blocks; b++)
+ if (!blocks)
{
- basic_block bb = BASIC_BLOCK (b);
-
- bb->global_live_at_start = NULL;
- bb->global_live_at_end = NULL;
+ rtx insn;
+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ if (INSN_P (insn))
+ free_EXPR_LIST_list (&LOG_LINKS (insn));
}
-
- ENTRY_BLOCK_PTR->global_live_at_end = NULL;
- EXIT_BLOCK_PTR->global_live_at_start = NULL;
+ else
+ EXECUTE_IF_SET_IN_SBITMAP (blocks, 0, i,
+ {
+ basic_block bb = BASIC_BLOCK (i);
+ rtx insn;
+ for (insn = bb->head; insn != NEXT_INSN (bb->end);
+ insn = NEXT_INSN (insn))
+ if (INSN_P (insn))
+ free_EXPR_LIST_list (&LOG_LINKS (insn));
+ });
}
/* Given a register bitmap, turn on the bits in a HARD_REG_SET that
diff --git a/gcc/recog.c b/gcc/recog.c
index 6c3ecd4..874d567 100644
--- a/gcc/recog.c
+++ b/gcc/recog.c
@@ -2778,8 +2778,7 @@ split_all_insns (upd_life)
if (changed)
{
- for (i = 0; i < n_basic_blocks; i++)
- find_sub_basic_blocks (BASIC_BLOCK (i));
+ find_many_sub_basic_blocks (blocks);
}
if (changed && upd_life)
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 4c0eb2c..d6908e9 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -1481,7 +1481,6 @@ void free_EXPR_LIST_node PARAMS ((rtx));
void free_INSN_LIST_node PARAMS ((rtx));
rtx alloc_INSN_LIST PARAMS ((rtx, rtx));
rtx alloc_EXPR_LIST PARAMS ((int, rtx, rtx));
-void clear_log_links PARAMS ((rtx));
/* regclass.c */
diff --git a/gcc/timevar.def b/gcc/timevar.def
index 7f62497..353a942 100644
--- a/gcc/timevar.def
+++ b/gcc/timevar.def
@@ -43,6 +43,9 @@ DEFTIMEVAR (TV_DUMP , "dump files")
DEFTIMEVAR (TV_CFG , "cfg construction")
/* Time spent by cleaning up CFG. */
DEFTIMEVAR (TV_CLEANUP_CFG , "cfg cleanup")
+/* Time spent by life analysis. */
+DEFTIMEVAR (TV_LIFE , "life analysis")
+DEFTIMEVAR (TV_LIFE_UPDATE , "life info update")
/* Timing in various stages of the compiler. */
DEFTIMEVAR (TV_CPP , "preprocessing")
DEFTIMEVAR (TV_LEX , "lexical analysis")
@@ -60,6 +63,7 @@ DEFTIMEVAR (TV_FLOW , "flow analysis")
DEFTIMEVAR (TV_COMBINE , "combiner")
DEFTIMEVAR (TV_IFCVT , "if-conversion")
DEFTIMEVAR (TV_REGMOVE , "regmove")
+DEFTIMEVAR (TV_MODE_SWITCH , "mode switching")
DEFTIMEVAR (TV_SCHED , "scheduling")
DEFTIMEVAR (TV_LOCAL_ALLOC , "local alloc")
DEFTIMEVAR (TV_GLOBAL_ALLOC , "global alloc")
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 2df15e7..3bc9dac 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -737,6 +737,10 @@ int flag_exceptions;
int flag_unwind_tables = 0;
+/* Nonzero means generate frame unwind info table exact at each insn boundary */
+
+int flag_asynchronous_unwind_tables = 0;
+
/* Nonzero means don't place uninitialized global data in common storage
by default. */
@@ -1096,6 +1100,8 @@ lang_independent_options f_options[] =
N_("Enable exception handling") },
{"unwind-tables", &flag_unwind_tables, 1,
N_("Just generate unwind tables for exception handling") },
+ {"asynchronous-unwind-tables", &flag_asynchronous_unwind_tables, 1,
+ N_("Generate unwind tables exact at each instruction boundary") },
{"non-call-exceptions", &flag_non_call_exceptions, 1,
N_("Support synchronous non-call exceptions") },
{"profile-arcs", &profile_arc_flag, 1,
@@ -2933,10 +2939,6 @@ rest_of_compilation (decl)
convert_from_ssa ();
/* New registers have been created. Rescan their usage. */
reg_scan (insns, max_reg_num (), 1);
- /* Life analysis used in SSA adds log_links but these
- shouldn't be there until the flow stage, so clear
- them away. */
- clear_log_links (insns);
close_dump_file (DFI_ussa, print_rtl_with_bb, insns);
timevar_pop (TV_FROM_SSA);
@@ -3370,7 +3372,7 @@ rest_of_compilation (decl)
register_life_up_to_date = 0;
#ifdef OPTIMIZE_MODE_SWITCHING
- timevar_push (TV_GCSE);
+ timevar_push (TV_MODE_SWITCH);
no_new_pseudos = 0;
if (optimize_mode_switching (NULL))
@@ -3382,7 +3384,7 @@ rest_of_compilation (decl)
}
no_new_pseudos = 1;
- timevar_pop (TV_GCSE);
+ timevar_pop (TV_MODE_SWITCH);
#endif
timevar_push (TV_SCHED);
@@ -4911,6 +4913,11 @@ toplev_main (argc, argv)
flag_rerun_cse_after_loop = 1;
}
+ if (flag_non_call_exceptions)
+ flag_asynchronous_unwind_tables = 1;
+ if (flag_asynchronous_unwind_tables)
+ flag_unwind_tables = 1;
+
/* Warn about options that are not supported on this machine. */
#ifndef INSN_SCHEDULING
if (flag_schedule_insns || flag_schedule_insns_after_reload)