Patch: bug in regmove
Dale Johannesen
dalej@apple.com
Sun Sep 14 01:28:00 GMT 2003
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.
More information about the Gcc-patches
mailing list