movstrqi/movstrhi inconsistency analysis, with case and patch

Hans-Peter Nilsson hans-peter.nilsson@axis.com
Mon Jan 19 02:30:00 GMT 1998


[ A slight inconsistency in the use of movstrhi/qi-patterns with large-size
  blocks is present in egcs-980115 and gcc-2.8.0-971225.  Analysis and patch
  follows.  The corresponding patch is sent to the gcc2-list. ]

 The maximum size used for a move with pattern movstrhi or movstrqi is
inconsistent; in one place the threshold is with
(egcs:expr.c:emit_block_move(); c:a line 1651):

  "(unsigned HOST_WIDE_INT) INTVAL (size) <= GET_MODE_MASK (mode)"

and in another (egcs:expr.c:emit_push_insn(); c:a line 2657 and on) it's with:

 "(unsigned) INTVAL (size) < (1 << (GET_MODE_BITSIZE (mode) - 1))"

 This means that the threshold is at 255 for the first case, and 127 for the 
second, if mode == QImode.  I guess it's an attempt to deal with the issue
with signedness in the size operand of the movstrM-patterns, but I would
believe that any sign-effect (the direction of the move?) should be taken care
of in the pattern.  Or is this an intended "feature" of the pattern?
Anyway, it should rather be consistent.

To see this, the machine must have a movstrhi or movstrqi, and it has to be a
*real* movstr-instruction, not some expansion that "FAIL"s long before
GET_MODE_MASK (mode) bytes.
 The ones I found were affected are gmicro, tahoe and vax.

The two different movstr-tests are located in a generic "block copy" function,
and an "argument-pushing" function respectively.  This means the effects of
the
difference is seen in the testcase below:

struct foo
{
  char array[32768];
} foobar;

void bar (struct foo *baz)
{
  *baz = foobar;
}

extern struct foo eck (struct foo);

void ock (void)
{
  eck (foobar);
}

which on a vax (--target=vaxv) looks like this (I just ran cc1 with
"-O2 -quiet", I did not care to install it or stuff):

	.file	"stdin"
gcc2_compiled.:
___gnu_compiled_c:
.text
	.align 2
.globl _bar
_bar:
	.word 0x0
	movc3 $32768,_foobar,*4(ap)
	ret
	.align 2
.globl _ock
_ock:
	.word 0x0
	movab -32768(sp),sp
	movl sp,r0
	movzwl $32768,-(sp)
	pushl r0
	pushab _foobar
	calls $3,_bcopy
	calls $0,_eck
	addl2 $32768,sp
	ret
.comm _foobar,32768

Now, bar() seems pretty straightforward; the block-copy-instruction movc3 is
used.  In ock(), suddenly bcopy() is used instead.  The following patch uses
the "wider" test, so movc3 is used in argument-passing as well:

Sun Jan 18 20:30:43 1998  Hans-Peter Nilsson  <hp@axis.se>

	* expr.c (emit_push_insn): Use same max-move-amount for movstrhi
	and movstrqi as in emit_block_move ().

*** expr.c.original	Sun Jan 18 20:16:20 1998
--- expr.c	Sun Jan 18 20:26:39 1998
*************** emit_push_insn (x, mode, type, size, ali
*** 2653,2660 ****
  #ifdef HAVE_movstrqi
	  if (HAVE_movstrqi
	      && GET_CODE (size) == CONST_INT
!	      && ((unsigned) INTVAL (size)
!		  < (1 << (GET_MODE_BITSIZE (QImode) - 1))))
	    {
	      rtx pat = gen_movstrqi (gen_rtx_MEM (BLKmode, temp),
				      xinner, size, GEN_INT (align));
--- 2653,2660 ----
  #ifdef HAVE_movstrqi
	  if (HAVE_movstrqi
	      && GET_CODE (size) == CONST_INT
!	      && ((unsigned HOST_WIDE_INT) INTVAL (size)
!		  <= GET_MODE_MASK (QImode)))
	    {
	      rtx pat = gen_movstrqi (gen_rtx_MEM (BLKmode, temp),
				      xinner, size, GEN_INT (align));
*************** emit_push_insn (x, mode, type, size, ali
*** 2668,2675 ****
  #ifdef HAVE_movstrhi
	  if (HAVE_movstrhi
	      && GET_CODE (size) == CONST_INT
!	      && ((unsigned) INTVAL (size)
!		  < (1 << (GET_MODE_BITSIZE (HImode) - 1))))
	    {
	      rtx pat = gen_movstrhi (gen_rtx_MEM (BLKmode, temp),
				      xinner, size, GEN_INT (align));
--- 2668,2675 ----
  #ifdef HAVE_movstrhi
	  if (HAVE_movstrhi
	      && GET_CODE (size) == CONST_INT
!	      && ((unsigned HOST_WIDE_INT) INTVAL (size)
!		  <= GET_MODE_MASK (HImode)))
	    {
	      rtx pat = gen_movstrhi (gen_rtx_MEM (BLKmode, temp),
				      xinner, size, GEN_INT (align));


Beware, FUD ahead:
I have a nagging feeling that the reason for making the threshold
twos-complement-immune anywhere is that precisely the Vax considers
the move-amount being twos-complement.
 That would require other patches (hopefully contained within the Vax port).
Anybody care to comment?

Best regards,
-- 
Hans-Peter Nilsson, Axis Communications AB, S - 223 70 LUND, SWEDEN
Hans-Peter.Nilsson@axis.se | http://www.axis.se/ | Tel +46 46191867,191800
Fax +46 46136130 | RFC 1855 compliance implemented; report loss of brain.



More information about the Gcc mailing list