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