On Wed, Nov 20, 2024 at 10:05 PM Richard Biener <richard.guent...@gmail.com>
wrote:

> On Sun, Nov 10, 2024 at 1:55 PM H.J. Lu <hjl.to...@gmail.com> wrote:
> >
> > For targets, like x86, which define TARGET_PROMOTE_PROTOTYPES to return
> > true, all integer arguments smaller than int are passed as int:
> >
> > [hjl@gnu-tgl-3 pr14907]$ cat x.c
> > extern int baz (char c1);
> >
> > int
> > foo (char c1)
> > {
> >   return baz (c1);
> > }
> > [hjl@gnu-tgl-3 pr14907]$ gcc -S -O2 -m32 x.c
> > [hjl@gnu-tgl-3 pr14907]$ cat x.s
> >         .file   "x.c"
> >         .text
> >         .p2align 4
> >         .globl  foo
> >         .type   foo, @function
> > foo:
> > .LFB0:
> >         .cfi_startproc
> >         movsbl  4(%esp), %eax
> >         movl    %eax, 4(%esp)
> >         jmp     baz
> >         .cfi_endproc
> > .LFE0:
> >         .size   foo, .-foo
> >         .ident  "GCC: (GNU) 14.2.1 20240912 (Red Hat 14.2.1-3)"
> >         .section        .note.GNU-stack,"",@progbits
> > [hjl@gnu-tgl-3 pr14907]$
> >
> > But integer promotion:
> >
> >         movsbl  4(%esp), %eax
> >         movl    %eax, 4(%esp)
> >
> > isn't necessary if incoming arguments and outgoing arguments are the
> > same.  Drop targetm.promote_prototypes from C, C++ and Ada frontends
> > and apply targetm.promote_prototypes during RTL call expansion.
>
> I'm only commenting on the RTL expansion bit below (thanks for doing this
> btw)
>
> > gcc/
> >
> >         PR middle-end/14907
> >         * calls.cc: Include "ssa.h", "tree-ssa-live.h" and
> >         "tree-outof-ssa.h".
> >         (get_promoted_int_value_from_ssa_name): New function.
> >         (get_promoted_int_value): Likewise.
> >         (initialize_argument_information): Call get_promoted_int_value
> >         to promote integer function argument.
> >         * gimple.cc (gimple_builtin_call_types_compatible_p): Remove the
> >         targetm.calls.promote_prototypes call.
> >         * tree.cc (tree_builtin_call_types_compatible_p): Likewise.
> >
> > gcc/ada/
> >
> >         PR middle-end/14907
> >         * gcc-interface/utils.cc (create_param_decl): Remove the
> >         targetm.calls.promote_prototypes call.
> >
> > gcc/c/
> >
> >         PR middle-end/14907
> >         * c-decl.cc (start_decl): Remove the
> >         targetm.calls.promote_prototypes call.
> >         (store_parm_decls_oldstyle): Likewise.
> >         (finish_function): Likewise.
> >         * c-typeck.cc (convert_argument): Likewise.
> >         (c_safe_arg_type_equiv_p): Likewise.
> >
> > gcc/cp/
> >
> >         PR middle-end/14907
> >         * call.cc (type_passed_as): Remove the
> >         targetm.calls.promote_prototypes call.
> >         (convert_for_arg_passing): Likewise.
> >         * typeck.cc (cxx_safe_arg_type_equiv_p): Likewise.
> >
> > gcc/testsuite/
> >
> >         PR middle-end/14907
> >         * gcc.target/i386/pr14907-1.c: New test.
> >         * gcc.target/i386/pr14907-2.c: Likewise.
> >         * gcc.target/i386/pr14907-3.c: Likewise.
> >         * gcc.target/i386/pr14907-4.c: Likewise.
> >         * gcc.target/i386/pr14907-5.c: Likewise.
> >         * gcc.target/i386/pr14907-6.c: Likewise.
> >         * gcc.target/i386/pr14907-7.c: Likewise.
> >         * gcc.target/i386/pr14907-8.c: Likewise.
> >         * gcc.target/i386/pr14907-9.c: Likewise.
> >         * gcc.target/i386/pr14907-10.c: Likewise.
> >         * gcc.target/i386/pr14907-11.c: Likewise.
> >         * gcc.target/i386/pr14907-12.c: Likewise.
> >         * gcc.target/i386/pr14907-13.c: Likewise.
> >         * gcc.target/i386/pr14907-14.c: Likewise.
> >         * gcc.target/i386/pr14907-15.c: Likewise.
> >         * gcc.target/i386/pr14907-16.c: Likewise.
> >         * gfortran.dg/pr14907-1.f90: Likewise.
> >
> > Signed-off-by: H.J. Lu <hjl.to...@gmail.com>
> > ---
> >  gcc/ada/gcc-interface/utils.cc             | 24 -------
> >  gcc/c/c-decl.cc                            | 40 -----------
> >  gcc/c/c-typeck.cc                          | 19 ++---
> >  gcc/calls.cc                               | 81 ++++++++++++++++++++++
> >  gcc/cp/call.cc                             | 10 ---
> >  gcc/cp/typeck.cc                           | 13 ++--
> >  gcc/gimple.cc                              | 10 +--
> >  gcc/testsuite/gcc.target/i386/pr14907-1.c  | 21 ++++++
> >  gcc/testsuite/gcc.target/i386/pr14907-10.c | 23 ++++++
> >  gcc/testsuite/gcc.target/i386/pr14907-11.c | 12 ++++
> >  gcc/testsuite/gcc.target/i386/pr14907-12.c | 17 +++++
> >  gcc/testsuite/gcc.target/i386/pr14907-13.c | 12 ++++
> >  gcc/testsuite/gcc.target/i386/pr14907-14.c | 17 +++++
> >  gcc/testsuite/gcc.target/i386/pr14907-15.c | 26 +++++++
> >  gcc/testsuite/gcc.target/i386/pr14907-16.c | 24 +++++++
> >  gcc/testsuite/gcc.target/i386/pr14907-2.c  | 21 ++++++
> >  gcc/testsuite/gcc.target/i386/pr14907-3.c  | 21 ++++++
> >  gcc/testsuite/gcc.target/i386/pr14907-4.c  | 21 ++++++
> >  gcc/testsuite/gcc.target/i386/pr14907-5.c  | 21 ++++++
> >  gcc/testsuite/gcc.target/i386/pr14907-6.c  | 21 ++++++
> >  gcc/testsuite/gcc.target/i386/pr14907-7.c  | 22 ++++++
> >  gcc/testsuite/gcc.target/i386/pr14907-8.c  | 23 ++++++
> >  gcc/testsuite/gcc.target/i386/pr14907-9.c  | 22 ++++++
> >  gcc/testsuite/gfortran.dg/pr14907-1.f90    | 17 +++++
> >  gcc/tree.cc                                | 14 ----
> >  25 files changed, 431 insertions(+), 121 deletions(-)
> >  create mode 100644 gcc/testsuite/gcc.target/i386/pr14907-1.c
> >  create mode 100644 gcc/testsuite/gcc.target/i386/pr14907-10.c
> >  create mode 100644 gcc/testsuite/gcc.target/i386/pr14907-11.c
> >  create mode 100644 gcc/testsuite/gcc.target/i386/pr14907-12.c
> >  create mode 100644 gcc/testsuite/gcc.target/i386/pr14907-13.c
> >  create mode 100644 gcc/testsuite/gcc.target/i386/pr14907-14.c
> >  create mode 100644 gcc/testsuite/gcc.target/i386/pr14907-15.c
> >  create mode 100644 gcc/testsuite/gcc.target/i386/pr14907-16.c
> >  create mode 100644 gcc/testsuite/gcc.target/i386/pr14907-2.c
> >  create mode 100644 gcc/testsuite/gcc.target/i386/pr14907-3.c
> >  create mode 100644 gcc/testsuite/gcc.target/i386/pr14907-4.c
> >  create mode 100644 gcc/testsuite/gcc.target/i386/pr14907-5.c
> >  create mode 100644 gcc/testsuite/gcc.target/i386/pr14907-6.c
> >  create mode 100644 gcc/testsuite/gcc.target/i386/pr14907-7.c
> >  create mode 100644 gcc/testsuite/gcc.target/i386/pr14907-8.c
> >  create mode 100644 gcc/testsuite/gcc.target/i386/pr14907-9.c
> >  create mode 100644 gcc/testsuite/gfortran.dg/pr14907-1.f90
> >
> > diff --git a/gcc/ada/gcc-interface/utils.cc
> b/gcc/ada/gcc-interface/utils.cc
> > index 3a571e0077b..127a83b13b6 100644
> > --- a/gcc/ada/gcc-interface/utils.cc
> > +++ b/gcc/ada/gcc-interface/utils.cc
> > @@ -3283,30 +3283,6 @@ tree
> >  create_param_decl (tree name, tree type)
> >  {
> >    tree param_decl = build_decl (input_location, PARM_DECL, name, type);
> > -
> > -  /* Honor TARGET_PROMOTE_PROTOTYPES like the C compiler, as not doing
> so
> > -     can lead to various ABI violations.  */
> > -  if (targetm.calls.promote_prototypes (NULL_TREE)
> > -      && INTEGRAL_TYPE_P (type)
> > -      && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
> > -    {
> > -      /* We have to be careful about biased types here.  Make a subtype
> > -        of integer_type_node with the proper biasing.  */
> > -      if (TREE_CODE (type) == INTEGER_TYPE
> > -         && TYPE_BIASED_REPRESENTATION_P (type))
> > -       {
> > -         tree subtype
> > -           = make_unsigned_type (TYPE_PRECISION (integer_type_node));
> > -         TREE_TYPE (subtype) = integer_type_node;
> > -         TYPE_BIASED_REPRESENTATION_P (subtype) = 1;
> > -         SET_TYPE_RM_MIN_VALUE (subtype, TYPE_MIN_VALUE (type));
> > -         SET_TYPE_RM_MAX_VALUE (subtype, TYPE_MAX_VALUE (type));
> > -         type = subtype;
> > -       }
> > -      else
> > -       type = integer_type_node;
> > -    }
> > -
> >    DECL_ARG_TYPE (param_decl) = type;
> >    return param_decl;
> >  }
> > diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
> > index ac47ef24a3d..d4e87bcf420 100644
> > --- a/gcc/c/c-decl.cc
> > +++ b/gcc/c/c-decl.cc
> > @@ -5709,26 +5709,6 @@ start_decl (struct c_declarator *declarator,
> struct c_declspecs *declspecs,
> >         DECL_EXTERNAL (decl) = !DECL_EXTERNAL (decl);
> >      }
> >
> > -  if (TREE_CODE (decl) == FUNCTION_DECL
> > -      && targetm.calls.promote_prototypes (TREE_TYPE (decl)))
> > -    {
> > -      struct c_declarator *ce = declarator;
> > -
> > -      if (ce->kind == cdk_pointer)
> > -       ce = declarator->declarator;
> > -      if (ce->kind == cdk_function)
> > -       {
> > -         tree args = ce->u.arg_info->parms;
> > -         for (; args; args = DECL_CHAIN (args))
> > -           {
> > -             tree type = TREE_TYPE (args);
> > -             if (type && INTEGRAL_TYPE_P (type)
> > -                 && TYPE_PRECISION (type) < TYPE_PRECISION
> (integer_type_node))
> > -               DECL_ARG_TYPE (args) = c_type_promotes_to (type);
> > -           }
> > -       }
> > -    }
> > -
> >    if (TREE_CODE (decl) == FUNCTION_DECL
> >        && DECL_DECLARED_INLINE_P (decl)
> >        && DECL_UNINLINABLE (decl)
> > @@ -11145,13 +11125,6 @@ store_parm_decls_oldstyle (tree fndecl, const
> struct c_arg_info *arg_info)
> >                      useful for argument types like uid_t.  */
> >                   DECL_ARG_TYPE (parm) = TREE_TYPE (parm);
> >
> > -                 if (targetm.calls.promote_prototypes (TREE_TYPE
> (current_function_decl))
> > -                     && INTEGRAL_TYPE_P (TREE_TYPE (parm))
> > -                     && (TYPE_PRECISION (TREE_TYPE (parm))
> > -                         < TYPE_PRECISION (integer_type_node)))
> > -                   DECL_ARG_TYPE (parm)
> > -                     = c_type_promotes_to (TREE_TYPE (parm));
> > -
> >                   /* ??? Is it possible to get here with a
> >                      built-in prototype or will it always have
> >                      been diagnosed as conflicting with an
> > @@ -11379,19 +11352,6 @@ finish_function (location_t end_loc)
> >    if (c_dialect_objc ())
> >      objc_finish_function ();
> >
> > -  if (TREE_CODE (fndecl) == FUNCTION_DECL
> > -      && targetm.calls.promote_prototypes (TREE_TYPE (fndecl)))
> > -    {
> > -      tree args = DECL_ARGUMENTS (fndecl);
> > -      for (; args; args = DECL_CHAIN (args))
> > -       {
> > -         tree type = TREE_TYPE (args);
> > -         if (INTEGRAL_TYPE_P (type)
> > -             && TYPE_PRECISION (type) < TYPE_PRECISION
> (integer_type_node))
> > -           DECL_ARG_TYPE (args) = c_type_promotes_to (type);
> > -       }
> > -    }
> > -
> >    if (DECL_INITIAL (fndecl) && DECL_INITIAL (fndecl) != error_mark_node)
> >      BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
> >
> > diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
> > index 201d75d2e9c..cc1ccda4424 100644
> > --- a/gcc/c/c-typeck.cc
> > +++ b/gcc/c/c-typeck.cc
> > @@ -4085,12 +4085,6 @@ convert_argument (location_t ploc, tree function,
> tree fundecl,
> >                                          val, origtype, ic_argpass,
> >                                          npc, fundecl, function,
> >                                          parmnum + 1, warnopt);
> > -
> > -  if (targetm.calls.promote_prototypes (fundecl ? TREE_TYPE (fundecl) :
> 0)
> > -      && INTEGRAL_TYPE_P (type)
> > -      && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
> > -    parmval = default_conversion (parmval);
> > -
> >    return parmval;
> >  }
> >
> > @@ -6572,17 +6566,12 @@ c_safe_arg_type_equiv_p (tree t1, tree t2)
> >        && TREE_CODE (t2) == POINTER_TYPE)
> >      return true;
> >
> > -  /* The signedness of the parameter matters only when an integral
> > -     type smaller than int is promoted to int, otherwise only the
> > -     precision of the parameter matters.
> > -     This check should make sure that the callee does not see
> > -     undefined values in argument registers.  */
> > +  /* Only the precision of the parameter matters.  This check should
> > +     make sure that the callee does not see undefined values in argument
> > +     registers.  */
> >    if (INTEGRAL_TYPE_P (t1)
> >        && INTEGRAL_TYPE_P (t2)
> > -      && TYPE_PRECISION (t1) == TYPE_PRECISION (t2)
> > -      && (TYPE_UNSIGNED (t1) == TYPE_UNSIGNED (t2)
> > -         || !targetm.calls.promote_prototypes (NULL_TREE)
> > -         || TYPE_PRECISION (t1) >= TYPE_PRECISION (integer_type_node)))
> > +      && TYPE_PRECISION (t1) == TYPE_PRECISION (t2))
> >      return true;
> >
> >    return comptypes (t1, t2);
> > diff --git a/gcc/calls.cc b/gcc/calls.cc
> > index f67067acad4..246abe34243 100644
> > --- a/gcc/calls.cc
> > +++ b/gcc/calls.cc
> > @@ -62,6 +62,9 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "value-query.h"
> >  #include "tree-pretty-print.h"
> >  #include "tree-eh.h"
> > +#include "ssa.h"
> > +#include "tree-ssa-live.h"
> > +#include "tree-outof-ssa.h"
> >
> >  /* Like PREFERRED_STACK_BOUNDARY but in units of bytes, not bits.  */
> >  #define STACK_BYTES (PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT)
> > @@ -1281,6 +1284,74 @@ maybe_complain_about_tail_call (tree call_expr,
> const char *reason)
> >    CALL_EXPR_MUST_TAIL_CALL (call_expr) = 0;
> >  }
> >
> > +/* Return the integer argument promoted from TYPE to PROMOTED_TYPE if
> ARG
> > +   isn't copied from the incoming argument.  Otherwise return the
> original
> > +   argument ORIGIN_ARG.  */
> > +
> > +static tree
> > +get_promoted_int_value_from_ssa_name (tree type, tree promoted_type,
> > +                                     tree arg, tree orig_arg)
> > +{
> > +  tree var = SSA_NAME_VAR (arg);
> > +  if (TREE_CODE (var) != PARM_DECL
> > +      || TYPE_MODE (type) != TYPE_MODE (DECL_ARG_TYPE (var)))
> > +    return fold_convert (promoted_type, var);
> > +  return orig_arg;
> > +}
> > +
> > +/* Return the promoted integer argument if ARG is smaller than int and
> > +   isn't copied from the incoming argument.  Otherwise return the
> original
> > +   argument.  */
> > +
> > +static tree
> > +get_promoted_int_value (tree arg)
> > +{
> > +  tree type = TREE_TYPE (arg);
> > +  if (!INTEGRAL_TYPE_P (type)
> > +      || TYPE_PRECISION (type) >= TYPE_PRECISION (integer_type_node))
> > +    return arg;
> > +
> > +  tree promoted_type = (TYPE_UNSIGNED (type)
> > +                       ? unsigned_type_node : integer_type_node);
>
> I think it's always integer_type_node.
>

Will fix it.


>
> > +
> > +  if (TREE_CODE (arg) != SSA_NAME)
> > +    return fold_convert (promoted_type, arg);
> > +
> > +  if (SSA_NAME_IS_DEFAULT_DEF (arg))
> > +    return get_promoted_int_value_from_ssa_name (type, promoted_type,
> > +                                                arg, arg);
>
> So apart from moving promotion to RTL this also seems to apply the
> optimization assuming incoming arguments are promoted?  But it doesn't
> seem to check whether the current function is binding locally (since the
> promotion isn't guaranteed by the ABI)?
>

We can use the incoming small integer argument type for the outgoing
argument.  If callee is a global function, we always properly extend the
incoming small integer arguments in callee.  If callee is a local function,
since DECL_ARG_TYPE has the original small integer type, we will
extend the incoming small integer arguments in callee if needed.


> > +  else
> > +    {
> > +      gimple *stmt = get_gimple_for_ssa_name (arg);
> > +      if (stmt == nullptr)
> > +       return fold_convert (promoted_type, arg);
> > +
> > +      gassign *g = as_a<gassign *> (stmt);
> > +      tree_code rhs_code = gimple_assign_rhs_code (g);
> > +      gimple_rhs_class rhs_class = get_gimple_rhs_class (rhs_code);
> > +
> > +      if (rhs_class == GIMPLE_SINGLE_RHS || gimple_assign_cast_p (g))
> > +       {
> > +         tree rhs = gimple_assign_rhs1 (g);
> > +         if (gimple_assign_cast_p (g))
> > +           {
> > +             tree lhs = gimple_assign_lhs (g);
> > +             if (!tree_nop_conversion_p (TREE_TYPE (lhs),
> > +                                         TREE_TYPE (rhs)))
> > +               return fold_convert (promoted_type, arg);
>
> Did you intend to convert 'rhs' here?  Otherwise why bother with
> casts at all?  I think converting 'rhs' is wrong in case the conversion
> was a truncation.
>

Will fix.


>
> > +           }
> > +
> > +         if (TREE_CODE (rhs) == SSA_NAME
> > +             && SSA_NAME_IS_DEFAULT_DEF (rhs))
> > +           return get_promoted_int_value_from_ssa_name (type,
> > +                                                        promoted_type,
> > +                                                        rhs, arg);
>
> The function behaves as returning 'arg' if rhs isn't a PARM_DECL,
> I think abstracting get_promoted_int_value_from_ssa_name makes
> the code harder to follow than when simply inlining it twice.
>
> I'd have prefered to see a patch applying promote_prototypes without
> optimizing more than we already do as first step.
>

Will fix.


>
> > +       }
> > +    }
> > +
> > +  return fold_convert (promoted_type, arg);
> > +}
> > +
> >  /* Fill in ARGS_SIZE and ARGS array based on the parameters found in
> >     CALL_EXPR EXP.
> >
> > @@ -1375,6 +1446,11 @@ initialize_argument_information (int num_actuals
> ATTRIBUTE_UNUSED,
> >        }
> >    }
> >
> > +  bool promote_p
> > +    = targetm.calls.promote_prototypes (fndecl
> > +                                       ? TREE_TYPE (fndecl)
> > +                                       : fntype);
> > +
> >    /* I counts args in order (to be) pushed; ARGPOS counts in order
> written.  */
> >    for (argpos = 0; argpos < num_actuals; i--, argpos++)
> >      {
> > @@ -1384,6 +1460,11 @@ initialize_argument_information (int num_actuals
> ATTRIBUTE_UNUSED,
> >        /* Replace erroneous argument with constant zero.  */
> >        if (type == error_mark_node || !COMPLETE_TYPE_P (type))
> >         args[i].tree_value = integer_zero_node, type = integer_type_node;
> > +      else if (promote_p)
> > +       {
> > +         args[i].tree_value = get_promoted_int_value
> (args[i].tree_value);
> > +         type = TREE_TYPE (args[i].tree_value);
> > +       }
>
> I would have expected to handle the promotion where we promote according
> to targetm.calls.promote_function_mode, so sth as simple as
>
> diff --git a/gcc/calls.cc b/gcc/calls.cc
> index f67067acad4..9fea9e287f3 100644
> --- a/gcc/calls.cc
> +++ b/gcc/calls.cc
> @@ -1524,6 +1524,11 @@ initialize_argument_information (int
> num_actuals ATTRIBUTE_UNUSED,
>           arg.pass_by_reference = true;
>         }
>
> +      if (promote_p
> +         && INTEGRAL_TYPE_P (type)
> +         && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
> +       type = integer_type_node;
> +
>        unsignedp = TYPE_UNSIGNED (type);
>        arg.type = type;
>        arg.mode
>
> OTOH, this also shows that PROMOTE_PROTOTYPES might change the ABI
> iff small integer types are passed differently from int.
>
> That said, expansion already deals with arg.type/mode being not equal to
> the
> actual argument.  The optimization to elide a promotion would then happen
> where we actually expand arg.
>
> I suggest you split the patch into three - honor promote_prototypes
> during expand,
> remove the handling from the frontends and adding the optimization to
> elide the
> promotion when not necessary.  I do hope somebody who is more familiar with
>

Will do.

Thanks.


> calls.cc will chime in as well.
>
> Richard.
>
> >        /* If TYPE is a transparent union or record, pass things the way
> >          we would pass the first field of the union or record.  We have
> > diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
> > index 220ac130b0b..8e9818538e1 100644
> > --- a/gcc/cp/call.cc
> > +++ b/gcc/cp/call.cc
> > @@ -9436,11 +9436,6 @@ type_passed_as (tree type)
> >    /* Pass classes with copy ctors by invisible reference.  */
> >    if (TREE_ADDRESSABLE (type))
> >      type = build_reference_type (type);
> > -  else if (targetm.calls.promote_prototypes (NULL_TREE)
> > -          && INTEGRAL_TYPE_P (type)
> > -          && COMPLETE_TYPE_P (type)
> > -          && tree_int_cst_lt (TYPE_SIZE (type), TYPE_SIZE
> (integer_type_node)))
> > -    type = integer_type_node;
> >
> >    return type;
> >  }
> > @@ -9476,11 +9471,6 @@ convert_for_arg_passing (tree type, tree val,
> tsubst_flags_t complain)
> >    /* Pass classes with copy ctors by invisible reference.  */
> >    else if (TREE_ADDRESSABLE (type))
> >      val = build1 (ADDR_EXPR, build_reference_type (type), val);
> > -  else if (targetm.calls.promote_prototypes (NULL_TREE)
> > -          && INTEGRAL_TYPE_P (type)
> > -          && COMPLETE_TYPE_P (type)
> > -          && tree_int_cst_lt (TYPE_SIZE (type), TYPE_SIZE
> (integer_type_node)))
> > -    val = cp_perform_integral_promotions (val, complain);
> >    if (complain & tf_warning)
> >      {
> >        if (warn_suggest_attribute_format)
> > diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
> > index 4c15e26f692..2aa5347ec1c 100644
> > --- a/gcc/cp/typeck.cc
> > +++ b/gcc/cp/typeck.cc
> > @@ -1373,17 +1373,12 @@ cxx_safe_arg_type_equiv_p (tree t1, tree t2)
> >        && TYPE_PTR_P (t2))
> >      return true;
> >
> > -  /* The signedness of the parameter matters only when an integral
> > -     type smaller than int is promoted to int, otherwise only the
> > -     precision of the parameter matters.
> > -     This check should make sure that the callee does not see
> > -     undefined values in argument registers.  */
> > +  /* Only the precision of the parameter matters.  This check should
> > +     make sure that the callee does not see undefined values in argument
> > +     registers.  */
> >    if (INTEGRAL_TYPE_P (t1)
> >        && INTEGRAL_TYPE_P (t2)
> > -      && TYPE_PRECISION (t1) == TYPE_PRECISION (t2)
> > -      && (TYPE_UNSIGNED (t1) == TYPE_UNSIGNED (t2)
> > -         || !targetm.calls.promote_prototypes (NULL_TREE)
> > -         || TYPE_PRECISION (t1) >= TYPE_PRECISION (integer_type_node)))
> > +      && TYPE_PRECISION (t1) == TYPE_PRECISION (t2))
> >      return true;
> >
> >    return same_type_p (t1, t2);
> > diff --git a/gcc/gimple.cc b/gcc/gimple.cc
> > index f7b313be40e..9f77d77d56d 100644
> > --- a/gcc/gimple.cc
> > +++ b/gcc/gimple.cc
> > @@ -2843,15 +2843,7 @@ gimple_builtin_call_types_compatible_p (const
> gimple *stmt, tree fndecl)
> >         return true;
> >        tree arg = gimple_call_arg (stmt, i);
> >        tree type = TREE_VALUE (targs);
> > -      if (!useless_type_conversion_p (type, TREE_TYPE (arg))
> > -         /* char/short integral arguments are promoted to int
> > -            by several frontends if targetm.calls.promote_prototypes
> > -            is true.  Allow such promotion too.  */
> > -         && !(INTEGRAL_TYPE_P (type)
> > -              && TYPE_PRECISION (type) < TYPE_PRECISION
> (integer_type_node)
> > -              && targetm.calls.promote_prototypes (TREE_TYPE (fndecl))
> > -              && useless_type_conversion_p (integer_type_node,
> > -                                            TREE_TYPE (arg))))
> > +      if (!useless_type_conversion_p (type, TREE_TYPE (arg)))
> >         return false;
> >        targs = TREE_CHAIN (targs);
> >      }
> > diff --git a/gcc/testsuite/gcc.target/i386/pr14907-1.c
> b/gcc/testsuite/gcc.target/i386/pr14907-1.c
> > new file mode 100644
> > index 00000000000..231819ed675
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/i386/pr14907-1.c
> > @@ -0,0 +1,21 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O2 -g0" } */
> > +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc').  */
> > +/* { dg-final { check-function-bodies "x86*" "" "" { target *-*-linux*
> *-*-gnu* } {^\t?\.} } } */
> > +
> > +/*
> > +x86*foo:
> > +x86*.LFB0:
> > +x86*   .cfi_startproc
> > +x86*   jmp     baz
> > +x86*   .cfi_endproc
> > +x86*...
> > +*/
> > +
> > +extern int baz (char);
> > +
> > +int
> > +foo (char c1)
> > +{
> > +  return baz (c1);
> > +}
> > diff --git a/gcc/testsuite/gcc.target/i386/pr14907-10.c
> b/gcc/testsuite/gcc.target/i386/pr14907-10.c
> > new file mode 100644
> > index 00000000000..099c4dc81d1
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/i386/pr14907-10.c
> > @@ -0,0 +1,23 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O2 -g0" } */
> > +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc').  */
> > +/* { dg-final { check-function-bodies "ia32*" "" "" { target { {
> *-*-linux* *-*-gnu* } && ia32 } } {^\t?\.} } } */
> > +
> > +/*
> > +ia32*foo:
> > +ia32*.LFB0:
> > +ia32*  .cfi_startproc
> > +ia32*  movsbl  4\(%esp\), %eax
> > +ia32*  movl    %eax, 4\(%esp\)
> > +ia32*  jmp     baz
> > +ia32*  .cfi_endproc
> > +ia32*...
> > +*/
> > +
> > +extern int baz (short);
> > +
> > +int
> > +foo (char c1)
> > +{
> > +  return baz (c1);
> > +}
> > diff --git a/gcc/testsuite/gcc.target/i386/pr14907-11.c
> b/gcc/testsuite/gcc.target/i386/pr14907-11.c
> > new file mode 100644
> > index 00000000000..12ac165c298
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/i386/pr14907-11.c
> > @@ -0,0 +1,12 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O2" } */
> > +
> > +extern int baz (char, char);
> > +
> > +int
> > +foo (char c1, char c2)
> > +{
> > +  return baz (c1, c2) + 1;
> > +}
> > +
> > +/* { dg-final { scan-assembler-not "movsbl" } } */
> > diff --git a/gcc/testsuite/gcc.target/i386/pr14907-12.c
> b/gcc/testsuite/gcc.target/i386/pr14907-12.c
> > new file mode 100644
> > index 00000000000..6cda72ef3a2
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/i386/pr14907-12.c
> > @@ -0,0 +1,17 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O2" } */
> > +
> > +struct s
> > +{
> > +  char c[20];
> > +};
> > +
> > +extern struct s baz (char, char);
> > +
> > +struct s
> > +foo (char c1, char c2)
> > +{
> > +  return baz (c1, c2);
> > +}
> > +
> > +/* { dg-final { scan-assembler-not "movsbl" } } */
> > diff --git a/gcc/testsuite/gcc.target/i386/pr14907-13.c
> b/gcc/testsuite/gcc.target/i386/pr14907-13.c
> > new file mode 100644
> > index 00000000000..b4130fdcb57
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/i386/pr14907-13.c
> > @@ -0,0 +1,12 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O2" } */
> > +
> > +extern int baz (char, char, ...);
> > +
> > +int
> > +foo (char c1, char c2)
> > +{
> > +  return baz (c1, c2, 0, 0, 0, 1);
> > +}
> > +
> > +/* { dg-final { scan-assembler-not "movsbl" } } */
> > diff --git a/gcc/testsuite/gcc.target/i386/pr14907-14.c
> b/gcc/testsuite/gcc.target/i386/pr14907-14.c
> > new file mode 100644
> > index 00000000000..9b8d7a7607d
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/i386/pr14907-14.c
> > @@ -0,0 +1,17 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O2" } */
> > +
> > +struct s
> > +{
> > +  char c[20];
> > +};
> > +
> > +extern struct s baz (char, char, ...);
> > +
> > +struct s
> > +foo (char c1, char c2)
> > +{
> > +  return baz (c1, c2, 0, 1);
> > +}
> > +
> > +/* { dg-final { scan-assembler-not "movsbl" } } */
> > diff --git a/gcc/testsuite/gcc.target/i386/pr14907-15.c
> b/gcc/testsuite/gcc.target/i386/pr14907-15.c
> > new file mode 100644
> > index 00000000000..08bc4ea9ac8
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/i386/pr14907-15.c
> > @@ -0,0 +1,26 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O2 -g0" } */
> > +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc').  */
> > +/* { dg-final { check-function-bodies "x64*" "" "" { target { {
> *-*-linux* *-*-gnu* } && { ! ia32 } } } {^\t?\.} } } */
> > +
> > +/*
> > +x64*foo:
> > +x64*.LFB1:
> > +x64*   .cfi_startproc
> > +x64*   jmp     baz
> > +x64*   .cfi_endproc
> > +x64*...
> > +*/
> > +
> > + __attribute__ ((noinline))
> > +static int
> > +baz (char c1)
> > +{
> > +  return c1;
> > +}
> > +
> > +int
> > +foo (char c1)
> > +{
> > +  return baz (c1);
> > +}
> > diff --git a/gcc/testsuite/gcc.target/i386/pr14907-16.c
> b/gcc/testsuite/gcc.target/i386/pr14907-16.c
> > new file mode 100644
> > index 00000000000..48c255ffb20
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/i386/pr14907-16.c
> > @@ -0,0 +1,24 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O2 -g0" } */
> > +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc').  */
> > +/* { dg-final { check-function-bodies "x64*" "" "" { target { {
> *-*-linux* *-*-gnu* } && { ! ia32 } } } {^\t?\.} } } */
> > +
> > +/*
> > +x64*foo:
> > +x64*.LFB0:
> > +x64*   .cfi_startproc
> > +x64*   andl    \$1, %edi
> > +x64*   jmp     baz
> > +x64*   .cfi_endproc
> > +x64*...
> > +*/
> > +
> > +#include <stdbool.h>
> > +
> > +extern int baz (bool);
> > +
> > +int
> > +foo (int c1)
> > +{
> > +  return baz (c1 & 0x1);
> > +}
> > diff --git a/gcc/testsuite/gcc.target/i386/pr14907-2.c
> b/gcc/testsuite/gcc.target/i386/pr14907-2.c
> > new file mode 100644
> > index 00000000000..5da7b029279
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/i386/pr14907-2.c
> > @@ -0,0 +1,21 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O2 -g0" } */
> > +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc').  */
> > +/* { dg-final { check-function-bodies "x86*" "" "" { target *-*-linux*
> *-*-gnu* } {^\t?\.} } } */
> > +
> > +/*
> > +x86*foo:
> > +x86*.LFB0:
> > +x86*   .cfi_startproc
> > +x86*   jmp     baz
> > +x86*   .cfi_endproc
> > +x86*...
> > +*/
> > +
> > +extern int baz (int, int, int, int, int, int, char, char);
> > +
> > +int
> > +foo (int a1, int a2, int a3, int a4, int a5, int a6, char c1, char c2)
> > +{
> > +  return baz (a1, a2, a3, a4, a5, a6, c1, c2);
> > +}
> > diff --git a/gcc/testsuite/gcc.target/i386/pr14907-3.c
> b/gcc/testsuite/gcc.target/i386/pr14907-3.c
> > new file mode 100644
> > index 00000000000..a8fb13f28f8
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/i386/pr14907-3.c
> > @@ -0,0 +1,21 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O2 -g0" } */
> > +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc').  */
> > +/* { dg-final { check-function-bodies "x86*" "" "" { target *-*-linux*
> *-*-gnu* } {^\t?\.} } } */
> > +
> > +/*
> > +x86*c1:
> > +x86*.LFB0:
> > +x86*   .cfi_startproc
> > +x86*   jmp     c2
> > +x86*   .cfi_endproc
> > +x86*...
> > +*/
> > +
> > +extern char c2 (char);
> > +
> > +char
> > +c1 (char c)
> > +{
> > +  return c2 (c);
> > +}
> > diff --git a/gcc/testsuite/gcc.target/i386/pr14907-4.c
> b/gcc/testsuite/gcc.target/i386/pr14907-4.c
> > new file mode 100644
> > index 00000000000..b5fb92fefcc
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/i386/pr14907-4.c
> > @@ -0,0 +1,21 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O2 -g0" } */
> > +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc').  */
> > +/* { dg-final { check-function-bodies "x86*" "" "" { target *-*-linux*
> *-*-gnu* } {^\t?\.} } } */
> > +
> > +/*
> > +x86*foo:
> > +x86*.LFB0:
> > +x86*   .cfi_startproc
> > +x86*   jmp     baz
> > +x86*   .cfi_endproc
> > +x86*...
> > +*/
> > +
> > +extern int baz (short);
> > +
> > +int
> > +foo (short c1)
> > +{
> > +  return baz (c1);
> > +}
> > diff --git a/gcc/testsuite/gcc.target/i386/pr14907-5.c
> b/gcc/testsuite/gcc.target/i386/pr14907-5.c
> > new file mode 100644
> > index 00000000000..d9abb5c8cfb
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/i386/pr14907-5.c
> > @@ -0,0 +1,21 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O2 -g0" } */
> > +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc').  */
> > +/* { dg-final { check-function-bodies "x86*" "" "" { target *-*-linux*
> *-*-gnu* } {^\t?\.} } } */
> > +
> > +/*
> > +x86*foo:
> > +x86*.LFB0:
> > +x86*   .cfi_startproc
> > +x86*   jmp     baz
> > +x86*   .cfi_endproc
> > +x86*...
> > +*/
> > +
> > +extern int baz (int, int, int, int, int, int, short, short);
> > +
> > +int
> > +foo (int a1, int a2, int a3, int a4, int a5, int a6, short c1, short c2)
> > +{
> > +  return baz (a1, a2, a3, a4, a5, a6, c1, c2);
> > +}
> > diff --git a/gcc/testsuite/gcc.target/i386/pr14907-6.c
> b/gcc/testsuite/gcc.target/i386/pr14907-6.c
> > new file mode 100644
> > index 00000000000..b6d0183656a
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/i386/pr14907-6.c
> > @@ -0,0 +1,21 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O2 -g0" } */
> > +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc').  */
> > +/* { dg-final { check-function-bodies "x86*" "" "" { target *-*-linux*
> *-*-gnu* } {^\t?\.} } } */
> > +
> > +/*
> > +x86*c1:
> > +x86*.LFB0:
> > +x86*   .cfi_startproc
> > +x86*   jmp     c2
> > +x86*   .cfi_endproc
> > +x86*...
> > +*/
> > +
> > +extern short c2 (short);
> > +
> > +short
> > +c1 (short c)
> > +{
> > +  return c2 (c);
> > +}
> > diff --git a/gcc/testsuite/gcc.target/i386/pr14907-7.c
> b/gcc/testsuite/gcc.target/i386/pr14907-7.c
> > new file mode 100644
> > index 00000000000..fbf511f691e
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/i386/pr14907-7.c
> > @@ -0,0 +1,22 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O2 -g0" } */
> > +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc').  */
> > +/* { dg-final { check-function-bodies "x64*" "" "" { target { {
> *-*-linux* *-*-gnu* } && { ! ia32 } } } {^\t?\.} } } */
> > +
> > +/*
> > +x64*foo:
> > +x64*.LFB0:
> > +x64*   .cfi_startproc
> > +x64*   movsbl  %dil, %edi
> > +x64*   jmp     baz
> > +x64*   .cfi_endproc
> > +x64*...
> > +*/
> > +
> > +extern int baz (int);
> > +
> > +int
> > +foo (char c1)
> > +{
> > +  return baz (c1);
> > +}
> > diff --git a/gcc/testsuite/gcc.target/i386/pr14907-8.c
> b/gcc/testsuite/gcc.target/i386/pr14907-8.c
> > new file mode 100644
> > index 00000000000..7d2611398c0
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/i386/pr14907-8.c
> > @@ -0,0 +1,23 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O2 -g0" } */
> > +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc').  */
> > +/* { dg-final { check-function-bodies "ia32*" "" "" { target { {
> *-*-linux* *-*-gnu* } && ia32 } } {^\t?\.} } } */
> > +
> > +/*
> > +ia32*foo:
> > +ia32*.LFB0:
> > +ia32*  .cfi_startproc
> > +ia32*  movsbl  4\(%esp\), %eax
> > +ia32*  movl    %eax, 4\(%esp\)
> > +ia32*  jmp     baz
> > +ia32*  .cfi_endproc
> > +ia32*...
> > +*/
> > +
> > +extern int baz (int);
> > +
> > +int
> > +foo (char c1)
> > +{
> > +  return baz (c1);
> > +}
> > diff --git a/gcc/testsuite/gcc.target/i386/pr14907-9.c
> b/gcc/testsuite/gcc.target/i386/pr14907-9.c
> > new file mode 100644
> > index 00000000000..a22383694bf
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/i386/pr14907-9.c
> > @@ -0,0 +1,22 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O2 -g0" } */
> > +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc').  */
> > +/* { dg-final { check-function-bodies "x64*" "" "" { target { {
> *-*-linux* *-*-gnu* } && { ! ia32 } } } {^\t?\.} } } */
> > +
> > +/*
> > +x64*foo:
> > +x64*.LFB0:
> > +x64*   .cfi_startproc
> > +x64*   movsbl  %dil, %edi
> > +x64*   jmp     baz
> > +x64*   .cfi_endproc
> > +x64*...
> > +*/
> > +
> > +extern int baz (short);
> > +
> > +int
> > +foo (char c1)
> > +{
> > +  return baz (c1);
> > +}
> > diff --git a/gcc/testsuite/gfortran.dg/pr14907-1.f90
> b/gcc/testsuite/gfortran.dg/pr14907-1.f90
> > new file mode 100644
> > index 00000000000..5e41cd6f54f
> > --- /dev/null
> > +++ b/gcc/testsuite/gfortran.dg/pr14907-1.f90
> > @@ -0,0 +1,17 @@
> > +! { dg-do compile }
> > +! { dg-options "-Os" }
> > +
> > +program test
> > +    use iso_c_binding, only: c_short
> > +    interface
> > +      subroutine foo(a) bind(c)
> > +        import c_short
> > +        integer(kind=c_short), intent(in), value :: a
> > +      end subroutine foo
> > +    end interface
> > +    integer(kind=c_short) a(5);
> > +    call foo (a(3))
> > +end
> > +
> > +! { dg-final { scan-assembler "movswl\t10\\(%rsp\\), %edi" { target { {
> *-*-linux* *-*-gnu* } && { ! ia32 } } } } }
> > +! { dg-final { scan-assembler "movswl\t-14\\(%ebp\\), %eax" { target {
> { *-*-linux* *-*-gnu* } && { ia32 } } } } }
> > diff --git a/gcc/tree.cc b/gcc/tree.cc
> > index b4c059d3b0d..2c3bf27a678 100644
> > --- a/gcc/tree.cc
> > +++ b/gcc/tree.cc
> > @@ -8676,20 +8676,6 @@ tree_builtin_call_types_compatible_p (const_tree
> call, tree fndecl)
> >               && POINTER_TYPE_P (TREE_TYPE (arg))
> >               && tree_nop_conversion_p (type, TREE_TYPE (arg)))
> >             continue;
> > -         /* char/short integral arguments are promoted to int
> > -            by several frontends if targetm.calls.promote_prototypes
> > -            is true.  Allow such promotion too.  */
> > -         if (INTEGRAL_TYPE_P (type)
> > -             && TYPE_PRECISION (type) < TYPE_PRECISION
> (integer_type_node)
> > -             && INTEGRAL_TYPE_P (TREE_TYPE (arg))
> > -             && !TYPE_UNSIGNED (TREE_TYPE (arg))
> > -             && targetm.calls.promote_prototypes (TREE_TYPE (fndecl))
> > -             && (gimple_form
> > -                 ? useless_type_conversion_p (integer_type_node,
> > -                                              TREE_TYPE (arg))
> > -                 : tree_nop_conversion_p (integer_type_node,
> > -                                          TREE_TYPE (arg))))
> > -           continue;
> >           return false;
> >         }
> >      }
> > --
> > 2.47.0
> >
>


-- 
H.J.

Reply via email to