diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 933b3b1761e..dbcdf3e26cc 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2003-11-20 Fariborz Jahanian + David Edelsohn + + * calls.c (expand_call): Allocate new temp in pass1. + (store_one_arg): If PARALLEL, calculate excess using mode size of + rtvec elt. + * expr.c (emit_push_insn): If PARALLEL, calculate offset using + mode size of rtvec elt. + * function.c (assign_parms): Use parm in register, if available. + 2003-11-20 Kazu Hirata * config/h8300/lib1funcs.asm (MOVP): Remove. diff --git a/gcc/calls.c b/gcc/calls.c index a3b86ade979..79d9b9c4452 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -2152,6 +2152,7 @@ expand_call (tree exp, rtx target, int ignore) #endif int initial_highest_arg_in_use = highest_outgoing_arg_in_use; + rtx temp_target = 0; char *initial_stack_usage_map = stack_usage_map; int old_stack_allocated; @@ -3266,7 +3267,11 @@ expand_call (tree exp, rtx target, int ignore) The Irix 6 ABI has examples of this. */ else if (GET_CODE (valreg) == PARALLEL) { - if (target == 0) + /* Second condition is added because "target" is freed at the + the end of "pass0" for -O2 when call is made to + expand_end_target_temps (). Its "in_use" flag has been set + to false, so allocate a new temp. */ + if (target == 0 || (pass == 1 && target == temp_target)) { /* This will only be assigned once, so it can be readonly. */ tree nt = build_qualified_type (TREE_TYPE (exp), @@ -3274,6 +3279,7 @@ expand_call (tree exp, rtx target, int ignore) | TYPE_QUAL_CONST)); target = assign_temp (nt, 0, 1, 1); + temp_target = target; preserve_temp_slots (target); } @@ -4615,9 +4621,18 @@ store_one_arg (struct arg_data *arg, rtx argblock, int flags, { /* PUSH_ROUNDING has no effect on us, because emit_push_insn for BLKmode is careful to avoid it. */ - excess = (arg->locate.size.constant - - int_size_in_bytes (TREE_TYPE (pval)) - + partial * UNITS_PER_WORD); + if (reg && GET_CODE (reg) == PARALLEL) + { + /* Use the size of the elt to compute excess. */ + rtx elt = XEXP (XVECEXP (reg, 0, 0), 0); + excess = (arg->locate.size.constant + - int_size_in_bytes (TREE_TYPE (pval)) + + partial * GET_MODE_SIZE (GET_MODE (elt))); + } + else + excess = (arg->locate.size.constant + - int_size_in_bytes (TREE_TYPE (pval)) + + partial * UNITS_PER_WORD); size_rtx = expand_expr (size_in_bytes (TREE_TYPE (pval)), NULL_RTX, TYPE_MODE (sizetype), 0); } diff --git a/gcc/expr.c b/gcc/expr.c index 320284c99ff..ac0249f3881 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -3474,9 +3474,19 @@ emit_push_insn (rtx x, enum machine_mode mode, tree type, rtx size, rtx temp; int used = partial * UNITS_PER_WORD; - int offset = used % (PARM_BOUNDARY / BITS_PER_UNIT); + int offset; int skip; + if (reg && GET_CODE (reg) == PARALLEL) + { + /* Use the size of the elt to compute offset. */ + rtx elt = XEXP (XVECEXP (reg, 0, 0), 0); + used = partial * GET_MODE_SIZE (GET_MODE (elt)); + offset = used % (PARM_BOUNDARY / BITS_PER_UNIT); + } + else + offset = used % (PARM_BOUNDARY / BITS_PER_UNIT); + if (size == 0) abort (); diff --git a/gcc/function.c b/gcc/function.c index 04d34243dff..7bd31906a54 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -4704,6 +4704,15 @@ assign_parms (tree fndecl) Set DECL_RTL to that place. */ + if (GET_CODE (entry_parm) == PARALLEL && nominal_mode != BLKmode) + { + /* Objects the size of a register can be combined in registers */ + rtx parmreg = gen_reg_rtx (nominal_mode); + emit_group_store (parmreg, entry_parm, TREE_TYPE (parm), + int_size_in_bytes (TREE_TYPE (parm))); + SET_DECL_RTL (parm, parmreg); + } + if (nominal_mode == BLKmode #ifdef BLOCK_REG_PADDING || (locate.where_pad == (BYTES_BIG_ENDIAN ? upward : downward) @@ -4727,7 +4736,8 @@ assign_parms (tree fndecl) assign_stack_local if space was not allocated in the argument list. If it was, this will not work if PARM_BOUNDARY is not a multiple of BITS_PER_WORD. It isn't clear how to fix this - if it becomes a problem. */ + if it becomes a problem. Exception is when BLKmode arrives + with arguments not conforming to word_mode. */ if (stack_parm == 0) { @@ -4735,7 +4745,9 @@ assign_parms (tree fndecl) PUT_MODE (stack_parm, GET_MODE (entry_parm)); set_mem_attributes (stack_parm, parm, 1); } - + else if (GET_CODE (entry_parm) == PARALLEL + && GET_MODE(entry_parm) == BLKmode) + ; else if (PARM_BOUNDARY % BITS_PER_WORD != 0) abort (); @@ -4798,7 +4810,10 @@ assign_parms (tree fndecl) move_block_from_reg (REGNO (entry_parm), mem, size_stored / UNITS_PER_WORD); } - SET_DECL_RTL (parm, stack_parm); + /* If parm is already bound to register pair, don't change + this binding. */ + if (! DECL_RTL_SET_P (parm)) + SET_DECL_RTL (parm, stack_parm); } else if (! ((! optimize && ! DECL_REGISTER (parm))