On Fri, 6 Jun 2025, Jakub Jelinek wrote: > Hi! > > On top of the just posted patch, the following patch attempts to > use value range to see if MSB is known to be false and for scalar integral > extension in that case tries to expand both sign and zero extension and > chooses based on RTX costs the cheaper one (if the costs are the same > uses what it used before, TYPE_UNSIGNED (TREE_TYPE (treeop0)) based. > > The patch regresses the gcc.target/i386/pr78103-3.c test, will post > a separate patch for that momentarily (with the intent that if all 3 > patches are approved, I'll commit the PR78103 related one before this one). > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
This is OK when we settle on the prerequesite. Richard. > 2025-06-06 Jakub Jelinek <ja...@redhat.com> > > PR middle-end/120434 > * expr.cc (expand_expr_real_2) <CASE_CONVERT>: If get_range_pos_neg > at -O2 for scalar integer extension suggests the most significant > bit of op0 is not set, try both unsigned and signed conversion and > choose the cheaper one. If both are the same cost, choose one > based on TYPE_UNSIGNED (TREE_TYPE (treeop0)). > > * gcc.target/i386/pr120434-2.c: New test. > > --- gcc/expr.cc.jj 2025-06-05 10:36:06.545069723 +0200 > +++ gcc/expr.cc 2025-06-05 19:14:45.601489036 +0200 > @@ -9885,14 +9885,68 @@ expand_expr_real_2 (const_sepops ops, rt > op0 = gen_rtx_fmt_e (TYPE_UNSIGNED (TREE_TYPE (treeop0)) > ? ZERO_EXTEND : SIGN_EXTEND, mode, op0); > > + else if (SCALAR_INT_MODE_P (GET_MODE (op0)) > + && optimize >= 2 > + && SCALAR_INT_MODE_P (mode) > + && (GET_MODE_SIZE (as_a <scalar_int_mode> (mode)) > + > GET_MODE_SIZE (as_a <scalar_int_mode> (GET_MODE (op0)))) > + && get_range_pos_neg (treeop0, > + currently_expanding_gimple_stmt) == 1) > + { > + /* If argument is known to be positive when interpreted > + as signed, we can expand it as both sign and zero > + extension. Choose the cheaper sequence in that case. */ > + bool speed_p = optimize_insn_for_speed_p (); > + rtx uns_ret = NULL_RTX, sgn_ret = NULL_RTX; > + do_pending_stack_adjust (); > + start_sequence (); > + if (target == NULL_RTX) > + uns_ret = convert_to_mode (mode, op0, 1); > + else > + convert_move (target, op0, 1); > + rtx_insn *uns_insns = end_sequence (); > + start_sequence (); > + if (target == NULL_RTX) > + sgn_ret = convert_to_mode (mode, op0, 0); > + else > + convert_move (target, op0, 0); > + rtx_insn *sgn_insns = end_sequence (); > + unsigned uns_cost = seq_cost (uns_insns, speed_p); > + unsigned sgn_cost = seq_cost (sgn_insns, speed_p); > + bool was_tie = false; > + > + /* If costs are the same then use as tie breaker the other other > + factor. */ > + if (uns_cost == sgn_cost) > + { > + uns_cost = seq_cost (uns_insns, !speed_p); > + sgn_cost = seq_cost (sgn_insns, !speed_p); > + was_tie = true; > + } > + > + if (dump_file && (dump_flags & TDF_DETAILS)) > + fprintf (dump_file, ";; positive extension:%s unsigned cost: %u; " > + "signed cost: %u\n", > + was_tie ? " (needed tie breaker)" : "", > + uns_cost, sgn_cost); > + if (uns_cost < sgn_cost > + || (uns_cost == sgn_cost && TYPE_UNSIGNED (TREE_TYPE (treeop0)))) > + { > + emit_insn (uns_insns); > + sgn_ret = uns_ret; > + } > + else > + emit_insn (sgn_insns); > + if (target == NULL_RTX) > + op0 = sgn_ret; > + else > + op0 = target; > + } > else if (target == 0) > - op0 = convert_to_mode (mode, op0, > - TYPE_UNSIGNED (TREE_TYPE > - (treeop0))); > + op0 = convert_to_mode (mode, op0, TYPE_UNSIGNED (TREE_TYPE (treeop0))); > else > { > - convert_move (target, op0, > - TYPE_UNSIGNED (TREE_TYPE (treeop0))); > + convert_move (target, op0, TYPE_UNSIGNED (TREE_TYPE (treeop0))); > op0 = target; > } > > --- gcc/testsuite/gcc.target/i386/pr120434-2.c.jj 2025-06-06 > 11:41:49.829197752 +0200 > +++ gcc/testsuite/gcc.target/i386/pr120434-2.c 2025-06-06 > 11:40:25.294236198 +0200 > @@ -0,0 +1,15 @@ > +/* PR middle-end/120434 */ > +/* { dg-do compile { target lp64 } } */ > +/* { dg-options "-O2 -mtune=generic -masm=att" } */ > +/* { dg-final { scan-assembler-not "\tmovslq\t%edi, %rdi" } } */ > +/* { dg-final { scan-assembler "\tmovl\t%edi, %edi" } } */ > + > +extern unsigned long long foo (unsigned long long x); > + > +unsigned long long > +bar (int x) > +{ > + if (x < 50) > + return 0; > + return foo (x); > +} > > Jakub > > -- Richard Biener <rguent...@suse.de> SUSE Software Solutions Germany GmbH, Frankenstrasse 146, 90461 Nuernberg, Germany; GF: Ivo Totev, Andrew Myers, Andrew McDonald, Boudien Moerman; HRB 36809 (AG Nuernberg)