On Tue, Nov 25, 2014 at 7:01 AM, Richard Biener <richard.guent...@gmail.com> wrote: > On Tue, Nov 25, 2014 at 1:57 PM, H.J. Lu <hongjiu...@intel.com> wrote: >> Hi, >> >> The enclosed testcase fails on x86 when compiled with -Os since we pass >> a byte parameter with a byte load in caller and read it as an int in >> callee. The reason it only shows up with -Os is x86 backend encodes >> a byte load with an int load if -O isn't used. When a byte load is >> used, the upper 24 bits of the register have random value for none >> WORD_REGISTER_OPERATIONS targets. >> >> It happens because setup_incoming_promotions in combine.c has >> >> /* The mode and signedness of the argument before any promotions happen >> (equal to the mode of the pseudo holding it at that stage). */ >> mode1 = TYPE_MODE (TREE_TYPE (arg)); >> uns1 = TYPE_UNSIGNED (TREE_TYPE (arg)); >> >> /* The mode and signedness of the argument after any source language >> and >> TARGET_PROMOTE_PROTOTYPES-driven promotions. */ >> mode2 = TYPE_MODE (DECL_ARG_TYPE (arg)); >> uns3 = TYPE_UNSIGNED (DECL_ARG_TYPE (arg)); >> >> /* The mode and signedness of the argument as it is actually passed, >> after any TARGET_PROMOTE_FUNCTION_ARGS-driven ABI promotions. */ >> mode3 = promote_function_mode (DECL_ARG_TYPE (arg), mode2, &uns3, >> TREE_TYPE (cfun->decl), 0); >> >> while they are actually passed in register by assign_parm_setup_reg in >> function.c: >> >> /* Store the parm in a pseudoregister during the function, but we may >> need to do it in a wider mode. Using 2 here makes the result >> consistent with promote_decl_mode and thus expand_expr_real_1. */ >> promoted_nominal_mode >> = promote_function_mode (data->nominal_type, data->nominal_mode, >> &unsignedp, >> TREE_TYPE (current_function_decl), 2); >> >> where nominal_type and nominal_mode are set up with TREE_TYPE (parm) >> and TYPE_MODE (nominal_type). TREE_TYPE here is > > I think the bug is here, not in combine.c. Can you try going back in history > for both snippets and see if they matched at some point? >
The bug was introduced by https://gcc.gnu.org/ml/gcc-cvs/2007-09/msg00613.html commit 5d93234932c3d8617ce92b77b7013ef6bede9508 Author: shinwell <shinwell@138bc75d-0d04-0410-961f-82ee72b054a4> Date: Thu Sep 20 11:01:18 2007 +0000 gcc/ * combine.c: Include cgraph.h. (setup_incoming_promotions): Rework to allow more aggressive elimination of sign extensions when all call sites of the current function are known to lie within the current unit. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@128618 138bc75d-0d04-0410-961f-82ee72b054a4 Before this commit, combine.c has enum machine_mode mode = TYPE_MODE (TREE_TYPE (arg)); int uns = TYPE_UNSIGNED (TREE_TYPE (arg)); mode = promote_mode (TREE_TYPE (arg), mode, &uns, 1); if (mode == GET_MODE (reg) && mode != DECL_MODE (arg)) { rtx x; x = gen_rtx_CLOBBER (DECL_MODE (arg), const0_rtx); x = gen_rtx_fmt_e ((uns ? ZERO_EXTEND : SIGN_EXTEND), mode, x); record_value_for_reg (reg, first, x); } It matches function.c: /* This is not really promoting for a call. However we need to be consistent with assign_parm_find_data_types and expand_expr_real_1. */ promoted_nominal_mode = promote_mode (data->nominal_type, data->nominal_mode, &unsignedp, 1); r128618 changed mode = promote_mode (TREE_TYPE (arg), mode, &uns, 1); to mode3 = promote_mode (DECL_ARG_TYPE (arg), mode2, &uns3, 1); It breaks none WORD_REGISTER_OPERATIONS targets. -- H.J.