diff mbox series

[v3,2/7] Add expand_promote_outgoing_argument

Message ID 20241110125550.787007-3-hjl.tools@gmail.com
State New
Headers show
Series Improve outgoing integer argument promotion | expand

Commit Message

H.J. Lu Nov. 10, 2024, 12:55 p.m. UTC
Since the C/C++/Ada frontends no longer promote integer argument smaller
than int, add expand_promote_outgoing_argument to promote it when expanding
builtin functions.

	PR middle-end/14907
	* expr.cc (expand_promote_outgoing_argument): New function.
	* expr.h (expand_promote_outgoing_argument): New prototype.
	* config/i386/i386-expand.cc (ix86_expand_binop_builtin): Call
	expand_promote_outgoing_argument to expand the outgoing
	argument.
	(ix86_expand_multi_arg_builtin): Likewise.
	(ix86_expand_unop_vec_merge_builtin): Likewise.
	(ix86_expand_sse_compare): Likewise.
	(ix86_expand_sse_comi): Likewise.
	(ix86_expand_sse_round): Likewise.
	(ix86_expand_sse_round_vec_pack_sfix): Likewise.
	(ix86_expand_sse_ptest): Likewise.
	(ix86_expand_sse_pcmpestr): Likewise.
	(ix86_expand_sse_pcmpistr): Likewise.
	(ix86_expand_args_builtin): Likewise.
	(ix86_expand_sse_comi_round): Likewise.
	(ix86_expand_round_builtin): Likewise.
	(ix86_expand_special_args_builtin): Likewise.
	(ix86_expand_vec_init_builtin): Likewise.
	(ix86_expand_vec_ext_builtin): Likewise.
	(ix86_expand_builtin): Likewise.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
---
 gcc/config/i386/i386-expand.cc | 244 ++++++++++++++++-----------------
 gcc/expr.cc                    |  18 +++
 gcc/expr.h                     |   1 +
 3 files changed, 141 insertions(+), 122 deletions(-)

Comments

Richard Biener Nov. 20, 2024, 2:17 p.m. UTC | #1
On Sun, Nov 10, 2024 at 1:55 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> Since the C/C++/Ada frontends no longer promote integer argument smaller
> than int, add expand_promote_outgoing_argument to promote it when expanding
> builtin functions.

I wonder if we should instead handle this in the generic builtin expansion code
instead?  Otherwise we'd need to fix all targets similarly?

Richard.

>         PR middle-end/14907
>         * expr.cc (expand_promote_outgoing_argument): New function.
>         * expr.h (expand_promote_outgoing_argument): New prototype.
>         * config/i386/i386-expand.cc (ix86_expand_binop_builtin): Call
>         expand_promote_outgoing_argument to expand the outgoing
>         argument.
>         (ix86_expand_multi_arg_builtin): Likewise.
>         (ix86_expand_unop_vec_merge_builtin): Likewise.
>         (ix86_expand_sse_compare): Likewise.
>         (ix86_expand_sse_comi): Likewise.
>         (ix86_expand_sse_round): Likewise.
>         (ix86_expand_sse_round_vec_pack_sfix): Likewise.
>         (ix86_expand_sse_ptest): Likewise.
>         (ix86_expand_sse_pcmpestr): Likewise.
>         (ix86_expand_sse_pcmpistr): Likewise.
>         (ix86_expand_args_builtin): Likewise.
>         (ix86_expand_sse_comi_round): Likewise.
>         (ix86_expand_round_builtin): Likewise.
>         (ix86_expand_special_args_builtin): Likewise.
>         (ix86_expand_vec_init_builtin): Likewise.
>         (ix86_expand_vec_ext_builtin): Likewise.
>         (ix86_expand_builtin): Likewise.
>
> Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
> ---
>  gcc/config/i386/i386-expand.cc | 244 ++++++++++++++++-----------------
>  gcc/expr.cc                    |  18 +++
>  gcc/expr.h                     |   1 +
>  3 files changed, 141 insertions(+), 122 deletions(-)
>
> diff --git a/gcc/config/i386/i386-expand.cc b/gcc/config/i386/i386-expand.cc
> index 5c4a8e07d62..ce887d96f6a 100644
> --- a/gcc/config/i386/i386-expand.cc
> +++ b/gcc/config/i386/i386-expand.cc
> @@ -10415,8 +10415,8 @@ ix86_expand_binop_builtin (enum insn_code icode, tree exp, rtx target)
>    rtx pat;
>    tree arg0 = CALL_EXPR_ARG (exp, 0);
>    tree arg1 = CALL_EXPR_ARG (exp, 1);
> -  rtx op0 = expand_normal (arg0);
> -  rtx op1 = expand_normal (arg1);
> +  rtx op0 = expand_promote_outgoing_argument (arg0);
> +  rtx op1 = expand_promote_outgoing_argument (arg1);
>    machine_mode tmode = insn_data[icode].operand[0].mode;
>    machine_mode mode0 = insn_data[icode].operand[1].mode;
>    machine_mode mode1 = insn_data[icode].operand[2].mode;
> @@ -10564,7 +10564,7 @@ ix86_expand_multi_arg_builtin (enum insn_code icode, tree exp, rtx target,
>    for (i = 0; i < nargs; i++)
>      {
>        tree arg = CALL_EXPR_ARG (exp, i);
> -      rtx op = expand_normal (arg);
> +      rtx op = expand_promote_outgoing_argument (arg);
>        int adjust = (comparison_p) ? 1 : 0;
>        machine_mode mode = insn_data[icode].operand[i+adjust+1].mode;
>
> @@ -10691,7 +10691,7 @@ ix86_expand_unop_vec_merge_builtin (enum insn_code icode, tree exp,
>  {
>    rtx pat;
>    tree arg0 = CALL_EXPR_ARG (exp, 0);
> -  rtx op1, op0 = expand_normal (arg0);
> +  rtx op1, op0 = expand_promote_outgoing_argument (arg0);
>    machine_mode tmode = insn_data[icode].operand[0].mode;
>    machine_mode mode0 = insn_data[icode].operand[1].mode;
>
> @@ -10727,8 +10727,8 @@ ix86_expand_sse_compare (const struct builtin_description *d,
>    rtx pat;
>    tree arg0 = CALL_EXPR_ARG (exp, 0);
>    tree arg1 = CALL_EXPR_ARG (exp, 1);
> -  rtx op0 = expand_normal (arg0);
> -  rtx op1 = expand_normal (arg1);
> +  rtx op0 = expand_promote_outgoing_argument (arg0);
> +  rtx op1 = expand_promote_outgoing_argument (arg1);
>    rtx op2;
>    machine_mode tmode = insn_data[d->icode].operand[0].mode;
>    machine_mode mode0 = insn_data[d->icode].operand[1].mode;
> @@ -10823,8 +10823,8 @@ ix86_expand_sse_comi (const struct builtin_description *d, tree exp,
>    rtx pat, set_dst;
>    tree arg0 = CALL_EXPR_ARG (exp, 0);
>    tree arg1 = CALL_EXPR_ARG (exp, 1);
> -  rtx op0 = expand_normal (arg0);
> -  rtx op1 = expand_normal (arg1);
> +  rtx op0 = expand_promote_outgoing_argument (arg0);
> +  rtx op1 = expand_promote_outgoing_argument (arg1);
>    enum insn_code icode = d->icode;
>    const struct insn_data_d *insn_p = &insn_data[icode];
>    machine_mode mode0 = insn_p->operand[0].mode;
> @@ -10916,7 +10916,7 @@ ix86_expand_sse_round (const struct builtin_description *d, tree exp,
>  {
>    rtx pat;
>    tree arg0 = CALL_EXPR_ARG (exp, 0);
> -  rtx op1, op0 = expand_normal (arg0);
> +  rtx op1, op0 = expand_promote_outgoing_argument (arg0);
>    machine_mode tmode = insn_data[d->icode].operand[0].mode;
>    machine_mode mode0 = insn_data[d->icode].operand[1].mode;
>
> @@ -10948,8 +10948,8 @@ ix86_expand_sse_round_vec_pack_sfix (const struct builtin_description *d,
>    rtx pat;
>    tree arg0 = CALL_EXPR_ARG (exp, 0);
>    tree arg1 = CALL_EXPR_ARG (exp, 1);
> -  rtx op0 = expand_normal (arg0);
> -  rtx op1 = expand_normal (arg1);
> +  rtx op0 = expand_promote_outgoing_argument (arg0);
> +  rtx op1 = expand_promote_outgoing_argument (arg1);
>    rtx op2;
>    machine_mode tmode = insn_data[d->icode].operand[0].mode;
>    machine_mode mode0 = insn_data[d->icode].operand[1].mode;
> @@ -10988,8 +10988,8 @@ ix86_expand_sse_ptest (const struct builtin_description *d, tree exp,
>    rtx pat;
>    tree arg0 = CALL_EXPR_ARG (exp, 0);
>    tree arg1 = CALL_EXPR_ARG (exp, 1);
> -  rtx op0 = expand_normal (arg0);
> -  rtx op1 = expand_normal (arg1);
> +  rtx op0 = expand_promote_outgoing_argument (arg0);
> +  rtx op1 = expand_promote_outgoing_argument (arg1);
>    machine_mode mode0 = insn_data[d->icode].operand[0].mode;
>    machine_mode mode1 = insn_data[d->icode].operand[1].mode;
>    enum rtx_code comparison = d->comparison;
> @@ -11047,11 +11047,11 @@ ix86_expand_sse_pcmpestr (const struct builtin_description *d,
>    tree arg3 = CALL_EXPR_ARG (exp, 3);
>    tree arg4 = CALL_EXPR_ARG (exp, 4);
>    rtx scratch0, scratch1;
> -  rtx op0 = expand_normal (arg0);
> -  rtx op1 = expand_normal (arg1);
> -  rtx op2 = expand_normal (arg2);
> -  rtx op3 = expand_normal (arg3);
> -  rtx op4 = expand_normal (arg4);
> +  rtx op0 = expand_promote_outgoing_argument (arg0);
> +  rtx op1 = expand_promote_outgoing_argument (arg1);
> +  rtx op2 = expand_promote_outgoing_argument (arg2);
> +  rtx op3 = expand_promote_outgoing_argument (arg3);
> +  rtx op4 = expand_promote_outgoing_argument (arg4);
>    machine_mode tmode0, tmode1, modev2, modei3, modev4, modei5, modeimm;
>
>    tmode0 = insn_data[d->icode].operand[0].mode;
> @@ -11150,9 +11150,9 @@ ix86_expand_sse_pcmpistr (const struct builtin_description *d,
>    tree arg1 = CALL_EXPR_ARG (exp, 1);
>    tree arg2 = CALL_EXPR_ARG (exp, 2);
>    rtx scratch0, scratch1;
> -  rtx op0 = expand_normal (arg0);
> -  rtx op1 = expand_normal (arg1);
> -  rtx op2 = expand_normal (arg2);
> +  rtx op0 = expand_promote_outgoing_argument (arg0);
> +  rtx op1 = expand_promote_outgoing_argument (arg1);
> +  rtx op2 = expand_promote_outgoing_argument (arg2);
>    machine_mode tmode0, tmode1, modev2, modev3, modeimm;
>
>    tmode0 = insn_data[d->icode].operand[0].mode;
> @@ -12135,7 +12135,7 @@ ix86_expand_args_builtin (const struct builtin_description *d,
>    for (i = 0; i < nargs; i++)
>      {
>        tree arg = CALL_EXPR_ARG (exp, i);
> -      rtx op = expand_normal (arg);
> +      rtx op = expand_promote_outgoing_argument (arg);
>        machine_mode mode = insn_p->operand[i + 1].mode;
>        /* Need to fixup modeless constant before testing predicate.  */
>        op = fixup_modeless_constant (op, mode);
> @@ -12400,10 +12400,10 @@ ix86_expand_sse_comi_round (const struct builtin_description *d,
>    tree arg1 = CALL_EXPR_ARG (exp, 1);
>    tree arg2 = CALL_EXPR_ARG (exp, 2);
>    tree arg3 = CALL_EXPR_ARG (exp, 3);
> -  rtx op0 = expand_normal (arg0);
> -  rtx op1 = expand_normal (arg1);
> -  rtx op2 = expand_normal (arg2);
> -  rtx op3 = expand_normal (arg3);
> +  rtx op0 = expand_promote_outgoing_argument (arg0);
> +  rtx op1 = expand_promote_outgoing_argument (arg1);
> +  rtx op2 = expand_promote_outgoing_argument (arg2);
> +  rtx op3 = expand_promote_outgoing_argument (arg3);
>    enum insn_code icode = d->icode;
>    const struct insn_data_d *insn_p = &insn_data[icode];
>    machine_mode mode0 = insn_p->operand[0].mode;
> @@ -12870,7 +12870,7 @@ ix86_expand_round_builtin (const struct builtin_description *d,
>    for (i = 0; i < nargs; i++)
>      {
>        tree arg = CALL_EXPR_ARG (exp, i);
> -      rtx op = expand_normal (arg);
> +      rtx op = expand_promote_outgoing_argument (arg);
>        machine_mode mode = insn_p->operand[i + 1].mode;
>        bool match = insn_p->operand[i + 1].predicate (op, mode);
>
> @@ -13318,7 +13318,7 @@ ix86_expand_special_args_builtin (const struct builtin_description *d,
>    if (klass == store)
>      {
>        arg = CALL_EXPR_ARG (exp, 0);
> -      op = expand_normal (arg);
> +      op = expand_promote_outgoing_argument (arg);
>        gcc_assert (target == 0);
>        if (memory)
>         {
> @@ -13355,7 +13355,7 @@ ix86_expand_special_args_builtin (const struct builtin_description *d,
>        machine_mode mode = insn_p->operand[i + 1].mode;
>
>        arg = CALL_EXPR_ARG (exp, i + arg_adjust);
> -      op = expand_normal (arg);
> +      op = expand_promote_outgoing_argument (arg);
>
>        if (i == memory)
>         {
> @@ -13479,7 +13479,7 @@ ix86_expand_vec_init_builtin (tree type, tree exp, rtx target)
>
>    for (i = 0; i < n_elt; ++i)
>      {
> -      rtx x = expand_normal (CALL_EXPR_ARG (exp, i));
> +      rtx x = expand_promote_outgoing_argument (CALL_EXPR_ARG (exp, i));
>        RTVEC_ELT (v, i) = gen_lowpart (inner_mode, x);
>      }
>
> @@ -13505,7 +13505,7 @@ ix86_expand_vec_ext_builtin (tree exp, rtx target)
>    arg0 = CALL_EXPR_ARG (exp, 0);
>    arg1 = CALL_EXPR_ARG (exp, 1);
>
> -  op0 = expand_normal (arg0);
> +  op0 = expand_promote_outgoing_argument (arg0);
>    elt = get_element_number (TREE_TYPE (arg0), arg1);
>
>    tmode = TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0)));
> @@ -13727,9 +13727,9 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
>        arg1 = CALL_EXPR_ARG (exp, 0);
>        arg2 = CALL_EXPR_ARG (exp, 1);
>        arg0 = CALL_EXPR_ARG (exp, 2);
> -      op0 = expand_normal (arg0);
> -      op1 = expand_normal (arg1);
> -      op2 = expand_normal (arg2);
> +      op0 = expand_promote_outgoing_argument (arg0);
> +      op1 = expand_promote_outgoing_argument (arg1);
> +      op2 = expand_promote_outgoing_argument (arg2);
>        mode0 = insn_data[icode].operand[0].mode;
>        mode1 = insn_data[icode].operand[1].mode;
>        mode2 = insn_data[icode].operand[2].mode;
> @@ -13750,7 +13750,7 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
>        return 0;
>
>      case IX86_BUILTIN_LDMXCSR:
> -      op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
> +      op0 = expand_promote_outgoing_argument (CALL_EXPR_ARG (exp, 0));
>        target = assign_stack_temp (SImode, GET_MODE_SIZE (SImode));
>        emit_move_insn (target, op0);
>        emit_insn (gen_sse_ldmxcsr (target));
> @@ -13763,7 +13763,7 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
>
>      case IX86_BUILTIN_CLFLUSH:
>         arg0 = CALL_EXPR_ARG (exp, 0);
> -       op0 = expand_normal (arg0);
> +       op0 = expand_promote_outgoing_argument (arg0);
>         icode = CODE_FOR_sse2_clflush;
>         if (!insn_data[icode].operand[0].predicate (op0, Pmode))
>           op0 = ix86_zero_extend_to_Pmode (op0);
> @@ -13773,7 +13773,7 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
>
>      case IX86_BUILTIN_CLWB:
>         arg0 = CALL_EXPR_ARG (exp, 0);
> -       op0 = expand_normal (arg0);
> +       op0 = expand_promote_outgoing_argument (arg0);
>         icode = CODE_FOR_clwb;
>         if (!insn_data[icode].operand[0].predicate (op0, Pmode))
>           op0 = ix86_zero_extend_to_Pmode (op0);
> @@ -13783,7 +13783,7 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
>
>      case IX86_BUILTIN_CLFLUSHOPT:
>         arg0 = CALL_EXPR_ARG (exp, 0);
> -       op0 = expand_normal (arg0);
> +       op0 = expand_promote_outgoing_argument (arg0);
>         icode = CODE_FOR_clflushopt;
>         if (!insn_data[icode].operand[0].predicate (op0, Pmode))
>           op0 = ix86_zero_extend_to_Pmode (op0);
> @@ -13796,9 +13796,9 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
>        arg0 = CALL_EXPR_ARG (exp, 0);
>        arg1 = CALL_EXPR_ARG (exp, 1);
>        arg2 = CALL_EXPR_ARG (exp, 2);
> -      op0 = expand_normal (arg0);
> -      op1 = expand_normal (arg1);
> -      op2 = expand_normal (arg2);
> +      op0 = expand_promote_outgoing_argument (arg0);
> +      op1 = expand_promote_outgoing_argument (arg1);
> +      op2 = expand_promote_outgoing_argument (arg2);
>        if (!REG_P (op0))
>         op0 = ix86_zero_extend_to_Pmode (op0);
>        if (!REG_P (op1))
> @@ -13814,8 +13814,8 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
>      case IX86_BUILTIN_MWAIT:
>        arg0 = CALL_EXPR_ARG (exp, 0);
>        arg1 = CALL_EXPR_ARG (exp, 1);
> -      op0 = expand_normal (arg0);
> -      op1 = expand_normal (arg1);
> +      op0 = expand_promote_outgoing_argument (arg0);
> +      op1 = expand_promote_outgoing_argument (arg1);
>        if (!REG_P (op0))
>         op0 = copy_to_mode_reg (SImode, op0);
>        if (!REG_P (op1))
> @@ -13827,9 +13827,9 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
>        arg0 = CALL_EXPR_ARG (exp, 0);
>        arg1 = CALL_EXPR_ARG (exp, 1);
>        arg2 = CALL_EXPR_ARG (exp, 2);
> -      op0 = expand_normal (arg0);
> -      op1 = expand_normal (arg1);
> -      op2 = expand_normal (arg2);
> +      op0 = expand_promote_outgoing_argument (arg0);
> +      op1 = expand_promote_outgoing_argument (arg1);
> +      op2 = expand_promote_outgoing_argument (arg2);
>        if (!REG_P (op0))
>         op0 = copy_to_mode_reg (SImode, op0);
>        if (!REG_P (op1))
> @@ -13841,7 +13841,7 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
>
>      case IX86_BUILTIN_UMONITOR:
>        arg0 = CALL_EXPR_ARG (exp, 0);
> -      op0 = expand_normal (arg0);
> +      op0 = expand_promote_outgoing_argument (arg0);
>
>        op0 = ix86_zero_extend_to_Pmode (op0);
>        emit_insn (gen_umonitor (Pmode, op0));
> @@ -13851,8 +13851,8 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
>      case IX86_BUILTIN_TPAUSE:
>        arg0 = CALL_EXPR_ARG (exp, 0);
>        arg1 = CALL_EXPR_ARG (exp, 1);
> -      op0 = expand_normal (arg0);
> -      op1 = expand_normal (arg1);
> +      op0 = expand_promote_outgoing_argument (arg0);
> +      op1 = expand_promote_outgoing_argument (arg1);
>
>        if (!REG_P (op0))
>         op0 = copy_to_mode_reg (SImode, op0);
> @@ -13925,7 +13925,7 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
>
>      case IX86_BUILTIN_CLZERO:
>        arg0 = CALL_EXPR_ARG (exp, 0);
> -      op0 = expand_normal (arg0);
> +      op0 = expand_promote_outgoing_argument (arg0);
>        if (!REG_P (op0))
>         op0 = ix86_zero_extend_to_Pmode (op0);
>        emit_insn (gen_clzero (Pmode, op0));
> @@ -13933,7 +13933,7 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
>
>      case IX86_BUILTIN_CLDEMOTE:
>        arg0 = CALL_EXPR_ARG (exp, 0);
> -      op0 = expand_normal (arg0);
> +      op0 = expand_promote_outgoing_argument (arg0);
>        icode = CODE_FOR_cldemote;
>        if (!insn_data[icode].operand[0].predicate (op0, Pmode))
>         op0 = ix86_zero_extend_to_Pmode (op0);
> @@ -13948,10 +13948,10 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
>         arg2 = CALL_EXPR_ARG (exp, 2);
>         arg3 = CALL_EXPR_ARG (exp, 3);
>
> -       op0 = expand_normal (arg0);
> -       op1 = expand_normal (arg1);
> -       op2 = expand_normal (arg2);
> -       op3 = expand_normal (arg3);
> +       op0 = expand_promote_outgoing_argument (arg0);
> +       op1 = expand_promote_outgoing_argument (arg1);
> +       op2 = expand_promote_outgoing_argument (arg2);
> +       op3 = expand_promote_outgoing_argument (arg3);
>
>         if (!REG_P (op0))
>           op0 = copy_to_mode_reg (V2DImode, op0);
> @@ -13988,9 +13988,9 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
>        arg1 = CALL_EXPR_ARG (exp, 1); // __m128i idata
>        arg2 = CALL_EXPR_ARG (exp, 2); // const void *p
>
> -      op0 = expand_normal (arg0);
> -      op1 = expand_normal (arg1);
> -      op2 = expand_normal (arg2);
> +      op0 = expand_promote_outgoing_argument (arg0);
> +      op1 = expand_promote_outgoing_argument (arg1);
> +      op2 = expand_promote_outgoing_argument (arg2);
>
>        if (!address_operand (op0, V2DImode))
>         {
> @@ -14060,9 +14060,9 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
>        arg1 = CALL_EXPR_ARG (exp, 1); // const __m128i * idata
>        arg2 = CALL_EXPR_ARG (exp, 2); // const void *p
>
> -      op0 = expand_normal (arg0);
> -      op1 = expand_normal (arg1);
> -      op2 = expand_normal (arg2);
> +      op0 = expand_promote_outgoing_argument (arg0);
> +      op1 = expand_promote_outgoing_argument (arg1);
> +      op2 = expand_promote_outgoing_argument (arg2);
>
>        if (!address_operand (op2, VOIDmode))
>         {
> @@ -14116,9 +14116,9 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
>         arg1 = CALL_EXPR_ARG (exp, 1); // __m128i key
>         arg2 = CALL_EXPR_ARG (exp, 2); // void *h
>
> -       op0 = expand_normal (arg0);
> -       op1 = expand_normal (arg1);
> -       op2 = expand_normal (arg2);
> +       op0 = expand_promote_outgoing_argument (arg0);
> +       op1 = expand_promote_outgoing_argument (arg1);
> +       op2 = expand_promote_outgoing_argument (arg2);
>
>         if (!REG_P (op0))
>           op0 = copy_to_mode_reg (SImode, op0);
> @@ -14152,10 +14152,10 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
>         arg2 = CALL_EXPR_ARG (exp, 2); // __m128i keyhi
>         arg3 = CALL_EXPR_ARG (exp, 3); // void *h
>
> -       op0 = expand_normal (arg0);
> -       op1 = expand_normal (arg1);
> -       op2 = expand_normal (arg2);
> -       op3 = expand_normal (arg3);
> +       op0 = expand_promote_outgoing_argument (arg0);
> +       op1 = expand_promote_outgoing_argument (arg1);
> +       op2 = expand_promote_outgoing_argument (arg2);
> +       op3 = expand_promote_outgoing_argument (arg3);
>
>         if (!REG_P (op0))
>           op0 = copy_to_mode_reg (SImode, op0);
> @@ -14191,10 +14191,10 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
>         arg2 = CALL_EXPR_ARG (exp, 2); // const int
>         arg3 = CALL_EXPR_ARG (exp, 3); // const int
>
> -       op0 = expand_normal (arg0);
> -       op1 = expand_normal (arg1);
> -       op2 = expand_normal (arg2);
> -       op3 = expand_normal (arg3);
> +       op0 = expand_promote_outgoing_argument (arg0);
> +       op1 = expand_promote_outgoing_argument (arg1);
> +       op2 = expand_promote_outgoing_argument (arg2);
> +       op3 = expand_promote_outgoing_argument (arg3);
>
>         if (!CONST_INT_P (op1) || !CONST_INT_P (op2) || !CONST_INT_P (op3))
>           {
> @@ -14264,8 +14264,8 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
>         arg0 = CALL_EXPR_ARG (exp, 0); // const void *
>         arg1 = CALL_EXPR_ARG (exp, 1); // const int
>
> -       op0 = expand_normal (arg0);
> -       op1 = expand_normal (arg1);
> +       op0 = expand_promote_outgoing_argument (arg0);
> +       op1 = expand_promote_outgoing_argument (arg1);
>
>         if (!CONST_INT_P (op1))
>           {
> @@ -14295,7 +14295,7 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
>      case IX86_BUILTIN_UWRMSR:
>        {
>         arg0 = CALL_EXPR_ARG (exp, 0);
> -       op0 = expand_normal (arg0);
> +       op0 = expand_promote_outgoing_argument (arg0);
>
>         if (CONST_INT_P (op0))
>           {
> @@ -14309,7 +14309,7 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
>         if (fcode == IX86_BUILTIN_UWRMSR)
>           {
>             arg1 = CALL_EXPR_ARG (exp, 1);
> -           op1 = expand_normal (arg1);
> +           op1 = expand_promote_outgoing_argument (arg1);
>             op1 = force_reg (DImode, op1);
>             icode = CODE_FOR_uwrmsr;
>             target = 0;
> @@ -14384,10 +14384,10 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
>        arg1 = CALL_EXPR_ARG (exp, 1);
>        arg2 = CALL_EXPR_ARG (exp, 2);
>        arg3 = CALL_EXPR_ARG (exp, 3);
> -      op0 = expand_normal (arg0);
> -      op1 = expand_normal (arg1);
> -      op2 = expand_normal (arg2);
> -      op3 = expand_normal (arg3);
> +      op0 = expand_promote_outgoing_argument (arg0);
> +      op1 = expand_promote_outgoing_argument (arg1);
> +      op2 = expand_promote_outgoing_argument (arg2);
> +      op3 = expand_promote_outgoing_argument (arg3);
>
>        if (!address_operand (op0, VOIDmode))
>         {
> @@ -14458,7 +14458,7 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
>        if (fcode == IX86_BUILTIN_RDPMC)
>         {
>           arg0 = CALL_EXPR_ARG (exp, 0);
> -         op2 = expand_normal (arg0);
> +         op2 = expand_promote_outgoing_argument (arg0);
>           if (!register_operand (op2, SImode))
>             op2 = copy_to_mode_reg (SImode, op2);
>
> @@ -14470,7 +14470,7 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
>        else if (fcode == IX86_BUILTIN_XGETBV)
>         {
>           arg0 = CALL_EXPR_ARG (exp, 0);
> -         op2 = expand_normal (arg0);
> +         op2 = expand_promote_outgoing_argument (arg0);
>           if (!register_operand (op2, SImode))
>             op2 = copy_to_mode_reg (SImode, op2);
>
> @@ -14496,7 +14496,7 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
>           emit_insn (insn);
>
>           arg0 = CALL_EXPR_ARG (exp, 0);
> -         op4 = expand_normal (arg0);
> +         op4 = expand_promote_outgoing_argument (arg0);
>           if (!address_operand (op4, VOIDmode))
>             {
>               op4 = convert_memory_address (Pmode, op4);
> @@ -14526,8 +14526,8 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
>
>        arg0 = CALL_EXPR_ARG (exp, 0);
>        arg1 = CALL_EXPR_ARG (exp, 1);
> -      op0 = expand_normal (arg0);
> -      op1 = expand_normal (arg1);
> +      op0 = expand_promote_outgoing_argument (arg0);
> +      op1 = expand_promote_outgoing_argument (arg1);
>
>        op0 = ix86_zero_extend_to_Pmode (op0);
>        if (!address_operand (op1, VOIDmode))
> @@ -14597,7 +14597,7 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
>         }
>
>        arg0 = CALL_EXPR_ARG (exp, 0);
> -      op0 = expand_normal (arg0);
> +      op0 = expand_promote_outgoing_argument (arg0);
>
>        if (!address_operand (op0, VOIDmode))
>         {
> @@ -14614,8 +14614,8 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
>      case IX86_BUILTIN_XSETBV:
>        arg0 = CALL_EXPR_ARG (exp, 0);
>        arg1 = CALL_EXPR_ARG (exp, 1);
> -      op0 = expand_normal (arg0);
> -      op1 = expand_normal (arg1);
> +      op0 = expand_promote_outgoing_argument (arg0);
> +      op1 = expand_promote_outgoing_argument (arg1);
>
>        if (!REG_P (op0))
>         op0 = copy_to_mode_reg (SImode, op0);
> @@ -14657,8 +14657,8 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
>      case IX86_BUILTIN_XSAVEC64:
>        arg0 = CALL_EXPR_ARG (exp, 0);
>        arg1 = CALL_EXPR_ARG (exp, 1);
> -      op0 = expand_normal (arg0);
> -      op1 = expand_normal (arg1);
> +      op0 = expand_promote_outgoing_argument (arg0);
> +      op1 = expand_promote_outgoing_argument (arg1);
>
>        if (!address_operand (op0, VOIDmode))
>         {
> @@ -14754,7 +14754,7 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
>      case IX86_BUILTIN_LDTILECFG:
>      case IX86_BUILTIN_STTILECFG:
>        arg0 = CALL_EXPR_ARG (exp, 0);
> -      op0 = expand_normal (arg0);
> +      op0 = expand_promote_outgoing_argument (arg0);
>
>        if (!address_operand (op0, VOIDmode))
>         {
> @@ -14772,7 +14772,7 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
>
>      case IX86_BUILTIN_LLWPCB:
>        arg0 = CALL_EXPR_ARG (exp, 0);
> -      op0 = expand_normal (arg0);
> +      op0 = expand_promote_outgoing_argument (arg0);
>
>        if (!register_operand (op0, Pmode))
>         op0 = ix86_zero_extend_to_Pmode (op0);
> @@ -14803,9 +14803,9 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
>        arg0 = CALL_EXPR_ARG (exp, 0);
>        arg1 = CALL_EXPR_ARG (exp, 1);
>        arg2 = CALL_EXPR_ARG (exp, 2);
> -      op0 = expand_normal (arg0);
> -      op1 = expand_normal (arg1);
> -      op2 = expand_normal (arg2);
> +      op0 = expand_promote_outgoing_argument (arg0);
> +      op1 = expand_promote_outgoing_argument (arg1);
> +      op2 = expand_promote_outgoing_argument (arg2);
>        mode0 = insn_data[icode].operand[0].mode;
>
>        if (!insn_data[icode].operand[0].predicate (op0, mode0))
> @@ -14843,8 +14843,8 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
>
>        arg0 = CALL_EXPR_ARG (exp, 0);
>        arg1 = CALL_EXPR_ARG (exp, 1);
> -      op0 = expand_normal (arg0);
> -      op1 = expand_normal (arg1);
> +      op0 = expand_promote_outgoing_argument (arg0);
> +      op1 = expand_promote_outgoing_argument (arg1);
>
>        if (!CONST_INT_P (op1))
>         {
> @@ -14898,7 +14898,7 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
>
>  rdrand_step:
>        arg0 = CALL_EXPR_ARG (exp, 0);
> -      op1 = expand_normal (arg0);
> +      op1 = expand_promote_outgoing_argument (arg0);
>        if (!address_operand (op1, VOIDmode))
>         {
>           op1 = convert_memory_address (Pmode, op1);
> @@ -14958,7 +14958,7 @@ rdrand_step:
>
>  rdseed_step:
>        arg0 = CALL_EXPR_ARG (exp, 0);
> -      op1 = expand_normal (arg0);
> +      op1 = expand_promote_outgoing_argument (arg0);
>        if (!address_operand (op1, VOIDmode))
>         {
>           op1 = convert_memory_address (Pmode, op1);
> @@ -15020,17 +15020,17 @@ rdseed_step:
>        arg2 = CALL_EXPR_ARG (exp, 2); /* unsigned int src2.  */
>        arg3 = CALL_EXPR_ARG (exp, 3); /* unsigned int *sum_out.  */
>
> -      op1 = expand_normal (arg0);
> +      op1 = expand_promote_outgoing_argument (arg0);
>
> -      op2 = expand_normal (arg1);
> +      op2 = expand_promote_outgoing_argument (arg1);
>        if (!register_operand (op2, mode0))
>         op2 = copy_to_mode_reg (mode0, op2);
>
> -      op3 = expand_normal (arg2);
> +      op3 = expand_promote_outgoing_argument (arg2);
>        if (!register_operand (op3, mode0))
>         op3 = copy_to_mode_reg (mode0, op3);
>
> -      op4 = expand_normal (arg3);
> +      op4 = expand_promote_outgoing_argument (arg3);
>        if (!address_operand (op4, VOIDmode))
>         {
>           op4 = convert_memory_address (Pmode, op4);
> @@ -15087,7 +15087,7 @@ rdseed_step:
>      case IX86_BUILTIN_WRITE_FLAGS:
>
>        arg0 = CALL_EXPR_ARG (exp, 0);
> -      op0 = expand_normal (arg0);
> +      op0 = expand_promote_outgoing_argument (arg0);
>        if (!general_no_elim_operand (op0, word_mode))
>         op0 = copy_to_mode_reg (word_mode, op0);
>
> @@ -15177,8 +15177,8 @@ rdseed_step:
>      kortest:
>        arg0 = CALL_EXPR_ARG (exp, 0); /* Mask reg src1.  */
>        arg1 = CALL_EXPR_ARG (exp, 1); /* Mask reg src2.  */
> -      op0 = expand_normal (arg0);
> -      op1 = expand_normal (arg1);
> +      op0 = expand_promote_outgoing_argument (arg0);
> +      op1 = expand_promote_outgoing_argument (arg1);
>
>        mode0 = insn_data[icode].operand[0].mode;
>        mode1 = insn_data[icode].operand[1].mode;
> @@ -15482,11 +15482,11 @@ rdseed_step:
>        arg2 = CALL_EXPR_ARG (exp, 2);
>        arg3 = CALL_EXPR_ARG (exp, 3);
>        arg4 = CALL_EXPR_ARG (exp, 4);
> -      op0 = expand_normal (arg0);
> -      op1 = expand_normal (arg1);
> -      op2 = expand_normal (arg2);
> -      op3 = expand_normal (arg3);
> -      op4 = expand_normal (arg4);
> +      op0 = expand_promote_outgoing_argument (arg0);
> +      op1 = expand_promote_outgoing_argument (arg1);
> +      op2 = expand_promote_outgoing_argument (arg2);
> +      op3 = expand_promote_outgoing_argument (arg3);
> +      op4 = expand_promote_outgoing_argument (arg4);
>        /* Note the arg order is different from the operand order.  */
>        mode0 = insn_data[icode].operand[1].mode;
>        mode2 = insn_data[icode].operand[3].mode;
> @@ -15699,11 +15699,11 @@ rdseed_step:
>        arg2 = CALL_EXPR_ARG (exp, 2);
>        arg3 = CALL_EXPR_ARG (exp, 3);
>        arg4 = CALL_EXPR_ARG (exp, 4);
> -      op0 = expand_normal (arg0);
> -      op1 = expand_normal (arg1);
> -      op2 = expand_normal (arg2);
> -      op3 = expand_normal (arg3);
> -      op4 = expand_normal (arg4);
> +      op0 = expand_promote_outgoing_argument (arg0);
> +      op1 = expand_promote_outgoing_argument (arg1);
> +      op2 = expand_promote_outgoing_argument (arg2);
> +      op3 = expand_promote_outgoing_argument (arg3);
> +      op4 = expand_promote_outgoing_argument (arg4);
>        mode1 = insn_data[icode].operand[1].mode;
>        mode2 = insn_data[icode].operand[2].mode;
>        mode3 = insn_data[icode].operand[3].mode;
> @@ -15812,7 +15812,7 @@ rdseed_step:
>      case IX86_BUILTIN_XABORT:
>        icode = CODE_FOR_xabort;
>        arg0 = CALL_EXPR_ARG (exp, 0);
> -      op0 = expand_normal (arg0);
> +      op0 = expand_promote_outgoing_argument (arg0);
>        mode0 = insn_data[icode].operand[0].mode;
>        if (!insn_data[icode].operand[0].predicate (op0, mode0))
>         {
> @@ -15841,7 +15841,7 @@ rdseed_step:
>        mode = (fcode == IX86_BUILTIN_INCSSPD ? SImode : DImode);
>
>        arg0 = CALL_EXPR_ARG (exp, 0);
> -      op0 = expand_normal (arg0);
> +      op0 = expand_promote_outgoing_argument (arg0);
>
>        op0 = force_reg (mode, op0);
>
> @@ -15851,7 +15851,7 @@ rdseed_step:
>      case IX86_BUILTIN_HRESET:
>        icode = CODE_FOR_hreset;
>        arg0 = CALL_EXPR_ARG (exp, 0);
> -      op0 = expand_normal (arg0);
> +      op0 = expand_promote_outgoing_argument (arg0);
>        op0 = force_reg (SImode, op0);
>        emit_insn (gen_hreset (op0));
>        return 0;
> @@ -15859,7 +15859,7 @@ rdseed_step:
>      case IX86_BUILTIN_RSTORSSP:
>      case IX86_BUILTIN_CLRSSBSY:
>        arg0 = CALL_EXPR_ARG (exp, 0);
> -      op0 = expand_normal (arg0);
> +      op0 = expand_promote_outgoing_argument (arg0);
>        icode = (fcode == IX86_BUILTIN_RSTORSSP
>                ? CODE_FOR_rstorssp
>                : CODE_FOR_clrssbsy);
> @@ -15881,9 +15881,9 @@ rdseed_step:
>               ? SImode : DImode);
>
>        arg0 = CALL_EXPR_ARG (exp, 0);
> -      op0 = expand_normal (arg0);
> +      op0 = expand_promote_outgoing_argument (arg0);
>        arg1 = CALL_EXPR_ARG (exp, 1);
> -      op1 = expand_normal (arg1);
> +      op1 = expand_promote_outgoing_argument (arg1);
>
>        op0 = force_reg (mode, op0);
>
> diff --git a/gcc/expr.cc b/gcc/expr.cc
> index caa1a72ba0b..0a1a70dab3c 100644
> --- a/gcc/expr.cc
> +++ b/gcc/expr.cc
> @@ -14136,3 +14136,21 @@ int_expr_size (const_tree exp)
>
>    return tree_to_shwi (size);
>  }
> +
> +/* Expand an outgoing argument ARG with promotion.  Since the C/C++
> +   frontends no longer promote integer argument smaller than int,
> +   promote it when expanding built functions.  */
> +
> +rtx
> +expand_promote_outgoing_argument (tree arg)
> +{
> +  tree type = TREE_TYPE (arg);
> +  if (INTEGRAL_TYPE_P (type)
> +      && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
> +    {
> +      tree promoted_type = (TYPE_UNSIGNED (type)
> +                           ? unsigned_type_node : integer_type_node);
> +      arg = fold_convert (promoted_type, arg);
> +    }
> +  return expand_normal (arg);
> +}
> diff --git a/gcc/expr.h b/gcc/expr.h
> index 04782b15f19..ed14750614b 100644
> --- a/gcc/expr.h
> +++ b/gcc/expr.h
> @@ -312,6 +312,7 @@ extern rtx expand_expr_real_2 (const_sepops, rtx, machine_mode,
>  extern rtx expand_expr_real_gassign (gassign *, rtx, machine_mode,
>                                      enum expand_modifier modifier,
>                                      rtx * = nullptr, bool = false);
> +extern rtx expand_promote_outgoing_argument (tree);
>
>  /* Generate code for computing expression EXP.
>     An rtx for the computed value is returned.  The value is never null.
> --
> 2.47.0
>
H.J. Lu Nov. 20, 2024, 10:28 p.m. UTC | #2
On Wed, Nov 20, 2024 at 10:18 PM Richard Biener <richard.guenther@gmail.com>
wrote:

> On Sun, Nov 10, 2024 at 1:55 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> >
> > Since the C/C++/Ada frontends no longer promote integer argument smaller
> > than int, add expand_promote_outgoing_argument to promote it when
> expanding
> > builtin functions.
>
> I wonder if we should instead handle this in the generic builtin expansion
> code
> instead?  Otherwise we'd need to fix all targets similarly?
>

This is for

 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117547

I think it should be fixed differently in the x86 backend.


> Richard.
>
> >         PR middle-end/14907
> >         * expr.cc (expand_promote_outgoing_argument): New function.
> >         * expr.h (expand_promote_outgoing_argument): New prototype.
> >         * config/i386/i386-expand.cc (ix86_expand_binop_builtin): Call
> >         expand_promote_outgoing_argument to expand the outgoing
> >         argument.
> >         (ix86_expand_multi_arg_builtin): Likewise.
> >         (ix86_expand_unop_vec_merge_builtin): Likewise.
> >         (ix86_expand_sse_compare): Likewise.
> >         (ix86_expand_sse_comi): Likewise.
> >         (ix86_expand_sse_round): Likewise.
> >         (ix86_expand_sse_round_vec_pack_sfix): Likewise.
> >         (ix86_expand_sse_ptest): Likewise.
> >         (ix86_expand_sse_pcmpestr): Likewise.
> >         (ix86_expand_sse_pcmpistr): Likewise.
> >         (ix86_expand_args_builtin): Likewise.
> >         (ix86_expand_sse_comi_round): Likewise.
> >         (ix86_expand_round_builtin): Likewise.
> >         (ix86_expand_special_args_builtin): Likewise.
> >         (ix86_expand_vec_init_builtin): Likewise.
> >         (ix86_expand_vec_ext_builtin): Likewise.
> >         (ix86_expand_builtin): Likewise.
> >
> > Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
> > ---
> >  gcc/config/i386/i386-expand.cc | 244 ++++++++++++++++-----------------
> >  gcc/expr.cc                    |  18 +++
> >  gcc/expr.h                     |   1 +
> >  3 files changed, 141 insertions(+), 122 deletions(-)
> >
> > diff --git a/gcc/config/i386/i386-expand.cc
> b/gcc/config/i386/i386-expand.cc
> > index 5c4a8e07d62..ce887d96f6a 100644
> > --- a/gcc/config/i386/i386-expand.cc
> > +++ b/gcc/config/i386/i386-expand.cc
> > @@ -10415,8 +10415,8 @@ ix86_expand_binop_builtin (enum insn_code icode,
> tree exp, rtx target)
> >    rtx pat;
> >    tree arg0 = CALL_EXPR_ARG (exp, 0);
> >    tree arg1 = CALL_EXPR_ARG (exp, 1);
> > -  rtx op0 = expand_normal (arg0);
> > -  rtx op1 = expand_normal (arg1);
> > +  rtx op0 = expand_promote_outgoing_argument (arg0);
> > +  rtx op1 = expand_promote_outgoing_argument (arg1);
> >    machine_mode tmode = insn_data[icode].operand[0].mode;
> >    machine_mode mode0 = insn_data[icode].operand[1].mode;
> >    machine_mode mode1 = insn_data[icode].operand[2].mode;
> > @@ -10564,7 +10564,7 @@ ix86_expand_multi_arg_builtin (enum insn_code
> icode, tree exp, rtx target,
> >    for (i = 0; i < nargs; i++)
> >      {
> >        tree arg = CALL_EXPR_ARG (exp, i);
> > -      rtx op = expand_normal (arg);
> > +      rtx op = expand_promote_outgoing_argument (arg);
> >        int adjust = (comparison_p) ? 1 : 0;
> >        machine_mode mode = insn_data[icode].operand[i+adjust+1].mode;
> >
> > @@ -10691,7 +10691,7 @@ ix86_expand_unop_vec_merge_builtin (enum
> insn_code icode, tree exp,
> >  {
> >    rtx pat;
> >    tree arg0 = CALL_EXPR_ARG (exp, 0);
> > -  rtx op1, op0 = expand_normal (arg0);
> > +  rtx op1, op0 = expand_promote_outgoing_argument (arg0);
> >    machine_mode tmode = insn_data[icode].operand[0].mode;
> >    machine_mode mode0 = insn_data[icode].operand[1].mode;
> >
> > @@ -10727,8 +10727,8 @@ ix86_expand_sse_compare (const struct
> builtin_description *d,
> >    rtx pat;
> >    tree arg0 = CALL_EXPR_ARG (exp, 0);
> >    tree arg1 = CALL_EXPR_ARG (exp, 1);
> > -  rtx op0 = expand_normal (arg0);
> > -  rtx op1 = expand_normal (arg1);
> > +  rtx op0 = expand_promote_outgoing_argument (arg0);
> > +  rtx op1 = expand_promote_outgoing_argument (arg1);
> >    rtx op2;
> >    machine_mode tmode = insn_data[d->icode].operand[0].mode;
> >    machine_mode mode0 = insn_data[d->icode].operand[1].mode;
> > @@ -10823,8 +10823,8 @@ ix86_expand_sse_comi (const struct
> builtin_description *d, tree exp,
> >    rtx pat, set_dst;
> >    tree arg0 = CALL_EXPR_ARG (exp, 0);
> >    tree arg1 = CALL_EXPR_ARG (exp, 1);
> > -  rtx op0 = expand_normal (arg0);
> > -  rtx op1 = expand_normal (arg1);
> > +  rtx op0 = expand_promote_outgoing_argument (arg0);
> > +  rtx op1 = expand_promote_outgoing_argument (arg1);
> >    enum insn_code icode = d->icode;
> >    const struct insn_data_d *insn_p = &insn_data[icode];
> >    machine_mode mode0 = insn_p->operand[0].mode;
> > @@ -10916,7 +10916,7 @@ ix86_expand_sse_round (const struct
> builtin_description *d, tree exp,
> >  {
> >    rtx pat;
> >    tree arg0 = CALL_EXPR_ARG (exp, 0);
> > -  rtx op1, op0 = expand_normal (arg0);
> > +  rtx op1, op0 = expand_promote_outgoing_argument (arg0);
> >    machine_mode tmode = insn_data[d->icode].operand[0].mode;
> >    machine_mode mode0 = insn_data[d->icode].operand[1].mode;
> >
> > @@ -10948,8 +10948,8 @@ ix86_expand_sse_round_vec_pack_sfix (const
> struct builtin_description *d,
> >    rtx pat;
> >    tree arg0 = CALL_EXPR_ARG (exp, 0);
> >    tree arg1 = CALL_EXPR_ARG (exp, 1);
> > -  rtx op0 = expand_normal (arg0);
> > -  rtx op1 = expand_normal (arg1);
> > +  rtx op0 = expand_promote_outgoing_argument (arg0);
> > +  rtx op1 = expand_promote_outgoing_argument (arg1);
> >    rtx op2;
> >    machine_mode tmode = insn_data[d->icode].operand[0].mode;
> >    machine_mode mode0 = insn_data[d->icode].operand[1].mode;
> > @@ -10988,8 +10988,8 @@ ix86_expand_sse_ptest (const struct
> builtin_description *d, tree exp,
> >    rtx pat;
> >    tree arg0 = CALL_EXPR_ARG (exp, 0);
> >    tree arg1 = CALL_EXPR_ARG (exp, 1);
> > -  rtx op0 = expand_normal (arg0);
> > -  rtx op1 = expand_normal (arg1);
> > +  rtx op0 = expand_promote_outgoing_argument (arg0);
> > +  rtx op1 = expand_promote_outgoing_argument (arg1);
> >    machine_mode mode0 = insn_data[d->icode].operand[0].mode;
> >    machine_mode mode1 = insn_data[d->icode].operand[1].mode;
> >    enum rtx_code comparison = d->comparison;
> > @@ -11047,11 +11047,11 @@ ix86_expand_sse_pcmpestr (const struct
> builtin_description *d,
> >    tree arg3 = CALL_EXPR_ARG (exp, 3);
> >    tree arg4 = CALL_EXPR_ARG (exp, 4);
> >    rtx scratch0, scratch1;
> > -  rtx op0 = expand_normal (arg0);
> > -  rtx op1 = expand_normal (arg1);
> > -  rtx op2 = expand_normal (arg2);
> > -  rtx op3 = expand_normal (arg3);
> > -  rtx op4 = expand_normal (arg4);
> > +  rtx op0 = expand_promote_outgoing_argument (arg0);
> > +  rtx op1 = expand_promote_outgoing_argument (arg1);
> > +  rtx op2 = expand_promote_outgoing_argument (arg2);
> > +  rtx op3 = expand_promote_outgoing_argument (arg3);
> > +  rtx op4 = expand_promote_outgoing_argument (arg4);
> >    machine_mode tmode0, tmode1, modev2, modei3, modev4, modei5, modeimm;
> >
> >    tmode0 = insn_data[d->icode].operand[0].mode;
> > @@ -11150,9 +11150,9 @@ ix86_expand_sse_pcmpistr (const struct
> builtin_description *d,
> >    tree arg1 = CALL_EXPR_ARG (exp, 1);
> >    tree arg2 = CALL_EXPR_ARG (exp, 2);
> >    rtx scratch0, scratch1;
> > -  rtx op0 = expand_normal (arg0);
> > -  rtx op1 = expand_normal (arg1);
> > -  rtx op2 = expand_normal (arg2);
> > +  rtx op0 = expand_promote_outgoing_argument (arg0);
> > +  rtx op1 = expand_promote_outgoing_argument (arg1);
> > +  rtx op2 = expand_promote_outgoing_argument (arg2);
> >    machine_mode tmode0, tmode1, modev2, modev3, modeimm;
> >
> >    tmode0 = insn_data[d->icode].operand[0].mode;
> > @@ -12135,7 +12135,7 @@ ix86_expand_args_builtin (const struct
> builtin_description *d,
> >    for (i = 0; i < nargs; i++)
> >      {
> >        tree arg = CALL_EXPR_ARG (exp, i);
> > -      rtx op = expand_normal (arg);
> > +      rtx op = expand_promote_outgoing_argument (arg);
> >        machine_mode mode = insn_p->operand[i + 1].mode;
> >        /* Need to fixup modeless constant before testing predicate.  */
> >        op = fixup_modeless_constant (op, mode);
> > @@ -12400,10 +12400,10 @@ ix86_expand_sse_comi_round (const struct
> builtin_description *d,
> >    tree arg1 = CALL_EXPR_ARG (exp, 1);
> >    tree arg2 = CALL_EXPR_ARG (exp, 2);
> >    tree arg3 = CALL_EXPR_ARG (exp, 3);
> > -  rtx op0 = expand_normal (arg0);
> > -  rtx op1 = expand_normal (arg1);
> > -  rtx op2 = expand_normal (arg2);
> > -  rtx op3 = expand_normal (arg3);
> > +  rtx op0 = expand_promote_outgoing_argument (arg0);
> > +  rtx op1 = expand_promote_outgoing_argument (arg1);
> > +  rtx op2 = expand_promote_outgoing_argument (arg2);
> > +  rtx op3 = expand_promote_outgoing_argument (arg3);
> >    enum insn_code icode = d->icode;
> >    const struct insn_data_d *insn_p = &insn_data[icode];
> >    machine_mode mode0 = insn_p->operand[0].mode;
> > @@ -12870,7 +12870,7 @@ ix86_expand_round_builtin (const struct
> builtin_description *d,
> >    for (i = 0; i < nargs; i++)
> >      {
> >        tree arg = CALL_EXPR_ARG (exp, i);
> > -      rtx op = expand_normal (arg);
> > +      rtx op = expand_promote_outgoing_argument (arg);
> >        machine_mode mode = insn_p->operand[i + 1].mode;
> >        bool match = insn_p->operand[i + 1].predicate (op, mode);
> >
> > @@ -13318,7 +13318,7 @@ ix86_expand_special_args_builtin (const struct
> builtin_description *d,
> >    if (klass == store)
> >      {
> >        arg = CALL_EXPR_ARG (exp, 0);
> > -      op = expand_normal (arg);
> > +      op = expand_promote_outgoing_argument (arg);
> >        gcc_assert (target == 0);
> >        if (memory)
> >         {
> > @@ -13355,7 +13355,7 @@ ix86_expand_special_args_builtin (const struct
> builtin_description *d,
> >        machine_mode mode = insn_p->operand[i + 1].mode;
> >
> >        arg = CALL_EXPR_ARG (exp, i + arg_adjust);
> > -      op = expand_normal (arg);
> > +      op = expand_promote_outgoing_argument (arg);
> >
> >        if (i == memory)
> >         {
> > @@ -13479,7 +13479,7 @@ ix86_expand_vec_init_builtin (tree type, tree
> exp, rtx target)
> >
> >    for (i = 0; i < n_elt; ++i)
> >      {
> > -      rtx x = expand_normal (CALL_EXPR_ARG (exp, i));
> > +      rtx x = expand_promote_outgoing_argument (CALL_EXPR_ARG (exp, i));
> >        RTVEC_ELT (v, i) = gen_lowpart (inner_mode, x);
> >      }
> >
> > @@ -13505,7 +13505,7 @@ ix86_expand_vec_ext_builtin (tree exp, rtx
> target)
> >    arg0 = CALL_EXPR_ARG (exp, 0);
> >    arg1 = CALL_EXPR_ARG (exp, 1);
> >
> > -  op0 = expand_normal (arg0);
> > +  op0 = expand_promote_outgoing_argument (arg0);
> >    elt = get_element_number (TREE_TYPE (arg0), arg1);
> >
> >    tmode = TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0)));
> > @@ -13727,9 +13727,9 @@ ix86_expand_builtin (tree exp, rtx target, rtx
> subtarget,
> >        arg1 = CALL_EXPR_ARG (exp, 0);
> >        arg2 = CALL_EXPR_ARG (exp, 1);
> >        arg0 = CALL_EXPR_ARG (exp, 2);
> > -      op0 = expand_normal (arg0);
> > -      op1 = expand_normal (arg1);
> > -      op2 = expand_normal (arg2);
> > +      op0 = expand_promote_outgoing_argument (arg0);
> > +      op1 = expand_promote_outgoing_argument (arg1);
> > +      op2 = expand_promote_outgoing_argument (arg2);
> >        mode0 = insn_data[icode].operand[0].mode;
> >        mode1 = insn_data[icode].operand[1].mode;
> >        mode2 = insn_data[icode].operand[2].mode;
> > @@ -13750,7 +13750,7 @@ ix86_expand_builtin (tree exp, rtx target, rtx
> subtarget,
> >        return 0;
> >
> >      case IX86_BUILTIN_LDMXCSR:
> > -      op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
> > +      op0 = expand_promote_outgoing_argument (CALL_EXPR_ARG (exp, 0));
> >        target = assign_stack_temp (SImode, GET_MODE_SIZE (SImode));
> >        emit_move_insn (target, op0);
> >        emit_insn (gen_sse_ldmxcsr (target));
> > @@ -13763,7 +13763,7 @@ ix86_expand_builtin (tree exp, rtx target, rtx
> subtarget,
> >
> >      case IX86_BUILTIN_CLFLUSH:
> >         arg0 = CALL_EXPR_ARG (exp, 0);
> > -       op0 = expand_normal (arg0);
> > +       op0 = expand_promote_outgoing_argument (arg0);
> >         icode = CODE_FOR_sse2_clflush;
> >         if (!insn_data[icode].operand[0].predicate (op0, Pmode))
> >           op0 = ix86_zero_extend_to_Pmode (op0);
> > @@ -13773,7 +13773,7 @@ ix86_expand_builtin (tree exp, rtx target, rtx
> subtarget,
> >
> >      case IX86_BUILTIN_CLWB:
> >         arg0 = CALL_EXPR_ARG (exp, 0);
> > -       op0 = expand_normal (arg0);
> > +       op0 = expand_promote_outgoing_argument (arg0);
> >         icode = CODE_FOR_clwb;
> >         if (!insn_data[icode].operand[0].predicate (op0, Pmode))
> >           op0 = ix86_zero_extend_to_Pmode (op0);
> > @@ -13783,7 +13783,7 @@ ix86_expand_builtin (tree exp, rtx target, rtx
> subtarget,
> >
> >      case IX86_BUILTIN_CLFLUSHOPT:
> >         arg0 = CALL_EXPR_ARG (exp, 0);
> > -       op0 = expand_normal (arg0);
> > +       op0 = expand_promote_outgoing_argument (arg0);
> >         icode = CODE_FOR_clflushopt;
> >         if (!insn_data[icode].operand[0].predicate (op0, Pmode))
> >           op0 = ix86_zero_extend_to_Pmode (op0);
> > @@ -13796,9 +13796,9 @@ ix86_expand_builtin (tree exp, rtx target, rtx
> subtarget,
> >        arg0 = CALL_EXPR_ARG (exp, 0);
> >        arg1 = CALL_EXPR_ARG (exp, 1);
> >        arg2 = CALL_EXPR_ARG (exp, 2);
> > -      op0 = expand_normal (arg0);
> > -      op1 = expand_normal (arg1);
> > -      op2 = expand_normal (arg2);
> > +      op0 = expand_promote_outgoing_argument (arg0);
> > +      op1 = expand_promote_outgoing_argument (arg1);
> > +      op2 = expand_promote_outgoing_argument (arg2);
> >        if (!REG_P (op0))
> >         op0 = ix86_zero_extend_to_Pmode (op0);
> >        if (!REG_P (op1))
> > @@ -13814,8 +13814,8 @@ ix86_expand_builtin (tree exp, rtx target, rtx
> subtarget,
> >      case IX86_BUILTIN_MWAIT:
> >        arg0 = CALL_EXPR_ARG (exp, 0);
> >        arg1 = CALL_EXPR_ARG (exp, 1);
> > -      op0 = expand_normal (arg0);
> > -      op1 = expand_normal (arg1);
> > +      op0 = expand_promote_outgoing_argument (arg0);
> > +      op1 = expand_promote_outgoing_argument (arg1);
> >        if (!REG_P (op0))
> >         op0 = copy_to_mode_reg (SImode, op0);
> >        if (!REG_P (op1))
> > @@ -13827,9 +13827,9 @@ ix86_expand_builtin (tree exp, rtx target, rtx
> subtarget,
> >        arg0 = CALL_EXPR_ARG (exp, 0);
> >        arg1 = CALL_EXPR_ARG (exp, 1);
> >        arg2 = CALL_EXPR_ARG (exp, 2);
> > -      op0 = expand_normal (arg0);
> > -      op1 = expand_normal (arg1);
> > -      op2 = expand_normal (arg2);
> > +      op0 = expand_promote_outgoing_argument (arg0);
> > +      op1 = expand_promote_outgoing_argument (arg1);
> > +      op2 = expand_promote_outgoing_argument (arg2);
> >        if (!REG_P (op0))
> >         op0 = copy_to_mode_reg (SImode, op0);
> >        if (!REG_P (op1))
> > @@ -13841,7 +13841,7 @@ ix86_expand_builtin (tree exp, rtx target, rtx
> subtarget,
> >
> >      case IX86_BUILTIN_UMONITOR:
> >        arg0 = CALL_EXPR_ARG (exp, 0);
> > -      op0 = expand_normal (arg0);
> > +      op0 = expand_promote_outgoing_argument (arg0);
> >
> >        op0 = ix86_zero_extend_to_Pmode (op0);
> >        emit_insn (gen_umonitor (Pmode, op0));
> > @@ -13851,8 +13851,8 @@ ix86_expand_builtin (tree exp, rtx target, rtx
> subtarget,
> >      case IX86_BUILTIN_TPAUSE:
> >        arg0 = CALL_EXPR_ARG (exp, 0);
> >        arg1 = CALL_EXPR_ARG (exp, 1);
> > -      op0 = expand_normal (arg0);
> > -      op1 = expand_normal (arg1);
> > +      op0 = expand_promote_outgoing_argument (arg0);
> > +      op1 = expand_promote_outgoing_argument (arg1);
> >
> >        if (!REG_P (op0))
> >         op0 = copy_to_mode_reg (SImode, op0);
> > @@ -13925,7 +13925,7 @@ ix86_expand_builtin (tree exp, rtx target, rtx
> subtarget,
> >
> >      case IX86_BUILTIN_CLZERO:
> >        arg0 = CALL_EXPR_ARG (exp, 0);
> > -      op0 = expand_normal (arg0);
> > +      op0 = expand_promote_outgoing_argument (arg0);
> >        if (!REG_P (op0))
> >         op0 = ix86_zero_extend_to_Pmode (op0);
> >        emit_insn (gen_clzero (Pmode, op0));
> > @@ -13933,7 +13933,7 @@ ix86_expand_builtin (tree exp, rtx target, rtx
> subtarget,
> >
> >      case IX86_BUILTIN_CLDEMOTE:
> >        arg0 = CALL_EXPR_ARG (exp, 0);
> > -      op0 = expand_normal (arg0);
> > +      op0 = expand_promote_outgoing_argument (arg0);
> >        icode = CODE_FOR_cldemote;
> >        if (!insn_data[icode].operand[0].predicate (op0, Pmode))
> >         op0 = ix86_zero_extend_to_Pmode (op0);
> > @@ -13948,10 +13948,10 @@ ix86_expand_builtin (tree exp, rtx target, rtx
> subtarget,
> >         arg2 = CALL_EXPR_ARG (exp, 2);
> >         arg3 = CALL_EXPR_ARG (exp, 3);
> >
> > -       op0 = expand_normal (arg0);
> > -       op1 = expand_normal (arg1);
> > -       op2 = expand_normal (arg2);
> > -       op3 = expand_normal (arg3);
> > +       op0 = expand_promote_outgoing_argument (arg0);
> > +       op1 = expand_promote_outgoing_argument (arg1);
> > +       op2 = expand_promote_outgoing_argument (arg2);
> > +       op3 = expand_promote_outgoing_argument (arg3);
> >
> >         if (!REG_P (op0))
> >           op0 = copy_to_mode_reg (V2DImode, op0);
> > @@ -13988,9 +13988,9 @@ ix86_expand_builtin (tree exp, rtx target, rtx
> subtarget,
> >        arg1 = CALL_EXPR_ARG (exp, 1); // __m128i idata
> >        arg2 = CALL_EXPR_ARG (exp, 2); // const void *p
> >
> > -      op0 = expand_normal (arg0);
> > -      op1 = expand_normal (arg1);
> > -      op2 = expand_normal (arg2);
> > +      op0 = expand_promote_outgoing_argument (arg0);
> > +      op1 = expand_promote_outgoing_argument (arg1);
> > +      op2 = expand_promote_outgoing_argument (arg2);
> >
> >        if (!address_operand (op0, V2DImode))
> >         {
> > @@ -14060,9 +14060,9 @@ ix86_expand_builtin (tree exp, rtx target, rtx
> subtarget,
> >        arg1 = CALL_EXPR_ARG (exp, 1); // const __m128i * idata
> >        arg2 = CALL_EXPR_ARG (exp, 2); // const void *p
> >
> > -      op0 = expand_normal (arg0);
> > -      op1 = expand_normal (arg1);
> > -      op2 = expand_normal (arg2);
> > +      op0 = expand_promote_outgoing_argument (arg0);
> > +      op1 = expand_promote_outgoing_argument (arg1);
> > +      op2 = expand_promote_outgoing_argument (arg2);
> >
> >        if (!address_operand (op2, VOIDmode))
> >         {
> > @@ -14116,9 +14116,9 @@ ix86_expand_builtin (tree exp, rtx target, rtx
> subtarget,
> >         arg1 = CALL_EXPR_ARG (exp, 1); // __m128i key
> >         arg2 = CALL_EXPR_ARG (exp, 2); // void *h
> >
> > -       op0 = expand_normal (arg0);
> > -       op1 = expand_normal (arg1);
> > -       op2 = expand_normal (arg2);
> > +       op0 = expand_promote_outgoing_argument (arg0);
> > +       op1 = expand_promote_outgoing_argument (arg1);
> > +       op2 = expand_promote_outgoing_argument (arg2);
> >
> >         if (!REG_P (op0))
> >           op0 = copy_to_mode_reg (SImode, op0);
> > @@ -14152,10 +14152,10 @@ ix86_expand_builtin (tree exp, rtx target, rtx
> subtarget,
> >         arg2 = CALL_EXPR_ARG (exp, 2); // __m128i keyhi
> >         arg3 = CALL_EXPR_ARG (exp, 3); // void *h
> >
> > -       op0 = expand_normal (arg0);
> > -       op1 = expand_normal (arg1);
> > -       op2 = expand_normal (arg2);
> > -       op3 = expand_normal (arg3);
> > +       op0 = expand_promote_outgoing_argument (arg0);
> > +       op1 = expand_promote_outgoing_argument (arg1);
> > +       op2 = expand_promote_outgoing_argument (arg2);
> > +       op3 = expand_promote_outgoing_argument (arg3);
> >
> >         if (!REG_P (op0))
> >           op0 = copy_to_mode_reg (SImode, op0);
> > @@ -14191,10 +14191,10 @@ ix86_expand_builtin (tree exp, rtx target, rtx
> subtarget,
> >         arg2 = CALL_EXPR_ARG (exp, 2); // const int
> >         arg3 = CALL_EXPR_ARG (exp, 3); // const int
> >
> > -       op0 = expand_normal (arg0);
> > -       op1 = expand_normal (arg1);
> > -       op2 = expand_normal (arg2);
> > -       op3 = expand_normal (arg3);
> > +       op0 = expand_promote_outgoing_argument (arg0);
> > +       op1 = expand_promote_outgoing_argument (arg1);
> > +       op2 = expand_promote_outgoing_argument (arg2);
> > +       op3 = expand_promote_outgoing_argument (arg3);
> >
> >         if (!CONST_INT_P (op1) || !CONST_INT_P (op2) || !CONST_INT_P
> (op3))
> >           {
> > @@ -14264,8 +14264,8 @@ ix86_expand_builtin (tree exp, rtx target, rtx
> subtarget,
> >         arg0 = CALL_EXPR_ARG (exp, 0); // const void *
> >         arg1 = CALL_EXPR_ARG (exp, 1); // const int
> >
> > -       op0 = expand_normal (arg0);
> > -       op1 = expand_normal (arg1);
> > +       op0 = expand_promote_outgoing_argument (arg0);
> > +       op1 = expand_promote_outgoing_argument (arg1);
> >
> >         if (!CONST_INT_P (op1))
> >           {
> > @@ -14295,7 +14295,7 @@ ix86_expand_builtin (tree exp, rtx target, rtx
> subtarget,
> >      case IX86_BUILTIN_UWRMSR:
> >        {
> >         arg0 = CALL_EXPR_ARG (exp, 0);
> > -       op0 = expand_normal (arg0);
> > +       op0 = expand_promote_outgoing_argument (arg0);
> >
> >         if (CONST_INT_P (op0))
> >           {
> > @@ -14309,7 +14309,7 @@ ix86_expand_builtin (tree exp, rtx target, rtx
> subtarget,
> >         if (fcode == IX86_BUILTIN_UWRMSR)
> >           {
> >             arg1 = CALL_EXPR_ARG (exp, 1);
> > -           op1 = expand_normal (arg1);
> > +           op1 = expand_promote_outgoing_argument (arg1);
> >             op1 = force_reg (DImode, op1);
> >             icode = CODE_FOR_uwrmsr;
> >             target = 0;
> > @@ -14384,10 +14384,10 @@ ix86_expand_builtin (tree exp, rtx target, rtx
> subtarget,
> >        arg1 = CALL_EXPR_ARG (exp, 1);
> >        arg2 = CALL_EXPR_ARG (exp, 2);
> >        arg3 = CALL_EXPR_ARG (exp, 3);
> > -      op0 = expand_normal (arg0);
> > -      op1 = expand_normal (arg1);
> > -      op2 = expand_normal (arg2);
> > -      op3 = expand_normal (arg3);
> > +      op0 = expand_promote_outgoing_argument (arg0);
> > +      op1 = expand_promote_outgoing_argument (arg1);
> > +      op2 = expand_promote_outgoing_argument (arg2);
> > +      op3 = expand_promote_outgoing_argument (arg3);
> >
> >        if (!address_operand (op0, VOIDmode))
> >         {
> > @@ -14458,7 +14458,7 @@ ix86_expand_builtin (tree exp, rtx target, rtx
> subtarget,
> >        if (fcode == IX86_BUILTIN_RDPMC)
> >         {
> >           arg0 = CALL_EXPR_ARG (exp, 0);
> > -         op2 = expand_normal (arg0);
> > +         op2 = expand_promote_outgoing_argument (arg0);
> >           if (!register_operand (op2, SImode))
> >             op2 = copy_to_mode_reg (SImode, op2);
> >
> > @@ -14470,7 +14470,7 @@ ix86_expand_builtin (tree exp, rtx target, rtx
> subtarget,
> >        else if (fcode == IX86_BUILTIN_XGETBV)
> >         {
> >           arg0 = CALL_EXPR_ARG (exp, 0);
> > -         op2 = expand_normal (arg0);
> > +         op2 = expand_promote_outgoing_argument (arg0);
> >           if (!register_operand (op2, SImode))
> >             op2 = copy_to_mode_reg (SImode, op2);
> >
> > @@ -14496,7 +14496,7 @@ ix86_expand_builtin (tree exp, rtx target, rtx
> subtarget,
> >           emit_insn (insn);
> >
> >           arg0 = CALL_EXPR_ARG (exp, 0);
> > -         op4 = expand_normal (arg0);
> > +         op4 = expand_promote_outgoing_argument (arg0);
> >           if (!address_operand (op4, VOIDmode))
> >             {
> >               op4 = convert_memory_address (Pmode, op4);
> > @@ -14526,8 +14526,8 @@ ix86_expand_builtin (tree exp, rtx target, rtx
> subtarget,
> >
> >        arg0 = CALL_EXPR_ARG (exp, 0);
> >        arg1 = CALL_EXPR_ARG (exp, 1);
> > -      op0 = expand_normal (arg0);
> > -      op1 = expand_normal (arg1);
> > +      op0 = expand_promote_outgoing_argument (arg0);
> > +      op1 = expand_promote_outgoing_argument (arg1);
> >
> >        op0 = ix86_zero_extend_to_Pmode (op0);
> >        if (!address_operand (op1, VOIDmode))
> > @@ -14597,7 +14597,7 @@ ix86_expand_builtin (tree exp, rtx target, rtx
> subtarget,
> >         }
> >
> >        arg0 = CALL_EXPR_ARG (exp, 0);
> > -      op0 = expand_normal (arg0);
> > +      op0 = expand_promote_outgoing_argument (arg0);
> >
> >        if (!address_operand (op0, VOIDmode))
> >         {
> > @@ -14614,8 +14614,8 @@ ix86_expand_builtin (tree exp, rtx target, rtx
> subtarget,
> >      case IX86_BUILTIN_XSETBV:
> >        arg0 = CALL_EXPR_ARG (exp, 0);
> >        arg1 = CALL_EXPR_ARG (exp, 1);
> > -      op0 = expand_normal (arg0);
> > -      op1 = expand_normal (arg1);
> > +      op0 = expand_promote_outgoing_argument (arg0);
> > +      op1 = expand_promote_outgoing_argument (arg1);
> >
> >        if (!REG_P (op0))
> >         op0 = copy_to_mode_reg (SImode, op0);
> > @@ -14657,8 +14657,8 @@ ix86_expand_builtin (tree exp, rtx target, rtx
> subtarget,
> >      case IX86_BUILTIN_XSAVEC64:
> >        arg0 = CALL_EXPR_ARG (exp, 0);
> >        arg1 = CALL_EXPR_ARG (exp, 1);
> > -      op0 = expand_normal (arg0);
> > -      op1 = expand_normal (arg1);
> > +      op0 = expand_promote_outgoing_argument (arg0);
> > +      op1 = expand_promote_outgoing_argument (arg1);
> >
> >        if (!address_operand (op0, VOIDmode))
> >         {
> > @@ -14754,7 +14754,7 @@ ix86_expand_builtin (tree exp, rtx target, rtx
> subtarget,
> >      case IX86_BUILTIN_LDTILECFG:
> >      case IX86_BUILTIN_STTILECFG:
> >        arg0 = CALL_EXPR_ARG (exp, 0);
> > -      op0 = expand_normal (arg0);
> > +      op0 = expand_promote_outgoing_argument (arg0);
> >
> >        if (!address_operand (op0, VOIDmode))
> >         {
> > @@ -14772,7 +14772,7 @@ ix86_expand_builtin (tree exp, rtx target, rtx
> subtarget,
> >
> >      case IX86_BUILTIN_LLWPCB:
> >        arg0 = CALL_EXPR_ARG (exp, 0);
> > -      op0 = expand_normal (arg0);
> > +      op0 = expand_promote_outgoing_argument (arg0);
> >
> >        if (!register_operand (op0, Pmode))
> >         op0 = ix86_zero_extend_to_Pmode (op0);
> > @@ -14803,9 +14803,9 @@ ix86_expand_builtin (tree exp, rtx target, rtx
> subtarget,
> >        arg0 = CALL_EXPR_ARG (exp, 0);
> >        arg1 = CALL_EXPR_ARG (exp, 1);
> >        arg2 = CALL_EXPR_ARG (exp, 2);
> > -      op0 = expand_normal (arg0);
> > -      op1 = expand_normal (arg1);
> > -      op2 = expand_normal (arg2);
> > +      op0 = expand_promote_outgoing_argument (arg0);
> > +      op1 = expand_promote_outgoing_argument (arg1);
> > +      op2 = expand_promote_outgoing_argument (arg2);
> >        mode0 = insn_data[icode].operand[0].mode;
> >
> >        if (!insn_data[icode].operand[0].predicate (op0, mode0))
> > @@ -14843,8 +14843,8 @@ ix86_expand_builtin (tree exp, rtx target, rtx
> subtarget,
> >
> >        arg0 = CALL_EXPR_ARG (exp, 0);
> >        arg1 = CALL_EXPR_ARG (exp, 1);
> > -      op0 = expand_normal (arg0);
> > -      op1 = expand_normal (arg1);
> > +      op0 = expand_promote_outgoing_argument (arg0);
> > +      op1 = expand_promote_outgoing_argument (arg1);
> >
> >        if (!CONST_INT_P (op1))
> >         {
> > @@ -14898,7 +14898,7 @@ ix86_expand_builtin (tree exp, rtx target, rtx
> subtarget,
> >
> >  rdrand_step:
> >        arg0 = CALL_EXPR_ARG (exp, 0);
> > -      op1 = expand_normal (arg0);
> > +      op1 = expand_promote_outgoing_argument (arg0);
> >        if (!address_operand (op1, VOIDmode))
> >         {
> >           op1 = convert_memory_address (Pmode, op1);
> > @@ -14958,7 +14958,7 @@ rdrand_step:
> >
> >  rdseed_step:
> >        arg0 = CALL_EXPR_ARG (exp, 0);
> > -      op1 = expand_normal (arg0);
> > +      op1 = expand_promote_outgoing_argument (arg0);
> >        if (!address_operand (op1, VOIDmode))
> >         {
> >           op1 = convert_memory_address (Pmode, op1);
> > @@ -15020,17 +15020,17 @@ rdseed_step:
> >        arg2 = CALL_EXPR_ARG (exp, 2); /* unsigned int src2.  */
> >        arg3 = CALL_EXPR_ARG (exp, 3); /* unsigned int *sum_out.  */
> >
> > -      op1 = expand_normal (arg0);
> > +      op1 = expand_promote_outgoing_argument (arg0);
> >
> > -      op2 = expand_normal (arg1);
> > +      op2 = expand_promote_outgoing_argument (arg1);
> >        if (!register_operand (op2, mode0))
> >         op2 = copy_to_mode_reg (mode0, op2);
> >
> > -      op3 = expand_normal (arg2);
> > +      op3 = expand_promote_outgoing_argument (arg2);
> >        if (!register_operand (op3, mode0))
> >         op3 = copy_to_mode_reg (mode0, op3);
> >
> > -      op4 = expand_normal (arg3);
> > +      op4 = expand_promote_outgoing_argument (arg3);
> >        if (!address_operand (op4, VOIDmode))
> >         {
> >           op4 = convert_memory_address (Pmode, op4);
> > @@ -15087,7 +15087,7 @@ rdseed_step:
> >      case IX86_BUILTIN_WRITE_FLAGS:
> >
> >        arg0 = CALL_EXPR_ARG (exp, 0);
> > -      op0 = expand_normal (arg0);
> > +      op0 = expand_promote_outgoing_argument (arg0);
> >        if (!general_no_elim_operand (op0, word_mode))
> >         op0 = copy_to_mode_reg (word_mode, op0);
> >
> > @@ -15177,8 +15177,8 @@ rdseed_step:
> >      kortest:
> >        arg0 = CALL_EXPR_ARG (exp, 0); /* Mask reg src1.  */
> >        arg1 = CALL_EXPR_ARG (exp, 1); /* Mask reg src2.  */
> > -      op0 = expand_normal (arg0);
> > -      op1 = expand_normal (arg1);
> > +      op0 = expand_promote_outgoing_argument (arg0);
> > +      op1 = expand_promote_outgoing_argument (arg1);
> >
> >        mode0 = insn_data[icode].operand[0].mode;
> >        mode1 = insn_data[icode].operand[1].mode;
> > @@ -15482,11 +15482,11 @@ rdseed_step:
> >        arg2 = CALL_EXPR_ARG (exp, 2);
> >        arg3 = CALL_EXPR_ARG (exp, 3);
> >        arg4 = CALL_EXPR_ARG (exp, 4);
> > -      op0 = expand_normal (arg0);
> > -      op1 = expand_normal (arg1);
> > -      op2 = expand_normal (arg2);
> > -      op3 = expand_normal (arg3);
> > -      op4 = expand_normal (arg4);
> > +      op0 = expand_promote_outgoing_argument (arg0);
> > +      op1 = expand_promote_outgoing_argument (arg1);
> > +      op2 = expand_promote_outgoing_argument (arg2);
> > +      op3 = expand_promote_outgoing_argument (arg3);
> > +      op4 = expand_promote_outgoing_argument (arg4);
> >        /* Note the arg order is different from the operand order.  */
> >        mode0 = insn_data[icode].operand[1].mode;
> >        mode2 = insn_data[icode].operand[3].mode;
> > @@ -15699,11 +15699,11 @@ rdseed_step:
> >        arg2 = CALL_EXPR_ARG (exp, 2);
> >        arg3 = CALL_EXPR_ARG (exp, 3);
> >        arg4 = CALL_EXPR_ARG (exp, 4);
> > -      op0 = expand_normal (arg0);
> > -      op1 = expand_normal (arg1);
> > -      op2 = expand_normal (arg2);
> > -      op3 = expand_normal (arg3);
> > -      op4 = expand_normal (arg4);
> > +      op0 = expand_promote_outgoing_argument (arg0);
> > +      op1 = expand_promote_outgoing_argument (arg1);
> > +      op2 = expand_promote_outgoing_argument (arg2);
> > +      op3 = expand_promote_outgoing_argument (arg3);
> > +      op4 = expand_promote_outgoing_argument (arg4);
> >        mode1 = insn_data[icode].operand[1].mode;
> >        mode2 = insn_data[icode].operand[2].mode;
> >        mode3 = insn_data[icode].operand[3].mode;
> > @@ -15812,7 +15812,7 @@ rdseed_step:
> >      case IX86_BUILTIN_XABORT:
> >        icode = CODE_FOR_xabort;
> >        arg0 = CALL_EXPR_ARG (exp, 0);
> > -      op0 = expand_normal (arg0);
> > +      op0 = expand_promote_outgoing_argument (arg0);
> >        mode0 = insn_data[icode].operand[0].mode;
> >        if (!insn_data[icode].operand[0].predicate (op0, mode0))
> >         {
> > @@ -15841,7 +15841,7 @@ rdseed_step:
> >        mode = (fcode == IX86_BUILTIN_INCSSPD ? SImode : DImode);
> >
> >        arg0 = CALL_EXPR_ARG (exp, 0);
> > -      op0 = expand_normal (arg0);
> > +      op0 = expand_promote_outgoing_argument (arg0);
> >
> >        op0 = force_reg (mode, op0);
> >
> > @@ -15851,7 +15851,7 @@ rdseed_step:
> >      case IX86_BUILTIN_HRESET:
> >        icode = CODE_FOR_hreset;
> >        arg0 = CALL_EXPR_ARG (exp, 0);
> > -      op0 = expand_normal (arg0);
> > +      op0 = expand_promote_outgoing_argument (arg0);
> >        op0 = force_reg (SImode, op0);
> >        emit_insn (gen_hreset (op0));
> >        return 0;
> > @@ -15859,7 +15859,7 @@ rdseed_step:
> >      case IX86_BUILTIN_RSTORSSP:
> >      case IX86_BUILTIN_CLRSSBSY:
> >        arg0 = CALL_EXPR_ARG (exp, 0);
> > -      op0 = expand_normal (arg0);
> > +      op0 = expand_promote_outgoing_argument (arg0);
> >        icode = (fcode == IX86_BUILTIN_RSTORSSP
> >                ? CODE_FOR_rstorssp
> >                : CODE_FOR_clrssbsy);
> > @@ -15881,9 +15881,9 @@ rdseed_step:
> >               ? SImode : DImode);
> >
> >        arg0 = CALL_EXPR_ARG (exp, 0);
> > -      op0 = expand_normal (arg0);
> > +      op0 = expand_promote_outgoing_argument (arg0);
> >        arg1 = CALL_EXPR_ARG (exp, 1);
> > -      op1 = expand_normal (arg1);
> > +      op1 = expand_promote_outgoing_argument (arg1);
> >
> >        op0 = force_reg (mode, op0);
> >
> > diff --git a/gcc/expr.cc b/gcc/expr.cc
> > index caa1a72ba0b..0a1a70dab3c 100644
> > --- a/gcc/expr.cc
> > +++ b/gcc/expr.cc
> > @@ -14136,3 +14136,21 @@ int_expr_size (const_tree exp)
> >
> >    return tree_to_shwi (size);
> >  }
> > +
> > +/* Expand an outgoing argument ARG with promotion.  Since the C/C++
> > +   frontends no longer promote integer argument smaller than int,
> > +   promote it when expanding built functions.  */
> > +
> > +rtx
> > +expand_promote_outgoing_argument (tree arg)
> > +{
> > +  tree type = TREE_TYPE (arg);
> > +  if (INTEGRAL_TYPE_P (type)
> > +      && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
> > +    {
> > +      tree promoted_type = (TYPE_UNSIGNED (type)
> > +                           ? unsigned_type_node : integer_type_node);
> > +      arg = fold_convert (promoted_type, arg);
> > +    }
> > +  return expand_normal (arg);
> > +}
> > diff --git a/gcc/expr.h b/gcc/expr.h
> > index 04782b15f19..ed14750614b 100644
> > --- a/gcc/expr.h
> > +++ b/gcc/expr.h
> > @@ -312,6 +312,7 @@ extern rtx expand_expr_real_2 (const_sepops, rtx,
> machine_mode,
> >  extern rtx expand_expr_real_gassign (gassign *, rtx, machine_mode,
> >                                      enum expand_modifier modifier,
> >                                      rtx * = nullptr, bool = false);
> > +extern rtx expand_promote_outgoing_argument (tree);
> >
> >  /* Generate code for computing expression EXP.
> >     An rtx for the computed value is returned.  The value is never null.
> > --
> > 2.47.0
> >
>
diff mbox series

Patch

diff --git a/gcc/config/i386/i386-expand.cc b/gcc/config/i386/i386-expand.cc
index 5c4a8e07d62..ce887d96f6a 100644
--- a/gcc/config/i386/i386-expand.cc
+++ b/gcc/config/i386/i386-expand.cc
@@ -10415,8 +10415,8 @@  ix86_expand_binop_builtin (enum insn_code icode, tree exp, rtx target)
   rtx pat;
   tree arg0 = CALL_EXPR_ARG (exp, 0);
   tree arg1 = CALL_EXPR_ARG (exp, 1);
-  rtx op0 = expand_normal (arg0);
-  rtx op1 = expand_normal (arg1);
+  rtx op0 = expand_promote_outgoing_argument (arg0);
+  rtx op1 = expand_promote_outgoing_argument (arg1);
   machine_mode tmode = insn_data[icode].operand[0].mode;
   machine_mode mode0 = insn_data[icode].operand[1].mode;
   machine_mode mode1 = insn_data[icode].operand[2].mode;
@@ -10564,7 +10564,7 @@  ix86_expand_multi_arg_builtin (enum insn_code icode, tree exp, rtx target,
   for (i = 0; i < nargs; i++)
     {
       tree arg = CALL_EXPR_ARG (exp, i);
-      rtx op = expand_normal (arg);
+      rtx op = expand_promote_outgoing_argument (arg);
       int adjust = (comparison_p) ? 1 : 0;
       machine_mode mode = insn_data[icode].operand[i+adjust+1].mode;
 
@@ -10691,7 +10691,7 @@  ix86_expand_unop_vec_merge_builtin (enum insn_code icode, tree exp,
 {
   rtx pat;
   tree arg0 = CALL_EXPR_ARG (exp, 0);
-  rtx op1, op0 = expand_normal (arg0);
+  rtx op1, op0 = expand_promote_outgoing_argument (arg0);
   machine_mode tmode = insn_data[icode].operand[0].mode;
   machine_mode mode0 = insn_data[icode].operand[1].mode;
 
@@ -10727,8 +10727,8 @@  ix86_expand_sse_compare (const struct builtin_description *d,
   rtx pat;
   tree arg0 = CALL_EXPR_ARG (exp, 0);
   tree arg1 = CALL_EXPR_ARG (exp, 1);
-  rtx op0 = expand_normal (arg0);
-  rtx op1 = expand_normal (arg1);
+  rtx op0 = expand_promote_outgoing_argument (arg0);
+  rtx op1 = expand_promote_outgoing_argument (arg1);
   rtx op2;
   machine_mode tmode = insn_data[d->icode].operand[0].mode;
   machine_mode mode0 = insn_data[d->icode].operand[1].mode;
@@ -10823,8 +10823,8 @@  ix86_expand_sse_comi (const struct builtin_description *d, tree exp,
   rtx pat, set_dst;
   tree arg0 = CALL_EXPR_ARG (exp, 0);
   tree arg1 = CALL_EXPR_ARG (exp, 1);
-  rtx op0 = expand_normal (arg0);
-  rtx op1 = expand_normal (arg1);
+  rtx op0 = expand_promote_outgoing_argument (arg0);
+  rtx op1 = expand_promote_outgoing_argument (arg1);
   enum insn_code icode = d->icode;
   const struct insn_data_d *insn_p = &insn_data[icode];
   machine_mode mode0 = insn_p->operand[0].mode;
@@ -10916,7 +10916,7 @@  ix86_expand_sse_round (const struct builtin_description *d, tree exp,
 {
   rtx pat;
   tree arg0 = CALL_EXPR_ARG (exp, 0);
-  rtx op1, op0 = expand_normal (arg0);
+  rtx op1, op0 = expand_promote_outgoing_argument (arg0);
   machine_mode tmode = insn_data[d->icode].operand[0].mode;
   machine_mode mode0 = insn_data[d->icode].operand[1].mode;
 
@@ -10948,8 +10948,8 @@  ix86_expand_sse_round_vec_pack_sfix (const struct builtin_description *d,
   rtx pat;
   tree arg0 = CALL_EXPR_ARG (exp, 0);
   tree arg1 = CALL_EXPR_ARG (exp, 1);
-  rtx op0 = expand_normal (arg0);
-  rtx op1 = expand_normal (arg1);
+  rtx op0 = expand_promote_outgoing_argument (arg0);
+  rtx op1 = expand_promote_outgoing_argument (arg1);
   rtx op2;
   machine_mode tmode = insn_data[d->icode].operand[0].mode;
   machine_mode mode0 = insn_data[d->icode].operand[1].mode;
@@ -10988,8 +10988,8 @@  ix86_expand_sse_ptest (const struct builtin_description *d, tree exp,
   rtx pat;
   tree arg0 = CALL_EXPR_ARG (exp, 0);
   tree arg1 = CALL_EXPR_ARG (exp, 1);
-  rtx op0 = expand_normal (arg0);
-  rtx op1 = expand_normal (arg1);
+  rtx op0 = expand_promote_outgoing_argument (arg0);
+  rtx op1 = expand_promote_outgoing_argument (arg1);
   machine_mode mode0 = insn_data[d->icode].operand[0].mode;
   machine_mode mode1 = insn_data[d->icode].operand[1].mode;
   enum rtx_code comparison = d->comparison;
@@ -11047,11 +11047,11 @@  ix86_expand_sse_pcmpestr (const struct builtin_description *d,
   tree arg3 = CALL_EXPR_ARG (exp, 3);
   tree arg4 = CALL_EXPR_ARG (exp, 4);
   rtx scratch0, scratch1;
-  rtx op0 = expand_normal (arg0);
-  rtx op1 = expand_normal (arg1);
-  rtx op2 = expand_normal (arg2);
-  rtx op3 = expand_normal (arg3);
-  rtx op4 = expand_normal (arg4);
+  rtx op0 = expand_promote_outgoing_argument (arg0);
+  rtx op1 = expand_promote_outgoing_argument (arg1);
+  rtx op2 = expand_promote_outgoing_argument (arg2);
+  rtx op3 = expand_promote_outgoing_argument (arg3);
+  rtx op4 = expand_promote_outgoing_argument (arg4);
   machine_mode tmode0, tmode1, modev2, modei3, modev4, modei5, modeimm;
 
   tmode0 = insn_data[d->icode].operand[0].mode;
@@ -11150,9 +11150,9 @@  ix86_expand_sse_pcmpistr (const struct builtin_description *d,
   tree arg1 = CALL_EXPR_ARG (exp, 1);
   tree arg2 = CALL_EXPR_ARG (exp, 2);
   rtx scratch0, scratch1;
-  rtx op0 = expand_normal (arg0);
-  rtx op1 = expand_normal (arg1);
-  rtx op2 = expand_normal (arg2);
+  rtx op0 = expand_promote_outgoing_argument (arg0);
+  rtx op1 = expand_promote_outgoing_argument (arg1);
+  rtx op2 = expand_promote_outgoing_argument (arg2);
   machine_mode tmode0, tmode1, modev2, modev3, modeimm;
 
   tmode0 = insn_data[d->icode].operand[0].mode;
@@ -12135,7 +12135,7 @@  ix86_expand_args_builtin (const struct builtin_description *d,
   for (i = 0; i < nargs; i++)
     {
       tree arg = CALL_EXPR_ARG (exp, i);
-      rtx op = expand_normal (arg);
+      rtx op = expand_promote_outgoing_argument (arg);
       machine_mode mode = insn_p->operand[i + 1].mode;
       /* Need to fixup modeless constant before testing predicate.  */
       op = fixup_modeless_constant (op, mode);
@@ -12400,10 +12400,10 @@  ix86_expand_sse_comi_round (const struct builtin_description *d,
   tree arg1 = CALL_EXPR_ARG (exp, 1);
   tree arg2 = CALL_EXPR_ARG (exp, 2);
   tree arg3 = CALL_EXPR_ARG (exp, 3);
-  rtx op0 = expand_normal (arg0);
-  rtx op1 = expand_normal (arg1);
-  rtx op2 = expand_normal (arg2);
-  rtx op3 = expand_normal (arg3);
+  rtx op0 = expand_promote_outgoing_argument (arg0);
+  rtx op1 = expand_promote_outgoing_argument (arg1);
+  rtx op2 = expand_promote_outgoing_argument (arg2);
+  rtx op3 = expand_promote_outgoing_argument (arg3);
   enum insn_code icode = d->icode;
   const struct insn_data_d *insn_p = &insn_data[icode];
   machine_mode mode0 = insn_p->operand[0].mode;
@@ -12870,7 +12870,7 @@  ix86_expand_round_builtin (const struct builtin_description *d,
   for (i = 0; i < nargs; i++)
     {
       tree arg = CALL_EXPR_ARG (exp, i);
-      rtx op = expand_normal (arg);
+      rtx op = expand_promote_outgoing_argument (arg);
       machine_mode mode = insn_p->operand[i + 1].mode;
       bool match = insn_p->operand[i + 1].predicate (op, mode);
 
@@ -13318,7 +13318,7 @@  ix86_expand_special_args_builtin (const struct builtin_description *d,
   if (klass == store)
     {
       arg = CALL_EXPR_ARG (exp, 0);
-      op = expand_normal (arg);
+      op = expand_promote_outgoing_argument (arg);
       gcc_assert (target == 0);
       if (memory)
 	{
@@ -13355,7 +13355,7 @@  ix86_expand_special_args_builtin (const struct builtin_description *d,
       machine_mode mode = insn_p->operand[i + 1].mode;
 
       arg = CALL_EXPR_ARG (exp, i + arg_adjust);
-      op = expand_normal (arg);
+      op = expand_promote_outgoing_argument (arg);
 
       if (i == memory)
 	{
@@ -13479,7 +13479,7 @@  ix86_expand_vec_init_builtin (tree type, tree exp, rtx target)
 
   for (i = 0; i < n_elt; ++i)
     {
-      rtx x = expand_normal (CALL_EXPR_ARG (exp, i));
+      rtx x = expand_promote_outgoing_argument (CALL_EXPR_ARG (exp, i));
       RTVEC_ELT (v, i) = gen_lowpart (inner_mode, x);
     }
 
@@ -13505,7 +13505,7 @@  ix86_expand_vec_ext_builtin (tree exp, rtx target)
   arg0 = CALL_EXPR_ARG (exp, 0);
   arg1 = CALL_EXPR_ARG (exp, 1);
 
-  op0 = expand_normal (arg0);
+  op0 = expand_promote_outgoing_argument (arg0);
   elt = get_element_number (TREE_TYPE (arg0), arg1);
 
   tmode = TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0)));
@@ -13727,9 +13727,9 @@  ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
       arg1 = CALL_EXPR_ARG (exp, 0);
       arg2 = CALL_EXPR_ARG (exp, 1);
       arg0 = CALL_EXPR_ARG (exp, 2);
-      op0 = expand_normal (arg0);
-      op1 = expand_normal (arg1);
-      op2 = expand_normal (arg2);
+      op0 = expand_promote_outgoing_argument (arg0);
+      op1 = expand_promote_outgoing_argument (arg1);
+      op2 = expand_promote_outgoing_argument (arg2);
       mode0 = insn_data[icode].operand[0].mode;
       mode1 = insn_data[icode].operand[1].mode;
       mode2 = insn_data[icode].operand[2].mode;
@@ -13750,7 +13750,7 @@  ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
       return 0;
 
     case IX86_BUILTIN_LDMXCSR:
-      op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
+      op0 = expand_promote_outgoing_argument (CALL_EXPR_ARG (exp, 0));
       target = assign_stack_temp (SImode, GET_MODE_SIZE (SImode));
       emit_move_insn (target, op0);
       emit_insn (gen_sse_ldmxcsr (target));
@@ -13763,7 +13763,7 @@  ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
 
     case IX86_BUILTIN_CLFLUSH:
 	arg0 = CALL_EXPR_ARG (exp, 0);
-	op0 = expand_normal (arg0);
+	op0 = expand_promote_outgoing_argument (arg0);
 	icode = CODE_FOR_sse2_clflush;
 	if (!insn_data[icode].operand[0].predicate (op0, Pmode))
 	  op0 = ix86_zero_extend_to_Pmode (op0);
@@ -13773,7 +13773,7 @@  ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
 
     case IX86_BUILTIN_CLWB:
 	arg0 = CALL_EXPR_ARG (exp, 0);
-	op0 = expand_normal (arg0);
+	op0 = expand_promote_outgoing_argument (arg0);
 	icode = CODE_FOR_clwb;
 	if (!insn_data[icode].operand[0].predicate (op0, Pmode))
 	  op0 = ix86_zero_extend_to_Pmode (op0);
@@ -13783,7 +13783,7 @@  ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
 
     case IX86_BUILTIN_CLFLUSHOPT:
 	arg0 = CALL_EXPR_ARG (exp, 0);
-	op0 = expand_normal (arg0);
+	op0 = expand_promote_outgoing_argument (arg0);
 	icode = CODE_FOR_clflushopt;
 	if (!insn_data[icode].operand[0].predicate (op0, Pmode))
 	  op0 = ix86_zero_extend_to_Pmode (op0);
@@ -13796,9 +13796,9 @@  ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
       arg0 = CALL_EXPR_ARG (exp, 0);
       arg1 = CALL_EXPR_ARG (exp, 1);
       arg2 = CALL_EXPR_ARG (exp, 2);
-      op0 = expand_normal (arg0);
-      op1 = expand_normal (arg1);
-      op2 = expand_normal (arg2);
+      op0 = expand_promote_outgoing_argument (arg0);
+      op1 = expand_promote_outgoing_argument (arg1);
+      op2 = expand_promote_outgoing_argument (arg2);
       if (!REG_P (op0))
 	op0 = ix86_zero_extend_to_Pmode (op0);
       if (!REG_P (op1))
@@ -13814,8 +13814,8 @@  ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
     case IX86_BUILTIN_MWAIT:
       arg0 = CALL_EXPR_ARG (exp, 0);
       arg1 = CALL_EXPR_ARG (exp, 1);
-      op0 = expand_normal (arg0);
-      op1 = expand_normal (arg1);
+      op0 = expand_promote_outgoing_argument (arg0);
+      op1 = expand_promote_outgoing_argument (arg1);
       if (!REG_P (op0))
 	op0 = copy_to_mode_reg (SImode, op0);
       if (!REG_P (op1))
@@ -13827,9 +13827,9 @@  ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
       arg0 = CALL_EXPR_ARG (exp, 0);
       arg1 = CALL_EXPR_ARG (exp, 1);
       arg2 = CALL_EXPR_ARG (exp, 2);
-      op0 = expand_normal (arg0);
-      op1 = expand_normal (arg1);
-      op2 = expand_normal (arg2);
+      op0 = expand_promote_outgoing_argument (arg0);
+      op1 = expand_promote_outgoing_argument (arg1);
+      op2 = expand_promote_outgoing_argument (arg2);
       if (!REG_P (op0))
 	op0 = copy_to_mode_reg (SImode, op0);
       if (!REG_P (op1))
@@ -13841,7 +13841,7 @@  ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
 
     case IX86_BUILTIN_UMONITOR:
       arg0 = CALL_EXPR_ARG (exp, 0);
-      op0 = expand_normal (arg0);
+      op0 = expand_promote_outgoing_argument (arg0);
 
       op0 = ix86_zero_extend_to_Pmode (op0);
       emit_insn (gen_umonitor (Pmode, op0));
@@ -13851,8 +13851,8 @@  ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
     case IX86_BUILTIN_TPAUSE:
       arg0 = CALL_EXPR_ARG (exp, 0);
       arg1 = CALL_EXPR_ARG (exp, 1);
-      op0 = expand_normal (arg0);
-      op1 = expand_normal (arg1);
+      op0 = expand_promote_outgoing_argument (arg0);
+      op1 = expand_promote_outgoing_argument (arg1);
 
       if (!REG_P (op0))
 	op0 = copy_to_mode_reg (SImode, op0);
@@ -13925,7 +13925,7 @@  ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
 
     case IX86_BUILTIN_CLZERO:
       arg0 = CALL_EXPR_ARG (exp, 0);
-      op0 = expand_normal (arg0);
+      op0 = expand_promote_outgoing_argument (arg0);
       if (!REG_P (op0))
 	op0 = ix86_zero_extend_to_Pmode (op0);
       emit_insn (gen_clzero (Pmode, op0));
@@ -13933,7 +13933,7 @@  ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
 
     case IX86_BUILTIN_CLDEMOTE:
       arg0 = CALL_EXPR_ARG (exp, 0);
-      op0 = expand_normal (arg0);
+      op0 = expand_promote_outgoing_argument (arg0);
       icode = CODE_FOR_cldemote;
       if (!insn_data[icode].operand[0].predicate (op0, Pmode))
 	op0 = ix86_zero_extend_to_Pmode (op0);
@@ -13948,10 +13948,10 @@  ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
 	arg2 = CALL_EXPR_ARG (exp, 2);
 	arg3 = CALL_EXPR_ARG (exp, 3);
 
-	op0 = expand_normal (arg0);
-	op1 = expand_normal (arg1);
-	op2 = expand_normal (arg2);
-	op3 = expand_normal (arg3);
+	op0 = expand_promote_outgoing_argument (arg0);
+	op1 = expand_promote_outgoing_argument (arg1);
+	op2 = expand_promote_outgoing_argument (arg2);
+	op3 = expand_promote_outgoing_argument (arg3);
 
 	if (!REG_P (op0))
 	  op0 = copy_to_mode_reg (V2DImode, op0);
@@ -13988,9 +13988,9 @@  ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
       arg1 = CALL_EXPR_ARG (exp, 1); // __m128i idata
       arg2 = CALL_EXPR_ARG (exp, 2); // const void *p
 
-      op0 = expand_normal (arg0);
-      op1 = expand_normal (arg1);
-      op2 = expand_normal (arg2);
+      op0 = expand_promote_outgoing_argument (arg0);
+      op1 = expand_promote_outgoing_argument (arg1);
+      op2 = expand_promote_outgoing_argument (arg2);
 
       if (!address_operand (op0, V2DImode))
 	{
@@ -14060,9 +14060,9 @@  ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
       arg1 = CALL_EXPR_ARG (exp, 1); // const __m128i * idata
       arg2 = CALL_EXPR_ARG (exp, 2); // const void *p
 
-      op0 = expand_normal (arg0);
-      op1 = expand_normal (arg1);
-      op2 = expand_normal (arg2);
+      op0 = expand_promote_outgoing_argument (arg0);
+      op1 = expand_promote_outgoing_argument (arg1);
+      op2 = expand_promote_outgoing_argument (arg2);
 
       if (!address_operand (op2, VOIDmode))
 	{
@@ -14116,9 +14116,9 @@  ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
 	arg1 = CALL_EXPR_ARG (exp, 1); // __m128i key
 	arg2 = CALL_EXPR_ARG (exp, 2); // void *h
 
-	op0 = expand_normal (arg0);
-	op1 = expand_normal (arg1);
-	op2 = expand_normal (arg2);
+	op0 = expand_promote_outgoing_argument (arg0);
+	op1 = expand_promote_outgoing_argument (arg1);
+	op2 = expand_promote_outgoing_argument (arg2);
 
 	if (!REG_P (op0))
 	  op0 = copy_to_mode_reg (SImode, op0);
@@ -14152,10 +14152,10 @@  ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
 	arg2 = CALL_EXPR_ARG (exp, 2); // __m128i keyhi
 	arg3 = CALL_EXPR_ARG (exp, 3); // void *h
 
-	op0 = expand_normal (arg0);
-	op1 = expand_normal (arg1);
-	op2 = expand_normal (arg2);
-	op3 = expand_normal (arg3);
+	op0 = expand_promote_outgoing_argument (arg0);
+	op1 = expand_promote_outgoing_argument (arg1);
+	op2 = expand_promote_outgoing_argument (arg2);
+	op3 = expand_promote_outgoing_argument (arg3);
 
 	if (!REG_P (op0))
 	  op0 = copy_to_mode_reg (SImode, op0);
@@ -14191,10 +14191,10 @@  ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
 	arg2 = CALL_EXPR_ARG (exp, 2); // const int
 	arg3 = CALL_EXPR_ARG (exp, 3); // const int
 
-	op0 = expand_normal (arg0);
-	op1 = expand_normal (arg1);
-	op2 = expand_normal (arg2);
-	op3 = expand_normal (arg3);
+	op0 = expand_promote_outgoing_argument (arg0);
+	op1 = expand_promote_outgoing_argument (arg1);
+	op2 = expand_promote_outgoing_argument (arg2);
+	op3 = expand_promote_outgoing_argument (arg3);
 
 	if (!CONST_INT_P (op1) || !CONST_INT_P (op2) || !CONST_INT_P (op3))
 	  {
@@ -14264,8 +14264,8 @@  ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
 	arg0 = CALL_EXPR_ARG (exp, 0); // const void *
 	arg1 = CALL_EXPR_ARG (exp, 1); // const int
 
-	op0 = expand_normal (arg0);
-	op1 = expand_normal (arg1);
+	op0 = expand_promote_outgoing_argument (arg0);
+	op1 = expand_promote_outgoing_argument (arg1);
 
 	if (!CONST_INT_P (op1))
 	  {
@@ -14295,7 +14295,7 @@  ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
     case IX86_BUILTIN_UWRMSR:
       {
 	arg0 = CALL_EXPR_ARG (exp, 0);
-	op0 = expand_normal (arg0);
+	op0 = expand_promote_outgoing_argument (arg0);
 
 	if (CONST_INT_P (op0))
 	  {
@@ -14309,7 +14309,7 @@  ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
 	if (fcode == IX86_BUILTIN_UWRMSR)
 	  {
 	    arg1 = CALL_EXPR_ARG (exp, 1);
-	    op1 = expand_normal (arg1);
+	    op1 = expand_promote_outgoing_argument (arg1);
 	    op1 = force_reg (DImode, op1);
 	    icode = CODE_FOR_uwrmsr;
 	    target = 0;
@@ -14384,10 +14384,10 @@  ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
       arg1 = CALL_EXPR_ARG (exp, 1);
       arg2 = CALL_EXPR_ARG (exp, 2);
       arg3 = CALL_EXPR_ARG (exp, 3);
-      op0 = expand_normal (arg0);
-      op1 = expand_normal (arg1);
-      op2 = expand_normal (arg2);
-      op3 = expand_normal (arg3);
+      op0 = expand_promote_outgoing_argument (arg0);
+      op1 = expand_promote_outgoing_argument (arg1);
+      op2 = expand_promote_outgoing_argument (arg2);
+      op3 = expand_promote_outgoing_argument (arg3);
 
       if (!address_operand (op0, VOIDmode))
 	{
@@ -14458,7 +14458,7 @@  ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
       if (fcode == IX86_BUILTIN_RDPMC)
 	{
 	  arg0 = CALL_EXPR_ARG (exp, 0);
-	  op2 = expand_normal (arg0);
+	  op2 = expand_promote_outgoing_argument (arg0);
 	  if (!register_operand (op2, SImode))
 	    op2 = copy_to_mode_reg (SImode, op2);
 
@@ -14470,7 +14470,7 @@  ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
       else if (fcode == IX86_BUILTIN_XGETBV)
 	{
 	  arg0 = CALL_EXPR_ARG (exp, 0);
-	  op2 = expand_normal (arg0);
+	  op2 = expand_promote_outgoing_argument (arg0);
 	  if (!register_operand (op2, SImode))
 	    op2 = copy_to_mode_reg (SImode, op2);
 
@@ -14496,7 +14496,7 @@  ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
 	  emit_insn (insn);
 
 	  arg0 = CALL_EXPR_ARG (exp, 0);
-	  op4 = expand_normal (arg0);
+	  op4 = expand_promote_outgoing_argument (arg0);
 	  if (!address_operand (op4, VOIDmode))
 	    {
 	      op4 = convert_memory_address (Pmode, op4);
@@ -14526,8 +14526,8 @@  ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
 
       arg0 = CALL_EXPR_ARG (exp, 0);
       arg1 = CALL_EXPR_ARG (exp, 1);
-      op0 = expand_normal (arg0);
-      op1 = expand_normal (arg1);
+      op0 = expand_promote_outgoing_argument (arg0);
+      op1 = expand_promote_outgoing_argument (arg1);
 
       op0 = ix86_zero_extend_to_Pmode (op0);
       if (!address_operand (op1, VOIDmode))
@@ -14597,7 +14597,7 @@  ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
 	}
 
       arg0 = CALL_EXPR_ARG (exp, 0);
-      op0 = expand_normal (arg0);
+      op0 = expand_promote_outgoing_argument (arg0);
 
       if (!address_operand (op0, VOIDmode))
 	{
@@ -14614,8 +14614,8 @@  ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
     case IX86_BUILTIN_XSETBV:
       arg0 = CALL_EXPR_ARG (exp, 0);
       arg1 = CALL_EXPR_ARG (exp, 1);
-      op0 = expand_normal (arg0);
-      op1 = expand_normal (arg1);
+      op0 = expand_promote_outgoing_argument (arg0);
+      op1 = expand_promote_outgoing_argument (arg1);
 
       if (!REG_P (op0))
 	op0 = copy_to_mode_reg (SImode, op0);
@@ -14657,8 +14657,8 @@  ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
     case IX86_BUILTIN_XSAVEC64:
       arg0 = CALL_EXPR_ARG (exp, 0);
       arg1 = CALL_EXPR_ARG (exp, 1);
-      op0 = expand_normal (arg0);
-      op1 = expand_normal (arg1);
+      op0 = expand_promote_outgoing_argument (arg0);
+      op1 = expand_promote_outgoing_argument (arg1);
 
       if (!address_operand (op0, VOIDmode))
 	{
@@ -14754,7 +14754,7 @@  ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
     case IX86_BUILTIN_LDTILECFG:
     case IX86_BUILTIN_STTILECFG:
       arg0 = CALL_EXPR_ARG (exp, 0);
-      op0 = expand_normal (arg0);
+      op0 = expand_promote_outgoing_argument (arg0);
 
       if (!address_operand (op0, VOIDmode))
 	{
@@ -14772,7 +14772,7 @@  ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
 
     case IX86_BUILTIN_LLWPCB:
       arg0 = CALL_EXPR_ARG (exp, 0);
-      op0 = expand_normal (arg0);
+      op0 = expand_promote_outgoing_argument (arg0);
 
       if (!register_operand (op0, Pmode))
 	op0 = ix86_zero_extend_to_Pmode (op0);
@@ -14803,9 +14803,9 @@  ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
       arg0 = CALL_EXPR_ARG (exp, 0);
       arg1 = CALL_EXPR_ARG (exp, 1);
       arg2 = CALL_EXPR_ARG (exp, 2);
-      op0 = expand_normal (arg0);
-      op1 = expand_normal (arg1);
-      op2 = expand_normal (arg2);
+      op0 = expand_promote_outgoing_argument (arg0);
+      op1 = expand_promote_outgoing_argument (arg1);
+      op2 = expand_promote_outgoing_argument (arg2);
       mode0 = insn_data[icode].operand[0].mode;
 
       if (!insn_data[icode].operand[0].predicate (op0, mode0))
@@ -14843,8 +14843,8 @@  ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
 
       arg0 = CALL_EXPR_ARG (exp, 0);
       arg1 = CALL_EXPR_ARG (exp, 1);
-      op0 = expand_normal (arg0);
-      op1 = expand_normal (arg1);
+      op0 = expand_promote_outgoing_argument (arg0);
+      op1 = expand_promote_outgoing_argument (arg1);
 
       if (!CONST_INT_P (op1))
 	{
@@ -14898,7 +14898,7 @@  ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
 
 rdrand_step:
       arg0 = CALL_EXPR_ARG (exp, 0);
-      op1 = expand_normal (arg0);
+      op1 = expand_promote_outgoing_argument (arg0);
       if (!address_operand (op1, VOIDmode))
 	{
 	  op1 = convert_memory_address (Pmode, op1);
@@ -14958,7 +14958,7 @@  rdrand_step:
 
 rdseed_step:
       arg0 = CALL_EXPR_ARG (exp, 0);
-      op1 = expand_normal (arg0);
+      op1 = expand_promote_outgoing_argument (arg0);
       if (!address_operand (op1, VOIDmode))
 	{
 	  op1 = convert_memory_address (Pmode, op1);
@@ -15020,17 +15020,17 @@  rdseed_step:
       arg2 = CALL_EXPR_ARG (exp, 2); /* unsigned int src2.  */
       arg3 = CALL_EXPR_ARG (exp, 3); /* unsigned int *sum_out.  */
 
-      op1 = expand_normal (arg0);
+      op1 = expand_promote_outgoing_argument (arg0);
 
-      op2 = expand_normal (arg1);
+      op2 = expand_promote_outgoing_argument (arg1);
       if (!register_operand (op2, mode0))
 	op2 = copy_to_mode_reg (mode0, op2);
 
-      op3 = expand_normal (arg2);
+      op3 = expand_promote_outgoing_argument (arg2);
       if (!register_operand (op3, mode0))
 	op3 = copy_to_mode_reg (mode0, op3);
 
-      op4 = expand_normal (arg3);
+      op4 = expand_promote_outgoing_argument (arg3);
       if (!address_operand (op4, VOIDmode))
 	{
 	  op4 = convert_memory_address (Pmode, op4);
@@ -15087,7 +15087,7 @@  rdseed_step:
     case IX86_BUILTIN_WRITE_FLAGS:
 
       arg0 = CALL_EXPR_ARG (exp, 0);
-      op0 = expand_normal (arg0);
+      op0 = expand_promote_outgoing_argument (arg0);
       if (!general_no_elim_operand (op0, word_mode))
 	op0 = copy_to_mode_reg (word_mode, op0);
 
@@ -15177,8 +15177,8 @@  rdseed_step:
     kortest:
       arg0 = CALL_EXPR_ARG (exp, 0); /* Mask reg src1.  */
       arg1 = CALL_EXPR_ARG (exp, 1); /* Mask reg src2.  */
-      op0 = expand_normal (arg0);
-      op1 = expand_normal (arg1);
+      op0 = expand_promote_outgoing_argument (arg0);
+      op1 = expand_promote_outgoing_argument (arg1);
 
       mode0 = insn_data[icode].operand[0].mode;
       mode1 = insn_data[icode].operand[1].mode;
@@ -15482,11 +15482,11 @@  rdseed_step:
       arg2 = CALL_EXPR_ARG (exp, 2);
       arg3 = CALL_EXPR_ARG (exp, 3);
       arg4 = CALL_EXPR_ARG (exp, 4);
-      op0 = expand_normal (arg0);
-      op1 = expand_normal (arg1);
-      op2 = expand_normal (arg2);
-      op3 = expand_normal (arg3);
-      op4 = expand_normal (arg4);
+      op0 = expand_promote_outgoing_argument (arg0);
+      op1 = expand_promote_outgoing_argument (arg1);
+      op2 = expand_promote_outgoing_argument (arg2);
+      op3 = expand_promote_outgoing_argument (arg3);
+      op4 = expand_promote_outgoing_argument (arg4);
       /* Note the arg order is different from the operand order.  */
       mode0 = insn_data[icode].operand[1].mode;
       mode2 = insn_data[icode].operand[3].mode;
@@ -15699,11 +15699,11 @@  rdseed_step:
       arg2 = CALL_EXPR_ARG (exp, 2);
       arg3 = CALL_EXPR_ARG (exp, 3);
       arg4 = CALL_EXPR_ARG (exp, 4);
-      op0 = expand_normal (arg0);
-      op1 = expand_normal (arg1);
-      op2 = expand_normal (arg2);
-      op3 = expand_normal (arg3);
-      op4 = expand_normal (arg4);
+      op0 = expand_promote_outgoing_argument (arg0);
+      op1 = expand_promote_outgoing_argument (arg1);
+      op2 = expand_promote_outgoing_argument (arg2);
+      op3 = expand_promote_outgoing_argument (arg3);
+      op4 = expand_promote_outgoing_argument (arg4);
       mode1 = insn_data[icode].operand[1].mode;
       mode2 = insn_data[icode].operand[2].mode;
       mode3 = insn_data[icode].operand[3].mode;
@@ -15812,7 +15812,7 @@  rdseed_step:
     case IX86_BUILTIN_XABORT:
       icode = CODE_FOR_xabort;
       arg0 = CALL_EXPR_ARG (exp, 0);
-      op0 = expand_normal (arg0);
+      op0 = expand_promote_outgoing_argument (arg0);
       mode0 = insn_data[icode].operand[0].mode;
       if (!insn_data[icode].operand[0].predicate (op0, mode0))
 	{
@@ -15841,7 +15841,7 @@  rdseed_step:
       mode = (fcode == IX86_BUILTIN_INCSSPD ? SImode : DImode);
 
       arg0 = CALL_EXPR_ARG (exp, 0);
-      op0 = expand_normal (arg0);
+      op0 = expand_promote_outgoing_argument (arg0);
 
       op0 = force_reg (mode, op0);
 
@@ -15851,7 +15851,7 @@  rdseed_step:
     case IX86_BUILTIN_HRESET:
       icode = CODE_FOR_hreset;
       arg0 = CALL_EXPR_ARG (exp, 0);
-      op0 = expand_normal (arg0);
+      op0 = expand_promote_outgoing_argument (arg0);
       op0 = force_reg (SImode, op0);
       emit_insn (gen_hreset (op0));
       return 0;
@@ -15859,7 +15859,7 @@  rdseed_step:
     case IX86_BUILTIN_RSTORSSP:
     case IX86_BUILTIN_CLRSSBSY:
       arg0 = CALL_EXPR_ARG (exp, 0);
-      op0 = expand_normal (arg0);
+      op0 = expand_promote_outgoing_argument (arg0);
       icode = (fcode == IX86_BUILTIN_RSTORSSP
 	       ? CODE_FOR_rstorssp
 	       : CODE_FOR_clrssbsy);
@@ -15881,9 +15881,9 @@  rdseed_step:
 	      ? SImode : DImode);
 
       arg0 = CALL_EXPR_ARG (exp, 0);
-      op0 = expand_normal (arg0);
+      op0 = expand_promote_outgoing_argument (arg0);
       arg1 = CALL_EXPR_ARG (exp, 1);
-      op1 = expand_normal (arg1);
+      op1 = expand_promote_outgoing_argument (arg1);
 
       op0 = force_reg (mode, op0);
 
diff --git a/gcc/expr.cc b/gcc/expr.cc
index caa1a72ba0b..0a1a70dab3c 100644
--- a/gcc/expr.cc
+++ b/gcc/expr.cc
@@ -14136,3 +14136,21 @@  int_expr_size (const_tree exp)
 
   return tree_to_shwi (size);
 }
+
+/* Expand an outgoing argument ARG with promotion.  Since the C/C++
+   frontends no longer promote integer argument smaller than int,
+   promote it when expanding built functions.  */
+
+rtx
+expand_promote_outgoing_argument (tree arg)
+{
+  tree type = TREE_TYPE (arg);
+  if (INTEGRAL_TYPE_P (type)
+      && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
+    {
+      tree promoted_type = (TYPE_UNSIGNED (type)
+			    ? unsigned_type_node : integer_type_node);
+      arg = fold_convert (promoted_type, arg);
+    }
+  return expand_normal (arg);
+}
diff --git a/gcc/expr.h b/gcc/expr.h
index 04782b15f19..ed14750614b 100644
--- a/gcc/expr.h
+++ b/gcc/expr.h
@@ -312,6 +312,7 @@  extern rtx expand_expr_real_2 (const_sepops, rtx, machine_mode,
 extern rtx expand_expr_real_gassign (gassign *, rtx, machine_mode,
 				     enum expand_modifier modifier,
 				     rtx * = nullptr, bool = false);
+extern rtx expand_promote_outgoing_argument (tree);
 
 /* Generate code for computing expression EXP.
    An rtx for the computed value is returned.  The value is never null.