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
This commit is contained in:
Jan Hubicka 2001-10-20 12:04:00 +02:00 committed by Jan Hubicka
parent 870628131c
commit b932f770f7
17 changed files with 321 additions and 215 deletions

View File

@ -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,

View File

@ -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

View File

@ -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 *));

View File

@ -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

View File

@ -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. */

View File

@ -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;
compute_outgoing_frequencies (b);
}
for (i = 0; i < n_basic_blocks; i++)
SET_STATE (BASIC_BLOCK (i), 0);
}
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)
/* 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);
}
}

View File

@ -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 */
}

View File

@ -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,

View File

@ -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;")

View File

@ -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

View File

@ -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;

View File

@ -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. */

View File

@ -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;
rtx insn;
int i;
for (i = insns; i; i = NEXT_INSN (i))
if (INSN_P (i))
LOG_LINKS (i) = 0;
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

View File

@ -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)

View File

@ -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 */

View File

@ -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")

View File

@ -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)