earlyclobbers in fix_trunc* on x86
Jim Kingdon
kingdon@redhat.com
Fri Sep 3 19:28:00 GMT 1999
OK, call me "Mr. Earlyclobber," but I just won't be able to rest as
long as operands are sitting there naked. Obsessed? Fixated? Some
say so, but listen to my bone-chilling tale of horror and you will
believe too.
As you'll recall, when last we tuned in, we were looking the case in
output_fix_trunc in i386.c in which operands[0] is a register. The
define_insn now (after the ia32 merge) looks like this:
(define_insn "*fix_truncdi_1"
[(set (match_operand:DI 0 "nonimmediate_operand" "m,?r")
(fix:DI (match_operand 1 "register_operand" "f,f")))
(clobber (match_operand:SI 2 "memory_operand" "o,o"))
(clobber (match_operand:DI 3 "memory_operand" "m,m"))
(clobber (match_scratch:SI 4 "=&r,=&r"))
(clobber (match_scratch:XF 5 "=f,f"))]
"TARGET_80387 && FLOAT_MODE_P (GET_MODE (operands[1]))"
"* return output_fix_trunc (insn, operands);"
[(set_attr "type" "multi")])
OK, so the age-old question is "is there a way for operands[0] to be
set, followed by a memory reference?" (if so we need an earlyclobber).
Look through output_fix_trunc and there are no ways to set operands[0]
(if it is a register) until we get to:
split_di (operands+0, 1, xops+0, xops+1);
split_di (operands+3, 1, xops+2, xops+3);
output_asm_insn ("mov{l}\t{%2, %0|%0, %2}", xops); <- sets operands[0]
output_asm_insn ("mov{l}\t{%3, %1|%1, %3}", xops); <- xops[3] can be memory
Therefore we do indeed need an earlyclobber for the case in which
operands[0] is DImode. Similarly, we don't need one for SImode,
because operands[0] isn't set until the last instruction.
I've enclosed a patch (untested, as it has been a while since the test
case which got me started on this still hit this situation).
Other solutions? Well, bringing back output_move_double or the
equivalent would take care of it. Ignore it on the grounds that
operands[3] can't refer to the same register? Maybe, although that is
a whole different analysis (which I haven't done) involving
assign_386_stack_local.
Jim "the man with the ampersand" Kingdon
Fri Sep 3 22:14:15 1999 Jim Kingdon < http://developer.redhat.com >
* config/i386/i386.md (*fix_truncdi_1): Earlyclobber operands[0].
* config/i386/i386.c (output_fix_trunc): Comment this situation.
Index: config/i386/i386.c
===================================================================
RCS file: /cvs/egcs/egcs/gcc/config/i386/i386.c,v
retrieving revision 1.86
diff -c -r1.86 i386.c
*** i386.c 1999/09/03 02:20:09 1.86
--- i386.c 1999/09/04 02:12:46
***************
*** 3194,3199 ****
--- 3194,3203 ----
{
split_di (operands+0, 1, xops+0, xops+1);
split_di (operands+3, 1, xops+2, xops+3);
+
+ /* The first of these sets operands[0] and the second
+ can be a memory reference; therefore operands[0] must
+ be an earlyclobber if it is a register. */
output_asm_insn ("mov{l}\t{%2, %0|%0, %2}", xops);
output_asm_insn ("mov{l}\t{%3, %1|%1, %3}", xops);
}
Index: config/i386/i386.md
===================================================================
RCS file: /cvs/egcs/egcs/gcc/config/i386/i386.md,v
retrieving revision 1.81
diff -c -r1.81 i386.md
*** i386.md 1999/09/02 04:20:20 1.81
--- i386.md 1999/09/04 02:12:53
***************
*** 2730,2736 ****
operands[3] = assign_386_stack_local (DImode, 1);")
(define_insn "*fix_truncdi_1"
! [(set (match_operand:DI 0 "nonimmediate_operand" "m,?r")
(fix:DI (match_operand 1 "register_operand" "f,f")))
(clobber (match_operand:SI 2 "memory_operand" "o,o"))
(clobber (match_operand:DI 3 "memory_operand" "m,m"))
--- 2730,2736 ----
operands[3] = assign_386_stack_local (DImode, 1);")
(define_insn "*fix_truncdi_1"
! [(set (match_operand:DI 0 "nonimmediate_operand" "m,?&r")
(fix:DI (match_operand 1 "register_operand" "f,f")))
(clobber (match_operand:SI 2 "memory_operand" "o,o"))
(clobber (match_operand:DI 3 "memory_operand" "m,m"))
More information about the Gcc-patches
mailing list