c/900: `gcc -O2' takes 30x as long to compile certain files
Bernd Schmidt
bernds@redhat.com
Mon Nov 27 06:50:00 GMT 2000
On Mon, 27 Nov 2000 meyering@ascend.com wrote:
> >Synopsis: `gcc -O2' takes 30x as long to compile certain files
> FYI, it began taking much longer to compile that file with -O2
> some time between Nov 11, (when it worked fine) and Nov 22.
This is because Franz Sirl reverted his accidental checkin of a loop
optimizer patch by Geoff Keating. I've looked closer at that patch, and
found that it does fix a bug. Not only can the bug lead to much higher
compile times as you noticed, it could also probably cause incorrect code
to be generated.
Basically, when determining whether the destination of a given SET is
a biv, we scan backwards to find sets of the source (if it's a register).
Only the first such set should be considered, but we currently scan past
it and call basic_induction_var recursively each time we see a set of
the source.
For correctness, we need to terminate the search as soon as we find an
insn that sets the register, whether or not it's a biv. It seems to me
that Geoff's patch leaves a small hole open in that code; I've added a
bit of code that tests for a set inside STRICT_LOW_PART/ZERO_EXTRACT/etc.
Bootstrapped on i686-linux & checked in.
Bernd
Based on a patch from Geoff Keating <geoffk@redhat.com>:
* loop.c (basic_induction_var): If a REG is set from something
that is not a biv, then the REG is not a biv. Even if it is
earlier set from something that is a biv.
Index: loop.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/loop.c,v
retrieving revision 1.296
diff -u -p -r1.296 loop.c
--- loop.c 2000/11/21 18:24:42 1.296
+++ loop.c 2000/11/27 14:41:16
@@ -5467,6 +5467,7 @@ basic_induction_var (loop, x, mode, dest
insn = p;
while (1)
{
+ rtx dest;
do
{
insn = PREV_INSN (insn);
@@ -5479,21 +5480,26 @@ basic_induction_var (loop, x, mode, dest
set = single_set (insn);
if (set == 0)
break;
+ dest = SET_DEST (set);
+ if (dest == x
+ || (GET_CODE (dest) == SUBREG
+ && (GET_MODE_SIZE (GET_MODE (dest)) <= UNITS_PER_WORD)
+ && (GET_MODE_CLASS (GET_MODE (dest)) == MODE_INT)
+ && SUBREG_REG (dest) == x))
+ return basic_induction_var (loop, SET_SRC (set),
+ (GET_MODE (SET_SRC (set)) == VOIDmode
+ ? GET_MODE (x)
+ : GET_MODE (SET_SRC (set))),
+ dest_reg, insn,
+ inc_val, mult_val, location);
- if ((SET_DEST (set) == x
- || (GET_CODE (SET_DEST (set)) == SUBREG
- && (GET_MODE_SIZE (GET_MODE (SET_DEST (set)))
- <= UNITS_PER_WORD)
- && (GET_MODE_CLASS (GET_MODE (SET_DEST (set)))
- == MODE_INT)
- && SUBREG_REG (SET_DEST (set)) == x))
- && basic_induction_var (loop, SET_SRC (set),
- (GET_MODE (SET_SRC (set)) == VOIDmode
- ? GET_MODE (x)
- : GET_MODE (SET_SRC (set))),
- dest_reg, insn,
- inc_val, mult_val, location))
- return 1;
+ while (GET_CODE (dest) == SIGN_EXTRACT
+ || GET_CODE (dest) == ZERO_EXTRACT
+ || GET_CODE (dest) == SUBREG
+ || GET_CODE (dest) == STRICT_LOW_PART)
+ dest = XEXP (dest, 0);
+ if (dest == x)
+ break;
}
/* Fall through. */
More information about the Gcc-patches
mailing list