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