bignum@math.keio.ac.jp (NIIMI Makoto) (02/03/90)
My friend ,Mr. Seyama, porting GNU CC to OS-9/68000.
He fond some bugs, but he can not mail to you.
So, I forward his mail to you.
If you want to contact him, please mail to me.
------------------------------------------------------------------------
GNU CC Version 1.34 bug report
I am poting GNU CC Version 1.34 to OS-9/68000 which is a unix link
operating system running on Motorola 680XX. Main differences as long as
gcc porting is concerned, are
(1) C libraries of OS-9/68000 uses registers for passing parameters.
(2) OS-9/68000 requires base register for accessing data area.
Beside the second difference, here is a bug report of -mregparm feature
of gcc. Although that feature is in only test stage, l hope this report
will be of some help.
This report also includes these independent of -mregparm. At first such
bugs are reported.
(1) Assume STRUCTURE_SIZE_BOUNDARY is not defined, (or defined to be 8).
(1-1) Then
struct z1 { char a;}
have 8 bit alignment, and if function `foo' has an argument of type
`struct z1', calling sequence of `foo' contains instruction
`subq.l #3,sp' to get PARM_BOUNDARY (32bit) alignment.
The following is my patch (store_one_arg in expr.c).
static void
store_one_arg (arg, argblock, may_be_alloca)
...
{
...
if (arg->reg != 0 && arg->partial == 0)
...
else if (TYPE_MODE (TREE_TYPE (pval)) != BLKmode)
...
else if (arg->stack != 0)
...
else
{
/* BLKmode, at least partly to be pushed. */
...
if (arg->size.var != 0)
...
else
{
register tree size = size_in_bytes (TREE_TYPE (pval));
/* PUSH_ROUNDING has no effect on us, because
emit_push_insn for BLKmode is careful to avoid it. */
/* CHANGED */
#ifndef PUSH_ROUNDING
excess = arg->size.constant - TREE_INT_CST_LOW (size);
#else
excess = arg->size.constant - PUSH_ROUNDING (TREE_INT_CST_LOW (size));
#endif
size_rtx = expand_expr (size, 0, VOIDmode, 0);
}
...
}
...
}
(1-2) If function `bar' takes an argument of type
struct z2 { char a; char b;},
calling sequence of `bar' contains instructions
move.b -1(fp),-(sp)
move.b -2(fp),-(sp)
to set up argument.
The following is my patch (emit_push_insn in expr.c).
static void
emit_push_insn (x, mode, size, align, partial, reg, extra, args_addr, args_so_far)
...
{
...
if (partial > 0)
...
if (extra)
...
if (mode == BLKmode)
{
...
if (size == 0)
...
if (partial != 0)
...
#ifdef PUSH_ROUNDING
/* ADDED */
align = PUSH_ROUNDING (align);
...
#endif /* PUSH_ROUNDING */
{
/* Otherwise make space on the stack and copy the data
to the address of that space. */
/* First deduct part put into registers from the size we need. */
if (partial != 0)
...
/* ADDED */
#ifdef PUSH_ROUNDING
if (args_addr == 0
&& GET_CODE (size) == CONST_INT
&& PUSH_ROUNDING (INTVAL (size)) != INTVAL (size))
size = gen_rtx (CONST_INT, VOIDmode, PUSH_ROUNDING (INTVAL (size)));
#endif
....
}
else if (partial > 0)
...
else
...
...
}
(1-3) A question. if a variable `x' of type
struct z3 { short a; int b; short c;}
comes into registers, member `x.b' can be correctly accessed ?. (In
this case, `x.b' is stored across two registers).
(2) Block profile code generation.
(2-1) (final in final.c) Becase the last insn may be a (conditional)
branch, `new_block' must be checked after exiting main `for' loop.
(2-2) (final in final.c) When `code_label' insn is used as a base
address of jump table, do not generat profile code.
(2-3) (BLOCK_PROFILER in tm-m68k.h) Since `addq.l #1,...' clobbers the
condition code register, CC_STATUS_INIT must be issued.
(2-4) For emity function `void do_nothing (void) {}', no profile code is
generated. Is it desirable ?.
(2-5) Detect conditional branches in parallel expression ?. (e.g. insn
using `dbra')
(3) Misc.
(3-1) combine_instructions (combine.c) Count up `total_distrib_*'.
(3-2) round_push (explow.c) `else' after `if (align == 1) ;' is missed ?.
(3-3) epand_call (expr.c) Argument NAMED of FUCNTION_ARG and
FUNCTION_ARG_PARTIAL_NREGS are incorrect if PUSH_ARG_REVERSED. In that
case, not `i < n_named_args' but `num_actuals - 1 - i < n_named_args'
must be used.
Now I report bugs of -mregparm feature.
(4) move_movables (loop.c) To find the insn loading function address,
skip `(insn ... (use ...))'.
static void
move_movables (movables, threshold, insn_count, loop_start, end, nregs)
...
{
...
for (m = movables; m; m = m->next)
{
/* Describe this movable insn. */
if (loop_dump_stream)
...
if (!m->done
&& (! m->cond
|| (1 == invariant_p (m->set_src)
&& (m->consec == 0
|| 1 == consec_sets_invariant_p (SET_DEST (PATTERN (m->insn)),
m->consec + 1,
m->insn))))
&& (! m->forces || m->forces->done))
{
...
if (loop_dump_stream)
...
if (moved_once[regno])
...
if (already_moved[regno]
|| (threshold * savings * m->lifetime) >= insn_count
|| (m->forces && m->forces->done
&& n_times_used[m->forces->regno] == 1))
{
...
for (count = m->consec; count >= 0; count--)
{
...
if (temp = find_reg_note (p, REG_LIBCALL, 0))
...
if (temp = find_reg_note (p, REG_RETVAL, 0))
{
...
/* THIS LOOP => */ for (temp = XEXP (temp, 0); temp != p;
temp = NEXT_INSN (temp))
{
(5) Order of allocating registers for parameters are reveresed in
`emit_library_call' (expr.c). For example, consider the call of
function
int foo (int a, int b).
If `foo' is not a library function then expand_call set value of `a' in
d0 and `b' in d1. But if `foo' is a library function such as __divsi3,
`emit_library_call' set value of `b' in d0 and `a' in d1.
(6) Conflict between FUNCTION_VALUE_REGNO_P and FUNCTION_ARG_REGNO_P.
If function value is returned via d0 and function arguments are passed
via d0 and d1, both macro return t for regno 0. On the other hand,
try_combine (combine.c) uses FUNCTION_VALUE_REGNO_P to inhibit
instruction combination. Consequently try_combine also inhibits
instruction combination using register which is used to pass argument.
Is it desirable ?.
(7) BLKmode arguments passed by regsiters.
If a function takes a BLKmode argument and that argument is passied via
registers, `assign_parms' (stmt.c) use `move_block_form_reg' to save
arguments into stack slot and `store_one_arg' use `move_block_to_reg' to
set arguments into registers. Both `move_block_from_reg' and
`move_block_to_reg' can move only BLKmode whose sizeof is a multiple of
UNITS_PER_WORD, if sizeof is 1 2 or 6 then only a part of argument is
passed.
(8) Final question. `save_for_inline' (integrate.c)
I found a forward reference in the chain of insns (REG_NOTES format `u')
when compiling the dhry benchmark program Version 2.1.
gcc -O -finline-functions -mc68000 -msoft-float -S dhry-2.c
Generated code of Proc_8 is different from the code generated without
the option `-finline-fucntions'.
90/01/31 Atsushi Seyama
5-7-20 HIGASI MACHI, HOYA, TOKYO, JAPAN
-------------------
;;; Keio University
;;; Faculty of Science and Technology
;;; Department of Math
;;; Makoto Niimi
;;; bignum@math.keio.ac.jp