summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/ira.c9
-rw-r--r--gcc/reload.h2
-rw-r--r--gcc/reload1.c26
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/pr48770.c21
6 files changed, 62 insertions, 10 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a0758e1dc95..6c6617b3c8f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,14 @@
2011-06-23 Jeff Law <law@redhat.com>
+ PR middle-end/48770
+ * reload.h (reload): Change to return a bool.
+ * ira.c (ira): If requested by reload, run a fast DCE pass after
+ reload has completed. Fix comment typo.
+ * reload1.c (need_dce): New file scoped static.
+ (reload): Set reload_completed here. Return whether or not a DCE
+ pass after reload is needed.
+ (delete_dead_insn): Set need_dce as needed.
+
PR middle-end/49465
* tree-ssa-threadupate.c (fix_duplicate_block_edges): Fix condition
to detect threading through joiner block. If there was already
diff --git a/gcc/ira.c b/gcc/ira.c
index 5cfe5c0fa6b..6cca90807df 100644
--- a/gcc/ira.c
+++ b/gcc/ira.c
@@ -383,6 +383,7 @@ along with GCC; see the file COPYING3. If not see
#include "integrate.h"
#include "ggc.h"
#include "ira-int.h"
+#include "dce.h"
struct target_ira default_target_ira;
@@ -3526,6 +3527,7 @@ ira (FILE *f)
int rebuild_p;
int saved_flag_ira_share_spill_slots;
basic_block bb;
+ bool need_dce;
timevar_push (TV_IRA);
@@ -3717,7 +3719,7 @@ ira (FILE *f)
df_set_flags (DF_NO_INSN_RESCAN);
build_insn_chain ();
- reload_completed = !reload (get_insns (), ira_conflicts_p);
+ need_dce = reload (get_insns (), ira_conflicts_p);
timevar_pop (TV_RELOAD);
@@ -3760,7 +3762,7 @@ ira (FILE *f)
#endif
/* The code after the reload has changed so much that at this point
- we might as well just rescan everything. Not that
+ we might as well just rescan everything. Note that
df_rescan_all_insns is not going to help here because it does not
touch the artificial uses and defs. */
df_finish_pass (true);
@@ -3772,6 +3774,9 @@ ira (FILE *f)
if (optimize)
df_analyze ();
+ if (need_dce && optimize)
+ run_fast_dce ();
+
timevar_pop (TV_IRA);
}
diff --git a/gcc/reload.h b/gcc/reload.h
index c9df112b2d0..ad0cfcd82d8 100644
--- a/gcc/reload.h
+++ b/gcc/reload.h
@@ -420,7 +420,7 @@ extern void reload_cse_regs (rtx);
extern void init_reload (void);
/* The reload pass itself. */
-extern int reload (rtx, int);
+extern bool reload (rtx, int);
/* Mark the slots in regs_ever_live for the hard regs
used by pseudo-reg number REGNO. */
diff --git a/gcc/reload1.c b/gcc/reload1.c
index a87e6ad08d6..a9aa01723ee 100644
--- a/gcc/reload1.c
+++ b/gcc/reload1.c
@@ -250,6 +250,10 @@ static char *reload_insn_firstobj;
examine. */
struct insn_chain *reload_insn_chain;
+/* TRUE if we potentially left dead insns in the insn stream and want to
+ run DCE immediately after reload, FALSE otherwise. */
+static bool need_dce;
+
/* List of all insns needing reloads. */
static struct insn_chain *insns_need_reload;
@@ -695,10 +699,11 @@ static int *temp_pseudo_reg_arr;
If GLOBAL is zero, we do not have enough information to do that,
so any pseudo reg that is spilled must go to the stack.
- Return value is nonzero if reload failed
- and we must not do any more for this function. */
+ Return value is TRUE if reload likely left dead insns in the
+ stream and a DCE pass should be run to elimiante them. Else the
+ return value is FALSE. */
-int
+bool
reload (rtx first, int global)
{
int i, n;
@@ -1329,7 +1334,9 @@ reload (rtx first, int global)
gcc_assert (bitmap_empty_p (&spilled_pseudos));
- return failure;
+ reload_completed = !failure;
+
+ return need_dce;
}
/* Yet another special case. Unfortunately, reg-stack forces people to
@@ -2123,14 +2130,19 @@ delete_dead_insn (rtx insn)
rtx prev = prev_active_insn (insn);
rtx prev_dest;
- /* If the previous insn sets a register that dies in our insn, delete it
- too. */
+ /* If the previous insn sets a register that dies in our insn make
+ a note that we want to run DCE immediately after reload.
+
+ We used to delete the previous insn & recurse, but that's wrong for
+ block local equivalences. Instead of trying to figure out the exact
+ circumstances where we can delete the potentially dead insns, just
+ let DCE do the job. */
if (prev && GET_CODE (PATTERN (prev)) == SET
&& (prev_dest = SET_DEST (PATTERN (prev)), REG_P (prev_dest))
&& reg_mentioned_p (prev_dest, PATTERN (insn))
&& find_regno_note (insn, REG_DEAD, REGNO (prev_dest))
&& ! side_effects_p (SET_SRC (PATTERN (prev))))
- delete_dead_insn (prev);
+ need_dce = 1;
SET_INSN_DELETED (insn);
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index b622eb3e421..c3e0f0e3ba8 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2011-06-23 Jeff Law <law@redhat.com>
+
+ PR middle-end/48770
+ * gcc.dg/pr48770.c: New test.
+
2011-06-23 Jan Hubicka <jh@suse.cz>
PR middle-end/49373
diff --git a/gcc/testsuite/gcc.dg/pr48770.c b/gcc/testsuite/gcc.dg/pr48770.c
new file mode 100644
index 00000000000..d0b855422d8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr48770.c
@@ -0,0 +1,21 @@
+/* { dg-do run } */
+/* { dg-options "-O -fprofile-arcs -fPIC -fno-dce -fno-forward-propagate" } */
+
+int test_goto2 (int f)
+{
+ int i;
+ for (i = 0; ({_Bool a = i < 10;a;}); i++)
+ {
+ if (i == f)
+ goto lab2;
+ }
+ return 4;
+lab2:
+ return 8;
+}
+
+int main ()
+{
+ test_goto2 (30);
+ return 0;
+}