i386.md (testsi to testqi spliters): New.

* i386.md (testsi to testqi spliters): New.

	2002-01-14  Josef Zlomek  <zlomek@matfyz.cz>

	cfg.c (dump_edge_info): added dumping of EDGE_CAN_FALLTHRU.

	Wed Jan  9 2002  Josef Zlomek  <zlomj9am@artax.karlin.mff.cuni.cz>

	* basic-block.h: New flag EDGE_CAN_FALLTHRU
	* cfganal.c (set_edge_can_fallthru_flag): New function; marks the edges
	that can be made fallthru.

	Mon Nov 12 16:25:53 CET 2001  Jan Hubicka  <jh@suse.cz>

	* cfglayout.c (cleanup_unconditional_jumps): New static function.
	(cfg_layout_initialize): Use it.

Co-Authored-By: Pavel Nejedly <bim@atrey.karlin.mff.cuni.cz>

From-SVN: r53383
This commit is contained in:
Jan Hubicka 2002-05-11 19:16:28 +02:00 committed by Jan Hubicka
parent a5c76ee6e2
commit 6c81a49011
6 changed files with 211 additions and 66 deletions

View File

@ -1,43 +1,21 @@
2002-05-11 Zack Weinberg <zack@codesourcery.com>
Sat May 11 14:34:35 CEST 2002 Jan Hubicka <jh@suse.cz>
* config/rs6000/rs6000.c (rs6000_default_long_calls,
rs6000_longcall_switch, rs6000_set_default_type_attributes): New.
(TARGET_SET_DEFAULT_TYPE_ATTRIBUTES): Set it.
(rs6000_override_options): Handle -m(no-)longcall.
(init_cumulative_args, output_mi_thunk): Check for both
longcall and shortcall attributes on the function.
(rs6000_attribute_table): Add "shortcall".
(rs6000_handle_longcall_attribute): Update comment.
(altivec_expand_unop_builtin, altivec_expand_binop_builtin,
altivec_expand_ternop_builtin): Add default clauses to switches
to silence warnings.
* i386.md (testsi to testqi spliters): New.
* config/rs6000/rs6000.h: Declare rs6000_longcall_switch and
rs6000_default_long_calls. Define REGISTER_TARGET_PRAGMAS.
(TARGET_OPTIONS): Add longcall and no-longcall.
2002-01-14 Josef Zlomek <zlomek@matfyz.cz>
* config/rs6000/rs6000.md (call_nonlocal_sysv,
call_value_nonlocal_sysv): Split by alternatives. One pair
accepts only SYMBOL_REFs and rejects if CALL_LONG is set in
the call cookie. The other pair accepts only LR/CTR and has
no restriction.
cfg.c (dump_edge_info): added dumping of EDGE_CAN_FALLTHRU.
* config.gcc (rs6000-*-* | powerpc*-*-* trailer stanza):
Set c_target_objs, cxx_target_objs; add t-rs6000-c-rule to
tmake_file.
* config/rs6000/rs6000-c.c: New file.
* config/rs6000/t-rs6000-c-rule: New file.
* config/rs6000/rs6000-protos.c: Add multiple-include guard.
Prototype rs6000_pragma_longcall.
Wed Jan 9 2002 Josef Zlomek <zlomj9am@artax.karlin.mff.cuni.cz>
* doc/extend.texi: Document shortcall attribute.
* doc/invoke.texi: Document -mlongcall, -mno-longcall.
* basic-block.h: New flag EDGE_CAN_FALLTHRU
* cfganal.c (set_edge_can_fallthru_flag): New function; marks the edges
that can be made fallthru.
2002-05-12 Marek Michalkiewicz <marekm@amelek.gda.pl>
Mon Nov 12 16:25:53 CET 2001 Jan Hubicka <jh@suse.cz>
* config/avr/avr.c (avr_mcu_types): Update supported devices.
* config/avr/avr.h (CPP_SPEC, LINK_SPEC, CRT_BINUTILS_SPECS): Likewise.
* config/avr/t-avr (MULTILIB_MATCHES): Likewise.
* cfglayout.c (cleanup_unconditional_jumps): New static function.
(cfg_layout_initialize): Use it.
2002-05-11 Kazu Hirata <kazu@cs.umass.edu>
@ -240,38 +218,38 @@ Thu May 9 14:52:45 CEST 2002 Jan Hubicka <jh@suse.cz>
* final.c (end_final): Use C trees to output data structures for profiling.
* Makefile.in (LIBGCC_DEPS): Added missing dependency on gcov-io.h
(profile.o): New dependency profile.h
(final.o): New dependency profile.h
* profile.h: New file. New global structure profile_info.
* final.h (count_edges_instrumented_now): Declare.
(current_function_cfg_checksum): Declare.
(function_list): New structure.
(functions_head, functions_tail): New static variables.
(end_final): Emits more data, removed some -ax stuff.
(final): Stores function names and chcksums.
* gcov-io.h (__write_gcov_string): New function.
(__read_gcov_string): New function.
* gcov.c (read_profile): New function.
(create_program_flow_graph): Uses read_profile instead of reading
(profile.o): New dependency profile.h
(final.o): New dependency profile.h
* profile.h: New file. New global structure profile_info.
* final.h (count_edges_instrumented_now): Declare.
(current_function_cfg_checksum): Declare.
(function_list): New structure.
(functions_head, functions_tail): New static variables.
(end_final): Emits more data, removed some -ax stuff.
(final): Stores function names and chcksums.
* gcov-io.h (__write_gcov_string): New function.
(__read_gcov_string): New function.
* gcov.c (read_profile): New function.
(create_program_flow_graph): Uses read_profile instead of reading
da_file.
(read_files): Removed da_file checking, it's done by read_profile now.
* libgcc2.c (bb_function_info): New structure.
(bb): New field in structure, removed some -ax stuff.
(__bb_exit_func): Changed structure of da_file.
* profile.c (count_edges_instrumented_now): New global variable.
(current_function_cfg_checksum): New global variable.
(max_counter_in_program): New global variable.
(get_exec_counts): New function.
(compute_checksum): New function.
(instrument_edges): Sets count_edges_instrumented_now.
(compute_branch_probabilities): Uses get_exec_counts instead of
(read_files): Removed da_file checking, it's done by read_profile now.
* libgcc2.c (bb_function_info): New structure.
(bb): New field in structure, removed some -ax stuff.
(__bb_exit_func): Changed structure of da_file.
* profile.c (count_edges_instrumented_now): New global variable.
(current_function_cfg_checksum): New global variable.
(max_counter_in_program): New global variable.
(get_exec_counts): New function.
(compute_checksum): New function.
(instrument_edges): Sets count_edges_instrumented_now.
(compute_branch_probabilities): Uses get_exec_counts instead of
reading da_file.
(branch_prob): Calls compute_checksum and writes extra data to bbg_file.
(init_branch_prob): Removed da_file checking, done in get_exec_counts
(branch_prob): Calls compute_checksum and writes extra data to bbg_file.
(init_branch_prob): Removed da_file checking, done in get_exec_counts
now.
(end_branch_prob): Removed da_file checking, done in get_exec_counts
(end_branch_prob): Removed da_file checking, done in get_exec_counts
now.
* gcov.texi: Updated information about gcov file format.
* gcov.texi: Updated information about gcov file format.
2002-05-09 Kazu Hirata <kazu@cs.umass.edu>

View File

@ -141,6 +141,7 @@ typedef struct edge_def {
#define EDGE_EH 8
#define EDGE_FAKE 16
#define EDGE_DFS_BACK 32
#define EDGE_CAN_FALLTHRU 64
#define EDGE_COMPLEX (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL | EDGE_EH)
@ -699,6 +700,7 @@ extern conflict_graph conflict_graph_compute
PARAMS ((regset,
partition));
extern bool mark_dfs_back_edges PARAMS ((void));
extern void set_edge_can_fallthru_flag PARAMS ((void));
extern void update_br_prob_note PARAMS ((basic_block));
extern void fixup_abnormal_edges PARAMS ((void));

View File

@ -609,7 +609,7 @@ dump_edge_info (file, e, do_succ)
if (e->flags)
{
static const char * const bitnames[]
= {"fallthru", "ab", "abcall", "eh", "fake", "dfs_back"};
= {"fallthru", "ab", "abcall", "eh", "fake", "dfs_back", "can_fallthru"};
int comma = 0;
int i, flags = e->flags;

View File

@ -189,6 +189,36 @@ mark_dfs_back_edges ()
return found;
}
/* Set the flag EDGE_CAN_FALLTHRU for edges that can be fallthru. */
void
set_edge_can_fallthru_flag ()
{
int i;
for (i = 0; i < n_basic_blocks; i++)
{
basic_block bb = BASIC_BLOCK (i);
edge e;
/* The FALLTHRU edge is also CAN_FALLTHRU edge. */
for (e = bb->succ; e; e = e->succ_next)
if (e->flags & EDGE_FALLTHRU)
e->flags |= EDGE_CAN_FALLTHRU;
/* If the BB ends with an invertable condjump all (2) edges are
CAN_FALLTHRU edges. */
if (!bb->succ || !bb->succ->succ_next || bb->succ->succ_next->succ_next)
continue;
if (!any_condjump_p (bb->end))
continue;
if (!invert_jump (bb->end, JUMP_LABEL (bb->end), 0))
continue;
invert_jump (bb->end, JUMP_LABEL (bb->end), 0);
bb->succ->flags |= EDGE_CAN_FALLTHRU;
bb->succ->succ_next->flags |= EDGE_CAN_FALLTHRU;
}
}
/* Return true if we need to add fake edge to exit.
Helper function for the flow_call_edges_add. */
@ -326,9 +356,12 @@ flow_call_edges_add (blocks)
/* Note that the following may create a new basic block
and renumber the existing basic blocks. */
e = split_block (bb, split_at_insn);
if (e)
blocks_split++;
if (split_at_insn != bb->end)
{
e = split_block (bb, split_at_insn);
if (e)
blocks_split++;
}
make_edge (bb, EXIT_BLOCK_PTR, EDGE_FAKE);
}

View File

@ -46,6 +46,7 @@ static void set_block_levels PARAMS ((tree, int));
static void change_scope PARAMS ((rtx, tree, tree));
void verify_insn_chain PARAMS ((void));
static void cleanup_unconditional_jumps PARAMS ((void));
static void fixup_fallthru_exit_predecessor PARAMS ((void));
static rtx unlink_insn_chain PARAMS ((rtx, rtx));
static rtx duplicate_insn_chain PARAMS ((rtx, rtx));
@ -578,6 +579,76 @@ verify_insn_chain ()
abort ();
}
/* Remove any unconditional jumps and forwarder block creating fallthru
edges instead. During BB reordering fallthru edges are not required
to target next basic block in the linear CFG layout, so the unconditional
jumps are not needed. If LOOPS is not null, also update loop structure &
dominators. */
static void
cleanup_unconditional_jumps ()
{
int i;
for (i = 0; i < n_basic_blocks; i++)
{
basic_block bb = BASIC_BLOCK (i);
if (!bb->succ)
continue;
if (bb->succ->flags & EDGE_FALLTHRU)
continue;
if (!bb->succ->succ_next)
{
rtx insn;
if (GET_CODE (bb->head) != CODE_LABEL && forwarder_block_p (bb) && i)
{
basic_block prev = BASIC_BLOCK (--i);
if (rtl_dump_file)
fprintf (rtl_dump_file, "Removing forwarder BB %i\n",
bb->index);
redirect_edge_succ (bb->pred, bb->succ->dest);
flow_delete_block (bb);
bb = prev;
}
else if (simplejump_p (bb->end))
{
rtx jump = bb->end;
if (rtl_dump_file)
fprintf (rtl_dump_file, "Removing jump %i in BB %i\n",
INSN_UID (jump), bb->index);
delete_insn (jump);
bb->succ->flags |= EDGE_FALLTHRU;
}
else
continue;
/* Cleanup barriers and delete ADDR_VECs in a way as they are belonging
to removed tablejump anyway. */
insn = NEXT_INSN (bb->end);
while (insn
&& (GET_CODE (insn) != NOTE
|| NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK))
{
rtx next = NEXT_INSN (insn);
if (GET_CODE (insn) == BARRIER)
delete_barrier (insn);
else if (GET_CODE (insn) == JUMP_INSN)
delete_insn_chain (PREV_INSN (insn), insn);
else if (GET_CODE (insn) == CODE_LABEL)
;
else if (GET_CODE (insn) != NOTE)
abort ();
insn = next;
}
}
}
}
/* The block falling through to exit must be the last one in the
reordered chain. Ensure that this condition is met. */
static void
@ -767,6 +838,14 @@ cfg_layout_redirect_edge (e, dest)
}
else
redirect_edge_and_branch (e, dest);
/* We don't want simplejumps in the insn stream during cfglayout. */
if (simplejump_p (src->end))
{
delete_insn (src->end);
delete_barrier (NEXT_INSN (src->end));
src->succ->flags |= EDGE_FALLTHRU;
}
dest->index = old_index;
}
@ -868,6 +947,8 @@ cfg_layout_initialize ()
around the code. */
alloc_aux_for_blocks (sizeof (struct reorder_block_def));
cleanup_unconditional_jumps ();
scope_to_insns_initialize ();
record_effective_endpoints ();

View File

@ -7640,6 +7640,56 @@
operands[3] = gen_rtx_AND (mode, operands[0], gen_int_mode (mask, mode));
})
;; Convert HImode/SImode test instructions with immediate to QImode ones.
;; i386 does not allow to encode test with 8bit sign extended immediate, so
;; this is relatively important trick.
;; Do the converison only post-reload to avoid limiting of the register class
;; to QI regs.
(define_split
[(set (reg 17)
(compare
(and (match_operand 0 "register_operand" "")
(match_operand 1 "const_int_operand" ""))
(const_int 0)))]
"(!TARGET_PROMOTE_QImode || optimize_size)
&& reload_completed
&& QI_REG_P (operands[0])
&& ((ix86_match_ccmode (insn, CCZmode)
&& !(INTVAL (operands[1]) & ~(255 << 8)))
|| (ix86_match_ccmode (insn, CCNOmode)
&& !(INTVAL (operands[1]) & ~(127 << 8))))
&& GET_MODE (operands[0]) != QImode"
[(set (reg:CCNO 17)
(compare:CCNO
(and:SI (zero_extract:SI (match_dup 0) (const_int 8) (const_int 8))
(match_dup 1))
(const_int 0)))]
"operands[0] = gen_lowpart (SImode, operands[0]);
operands[1] = gen_int_mode (INTVAL (operands[1]) >> 8, QImode);")
(define_split
[(set (reg 17)
(compare
(and (match_operand 0 "nonimmediate_operand" "")
(match_operand 1 "const_int_operand" ""))
(const_int 0)))]
"(!TARGET_PROMOTE_QImode || optimize_size)
&& reload_completed
&& (!REG_P (operands[0]) || ANY_QI_REG_P (operands[0]))
&& ((ix86_match_ccmode (insn, CCZmode)
&& !(INTVAL (operands[1]) & ~255))
|| (ix86_match_ccmode (insn, CCNOmode)
&& !(INTVAL (operands[1]) & ~127)))
&& GET_MODE (operands[0]) != QImode"
[(set (reg:CCNO 17)
(compare:CCNO
(and:QI (match_dup 0)
(match_dup 1))
(const_int 0)))]
"operands[0] = gen_lowpart (QImode, operands[0]);
operands[1] = gen_lowpart (QImode, operands[1]);")
;; %%% This used to optimize known byte-wide and operations to memory,
;; and sometimes to QImode registers. If this is considered useful,
;; it should be done with splitters.
@ -16494,7 +16544,8 @@
(const_int 0)))]
"ix86_match_ccmode (insn, CCNOmode)
&& (true_regnum (operands[0]) != 0
|| CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'K'))
|| (GET_CODE (operands[1]) == CONST_INT
&& CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'K')))
&& find_regno_note (insn, REG_DEAD, true_regnum (operands[0]))"
[(parallel
[(set (reg:CCNO 17)