Commit e78d9500 by Jeffrey A Law Committed by Jeff Law

gcse.c (run_jump_opt_after_gcse): New variable.

        * gcse.c (run_jump_opt_after_gcse): New variable.
        (gcse_main): Returns an integer.
        (hash_scan_set): Record initializations from CONST_DOUBLEs too.
        (try_replace_reg): Update some comments.
        (cprop_insn): Allow propagation into some JUMP_INSNs too.
        * rtl.h (gcse_main): Update prototype.
        * toplev.c (rest_of_compilation): If gcse_main returns nonzero,
        then run a jump optimization pass.
        * jump.c (delete_barrier_successors): Delete nop jumps too.

From-SVN: r25673
parent b7975aed
Wed Mar 10 20:28:29 1999 Jeffrey A Law (law@cygnus.com)
* gcse.c (run_jump_opt_after_gcse): New variable.
(gcse_main): Returns an integer.
(hash_scan_set): Record initializations from CONST_DOUBLEs too.
(try_replace_reg): Update some comments.
(cprop_insn): Allow propagation into some JUMP_INSNs too.
* rtl.h (gcse_main): Update prototype.
* toplev.c (rest_of_compilation): If gcse_main returns nonzero,
then run a jump optimization pass.
* jump.c (delete_barrier_successors): Delete nop jumps too.
Wed Mar 10 19:04:31 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
* sh.c (fp_arith_reg_operand): Actually test if reg is suitable
......
......@@ -188,7 +188,7 @@ yyy
4) Perform global cse.
5) Perform another pass of copy/constant propagation [only if PRE].
5) Perform another pass of copy/constant propagation.
Two passes of copy/constant propagation are done because the first one
enables more GCSE and the second one helps to clean up the copies that
......@@ -333,6 +333,15 @@ static int_list_ptr *s_succs;
static int *num_preds;
static int *num_succs;
/* Note whether or not we should run jump optimization after gcse. We
want to do this for two cases.
* If we changed any jumps via cprop.
* If we added any labels via edge splitting. */
static int run_jump_opt_after_gcse;
/* Hash table of expressions. */
struct expr
......@@ -648,7 +657,7 @@ static void add_label_notes PROTO ((rtx, rtx));
/* Entry point for global common subexpression elimination.
F is the first instruction in the function. */
void
int
gcse_main (f, file)
rtx f;
FILE *file;
......@@ -661,10 +670,12 @@ gcse_main (f, file)
/* Point to release obstack data from for each pass. */
char *gcse_obstack_bottom;
run_jump_opt_after_gcse = 0;
/* It's impossible to construct a correct control flow graph in the
presense of setjmp, so just punt to be safe. */
if (current_function_calls_setjmp)
return;
return 0;
/* For calling dump_foo fns from gdb. */
debug_stderr = stderr;
......@@ -677,7 +688,7 @@ gcse_main (f, file)
{
/* Free storage allocated by find_basic_blocks. */
free_basic_block_vars (0);
return;
return 0;
}
/* See what modes support reg/reg copy operations. */
......@@ -778,6 +789,7 @@ gcse_main (f, file)
free_bb_mem ();
/* Free storage allocated by find_basic_blocks. */
free_basic_block_vars (0);
return run_jump_opt_after_gcse;
}
/* Misc. utilities. */
......@@ -1800,7 +1812,8 @@ hash_scan_set (pat, insn, set_p)
&& REGNO (src) >= FIRST_PSEUDO_REGISTER
&& can_copy_p [GET_MODE (dest)])
/* ??? CONST_INT:wip */
|| GET_CODE (src) == CONST_INT)
|| GET_CODE (src) == CONST_INT
|| GET_CODE (src) == CONST_DOUBLE)
/* A copy is not available if its src or dest is subsequently
modified. Here we want to search from INSN+1 on, but
oprs_available_p searches from INSN on. */
......@@ -3690,6 +3703,11 @@ static int
try_replace_reg (from, to, insn)
rtx from, to, insn;
{
/* If this fails we could try to simplify the result of the
replacement and attempt to recognize the simplified insn.
But we need a general simplify_rtx that doesn't have pass
specific state variables. I'm not aware of one at the moment. */
return validate_replace_src (from, to, insn);
}
......@@ -3723,8 +3741,10 @@ cprop_insn (insn)
struct reg_use *reg_used;
int changed = 0;
/* ??? For now only propagate into SETs. */
if (GET_CODE (insn) != INSN
/* Only propagate into SETs. Note that a conditional jump is a
SET with pc_rtx as the destination. */
if ((GET_CODE (insn) != INSN
&& GET_CODE (insn) != JUMP_INSN)
|| GET_CODE (PATTERN (insn)) != SET)
return 0;
......@@ -3760,9 +3780,12 @@ cprop_insn (insn)
abort ();
src = SET_SRC (pat);
if (GET_CODE (src) == CONST_INT)
/* Constant propagation. */
if (GET_CODE (src) == CONST_INT || GET_CODE (src) == CONST_DOUBLE)
{
if (try_replace_reg (reg_used->reg_rtx, src, insn))
/* Handle normal insns first. */
if (GET_CODE (insn) == INSN
&& try_replace_reg (reg_used->reg_rtx, src, insn))
{
changed = 1;
const_prop_count++;
......@@ -3770,13 +3793,90 @@ cprop_insn (insn)
{
fprintf (gcse_file, "CONST-PROP: Replacing reg %d in insn %d with constant ",
regno, INSN_UID (insn));
fprintf (gcse_file, HOST_WIDE_INT_PRINT_DEC, INTVAL (src));
print_rtl (gcse_file, src);
fprintf (gcse_file, "\n");
}
/* The original insn setting reg_used may or may not now be
deletable. We leave the deletion to flow. */
}
/* Try to propagate a CONST_INT into a conditional jump.
We're pretty specific about what we will handle in this
code, we can extend this as necessary over time.
Right now the insn in question must look like
(set (pc) (if_then_else ...))
Note this does not currently handle machines which use cc0. */
else if (GET_CODE (insn) == JUMP_INSN && condjump_p (insn))
{
/* We want a copy of the JUMP_INSN so we can modify it
in-place as needed without effecting the original. */
rtx copy = copy_rtx (insn);
rtx set = PATTERN (copy);
rtx temp;
/* Replace the register with the appropriate constant. */
replace_rtx (SET_SRC (set), reg_used->reg_rtx, src);
temp = simplify_ternary_operation (GET_CODE (SET_SRC (set)),
GET_MODE (SET_SRC (set)),
GET_MODE (XEXP (SET_SRC (set), 0)),
XEXP (SET_SRC (set), 0),
XEXP (SET_SRC (set), 1),
XEXP (SET_SRC (set), 2));
/* If no simplification can be made, then try the next
register. */
if (temp)
SET_SRC (set) = temp;
else
continue;
/* That may have changed the structure of TEMP, so
force it to be rerecognized if it has not turned
into a nop or unconditional jump. */
INSN_CODE (copy) = -1;
if ((SET_DEST (set) == pc_rtx
&& (SET_SRC (set) == pc_rtx
|| GET_CODE (SET_SRC (set)) == LABEL_REF))
|| recog (PATTERN (copy), copy, NULL) >= 0)
{
/* This has either become an unconditional jump
or a nop-jump. We'd like to delete nop jumps
here, but doing so confuses gcse. So we just
make the replacement and let later passes
sort things out. */
PATTERN (insn) = set;
INSN_CODE (insn) = -1;
/* One less use of the label this insn used to jump to
if we turned this into a NOP jump. */
if (SET_SRC (set) == pc_rtx && JUMP_LABEL (insn) != 0)
--LABEL_NUSES (JUMP_LABEL (insn));
/* If this has turned into an unconditional jump,
then put a barrier after it so that the unreachable
code will be deleted. */
if (GET_CODE (SET_SRC (set)) == LABEL_REF)
emit_barrier_after (insn);
run_jump_opt_after_gcse = 1;
changed = 1;
const_prop_count++;
if (gcse_file != NULL)
{
fprintf (gcse_file, "CONST-PROP: Replacing reg %d in insn %d with constant ",
regno, INSN_UID (insn));
print_rtl (gcse_file, src);
fprintf (gcse_file, "\n");
}
}
}
}
else if (GET_CODE (src) == REG
&& REGNO (src) >= FIRST_PSEUDO_REGISTER
......
......@@ -2076,7 +2076,9 @@ init_label_info (f)
return largest_uid;
}
/* Delete insns following barriers, up to next label. */
/* Delete insns following barriers, up to next label.
Also delete no-op jumps created by gcse. */
static void
delete_barrier_successors (f)
rtx f;
......@@ -2098,6 +2100,14 @@ delete_barrier_successors (f)
}
/* INSN is now the code_label. */
}
/* Also remove (set (pc) (pc)) insns which can be created by
gcse. We eliminate such insns now to avoid having them
cause problems later. */
else if (GET_CODE (insn) == JUMP_INSN
&& SET_SRC (PATTERN (insn)) == pc_rtx
&& SET_DEST (PATTERN (insn)) == pc_rtx)
insn = delete_insn (insn);
else
insn = NEXT_INSN (insn);
}
......
......@@ -1452,7 +1452,7 @@ extern rtx expand_mult_highpart PROTO ((enum machine_mode, rtx,
/* In gcse.c */
#ifdef BUFSIZ
extern void gcse_main PROTO ((rtx, FILE *));
extern int gcse_main PROTO ((rtx, FILE *));
#endif
/* In global.c */
......
......@@ -3789,7 +3789,16 @@ rest_of_compilation (decl)
if (gcse_dump)
open_dump_file (".gcse", IDENTIFIER_POINTER (DECL_NAME (decl)));
TIMEVAR (gcse_time, gcse_main (insns, rtl_dump_file));
TIMEVAR (gcse_time, tem = gcse_main (insns, rtl_dump_file));
/* If gcse altered any jumps, rerun jump optimizations to clean
things up. */
if (tem)
{
TIMEVAR (jump_time, jump_optimize (insns, !JUMP_CROSS_JUMP,
!JUMP_NOOP_MOVES,
!JUMP_AFTER_REGSCAN));
}
if (gcse_dump)
{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment