This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
Re: Gcc 3.1 performance regressions with respect to 2.95.3
> >> Gcc 3.1 is slower in the areas: E exception handling, L loop
> >> overhead, G io and S Stepanov.
>
> The loop/Stepanov slowdown is an optimizer bug which also affects C. For
> the loop in
>
> double accumulate(double* first, double* last, double result)
> {
> for (; first != last; ++first)
> result += *first;
> return result;
> }
>
> we used to produce
>
> cmpl %edx,%eax
> je .L4
> .L6:
> faddl (%eax)
> addl $8,%eax
> cmpl %edx,%eax
> jne .L6
> .L4:
>
> but now we produce
>
> .L9:
> cmpl %edx, %eax
> je .L8
> faddl (%eax)
> addl $8, %eax
> jmp .L9
> .L8:
>
> which is one insn shorter but about 20% slower on i686. This pessimization
> seems to be performed by the flow2 pass; until that point the rtl looks
> like the old form.
Hi,
I've reviewed the code and found few problems. There is cut&paste in
outgoing_edges_math in the condtion, also outgoing_edges_match is supposed to
avoid merging of loop header and loop body via frequencies. This does not work
well as both branches often gets equivalent frequencies and thus nothing
happends. Andreas benchmarked that this test is hit or miss with profile
feedback and waste code without profile, so it is definitly too strict. I've
relaxed the test and added test for loop depths. The loop depths test may go
away once we add proper BB duplicating pass (one is available on cfg-branch by
Josef).
I also did brief review of loop_depth updating code (as loop_depths
are otherwise unused) and found one problem. This is not major as code
w/o proper updating will just miss few optimization oppurtunities, not many.
Despite the complexity this patch is I hope safe and solves performance
regression relative to 3.0, so I think it is 3.1 branch candidate.
Bootstrapped/regtested i386
Honza
Sun Mar 17 20:54:54 CET 2002 Jan Hubicka <jh@suse.cz>
* cfgcleanup.c (outgoing_edges_math): Fix condition; relax
frequencies match; avoid match on different loop depths.
(try_crossjump_to_bb): Kill tests that no longer brings time
savings.
* cfgrtl.c (force_nonfallthru_and_redirect): Fix loop_depth
updating code.
(split_edge): Likewise.
*** cfgcleanup.c.old Sun Mar 17 02:08:28 2002
--- cfgcleanup.c Sun Mar 17 19:37:59 2002
*************** outgoing_edges_match (mode, bb1, bb2)
*** 1116,1124 ****
if (!bb2->succ
|| !bb2->succ->succ_next
! || bb1->succ->succ_next->succ_next
|| !any_condjump_p (bb2->end)
! || !onlyjump_p (bb1->end))
return false;
b1 = BRANCH_EDGE (bb1);
--- 1123,1142 ----
if (!bb2->succ
|| !bb2->succ->succ_next
! || bb2->succ->succ_next->succ_next
|| !any_condjump_p (bb2->end)
! || !onlyjump_p (bb2->end))
! return false;
!
! /* Do not crossjump across loop boundaries. This is temporary workaround
! for common scenario where we crossjumping results in killing the
! duplicated loop condition making bb-reorder to rotate loop incorectly
! and inserting the extra unconditional jump inside.
!
! This check should go away once bb-reorder knows how to re-duplicate
! code in this case or rotate the loops to avoid this scenario properly.
! */
! if (bb1->loop_depth != bb2->loop_depth)
return false;
b1 = BRANCH_EDGE (bb1);
*************** outgoing_edges_match (mode, bb1, bb2)
*** 1196,1203 ****
prob2 = REG_BR_PROB_BASE - b2->probability;
/* Fail if the difference in probabilities is
! greater than 5%. */
! if (abs (b1->probability - prob2) > REG_BR_PROB_BASE / 20)
{
if (rtl_dump_file)
fprintf (rtl_dump_file,
--- 1213,1221 ----
prob2 = REG_BR_PROB_BASE - b2->probability;
/* Fail if the difference in probabilities is
! greater than 50%. This rules out two well predictable branches
! with oposite outcomes. */
! if (abs (b1->probability - prob2) > REG_BR_PROB_BASE / 5)
{
if (rtl_dump_file)
fprintf (rtl_dump_file,
*************** try_crossjump_to_edge (mode, e1, e2)
*** 1299,1310 ****
away. We do this to look past the unconditional jump following a
conditional jump that is required due to the current CFG shape. */
if (src1->pred
- && !src1->pred->pred_next
&& FORWARDER_BLOCK_P (src1))
e1 = src1->pred, src1 = e1->src;
if (src2->pred
- && !src2->pred->pred_next
&& FORWARDER_BLOCK_P (src2))
e2 = src2->pred, src2 = e2->src;
--- 1316,1325 ----
*** cfgrtl.c.old Sun Mar 17 19:12:26 2002
--- cfgrtl.c Sun Mar 17 19:16:36 2002
*************** force_nonfallthru_and_redirect (e, targe
*** 968,973 ****
--- 968,976 ----
/* Change the existing edge's source to be the new block, and add
a new edge from the entry block to the new block. */
e->src = bb;
+ bb->count = e->count;
+ bb->frequency = EDGE_FREQUENCY (e);
+ bb->loop_depth = 0;
for (pe1 = &ENTRY_BLOCK_PTR->succ; *pe1; pe1 = &(*pe1)->succ_next)
if (*pe1 == e)
{
*************** split_edge (edge_in)
*** 1254,1259 ****
--- 1257,1263 ----
: edge_in->dest->index, before, NULL);
bb->count = edge_in->count;
bb->frequency = EDGE_FREQUENCY (edge_in);
+ bb->loop_depth = edge_in->dest->loop_depth;
/* ??? This info is likely going to be out of date very soon. */
if (edge_in->dest->global_live_at_start)