On Sun, Nov 10, 2024 at 8: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.

PING.

> 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);
> +
> +  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);
> +  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);
> +           }
> +
> +         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);
> +       }
> +    }
> +
> +  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);
> +       }
>
>        /* 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