summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog18
-rw-r--r--gcc/basic-block.h1
-rw-r--r--gcc/cfgcleanup.c68
-rw-r--r--gcc/cfglayout.c2
-rw-r--r--gcc/cfgrtl.c13
-rw-r--r--gcc/config/i386/i386.c20
-rw-r--r--gcc/gcse.c7
-rw-r--r--gcc/ifcvt.c1
8 files changed, 89 insertions, 41 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 8935aff4931..ee9b1d2f6b9 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,21 @@
+Thu Jan 10 22:35:54 CET 2002 Jan Hubicka <jh@suse.cz>
+
+ * basic-block.h (update_br_prob_note): Declare.
+ * cfgcleanup.c (try_simplify_condjump): Call update_br_prob_note.
+ (try_forward_edges): Care negative frequencies and update note.
+ (outgoing_edges_match): Tweek conditional merging heuristics.
+ (try_crossjump_to_edge): use update_br_prob_note.
+ * cfglayout.c (fixup_reorder_chain): Likewise.
+ * cfrtl.c (update_br_prob_note): New.
+ * ifcvt.c (dead_or_predicable): Call update_br_prob_note.
+
+ * i386.c (ix86_decompose_address): Return -1 if address contains
+ shift.
+ (legitimate_address_p): Require ix86_decompose_address to return 1.
+
+ * gcse.c (hash_scan_set): Use CONSTANT_INSN_P.
+ (cprop_insn): Likewise.
+
2002-01-10 Kazu Hirata <kazu@hxi.com>
* toplev.c: Fix formatting.
diff --git a/gcc/basic-block.h b/gcc/basic-block.h
index 338763f3b2c..29df84af335 100644
--- a/gcc/basic-block.h
+++ b/gcc/basic-block.h
@@ -687,6 +687,7 @@ extern conflict_graph conflict_graph_compute
PARAMS ((regset,
partition));
extern bool mark_dfs_back_edges PARAMS ((void));
+extern void update_br_prob_note PARAMS ((basic_block));
/* In dominance.c */
diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c
index 0af87b4b3a4..5015c814941 100644
--- a/gcc/cfgcleanup.c
+++ b/gcc/cfgcleanup.c
@@ -177,6 +177,7 @@ try_simplify_condjump (cbranch_block)
jump_dest_block);
cbranch_jump_edge->flags |= EDGE_FALLTHRU;
cbranch_fallthru_edge->flags &= ~EDGE_FALLTHRU;
+ update_br_prob_note (cbranch_block);
/* Delete the block with the unconditional jump, and clean up the mess. */
flow_delete_block (jump_block);
@@ -521,7 +522,11 @@ try_forward_edges (mode, b)
edge t;
first->count -= edge_count;
+ if (first->count < 0)
+ first->count = 0;
first->frequency -= edge_frequency;
+ if (first->frequency < 0)
+ first->frequency = 0;
if (first->succ->succ_next)
{
edge e;
@@ -535,9 +540,11 @@ try_forward_edges (mode, b)
prob = edge_frequency * REG_BR_PROB_BASE / first->frequency;
else
prob = 0;
+ if (prob > t->probability)
+ prob = t->probability;
t->probability -= prob;
prob = REG_BR_PROB_BASE - prob;
- if (prob == 0)
+ if (prob <= 0)
{
first->succ->probability = REG_BR_PROB_BASE;
first->succ->succ_next->probability = 0;
@@ -546,6 +553,7 @@ try_forward_edges (mode, b)
for (e = first->succ; e; e = e->succ_next)
e->probability = ((e->probability * REG_BR_PROB_BASE)
/ (double) prob);
+ update_br_prob_note (first);
}
else
{
@@ -558,8 +566,10 @@ try_forward_edges (mode, b)
n++;
t = first->succ;
}
- t->count -= edge_count;
+ t->count -= edge_count;
+ if (t->count < 0)
+ t->count = 0;
first = t->dest;
}
while (first != target);
@@ -745,6 +755,7 @@ merge_blocks (e, b, c, mode)
/* If B has a fallthru edge to C, no need to move anything. */
if (e->flags & EDGE_FALLTHRU)
{
+ int b_index = b->index, c_index = c->index;
/* We need to update liveness in case C already has broken liveness
or B ends by conditional jump to next instructions that will be
removed. */
@@ -756,7 +767,7 @@ merge_blocks (e, b, c, mode)
if (rtl_dump_file)
fprintf (rtl_dump_file, "Merged %d and %d without moving.\n",
- b->index, c->index);
+ b_index, c_index);
return true;
}
@@ -1147,32 +1158,30 @@ outgoing_edges_match (mode, bb1, bb2)
we will only have one branch prediction bit to work with. Thus
we require the existing branches to have probabilities that are
roughly similar. */
- /* ??? We should use bb->frequency to allow merging in infrequently
- executed blocks, but at the moment it is not available when
- cleanup_cfg is run. */
- if (match && !optimize_size)
+ if (match
+ && !optimize_size
+ && bb1->frequency > BB_FREQ_MAX / 1000
+ && bb2->frequency > BB_FREQ_MAX / 1000)
{
- rtx note1, note2;
- int prob1, prob2;
+ int prob2;
- note1 = find_reg_note (bb1->end, REG_BR_PROB, 0);
- note2 = find_reg_note (bb2->end, REG_BR_PROB, 0);
+ if (b1->dest == b2->dest)
+ prob2 = b2->probability;
+ else
+ /* Do not use f2 probability as f2 may be forwarded. */
+ prob2 = REG_BR_PROB_BASE - b2->probability;
- if (note1 && note2)
+ /* Fail if the difference in probabilities is
+ greater than 5%. */
+ if (abs (b1->probability - prob2) > REG_BR_PROB_BASE / 20)
{
- prob1 = INTVAL (XEXP (note1, 0));
- prob2 = INTVAL (XEXP (note2, 0));
- if (reverse)
- prob2 = REG_BR_PROB_BASE - prob2;
-
- /* Fail if the difference in probabilities is
- greater than 5%. */
- if (abs (prob1 - prob2) > REG_BR_PROB_BASE / 20)
- return false;
- }
+ if (rtl_dump_file)
+ fprintf (rtl_dump_file,
+ "Outcomes of branch in bb %i and %i differs to much (%i %i)\n",
+ bb1->index, bb2->index, b1->probability, prob2);
- else if (note1 || note2)
- return false;
+ return false;
+ }
}
if (rtl_dump_file && match)
@@ -1259,7 +1268,6 @@ try_crossjump_to_edge (mode, e1, e2)
edge s;
rtx last;
rtx label;
- rtx note;
/* Search backward through forwarder blocks. We don't need to worry
about multiple entry or chained forwarders, as they will be optimized
@@ -1356,8 +1364,14 @@ try_crossjump_to_edge (mode, e1, e2)
if (FORWARDER_BLOCK_P (s2->dest))
{
s2->dest->succ->count -= s2->count;
+ if (s2->dest->succ->count < 0)
+ s2->dest->succ->count = 0;
s2->dest->count -= s2->count;
s2->dest->frequency -= EDGE_FREQUENCY (s);
+ if (s2->dest->frequency < 0)
+ s2->dest->frequency = 0;
+ if (s2->dest->count < 0)
+ s2->dest->count = 0;
}
if (!redirect_to->frequency && !src1->frequency)
@@ -1369,9 +1383,7 @@ try_crossjump_to_edge (mode, e1, e2)
/ (redirect_to->frequency + src1->frequency));
}
- note = find_reg_note (redirect_to->end, REG_BR_PROB, 0);
- if (note)
- XEXP (note, 0) = GEN_INT (BRANCH_EDGE (redirect_to)->probability);
+ update_br_prob_note (redirect_to);
/* Edit SRC1 to go to REDIRECT_TO at NEWPOS1. */
diff --git a/gcc/cfglayout.c b/gcc/cfglayout.c
index ef5206bb69a..329e9f80b18 100644
--- a/gcc/cfglayout.c
+++ b/gcc/cfglayout.c
@@ -412,6 +412,7 @@ fixup_reorder_chain ()
{
e_fall->flags &= ~EDGE_FALLTHRU;
e_taken->flags |= EDGE_FALLTHRU;
+ update_br_prob_note (bb);
e = e_fall, e_fall = e_taken, e_taken = e;
}
}
@@ -423,6 +424,7 @@ fixup_reorder_chain ()
{
e_fall->flags &= ~EDGE_FALLTHRU;
e_taken->flags |= EDGE_FALLTHRU;
+ update_br_prob_note (bb);
continue;
}
}
diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c
index 56b3bf28e6a..a4f25f8964c 100644
--- a/gcc/cfgrtl.c
+++ b/gcc/cfgrtl.c
@@ -1510,6 +1510,19 @@ print_rtl_with_bb (outf, rtx_first)
}
}
+void
+update_br_prob_note (bb)
+ basic_block bb;
+{
+ rtx note;
+ if (GET_CODE (bb->end) != JUMP_INSN)
+ return;
+ note = find_reg_note (bb->end, REG_BR_PROB, NULL_RTX);
+ if (!note || INTVAL (XEXP (note, 0)) == BRANCH_EDGE (bb)->probability)
+ return;
+ XEXP (note, 0) = GEN_INT (BRANCH_EDGE (bb)->probability);
+}
+
/* Verify the CFG consistency. This function check some CFG invariants and
aborts when something is wrong. Hope that this function will help to
convert many optimization passes to preserve CFG consistent.
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 91ccb8ce400..4d047809f79 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -4349,8 +4349,10 @@ ix86_expand_epilogue (style)
}
/* Extract the parts of an RTL expression that is a valid memory address
- for an instruction. Return false if the structure of the address is
- grossly off. */
+ for an instruction. Return 0 if the structure of the address is
+ grossly off. Return -1 if the address contains ASHIFT, so it is not
+ strictly valid, but still used for computing length of lea instruction.
+ */
static int
ix86_decompose_address (addr, out)
@@ -4362,6 +4364,7 @@ ix86_decompose_address (addr, out)
rtx disp = NULL_RTX;
HOST_WIDE_INT scale = 1;
rtx scale_rtx = NULL_RTX;
+ int retval = 1;
if (GET_CODE (addr) == REG || GET_CODE (addr) == SUBREG)
base = addr;
@@ -4402,7 +4405,7 @@ ix86_decompose_address (addr, out)
disp = op1;
}
else
- return FALSE;
+ return 0;
}
else if (GET_CODE (addr) == MULT)
{
@@ -4417,11 +4420,12 @@ ix86_decompose_address (addr, out)
index = XEXP (addr, 0);
tmp = XEXP (addr, 1);
if (GET_CODE (tmp) != CONST_INT)
- return FALSE;
+ return 0;
scale = INTVAL (tmp);
if ((unsigned HOST_WIDE_INT) scale > 3)
- return FALSE;
+ return 0;
scale = 1 << scale;
+ retval = -1;
}
else
disp = addr; /* displacement */
@@ -4430,7 +4434,7 @@ ix86_decompose_address (addr, out)
if (scale_rtx)
{
if (GET_CODE (scale_rtx) != CONST_INT)
- return FALSE;
+ return 0;
scale = INTVAL (scale_rtx);
}
@@ -4471,7 +4475,7 @@ ix86_decompose_address (addr, out)
out->disp = disp;
out->scale = scale;
- return TRUE;
+ return retval;
}
/* Return cost of the memory address x.
@@ -4684,7 +4688,7 @@ legitimate_address_p (mode, addr, strict)
debug_rtx (addr);
}
- if (! ix86_decompose_address (addr, &parts))
+ if (ix86_decompose_address (addr, &parts) <= 0)
{
reason = "decomposition failed";
goto report_error;
diff --git a/gcc/gcse.c b/gcc/gcse.c
index e8361fc5aab..af3b29e4ca6 100644
--- a/gcc/gcse.c
+++ b/gcc/gcse.c
@@ -2204,9 +2204,7 @@ hash_scan_set (pat, insn, set_p)
&& REGNO (src) >= FIRST_PSEUDO_REGISTER
&& can_copy_p [GET_MODE (dest)]
&& REGNO (src) != regno)
- || GET_CODE (src) == CONST_INT
- || GET_CODE (src) == SYMBOL_REF
- || GET_CODE (src) == CONST_DOUBLE)
+ || CONSTANT_P (src))
/* 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. */
@@ -4155,8 +4153,7 @@ cprop_insn (bb, insn, alter_jumps)
src = SET_SRC (pat);
/* Constant propagation. */
- if (GET_CODE (src) == CONST_INT || GET_CODE (src) == CONST_DOUBLE
- || GET_CODE (src) == SYMBOL_REF)
+ if (CONSTANT_P (src))
{
/* Handle normal insns first. */
if (GET_CODE (insn) == INSN
diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c
index f6a07e96670..2939de4483e 100644
--- a/gcc/ifcvt.c
+++ b/gcc/ifcvt.c
@@ -2657,6 +2657,7 @@ dead_or_predicable (test_bb, merge_bb, other_bb, new_dest, reversep)
probability = BRANCH_EDGE (test_bb)->probability;
BRANCH_EDGE (test_bb)->probability = FALLTHRU_EDGE (test_bb)->probability;
FALLTHRU_EDGE (test_bb)->probability = probability;
+ update_br_prob_note (test_bb);
}
/* Move the insns out of MERGE_BB to before the branch. */