This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Patch: bug in regmove


This is best illustrated by example. My failing case for this one is on darwin/x86, not a common target
(even here), but I expect it fails on other x86s as well.


#include <stdio.h>
double foo(void) {
        return 12345678.0;
}
int
main(int argc, char *argv[]) {
        double now = foo();
        double then = (double)argc;  /* 1 expected */

        double d = (double)((now - then) / 60.0L);
        printf("d = %g\n", d);
        if (d > 205760. && d < 205762.)
          return 0;
        abort();
}

When compiled with -O2, regmove attempts to propagate reg 68 backward here:

(insn 15 13 16 0 0x3c6ad4 (set (reg:DF 64)
        (minus:DF (reg/v:DF 61)
            (float:DF (reg/v:SI 59)))) 421 {*fop_df_3}

(insn 19 18 20 0 0x3c6ad4 (set (reg:XF 68)
(div:XF (float_extend:XF (reg:DF 64))
(float_extend:XF (mem/u/f:SF (plus:SI (reg:SI 3 ebx)
(const:SI (minus:SI (symbol_ref/u:SI ("*LC1"))
(symbol_ref:SI ("*"L00000000002$pb""))))) [0 S4 A32])))) 437 {*fop_xf_7}


So it tries this, where the divide is valid but the minus is not:

(insn 15 13 16 0 0x3c6ad4 (set (reg:XF 68)
        (minus:DF (reg/v:DF 61)
            (float:DF (reg/v:SI 59)))) 421 {*fop_df_3}

(insn:HI 19 18 20 0 0x3c6ad4 (set (reg:XF 68)
(div:XF (float_extend:XF (reg:XF 68))
(float_extend:XF (mem/u/f:SF (plus:SI (reg:SI 3 ebx)
(const:SI (minus:SI (symbol_ref/u:SI ("*LC1"))
(symbol_ref:SI ("*"L00000000002$pb""))))) [0 S4 A32])))) 437 {*fop_xf_7}


and figures out that it is invalid, and tries to back off to the original. That's where the bug is.
In backing off the divide, it first substitutes R64 for R68 throughout and rerecognizes the insn, then substitutes
R68 for the destination only. In this case, the intermediate form with R64 throughout is not valid,
so the intermediate recognition fails and the backing off doesn't get done.The following patch redoes
the backing-off in a way that doesn't attempt to recognize an intermediate form. (Should be minutely
faster, too.) Bootstrapped and tested on Darwin, to the extent currently possible.


Index: regmove.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/regmove.c,v
retrieving revision 1.149
diff -u -d -b -w -c -3 -p -r1.149 regmove.c
*** regmove.c 22 Aug 2003 06:45:14 -0000 1.149
--- regmove.c 11 Sep 2003 19:48:24 -0000
*************** regmove_optimize (rtx f, int nregs, FILE
*** 1406,1416 ****
{
/* Change all source operands back.
This modifies the dst as a side-effect. */
! validate_replace_rtx (dst, src, insn);
/* Now make sure the dst is right. */
validate_change (insn,
recog_data.operand_loc[match_no],
! dst, 0);
}
}
break;
--- 1406,1420 ----
{
/* Change all source operands back.
This modifies the dst as a side-effect. */
! validate_replace_rtx_group (dst, src, insn);
! /* It is possible for the intermediate step
! to be an invalid insn, so don't try to
! validate it. */
/* Now make sure the dst is right. */
validate_change (insn,
recog_data.operand_loc[match_no],
! dst, 1);
! apply_change_group ();
}
}
break;


2003-09-13 Dale Johannesen <dalej@apple.com>

* regmove.c (regmove_optimize): Don't try to recognize possibly invalid
intermediate form when backing off unsuccessful change attempt.



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]