aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog11
-rw-r--r--gcc/df-problems.c21
-rw-r--r--gcc/df.h1
-rw-r--r--gcc/ifcvt.c29
4 files changed, 44 insertions, 18 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 2684bec..bf74e84 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,14 @@
+2010-04-22 Bernd Schmidt <bernds@codesourcery.com>
+
+ * ifcvt.c (dead_or_predicable): Use df_simulate_find_defs and
+ df_simulate_find_noclobber_defs as appropriate. Keep track of an
+ extra set merge_set_noclobber, and use it to relax the final test
+ slightly.
+ * df.h (df_simulate_find_noclobber_defs): Declare.
+ * df-problems.c (df_simulate_find_defs): Don't ignore partial or
+ conditional defs.
+ (df_simulate_find_noclobber_defs): New function.
+
2010-04-22 Uros Bizjak <ubizjak@gmail.com>
* config/i386/i386.md: Use {} around multi-line preparation statements.
diff --git a/gcc/df-problems.c b/gcc/df-problems.c
index e0ec167..fb89909 100644
--- a/gcc/df-problems.c
+++ b/gcc/df-problems.c
@@ -3745,9 +3745,22 @@ df_simulate_find_defs (rtx insn, bitmap defs)
for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++)
{
df_ref def = *def_rec;
- /* If the def is to only part of the reg, it does
- not kill the other defs that reach here. */
- if (!(DF_REF_FLAGS (def) & (DF_REF_PARTIAL | DF_REF_CONDITIONAL)))
+ bitmap_set_bit (defs, DF_REF_REGNO (def));
+ }
+}
+
+/* Find the set of real DEFs, which are not clobbers, for INSN. */
+
+void
+df_simulate_find_noclobber_defs (rtx insn, bitmap defs)
+{
+ df_ref *def_rec;
+ unsigned int uid = INSN_UID (insn);
+
+ for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++)
+ {
+ df_ref def = *def_rec;
+ if (!(DF_REF_FLAGS (def) & (DF_REF_MUST_CLOBBER | DF_REF_MAY_CLOBBER)))
bitmap_set_bit (defs, DF_REF_REGNO (def));
}
}
@@ -3939,7 +3952,7 @@ df_simulate_one_insn_forwards (basic_block bb, rtx insn, bitmap live)
while here the scan is performed forwards! So, first assume that the
def is live, and if this is not true REG_UNUSED notes will rectify the
situation. */
- df_simulate_find_defs (insn, live);
+ df_simulate_find_noclobber_defs (insn, live);
/* Clear all of the registers that go dead. */
for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
diff --git a/gcc/df.h b/gcc/df.h
index 194cbcf..c73f00f 100644
--- a/gcc/df.h
+++ b/gcc/df.h
@@ -978,6 +978,7 @@ extern void df_note_add_problem (void);
extern void df_md_add_problem (void);
extern void df_md_simulate_artificial_defs_at_top (basic_block, bitmap);
extern void df_md_simulate_one_insn (basic_block, rtx, bitmap);
+extern void df_simulate_find_noclobber_defs (rtx, bitmap);
extern void df_simulate_find_defs (rtx, bitmap);
extern void df_simulate_defs (rtx, bitmap);
extern void df_simulate_uses (rtx, bitmap);
diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c
index 0c2d437..dcf44b8 100644
--- a/gcc/ifcvt.c
+++ b/gcc/ifcvt.c
@@ -3994,7 +3994,7 @@ dead_or_predicable (basic_block test_bb, basic_block merge_bb,
that any registers modified are dead at the branch site. */
rtx insn, cond, prev;
- bitmap merge_set, test_live, test_set;
+ bitmap merge_set, merge_set_noclobber, test_live, test_set;
unsigned i, fail = 0;
bitmap_iterator bi;
@@ -4030,11 +4030,14 @@ dead_or_predicable (basic_block test_bb, basic_block merge_bb,
/* Collect:
MERGE_SET = set of registers set in MERGE_BB
+ MERGE_SET_NOCLOBBER = like MERGE_SET, but only includes registers
+ that are really set, not just clobbered.
TEST_LIVE = set of registers live at EARLIEST
- TEST_SET = set of registers set between EARLIEST and the
- end of the block. */
+ TEST_SET = set of registers set between EARLIEST and the
+ end of the block. */
merge_set = BITMAP_ALLOC (&reg_obstack);
+ merge_set_noclobber = BITMAP_ALLOC (&reg_obstack);
test_live = BITMAP_ALLOC (&reg_obstack);
test_set = BITMAP_ALLOC (&reg_obstack);
@@ -4051,13 +4054,8 @@ dead_or_predicable (basic_block test_bb, basic_block merge_bb,
{
if (NONDEBUG_INSN_P (insn))
{
- unsigned int uid = INSN_UID (insn);
- df_ref *def_rec;
- for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++)
- {
- df_ref def = *def_rec;
- bitmap_set_bit (merge_set, DF_REF_REGNO (def));
- }
+ df_simulate_find_defs (insn, merge_set);
+ df_simulate_find_noclobber_defs (insn, merge_set_noclobber);
}
}
@@ -4065,7 +4063,7 @@ dead_or_predicable (basic_block test_bb, basic_block merge_bb,
hard registers before reload. */
if (SMALL_REGISTER_CLASSES && ! reload_completed)
{
- EXECUTE_IF_SET_IN_BITMAP (merge_set, 0, i, bi)
+ EXECUTE_IF_SET_IN_BITMAP (merge_set_noclobber, 0, i, bi)
{
if (i < FIRST_PSEUDO_REGISTER
&& ! fixed_regs[i]
@@ -4085,7 +4083,7 @@ dead_or_predicable (basic_block test_bb, basic_block merge_bb,
{
if (INSN_P (insn))
{
- df_simulate_find_defs (insn, test_set);
+ df_simulate_find_noclobber_defs (insn, test_set);
df_simulate_one_insn_backwards (test_bb, insn, test_live);
}
prev = PREV_INSN (insn);
@@ -4094,16 +4092,19 @@ dead_or_predicable (basic_block test_bb, basic_block merge_bb,
}
/* We can perform the transformation if
- MERGE_SET & (TEST_SET | TEST_LIVE)
+ MERGE_SET_NOCLOBBER & TEST_SET
+ and
+ MERGE_SET & TEST_LIVE)
and
TEST_SET & DF_LIVE_IN (merge_bb)
are empty. */
- if (bitmap_intersect_p (test_set, merge_set)
+ if (bitmap_intersect_p (test_set, merge_set_noclobber)
|| bitmap_intersect_p (test_live, merge_set)
|| bitmap_intersect_p (test_set, df_get_live_in (merge_bb)))
fail = 1;
+ BITMAP_FREE (merge_set_noclobber);
BITMAP_FREE (merge_set);
BITMAP_FREE (test_live);
BITMAP_FREE (test_set);