aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJeffrey A Law <law@cygnus.com>1999-03-10 19:45:18 +0000
committerJeff Law <law@gcc.gnu.org>1999-03-10 12:45:18 -0700
commite78d9500be1a9722b1936bab50706befa67ee6ca (patch)
tree3207b4993cd0675a87b6ff1209d6388684e2eb53 /gcc
parentb7975aedf6113725502bcc8327ace12c7bf568aa (diff)
downloadgcc-e78d9500be1a9722b1936bab50706befa67ee6ca.zip
gcc-e78d9500be1a9722b1936bab50706befa67ee6ca.tar.gz
gcc-e78d9500be1a9722b1936bab50706befa67ee6ca.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog12
-rw-r--r--gcc/gcse.c120
-rw-r--r--gcc/jump.c12
-rw-r--r--gcc/rtl.h2
-rw-r--r--gcc/toplev.c11
5 files changed, 144 insertions, 13 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 93012fe..6c0b0c2 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,15 @@
+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
diff --git a/gcc/gcse.c b/gcc/gcse.c
index e9d4afa..a805704 100644
--- a/gcc/gcse.c
+++ b/gcc/gcse.c
@@ -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
diff --git a/gcc/jump.c b/gcc/jump.c
index 7d25a97..4ffeeff 100644
--- a/gcc/jump.c
+++ b/gcc/jump.c
@@ -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);
}
diff --git a/gcc/rtl.h b/gcc/rtl.h
index bee3f05..7f4460f 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -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 */
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 2cc2885..f9a4c20 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.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)
{