This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
Re: c/2100: -fstrength-reduce (is active with -O2) produces wrong code
- To: dllorens at inf dot uji dot es
- Subject: Re: c/2100: -fstrength-reduce (is active with -O2) produces wrong code
- From: Franz Sirl <Franz dot Sirl-kernel at lauterbach dot com>
- Date: Wed, 28 Feb 2001 01:12:33 +0100
- Cc: gcc-gnats at gcc dot gnu dot org,gcc-bugs at gcc dot gnu dot org
At 17:29 26.02.2001, dllorens@inf.uji.es wrote:
> >Number: 2100
> >Category: c
> >Synopsis: -fstrength-reduce (is active with -O2) produces wrong code
> >Confidential: no
> >Severity: serious
> >Priority: medium
> >Responsible: unassigned
> >State: open
> >Class: wrong-code
> >Submitter-Id: net
> >Arrival-Date: Mon Feb 26 08:36:03 PST 2001
> >Closed-Date:
> >Last-Modified:
> >Originator: David Llorens
> >Release: gcc version 2.95.2 19991024 (release)
> >Organization:
> >Environment:
>Linux 2.2.16-3smp
> >Description:
>The -fstrength-reduce optimization flag (which is active
>with the common -O2 option), produces wrong code.
>
>I have tested two gcc versions, both fail:
> - gcc version 2.95.2 19991024 (release)
> - egcs-2.91.66 19990314/Linux (egcs-1.1.2 release)
Wow, this seems to be a long-standing bug in check_final_value()/loop.c,
the testcase shows it nicely on x86-linux. Look at this check in
check_final_value():
if ((final_value = final_giv_value (loop, v))
&& (v->always_computable || last_use_this_basic_block (v->dest_reg,
v->insn)))
{
We reach here with this GIV for posGreatest:
(gdb) p *v
$8 = {insn = 0x8271228, new_reg = 0x0, src_reg = 0x82704dc, giv_type =
DEST_REG, dest_reg = 0x827054c, location = 0x0,
mode = SImode, mem_mode = 135364066, mult_val = 0x822b6a8, add_val =
0x822b6a0, benefit = 1, final_value = 0x0,
combined_with = 0, replaceable = 0, not_replaceable = 0, ignore = 0,
always_computable = 0, always_executed = 0,
maybe_multiple = 0, cant_derive = 1, maybe_dead = 0, auto_inc_opt = 0,
unrolled = 0, shared = 0, no_const_addval = 1,
lifetime = 38, derive_adjustment = 0x0, next_iv = 0x8274bac, same = 0x0,
derived_from = 0x0, const_adjust = -1073747912,
ix = 0, same_insn = 0x0, last_use = 0x0}
That means last_use_this_basic_block() gets called and correctly detects
that this is the last use of the GIV until the next CODE_LABEL. But this
check is apparently not strong enough :-( for this kind of loop. Because
check_final_value() returns TRUE for this GIV, posGreatest is _always_
assigned the final value of the loop minus 1 after the loop, which in this
case breaks the surrounding loop.
Possible fixes:
- don't check last_use_this_basic_block() at all in check_final_value()
- don't call last_use_this_basic_block() for GIVs of type DEST_REG (hmm?)
- check the surrounding loop (if any) for uses of the GIV too?
Opinions?
Franz.