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.

Reply via email to