On Thu, Sep 18, 2025 at 9:01 PM H.J. Lu <[email protected]> wrote: > > On Mon, Aug 25, 2025 at 5:59 AM H.J. Lu <[email protected]> wrote: > > > > On Fri, Jun 27, 2025 at 05:53:57AM +0800, H.J. Lu wrote: > > > Here is the v3 patch. The difference from v2 is to use > > > > > > if (MEM_P (src) > > > && MEM_EXPR (src) > > > && (TREE_CODE (get_base_address (MEM_EXPR (src))) > > > == PARM_DECL)) > > > continue; > > > > > > to check incoming arguments on stack. > > > > > > OK for master? > > > > > > Thanks. > > > > > > > I forgot to include the patch. Here it is. OK for master? > > > > Thanks. > > > > H.J. > > --- > > 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 are copied to outgoing arguments > > directly. > > > > We can use the incoming argument value as the outgoing argument as if it > > has been promoted if > > > > 1. Caller and callee are not nested functions. > > 2. Caller and callee have the same incoming argument order. Add a new > > target hook, TARGET_SAME_FUNCTION_ARGUMENT_ORDER_P, which returns true > > if caller and callee have the same incoming argument order. If the > > incoming argument order of the caller is different from the incoming > > argument order of the callee since the same register may be used for > > different incoming arguments in caller and callee. Copying from one > > incoming argument register in the caller to an outgoing argument may > > override another incoming argument register. > > 3. The incoming argument is unchanged before call expansion. > > > > Otherwise, using the incoming argument as the outgoing argument may change > > values of other incoming arguments or the wrong outgoing argument value > > may be used. > > > > 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. > > > > Tested on x86-64, x32 and i686. > > > > NB: I tried to elide all incoming argument copying for all types, not > > just integer arguments smaller than int. But GCC was miscompiled which > > is related to function inlining. There is > > > > foo > > call baz > > > > bar > > call foo > > > > when foo is inlined > > > > bar > > call baz > > > > the incoming arguments, which aren't integer arguments smaller than int, > > for baz get the wrong values sometimes. > > > > gcc/ > > > > PR middle-end/14907 > > * calls.cc (arg_data): Add incoming_argument_value. > > (precompute_register_parameters): Set args[i].value to > > args[i].incoming_argument_value if not nullptr. > > (get_incoming_argument_value): New function. > > (initialize_argument_information): Set > > args[i].incoming_argument_value with get_incoming_argument_value. > > (store_one_arg): Set arg->value to arg->incoming_argument_value > > if not nullptr. > > * function.h (function): Add before_first_expand_call and > > no_incoming_argument_value. > > * target.def (same_incoming_argument_order_p): New target hook > > for calls. > > * config/i386/i386.cc (ix86_same_incoming_argument_order_p): New. > > (TARGET_SAME_FUNCTION_ARGUMENT_ORDER_P): Likewise. > > * doc/tm.texi: Regenerated. > > * doc/tm.texi.in (TARGET_SAME_FUNCTION_ARGUMENT_ORDER_P): New hook. > > > > gcc/testsuite/ > > > > PR middle-end/14907 > > * gcc.dg/elide-1a.c: New test. > > * gcc.dg/elide-1b.c: Likewise. > > * gcc.dg/elide-2a.c: Likewise. > > * gcc.dg/elide-2b.c: Likewise. > > * gcc.target/i386/pr14907-1.c: Likewise. > > * 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-7a.c: Likewise. > > * gcc.target/i386/pr14907-7b.c: Likewise. > > * gcc.target/i386/pr14907-8a.c: Likewise. > > * gcc.target/i386/pr14907-8b.c: Likewise. > > * gcc.target/i386/pr14907-9a.c: Likewise. > > * gcc.target/i386/pr14907-9b.c: Likewise. > > * gcc.target/i386/pr14907-10a.c: Likewise. > > * gcc.target/i386/pr14907-10b.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. > > * gcc.target/i386/pr14907-17.c: Likewise. > > * gcc.target/i386/pr14907-18.c: Likewise. > > * gcc.target/i386/pr14907-19.c: Likewise. > > * gcc.target/i386/pr14907-20a.c: Likewise. > > * gcc.target/i386/pr14907-20b.c: Likewise. > > * gcc.target/i386/pr14907-21.c: Likewise. > > * gcc.target/i386/pr14907-22.c: Likewise. > > * gcc.target/i386/pr14907-23.c: Likewise. > > > > Signed-off-by: H.J. Lu <[email protected]> > > --- > > gcc/calls.cc | 212 ++++++++++++++++++-- > > gcc/config/i386/i386.cc | 16 ++ > > gcc/doc/tm.texi | 6 + > > gcc/doc/tm.texi.in | 2 + > > gcc/function.h | 7 + > > gcc/target.def | 8 + > > gcc/testsuite/gcc.dg/elide-1a.c | 10 + > > gcc/testsuite/gcc.dg/elide-1b.c | 26 +++ > > gcc/testsuite/gcc.dg/elide-2a.c | 12 ++ > > gcc/testsuite/gcc.dg/elide-2b.c | 30 +++ > > gcc/testsuite/gcc.target/i386/pr14907-1.c | 21 ++ > > gcc/testsuite/gcc.target/i386/pr14907-10a.c | 24 +++ > > gcc/testsuite/gcc.target/i386/pr14907-10b.c | 20 ++ > > 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-17.c | 28 +++ > > gcc/testsuite/gcc.target/i386/pr14907-18.c | 24 +++ > > gcc/testsuite/gcc.target/i386/pr14907-19.c | 26 +++ > > gcc/testsuite/gcc.target/i386/pr14907-2.c | 21 ++ > > gcc/testsuite/gcc.target/i386/pr14907-20a.c | 27 +++ > > gcc/testsuite/gcc.target/i386/pr14907-20b.c | 23 +++ > > gcc/testsuite/gcc.target/i386/pr14907-21.c | 28 +++ > > gcc/testsuite/gcc.target/i386/pr14907-22.c | 28 +++ > > gcc/testsuite/gcc.target/i386/pr14907-23.c | 11 + > > 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-7a.c | 22 ++ > > gcc/testsuite/gcc.target/i386/pr14907-7b.c | 17 ++ > > gcc/testsuite/gcc.target/i386/pr14907-8a.c | 22 ++ > > gcc/testsuite/gcc.target/i386/pr14907-8b.c | 17 ++ > > gcc/testsuite/gcc.target/i386/pr14907-9a.c | 24 +++ > > gcc/testsuite/gcc.target/i386/pr14907-9b.c | 19 ++ > > 38 files changed, 906 insertions(+), 17 deletions(-) > > create mode 100644 gcc/testsuite/gcc.dg/elide-1a.c > > create mode 100644 gcc/testsuite/gcc.dg/elide-1b.c > > create mode 100644 gcc/testsuite/gcc.dg/elide-2a.c > > create mode 100644 gcc/testsuite/gcc.dg/elide-2b.c > > create mode 100644 gcc/testsuite/gcc.target/i386/pr14907-1.c > > create mode 100644 gcc/testsuite/gcc.target/i386/pr14907-10a.c > > create mode 100644 gcc/testsuite/gcc.target/i386/pr14907-10b.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-17.c > > create mode 100644 gcc/testsuite/gcc.target/i386/pr14907-18.c > > create mode 100644 gcc/testsuite/gcc.target/i386/pr14907-19.c > > create mode 100644 gcc/testsuite/gcc.target/i386/pr14907-2.c > > create mode 100644 gcc/testsuite/gcc.target/i386/pr14907-20a.c > > create mode 100644 gcc/testsuite/gcc.target/i386/pr14907-20b.c > > create mode 100644 gcc/testsuite/gcc.target/i386/pr14907-21.c > > create mode 100644 gcc/testsuite/gcc.target/i386/pr14907-22.c > > create mode 100644 gcc/testsuite/gcc.target/i386/pr14907-23.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-7a.c > > create mode 100644 gcc/testsuite/gcc.target/i386/pr14907-7b.c > > create mode 100644 gcc/testsuite/gcc.target/i386/pr14907-8a.c > > create mode 100644 gcc/testsuite/gcc.target/i386/pr14907-8b.c > > create mode 100644 gcc/testsuite/gcc.target/i386/pr14907-9a.c > > create mode 100644 gcc/testsuite/gcc.target/i386/pr14907-9b.c > > > > diff --git a/gcc/calls.cc b/gcc/calls.cc > > index bb8a6d09f82..c78337cf4b0 100644 > > --- a/gcc/calls.cc > > +++ b/gcc/calls.cc > > @@ -75,6 +75,8 @@ struct arg_data > > machine_mode mode; > > /* Current RTL value for argument, or 0 if it isn't precomputed. */ > > rtx value; > > + /* RTL value from the incoming argument, or 0 if it isn't available. */ > > + rtx incoming_argument_value; > > /* Initially-compute RTL value for argument; only for const functions. > > */ > > rtx initial_value; > > /* Register to pass this argument in, 0 if passed on stack, or an > > @@ -1019,7 +1021,10 @@ precompute_register_parameters (int num_actuals, > > struct arg_data *args, > > if (args[i].value == 0) > > { > > push_temp_slots (); > > - args[i].value = expand_normal (args[i].tree_value); > > + if (args[i].incoming_argument_value) > > + args[i].value = args[i].incoming_argument_value; > > + else > > + args[i].value = expand_normal (args[i].tree_value); > > preserve_temp_slots (args[i].value); > > pop_temp_slots (); > > } > > @@ -1288,6 +1293,152 @@ maybe_complain_about_tail_call (tree call_expr, > > const char *reason) > > } > > } > > > > +/* Return the value of the incoming argument, INCOMING_ARG if ARG, which > > + is an outgoing argument, is copied directly from the incoming argument. > > + Otherwise return nullptr. */ > > + > > +static rtx > > +get_incoming_argument_value (const_tree fndecl, tree incoming_arg, > > + tree arg) > > +{ > > + if (cfun->no_incoming_argument_value) > > + return nullptr; > > + > > + /* Skip nested callee and caller. */ > > + if ((fndecl && DECL_STATIC_CHAIN (fndecl)) > > + || DECL_STATIC_CHAIN (current_function_decl)) > > + { > > +no_incoming_argument_value: > > + cfun->no_incoming_argument_value = 1; > > + return nullptr; > > + } > > + > > + /* Skip if the incoming argument order of the caller is different from > > + the incoming argument order of the callee since the same register > > + may be used for different incoming arguments in caller and callee. > > + Copying from one incoming argument in the caller to an outgoing > > + argument may override another incoming argument. */ > > + if (!targetm.calls.same_incoming_argument_order_p (fndecl)) > > + goto no_incoming_argument_value; > > + > > + rtx_insn *before_call_expand = get_last_insn (); > > + if (cfun->before_first_expand_call == nullptr) > > + { > > + cfun->before_first_expand_call = before_call_expand; > > + > > + /* Scan from the function start. */ > > + rtx_insn *insn, *start = get_insns (); > > + for (insn = start; insn; insn = NEXT_INSN (insn)) > > + { > > + /* Skip argument assignments before NOTE_INSN_FUNCTION_BEG. */ > > + if (NOTE_P (insn) > > + && NOTE_KIND (insn) == NOTE_INSN_FUNCTION_BEG) > > + { > > + insn = NEXT_INSN (insn); > > + break; > > + } > > + > > + if (!NONDEBUG_INSN_P (insn)) > > + continue; > > + > > + rtx set = single_set (insn); > > + /* Don't know if the incoming arguments are changed. */ > > + if (!set) > > + goto no_incoming_argument_value; > > + > > + rtx dest = SET_DEST (set); > > + /* Don't know if the incoming arguments are changed. */ > > + if (!REG_P (dest)) > > + goto no_incoming_argument_value; > > + > > + rtx src = SET_SRC (set); > > + if (REG_P (src) > > + && REG_ATTRS (dest) == REG_ATTRS (src)) > > + continue; > > + > > + /* Function argument source is OK. */ > > + if (MEM_P (src) > > + && MEM_EXPR (src) > > + && (TREE_CODE (get_base_address (MEM_EXPR (src))) > > + == PARM_DECL)) > > + continue; > > + > > + > > + /* Don't know if the incoming arguments are changed. */ > > + goto no_incoming_argument_value; > > + } > > + > > + /* Check if the incoming argument may be changed after > > + NOTE_INSN_FUNCTION_BEG. */ > > + for (; insn; insn = NEXT_INSN (insn)) > > + { > > + if (!NONDEBUG_INSN_P (insn)) > > + continue; > > + > > + rtx set = single_set (insn); > > + if (set) > > + { > > + rtx dest = SET_DEST (set); > > + if (REG_P (dest) && !HARD_REGISTER_P (dest)) > > + { > > + /* Skip assignment from the hidden argument of the > > + return value. */ > > + tree result = DECL_RESULT (current_function_decl); > > + if (DECL_RTL_SET_P (result)) > > + { > > + rtx result_rtl = DECL_RTL (result); > > + if (result_rtl && MEM_P (result_rtl)) > > + { > > + rtx src = SET_SRC (set); > > + result_rtl = XEXP (result_rtl, 0); > > + if (rtx_equal_p (src, result_rtl)) > > + continue; > > + } > > + } > > + } > > + } > > + > > + /* Don't use the incoming argument if there are any > > + instructions which may change incoming arguments. */ > > + goto no_incoming_argument_value; > > + } > > + } > > + /* Incoming arguments aren't preserved after the first call. */ > > + else if (cfun->before_first_expand_call != before_call_expand) > > + goto no_incoming_argument_value; > > + > > + if (TREE_CODE (arg) != SSA_NAME) > > + return nullptr; > > + > > + if (!SSA_NAME_IS_DEFAULT_DEF (arg)) > > + return nullptr; > > + > > + tree var = SSA_NAME_VAR (arg); > > + if (TREE_CODE (var) != PARM_DECL) > > + return nullptr; > > + tree arg_type = TREE_TYPE (arg); > > + if (TYPE_MODE (arg_type) != TYPE_MODE (DECL_ARG_TYPE (var))) > > + return nullptr; > > + > > + /* Return nullptr if the outgoing argument isn't copied directly from > > + the corresponding incoming argument. In the case, the incoming > > + argument order of the caller is different from the incoming argument > > + of the callee and the same argument slot maps to different arguments > > + in caller and callee. */ > > + if (var != incoming_arg) > > + return nullptr; > > + > > + /* Return the small integer incoming argument as int for the outgoing > > + argument without extension. 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. */ > > + rtx incoming_rtl = shallow_copy_rtx (DECL_INCOMING_RTL (var)); > > + PUT_MODE (incoming_rtl, SImode); > > + return incoming_rtl; > > +} > > + > > /* Fill in ARGS_SIZE and ARGS array based on the parameters found in > > CALL_EXPR EXP. > > > > @@ -1349,6 +1500,7 @@ initialize_argument_information (int num_actuals > > ATTRIBUTE_UNUSED, > > /* In this loop, we consider args in the order they are written. > > We fill up ARGS from the back. */ > > > > + int implicit_argument = 0; > > i = num_actuals - 1; > > { > > int j = i; > > @@ -1359,6 +1511,7 @@ initialize_argument_information (int num_actuals > > ATTRIBUTE_UNUSED, > > { > > args[j].tree_value = struct_value_addr_value; > > j--; > > + implicit_argument++; > > } > > argpos = 0; > > FOR_EACH_CALL_EXPR_ARG (arg, iter, exp) > > @@ -1387,19 +1540,38 @@ initialize_argument_information (int num_actuals > > ATTRIBUTE_UNUSED, > > ? TREE_TYPE (fndecl) > > : fntype); > > > > + tree incoming_arg = nullptr; > > + > > /* I counts args in order (to be) pushed; ARGPOS counts in order > > written. */ > > for (argpos = 0; argpos < num_actuals; i--, argpos++) > > { > > tree type = TREE_TYPE (args[i].tree_value); > > int unsignedp; > > > > + if (argpos >= implicit_argument) > > + { > > + if (incoming_arg == nullptr) > > + incoming_arg = DECL_ARGUMENTS (current_function_decl); > > + else > > + incoming_arg = DECL_CHAIN (incoming_arg); > > + } > > + > > /* 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 > > - && INTEGRAL_TYPE_P (type) > > - && TYPE_PRECISION (type) < TYPE_PRECISION > > (integer_type_node)) > > - type = integer_type_node; > > + else > > + { > > + if (promote_p > > + && INTEGRAL_TYPE_P (type) > > + && (TYPE_PRECISION (type) > > + < TYPE_PRECISION (integer_type_node))) > > + { > > + type = integer_type_node; > > + args[i].incoming_argument_value > > + = get_incoming_argument_value (fndecl, incoming_arg, > > + 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 > > @@ -5073,18 +5245,24 @@ store_one_arg (struct arg_data *arg, rtx argblock, > > int flags, > > if (arg->pass_on_stack) > > stack_arg_under_construction++; > > > > - arg->value = expand_expr (pval, > > - (partial > > - || TYPE_MODE (TREE_TYPE (pval)) != > > arg->mode) > > - ? NULL_RTX : arg->stack, > > - VOIDmode, EXPAND_STACK_PARM); > > - > > - /* If we are promoting object (or for any other reason) the mode > > - doesn't agree, convert the mode. */ > > - > > - if (arg->mode != TYPE_MODE (TREE_TYPE (pval))) > > - arg->value = convert_modes (arg->mode, TYPE_MODE (TREE_TYPE (pval)), > > - arg->value, arg->unsignedp); > > + if (arg->incoming_argument_value) > > + arg->value = arg->incoming_argument_value; > > + else > > + { > > + arg->value = expand_expr (pval, > > + (partial > > + || TYPE_MODE (TREE_TYPE (pval)) != > > arg->mode) > > + ? NULL_RTX : arg->stack, > > + VOIDmode, EXPAND_STACK_PARM); > > + > > + /* If we are promoting object (or for any other reason) the mode > > + doesn't agree, convert the mode. */ > > + > > + if (arg->mode != TYPE_MODE (TREE_TYPE (pval))) > > + arg->value = convert_modes (arg->mode, > > + TYPE_MODE (TREE_TYPE (pval)), > > + arg->value, arg->unsignedp); > > + } > > > > if (arg->pass_on_stack) > > stack_arg_under_construction--; > > diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc > > index 55c9b16dd38..d0f1a7ef80e 100644 > > --- a/gcc/config/i386/i386.cc > > +++ b/gcc/config/i386/i386.cc > > @@ -4497,6 +4497,19 @@ ix86_return_in_memory (const_tree type, const_tree > > fntype ATTRIBUTE_UNUSED) > > } > > } > > > > +/* Implement TARGET_SAME_INCOMING_ARGUMENT_ORDER_P. */ > > + > > +static bool > > +ix86_same_incoming_argument_order_p (const_tree fndecl) > > +{ > > + /* 64-bit SYSV ABI and 64-bit MS ABI have different argument orders. > > + Copying one incoming argument register to another outgoing argument > > + register may override the other incoming argument register. */ > > + return (!TARGET_64BIT > > + || (ix86_function_abi (current_function_decl) > > + == ix86_function_abi (fndecl))); > > +} > > + > > /* Implement TARGET_PUSH_ARGUMENT. */ > > > > static bool > > @@ -27819,6 +27832,9 @@ static const scoped_attribute_specs *const > > ix86_attribute_table[] = > > #define TARGET_CXX_ADJUST_CDTOR_CALLABI_FNTYPE > > ix86_cxx_adjust_cdtor_callabi_fntype > > #undef TARGET_PROMOTE_PROTOTYPES > > #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true > > +#undef TARGET_SAME_INCOMING_ARGUMENT_ORDER_P > > +#define TARGET_SAME_INCOMING_ARGUMENT_ORDER_P \ > > + ix86_same_incoming_argument_order_p > > #undef TARGET_PUSH_ARGUMENT > > #define TARGET_PUSH_ARGUMENT ix86_push_argument > > #undef TARGET_SETUP_INCOMING_VARARGS > > diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi > > index 4c338c382ad..0038b718ab9 100644 > > --- a/gcc/doc/tm.texi > > +++ b/gcc/doc/tm.texi > > @@ -4057,6 +4057,12 @@ cases of mismatch, it also makes for better code on > > certain machines. > > The default is to not promote prototypes. > > @end deftypefn > > > > +@deftypefn {Target Hook} bool TARGET_SAME_INCOMING_ARGUMENT_ORDER_P > > (const_tree @var{fndecl}) > > +This target hook returns @code{true} if the incoming argument order of > > +the caller is the same as the incoming argument order of the calee > > +@var{fndecl}. The default is to return @code{true}. > > +@end deftypefn > > + > > @deftypefn {Target Hook} bool TARGET_PUSH_ARGUMENT (unsigned int > > @var{npush}) > > This target hook returns @code{true} if push instructions will be > > used to pass outgoing arguments. When the push instruction usage is > > diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in > > index 12b8ed660a0..5f4e78ed177 100644 > > --- a/gcc/doc/tm.texi.in > > +++ b/gcc/doc/tm.texi.in > > @@ -3210,6 +3210,8 @@ control passing certain arguments in registers. > > > > @hook TARGET_PROMOTE_PROTOTYPES > > > > +@hook TARGET_SAME_INCOMING_ARGUMENT_ORDER_P > > + > > @hook TARGET_PUSH_ARGUMENT > > > > @defmac PUSH_ARGS_REVERSED > > diff --git a/gcc/function.h b/gcc/function.h > > index 370629f4de2..c7e5c171f64 100644 > > --- a/gcc/function.h > > +++ b/gcc/function.h > > @@ -346,6 +346,9 @@ struct GTY(()) function { > > a string describing the reason for failure. */ > > const char * GTY((skip)) cannot_be_copied_reason; > > > > + /* The instruction before the first call expansion. */ > > + rtx_insn *before_first_expand_call; > > + > > /* Last assigned dependence info clique. */ > > unsigned short last_clique; > > > > @@ -451,6 +454,10 @@ struct GTY(()) function { > > > > /* Nonzero if reload will have to split basic blocks. */ > > unsigned int split_basic_blocks_after_reload : 1; > > + > > + /* Nonzero if the incoming argument can't be used as the outgoing > > + argument. */ > > + unsigned int no_incoming_argument_value : 1; > > }; > > > > /* Add the decl D to the local_decls list of FUN. */ > > diff --git a/gcc/target.def b/gcc/target.def > > index 5dd8f253ef6..e0e87bed79e 100644 > > --- a/gcc/target.def > > +++ b/gcc/target.def > > @@ -4857,6 +4857,14 @@ The default is to not promote prototypes.", > > bool, (const_tree fntype), > > hook_bool_const_tree_false) > > > > +DEFHOOK > > +(same_incoming_argument_order_p, > > + "This target hook returns @code{true} if the incoming argument order of\n\ > > +the caller is the same as the incoming argument order of the calee\n\ > > +@var{fndecl}. The default is to return @code{true}.", > > + bool, (const_tree fndecl), > > + hook_bool_const_tree_true) > > + > > DEFHOOK > > (struct_value_rtx, > > "This target hook should return the location of the structure value\n\ > > diff --git a/gcc/testsuite/gcc.dg/elide-1a.c > > b/gcc/testsuite/gcc.dg/elide-1a.c > > new file mode 100644 > > index 00000000000..282ac98d956 > > --- /dev/null > > +++ b/gcc/testsuite/gcc.dg/elide-1a.c > > @@ -0,0 +1,10 @@ > > +/* { dg-do compile } */ > > +/* { dg-options "-O2" } */ > > + > > +extern int baz (char, char); > > + > > +int > > +foo (char c1, char c2) > > +{ > > + return baz (c2, c1) + 1; > > +} > > diff --git a/gcc/testsuite/gcc.dg/elide-1b.c > > b/gcc/testsuite/gcc.dg/elide-1b.c > > new file mode 100644 > > index 00000000000..034071974d1 > > --- /dev/null > > +++ b/gcc/testsuite/gcc.dg/elide-1b.c > > @@ -0,0 +1,26 @@ > > +/* { dg-do run } */ > > +/* { dg-options "-O2" } */ > > +/* { dg-additional-sources elide-1a.c } */ > > + > > +extern int foo (int, int); > > + > > +/* Verify that arguments aren't elided. */ > > + > > +int > > +baz (int c1, int c2) > > +{ > > + if (c1 != 3) > > + __builtin_abort (); > > + if (c2 != -1) > > + __builtin_abort (); > > + > > + return c1 - c2; > > +} > > + > > +int > > +main (void) > > +{ > > + if (foo (-1, 3) != 5) > > + __builtin_abort (); > > + return 0; > > +} > > diff --git a/gcc/testsuite/gcc.dg/elide-2a.c > > b/gcc/testsuite/gcc.dg/elide-2a.c > > new file mode 100644 > > index 00000000000..b2b63d1199e > > --- /dev/null > > +++ b/gcc/testsuite/gcc.dg/elide-2a.c > > @@ -0,0 +1,12 @@ > > +/* { dg-do compile } */ > > +/* { dg-options "-O2" } */ > > + > > +extern int baz1 (char, char); > > +extern void baz2 (char, char); > > + > > +int > > +foo (char c1, char c2) > > +{ > > + baz2 (c1, c2); > > + return baz1 (c1, c2); > > +} > > diff --git a/gcc/testsuite/gcc.dg/elide-2b.c > > b/gcc/testsuite/gcc.dg/elide-2b.c > > new file mode 100644 > > index 00000000000..fc411863f30 > > --- /dev/null > > +++ b/gcc/testsuite/gcc.dg/elide-2b.c > > @@ -0,0 +1,30 @@ > > +/* { dg-do run } */ > > +/* { dg-options "-O2" } */ > > +/* { dg-additional-sources elide-2a.c } */ > > + > > +extern int foo (int, int); > > + > > +int > > +baz1 (int c1, int c2) > > +{ > > + return c2 + c1; > > +} > > + > > +/* Verify that arguments aren't elided. */ > > + > > +void > > +baz2 (int c1, int c2) > > +{ > > + if (c1 != -1) > > + __builtin_abort (); > > + if (c2 != 3) > > + __builtin_abort (); > > +} > > + > > +int > > +main (void) > > +{ > > + if (foo (-1, 3) != 2) > > + __builtin_abort (); > > + return 0; > > +} > > 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-10a.c > > b/gcc/testsuite/gcc.target/i386/pr14907-10a.c > > new file mode 100644 > > index 00000000000..dfe401bf1ef > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/i386/pr14907-10a.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*... > > +x64* movsbl %dil, %eax > > +x64*... > > +x64* movsbl %sil, %edi > > +x64* movl %eax, %esi > > +x64* call baz > > +x64*... > > +*/ > > + > > +extern int baz (char, char); > > + > > +int > > +foo (char c1, char c2) > > +{ > > + return baz (c2, c1) + 1; > > +} > > diff --git a/gcc/testsuite/gcc.target/i386/pr14907-10b.c > > b/gcc/testsuite/gcc.target/i386/pr14907-10b.c > > new file mode 100644 > > index 00000000000..d2c5fbd7f19 > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/i386/pr14907-10b.c > > @@ -0,0 +1,20 @@ > > +/* { 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*... > > +ia32* movsbl 24\(%esp\), %eax > > +ia32* pushl %eax > > +ia32*... > > +ia32* movsbl 32\(%esp\), %eax > > +ia32* pushl %eax > > +ia32*... > > +ia32* call baz > > +ia32*... > > +*/ > > + > > +#include "pr14907-10a.c" > > 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-17.c > > b/gcc/testsuite/gcc.target/i386/pr14907-17.c > > new file mode 100644 > > index 00000000000..079cb4475a2 > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/i386/pr14907-17.c > > @@ -0,0 +1,28 @@ > > +/* { 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* movl %edi, %eax > > +x64* movl base\(%rip\), %edi > > +x64* movsbl %sil, %esi > > +x64* movsbl %al, %edi > > +x64* jmp baz > > +x64* .cfi_endproc > > +x64*... > > +*/ > > + > > +extern int baz (char, char); > > + > > +extern int base; > > + > > +int > > +foo (char c1, char c2) > > +{ > > + asm volatile ("": : "D" (base)); > > + return baz (c1, c2); > > +} > > diff --git a/gcc/testsuite/gcc.target/i386/pr14907-18.c > > b/gcc/testsuite/gcc.target/i386/pr14907-18.c > > new file mode 100644 > > index 00000000000..5d8eadfce2c > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/i386/pr14907-18.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 "x86*" "" "" { target { *-*-linux* > > *-*-gnu* } } {^\t?\.} } } */ > > + > > +/* > > +x86*foo: > > +x86*.LFB0: > > +x86*... > > +x86* call baz2 > > +x86*... > > +x86* jmp baz1 > > +x86*... > > +*/ > > + > > +extern int baz1 (char, char); > > +extern void baz2 (char, char); > > + > > +int > > +foo (char c1, char c2) > > +{ > > + baz2 (c1, c2); > > + return baz1 (c1, c2); > > +} > > diff --git a/gcc/testsuite/gcc.target/i386/pr14907-19.c > > b/gcc/testsuite/gcc.target/i386/pr14907-19.c > > new file mode 100644 > > index 00000000000..07712e5da20 > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/i386/pr14907-19.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 "ia32*" "" "" { target { { > > *-*-linux* *-*-gnu* } && { ia32 } } } {^\t?\.} } } */ > > + > > +/* > > +ia32*foo: > > +ia32*.LFB0: > > +ia32* .cfi_startproc > > +ia32* movl 8\(%esp\), %edx > > +ia32* movl 4\(%esp\), %eax > > +ia32* jmp baz > > +ia32* .cfi_endproc > > +ia32*... > > +*/ > > + > > +__attribute__ ((regparm (2))) > > +extern int baz (char, char); > > + > > +int > > +foo (char c1, char c2) > > +{ > > + return baz (c1, c2); > > +} > > + > > +/* { dg-final { scan-assembler-not "movsbl" } } */ > > 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-20a.c > > b/gcc/testsuite/gcc.target/i386/pr14907-20a.c > > new file mode 100644 > > index 00000000000..1d65185b021 > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/i386/pr14907-20a.c > > @@ -0,0 +1,27 @@ > > +/* { dg-do compile { target ia32 } } */ > > +/* { 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*... > > +ia32* pushl %edx > > +ia32*... > > +ia32* pushl %eax > > +ia32*... > > +ia32* call baz > > +ia32*... > > +*/ > > + > > +extern int baz (char, char); > > + > > +__attribute__ ((regparm (2))) > > +int > > +foo (char c1, char c2) > > +{ > > + return baz (c1, c2); > > +} > > + > > +/* { dg-final { scan-assembler-not "movsbl" } } */ > > diff --git a/gcc/testsuite/gcc.target/i386/pr14907-20b.c > > b/gcc/testsuite/gcc.target/i386/pr14907-20b.c > > new file mode 100644 > > index 00000000000..2dcd8a94c81 > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/i386/pr14907-20b.c > > @@ -0,0 +1,23 @@ > > +/* { dg-do run { target ia32 } } */ > > +/* { dg-options "-O2" } */ > > +/* { dg-additional-sources pr14907-20a.c } */ > > + > > +extern int foo (int, int) __attribute__ ((regparm (2))); > > + > > +int > > +baz (int c1, int c2) > > +{ > > + if (c1 != -1) > > + __builtin_abort (); > > + if (c2 != 3) > > + __builtin_abort (); > > + return c1 + c2; > > +} > > + > > +int > > +main (void) > > +{ > > + if (foo (-1, 3) != 2) > > + __builtin_abort (); > > + return 0; > > +} > > diff --git a/gcc/testsuite/gcc.target/i386/pr14907-21.c > > b/gcc/testsuite/gcc.target/i386/pr14907-21.c > > new file mode 100644 > > index 00000000000..1e6cd18349c > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/i386/pr14907-21.c > > @@ -0,0 +1,28 @@ > > +/* { dg-do run { target { ! x32 } } } */ > > +/* { dg-options "-O2" } */ > > + > > +#include <stdint.h> > > + > > +__attribute__ ((sysv_abi, noipa)) > > +uint8_t > > +foo (uint8_t a, uint8_t b, uint8_t c, uint8_t d, > > + uint8_t e, uint8_t f, uint8_t g) > > +{ > > + return a + b + c + d + e + f + g; > > +} > > + > > +__attribute__((ms_abi, noipa)) > > +uint8_t > > +bar (uint8_t a, uint8_t b, uint8_t c, uint8_t d, > > + uint8_t e, uint8_t f, uint8_t g) > > +{ > > + return foo (a, b, c, d, e, f, g); > > +} > > + > > +int > > +main (void) > > +{ > > + if (bar (0, 1, 2, 3, 4, 5, 6) != 21) > > + __builtin_abort (); > > + return 0; > > +} > > diff --git a/gcc/testsuite/gcc.target/i386/pr14907-22.c > > b/gcc/testsuite/gcc.target/i386/pr14907-22.c > > new file mode 100644 > > index 00000000000..591c8efd438 > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/i386/pr14907-22.c > > @@ -0,0 +1,28 @@ > > +/* { dg-do run { target { ! x32 } } } */ > > +/* { dg-options "-O2" } */ > > + > > +#include <stdint.h> > > + > > +__attribute__((ms_abi, noipa)) > > +uint8_t > > +foo (uint8_t a, uint8_t b, uint8_t c, uint8_t d, > > + uint8_t e, uint8_t f, uint8_t g) > > +{ > > + return a + b + c + d + e + f + g; > > +} > > + > > +__attribute__ ((sysv_abi, noipa)) > > +uint8_t > > +bar (uint8_t a, uint8_t b, uint8_t c, uint8_t d, > > + uint8_t e, uint8_t f, uint8_t g) > > +{ > > + return foo (a, b, c, d, e, f, g); > > +} > > + > > +int > > +main (void) > > +{ > > + if (bar (0, 1, 2, 3, 4, 5, 6) != 21) > > + __builtin_abort (); > > + return 0; > > +} > > diff --git a/gcc/testsuite/gcc.target/i386/pr14907-23.c > > b/gcc/testsuite/gcc.target/i386/pr14907-23.c > > new file mode 100644 > > index 00000000000..5082b4de589 > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/i386/pr14907-23.c > > @@ -0,0 +1,11 @@ > > +/* { dg-do compile { target maybe_x32 } } */ > > +/* { dg-require-effective-target maybe_x32 } */ > > +/* { dg-options "-mx32 -O2" } */ > > + > > +extern int baz (int a1, int a2, int a3, int a4, int a5, int a6, int *a7); > > + > > +int > > +foo (int a1, int a2, int a3, int a4, int a5, int a6, int *a7) > > +{ > > + return baz (a1, a2, a3, a4, a5, a6, a7); > > +} > > 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-7a.c > > b/gcc/testsuite/gcc.target/i386/pr14907-7a.c > > new file mode 100644 > > index 00000000000..fbf511f691e > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/i386/pr14907-7a.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-7b.c > > b/gcc/testsuite/gcc.target/i386/pr14907-7b.c > > new file mode 100644 > > index 00000000000..56596e080e2 > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/i386/pr14907-7b.c > > @@ -0,0 +1,17 @@ > > +/* { 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*... > > +*/ > > + > > +#include "pr14907-7a.c" > > diff --git a/gcc/testsuite/gcc.target/i386/pr14907-8a.c > > b/gcc/testsuite/gcc.target/i386/pr14907-8a.c > > new file mode 100644 > > index 00000000000..a22383694bf > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/i386/pr14907-8a.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/gcc.target/i386/pr14907-8b.c > > b/gcc/testsuite/gcc.target/i386/pr14907-8b.c > > new file mode 100644 > > index 00000000000..4e30f323e04 > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/i386/pr14907-8b.c > > @@ -0,0 +1,17 @@ > > +/* { 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*... > > +*/ > > + > > +#include "pr14907-8a.c" > > diff --git a/gcc/testsuite/gcc.target/i386/pr14907-9a.c > > b/gcc/testsuite/gcc.target/i386/pr14907-9a.c > > new file mode 100644 > > index 00000000000..ee8d0b0805f > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/i386/pr14907-9a.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* movsbl %dil, %eax > > +x64* movsbl %sil, %edi > > +x64* movl %eax, %esi > > +x64* jmp baz > > +x64* .cfi_endproc > > +x64*... > > +*/ > > + > > +extern int baz (char, char); > > + > > +int > > +foo (char c1, char c2) > > +{ > > + return baz (c2, c1); > > +} > > diff --git a/gcc/testsuite/gcc.target/i386/pr14907-9b.c > > b/gcc/testsuite/gcc.target/i386/pr14907-9b.c > > new file mode 100644 > > index 00000000000..d094e2f4ce7 > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/i386/pr14907-9b.c > > @@ -0,0 +1,19 @@ > > +/* { 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 8\(%esp\), %eax > > +ia32* movsbl 4\(%esp\), %edx > > +ia32* movl %eax, 4\(%esp\) > > +ia32* movl %edx, 8\(%esp\) > > +ia32* jmp baz > > +ia32* .cfi_endproc > > +ia32*... > > +*/ > > + > > +#include "pr14907-9a.c" > > -- > > 2.51.0 > > > > PING. > > -- > H.J.
PING^2. -- H.J.
