2011-09-06 Jakub Jelinek PR debug/50299 * calls.c (load_register_parameters): Use use_reg_mode instead of use_reg when adding a single register CALL_INSN_FUNCTION_USAGE entry. (expand_call): Set EXPR_LIST mode to TYPE_MODE of the argument for stack CALL_INSN_FUNCTION_USAGE uses. * expr.h (use_reg_mode): New prototype. (use_reg): Changed into inline around use_reg_mode. * expr.c (use_reg): Renamed to... (use_reg_mode): ... this. Added MODE argument, set EXPR_LIST mode to that mode instead of VOIDmode. * var-tracking.c (prepare_call_arguments): Don't track parameters whose EXPR_LIST mode is VOIDmode, BLKmode or X mode isn't convertible to it using lowpart_subreg. Convert VALUE and REG/MEM to the EXPR_LIST mode. --- gcc/calls.c.jj 2011-08-22 08:17:07.000000000 +0200 +++ gcc/calls.c 2011-09-05 19:47:47.000000000 +0200 @@ -1756,7 +1756,8 @@ load_register_parameters (struct arg_dat if (GET_CODE (reg) == PARALLEL) use_group_regs (call_fusage, reg); else if (nregs == -1) - use_reg (call_fusage, reg); + use_reg_mode (call_fusage, reg, + TYPE_MODE (TREE_TYPE (args[i].tree_value))); else if (nregs > 0) use_regs (call_fusage, REGNO (reg), nregs); } @@ -2815,10 +2816,10 @@ expand_call (tree exp, rtx target, int i } if (args[i].stack) - call_fusage = gen_rtx_EXPR_LIST (VOIDmode, - gen_rtx_USE (VOIDmode, - args[i].stack), - call_fusage); + call_fusage + = gen_rtx_EXPR_LIST (TYPE_MODE (TREE_TYPE (args[i].tree_value)), + gen_rtx_USE (VOIDmode, args[i].stack), + call_fusage); } /* If we have a parm that is passed in registers but not in memory --- gcc/expr.h.jj 2011-07-27 23:25:36.000000000 +0200 +++ gcc/expr.h 2011-09-05 18:05:31.000000000 +0200 @@ -321,8 +321,16 @@ extern void emit_group_store (rtx, rtx, /* Copy BLKmode object from a set of registers. */ extern rtx copy_blkmode_from_reg (rtx, rtx, tree); +/* Mark REG as holding a parameter for the next CALL_INSN. + Mode is TYPE_MODE of the non-promoted parameter, or VOIDmode. */ +extern void use_reg_mode (rtx *, rtx, enum machine_mode); + /* Mark REG as holding a parameter for the next CALL_INSN. */ -extern void use_reg (rtx *, rtx); +static inline void +use_reg (rtx *fusage, rtx reg) +{ + use_reg_mode (fusage, reg, VOIDmode); +} /* Mark NREGS consecutive regs, starting at REGNO, as holding parameters for the next CALL_INSN. */ --- gcc/expr.c.jj 2011-09-02 16:29:39.000000000 +0200 +++ gcc/expr.c 2011-09-05 19:47:32.000000000 +0200 @@ -2184,13 +2184,12 @@ copy_blkmode_from_reg (rtx tgtblk, rtx s to by CALL_FUSAGE. REG must denote a hard register. */ void -use_reg (rtx *call_fusage, rtx reg) +use_reg_mode (rtx *call_fusage, rtx reg, enum machine_mode mode) { gcc_assert (REG_P (reg) && REGNO (reg) < FIRST_PSEUDO_REGISTER); *call_fusage - = gen_rtx_EXPR_LIST (VOIDmode, - gen_rtx_USE (VOIDmode, reg), *call_fusage); + = gen_rtx_EXPR_LIST (mode, gen_rtx_USE (VOIDmode, reg), *call_fusage); } /* Add USE expressions to *CALL_FUSAGE for each of NREGS consecutive regs, --- gcc/var-tracking.c.jj 2011-08-30 10:52:41.000000000 +0200 +++ gcc/var-tracking.c 2011-09-05 19:48:10.000000000 +0200 @@ -5730,11 +5730,18 @@ prepare_call_arguments (basic_block bb, { rtx item = NULL_RTX; x = XEXP (XEXP (link, 0), 0); - if (REG_P (x)) + if (GET_MODE (link) == VOIDmode + || GET_MODE (link) == BLKmode + || (GET_MODE (link) != GET_MODE (x) + && (GET_MODE_CLASS (GET_MODE (link)) != MODE_INT + || GET_MODE_CLASS (GET_MODE (x)) != MODE_INT))) + /* Can't do anything for these, if the original type mode + isn't known or can't be converted. */; + else if (REG_P (x)) { cselib_val *val = cselib_lookup (x, GET_MODE (x), 0, VOIDmode); if (val && cselib_preserved_value_p (val)) - item = gen_rtx_CONCAT (GET_MODE (x), x, val->val_rtx); + item = val->val_rtx; else if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT) { enum machine_mode mode = GET_MODE (x); @@ -5749,10 +5756,7 @@ prepare_call_arguments (basic_block bb, val = cselib_lookup (reg, mode, 0, VOIDmode); if (val && cselib_preserved_value_p (val)) { - item = gen_rtx_CONCAT (GET_MODE (x), x, - lowpart_subreg (GET_MODE (x), - val->val_rtx, - mode)); + item = val->val_rtx; break; } } @@ -5776,7 +5780,7 @@ prepare_call_arguments (basic_block bb, } val = cselib_lookup (mem, GET_MODE (mem), 0, VOIDmode); if (val && cselib_preserved_value_p (val)) - item = gen_rtx_CONCAT (GET_MODE (x), copy_rtx (x), val->val_rtx); + item = val->val_rtx; else if (GET_MODE_CLASS (GET_MODE (mem)) != MODE_INT) { /* For non-integer stack argument see also if they weren't @@ -5787,15 +5791,22 @@ prepare_call_arguments (basic_block bb, val = cselib_lookup (adjust_address_nv (mem, imode, 0), imode, 0, VOIDmode); if (val && cselib_preserved_value_p (val)) - item = gen_rtx_CONCAT (GET_MODE (x), copy_rtx (x), - lowpart_subreg (GET_MODE (x), - val->val_rtx, - imode)); + item = lowpart_subreg (GET_MODE (x), val->val_rtx, + imode); } } } if (item) - call_arguments = gen_rtx_EXPR_LIST (VOIDmode, item, call_arguments); + { + rtx x2 = x; + if (GET_MODE (item) != GET_MODE (link)) + item = lowpart_subreg (GET_MODE (link), item, GET_MODE (item)); + if (GET_MODE (x2) != GET_MODE (link)) + x2 = lowpart_subreg (GET_MODE (link), x2, GET_MODE (x2)); + item = gen_rtx_CONCAT (GET_MODE (link), x2, item); + call_arguments + = gen_rtx_EXPR_LIST (VOIDmode, item, call_arguments); + } if (t && t != void_list_node) { tree argtype = TREE_VALUE (t);