[su]divsi3 in sh.md

SAITOH Masanobu masanobu@iij.ad.jp
Thu Jul 6 01:47:00 GMT 2000


 Some complexed function becomes wrong under coff-sh
(I tested egcs-20000703, NetBSD/sh3 1.4.1).

 zic in tzcode ( ftp://elsie.nci.nih.gov/pub/ ) dies by
bus error when it was compiled with -O1 (-O2 works fine).

The isleap() macro in zic.c::rpytime() will call __sdivsi3().

-------------- a part of zic.c::rpytime() ----------------
#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))

static time_t
rpytime(rp, wantedy)
register const struct rule * const	rp;
register const int			wantedy;
{
	register int	y, m, i;
	register long	dayoff;			/* with a nod to Margaret O. */
	register time_t	t;

	if (wantedy == INT_MIN)
		return min_time;
	if (wantedy == INT_MAX)
		return max_time;
	dayoff = 0;
	m = TM_JANUARY;
	y = EPOCH_YEAR;
	while (wantedy != y) {
		if (wantedy > y) {
			i = len_years[isleap(y)];
			++y;
		} else {
			--y;
			i = -len_years[isleap(y)];
		}
		dayoff = oadd(dayoff, eitol(i));
	}
	while (m != rp->r_month) {
		i = len_months[isleap(y)][m];
		dayoff = oadd(dayoff, eitol(i));
		++m;
	}
	.
	.
	.
--------------------------------------------------------------

--------------------- part of zic.s (-O1) --------------------
L1282:
	add	#-4,r15
	mov.l	L1329,r1
	jsr	@r1
	mov	r9,r4
	mov.l	L1330,r1
	mov	r11,r4
	jsr	@r1
	mov	r0,r5
	mov	r0,r11
	add	#4,r15
	cmp/eq	r10,r8
	bf	L1278
L1277:
	mov.l	@(24,r12),r1
	mov.l	@r14,r0
	cmp/eq	r1,r0
	bt	L1316
	mov.l	L1331,r9
	mov	r10,r4
	jsr	@r13		<===    r13 is the address of __sdivsi3().
	mov	#100,r5			But, it doesn't set (the instruction
	mov	r0,r1			to set r13 appear later of this
	shll2	r1			instruction).
	mov	r1,r8
	add	r0,r8
	.align 2
L1288:
--------------------------------------------------------------

gcc/config/sh/sh.md says:

-------------------- sh.md::divsi3 ---------------------------
(define_expand "divsi3"
  [(set (match_dup 3) (symbol_ref:SI "__sdivsi3"))
   (set (reg:SI 4) (match_operand:SI 1 "general_operand" ""))
   (set (reg:SI 5) (match_operand:SI 2 "general_operand" ""))
   (parallel [(set (match_operand:SI 0 "register_operand" "")
		   (div:SI (reg:SI 4)
			   (reg:SI 5)))
	      (clobber (reg:SI 18))
	      (clobber (reg:SI 17))
	      (clobber (reg:SI 1))
	      (clobber (reg:SI 2))
	      (clobber (reg:SI 3))
	      (use (match_dup 3))])]
  ""
  "
{
  rtx first, last;

  operands[3] = gen_reg_rtx(SImode);
  /* Emit the move of the address to a pseudo outside of the libcall.  */
  if (TARGET_HARD_SH4)
    {
	/***********************************************
	 It seems following insn IS the "first" insn to
	block with REG_LIBCALL-REG_RETVAL
	************************************************/
      emit_move_insn (operands[3],
		      gen_rtx_SYMBOL_REF (SImode, \"__sdivsi3_i4\"));
      if (TARGET_FPU_SINGLE)
	last = gen_divsi3_i4_single (operands[0], operands[3]);
      else
	last = gen_divsi3_i4 (operands[0], operands[3]);
    }
  else
    {
	/***********************************************
	 It seems following insn IS the "first" insn to
	block with REG_LIBCALL-REG_RETVAL
	************************************************/
      emit_move_insn (operands[3], gen_rtx_SYMBOL_REF (SImode, \"__sdivsi3\"));
      last = gen_divsi3_i1 (operands[0], operands[3]);
    }
	/***********************************************
	 It seems following insn ISN'T the "first" insn to
	block with REG_LIBCALL-REG_RETVAL
	************************************************/
  first = emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
  emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
  last = emit_insn (last);
  /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
     invariant code motion can move it.  */
  REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
  REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
  DONE;
}")
-----------------------------------------------------------------------



 It seems following patch fixes this problem. Is this correct?

--------------------- patch for udivsi3 and sdivsi3 --------------------
*** sh.md.orig	Fri Jun  2 08:14:27 2000
--- sh.md	Thu Jul  6 11:17:45 2000
***************
*** 937,943 ****
    /* Emit the move of the address to a pseudo outside of the libcall.  */
    if (TARGET_HARD_SH4)
      {
!       emit_move_insn (operands[3],
  		      gen_rtx_SYMBOL_REF (SImode, \"__udivsi3_i4\"));
        if (TARGET_FPU_SINGLE)
  	last = gen_udivsi3_i4_single (operands[0], operands[3]);
--- 937,943 ----
    /* Emit the move of the address to a pseudo outside of the libcall.  */
    if (TARGET_HARD_SH4)
      {
!       first = emit_move_insn (operands[3],
  		      gen_rtx_SYMBOL_REF (SImode, \"__udivsi3_i4\"));
        if (TARGET_FPU_SINGLE)
  	last = gen_udivsi3_i4_single (operands[0], operands[3]);
***************
*** 946,956 ****
      }
    else
      {
!       emit_move_insn (operands[3],
  		      gen_rtx_SYMBOL_REF (SImode, \"__udivsi3\"));
        last = gen_udivsi3_i1 (operands[0], operands[3]);
      }
!   first = emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
    emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
    last = emit_insn (last);
    /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
--- 946,956 ----
      }
    else
      {
!       first = emit_move_insn (operands[3],
  		      gen_rtx_SYMBOL_REF (SImode, \"__udivsi3\"));
        last = gen_udivsi3_i1 (operands[0], operands[3]);
      }
!   emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
    emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
    last = emit_insn (last);
    /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
***************
*** 1023,1029 ****
    /* Emit the move of the address to a pseudo outside of the libcall.  */
    if (TARGET_HARD_SH4)
      {
!       emit_move_insn (operands[3],
  		      gen_rtx_SYMBOL_REF (SImode, \"__sdivsi3_i4\"));
        if (TARGET_FPU_SINGLE)
  	last = gen_divsi3_i4_single (operands[0], operands[3]);
--- 1023,1029 ----
    /* Emit the move of the address to a pseudo outside of the libcall.  */
    if (TARGET_HARD_SH4)
      {
!       first = emit_move_insn (operands[3],
  		      gen_rtx_SYMBOL_REF (SImode, \"__sdivsi3_i4\"));
        if (TARGET_FPU_SINGLE)
  	last = gen_divsi3_i4_single (operands[0], operands[3]);
***************
*** 1032,1041 ****
      }
    else
      {
!       emit_move_insn (operands[3], gen_rtx_SYMBOL_REF (SImode, \"__sdivsi3\"));
        last = gen_divsi3_i1 (operands[0], operands[3]);
      }
!   first = emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
    emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
    last = emit_insn (last);
    /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
--- 1032,1041 ----
      }
    else
      {
!       first = emit_move_insn (operands[3], gen_rtx_SYMBOL_REF (SImode, \"__sdivsi3\"));
        last = gen_divsi3_i1 (operands[0], operands[3]);
      }
!   emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
    emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
    last = emit_insn (last);
    /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
-----------------------------------------------------------------------




But, a new problem occurred after this patch was applied.

Followin programs doesn't work when it compiled with -O1
(-O2 works fine).

------ test code for new patch -----------
#include <stdio.h>
#include <stdlib.h>


int g = 1;

int
main()
{
	int a = 1, b = 1;

#define DIV(g)	(g * 8 / 3)

	printf("--- a = %d, DIV = %d\n", a, DIV(g));
	printf("--- (a > DIV) = %d\n", a > DIV(g));

	while (a > DIV(g)) {
		printf("why?\n");
		if (b == 1)
			break;
	}
	return 0;
}
-----------------

-------------- gcc -O2 -S ----------------
	.file	"wh2.c"
	.data
gcc2_compiled.:
___gnu_compiled_c:
	.global	_g
	.align 2
_g:
	.long	1
	.text
	.align 2
LC0:
	.ascii "--- a = %d, DIV = %d\12\0"
	.align 2
LC1:
	.ascii "--- (a > DIV) = %d\12\0"
	.align 2
LC2:
	.ascii "why?\12\0"
	.align 2
	.global	_main
_main:
	mov.l	r8,@-r15
	mov.l	r9,@-r15
	mov.l	r10,@-r15
	mov.l	r11,@-r15
	mov.l	r12,@-r15
	mov.l	r14,@-r15
	sts.l	pr,@-r15
	mov.l	L11,r1
	jsr	@r1
	mov	r15,r14
	mov	#1,r10
	mov	r10,r11
	add	#-4,r15
	mov.l	L12,r8
	mov.l	@r8,r4
	mov.l	L13,r7
	shll2	r4
	add	r4,r4
	jsr	@r7
	mov	#3,r5
	mov.l	L14,r9
	mov.l	L15,r4
	mov	r10,r5
	jsr	@r9
	mov	r0,r6
	mov.l	@r8,r4
	mov.l	L13,r7
	shll2	r4
	add	r4,r4
	jsr	@r7
	mov	#3,r5
	cmp/gt	r0,r10
	mov.l	L16,r4
	jsr	@r9
	movt	r5
	add	#4,r15
	mov	r9,r8
	.align 2
L10:
	cmp/gt	r12,r11		<= r12 is uninitialized
	bf	L8
	mov.l	L17,r4
	jsr	@r8
	add	#-4,r15
	add	#4,r15
	mov	r10,r0
	cmp/eq	#1,r0
	bf	L10
L8:
	mov	#0,r0
	mov	r14,r15
	lds.l	@r15+,pr
	mov.l	@r15+,r14
	mov.l	@r15+,r12
	mov.l	@r15+,r11
	mov.l	@r15+,r10
	mov.l	@r15+,r9
	rts	
	mov.l	@r15+,r8
L18:
	.align 2
L11:
	.long	___main
L12:
	.long	_g
L13:
	.long	___sdivsi3
L14:
	.long	_printf
L15:
	.long	LC0
L16:
	.long	LC1
L17:
	.long	LC2
------------------------------------------

 I don't know how to solve this problem.

----------------------------------------------------------
		SAITOH Masanobu (masanobu@iij.ad.jp
				  msaitoh@netbsd.org)


More information about the Gcc-bugs mailing list