Bug 95083 - x86 fp_movcc expansion depends on real_cst sharing
Summary: x86 fp_movcc expansion depends on real_cst sharing
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: target (show other bugs)
Version: 11.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: missed-optimization
Depends on:
Blocks:
 
Reported: 2020-05-12 13:41 UTC by Richard Biener
Modified: 2023-07-20 08:42 UTC (History)
1 user (show)

See Also:
Host:
Target: x86_64-*-* i?86-*-*
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Richard Biener 2020-05-12 13:41:08 UTC
I see gcc.target/i386/avxfp-1.c FAILing, which is

double x;
void
t()
{
  x=x>5?x:5;
}

double x;
void
q()
{
  x=x<5?x:5;
}

and q() recognized as FP min by ix86_expand_fp_movcc because the doesn't
pass prepare_cmp_insn () and later ifcvt matches up the originally
distinct pseudos for the two mentions of '5'.  For t() prepare_cmp_insn ()
succeeeds and ix86_expand_fp_movcc expands this to a UNSPEC_BLEND
(because the two mentions of '5' get a different pseudo so this doesn't
look like a max).  The first prepare_cmp_insn fails because it is fed

(lt (reg:DF 82 [ x.3_1 ])
    (const_double:DF 5.0e+0 [0x0.ap+3]))

and appearantly we cannot do a lt compare(?) (but later during ifcvt we can).

Note the above is when expanding from a COND_EXPR, thus

t ()
{
  double x.1_1;
  double iftmp.0_3;

;;   basic block 2, loop depth 0
;;    pred:       ENTRY
  x.1_1 = x;
  iftmp.0_3 = x.1_1 > 5.0e+0 ? x.1_1 : 5.0e+0;
  x = iftmp.0_3;
  return;

and

q ()
{
  double x.3_1;
  double iftmp.2_3;

;;   basic block 2, loop depth 0
;;    pred:       ENTRY
  x.3_1 = x;
  iftmp.2_3 = x.3_1 < 5.0e+0 ? x.3_1 : 5.0e+0;
  x = iftmp.2_3;
  return;

similar FAILs occur for

FAIL: gcc.target/i386/avxfp-1.c scan-assembler vmaxsd
FAIL: gcc.target/i386/avxfp-2.c scan-assembler vminsd
FAIL: gcc.target/i386/ssefp-1.c scan-assembler maxsd
FAIL: gcc.target/i386/ssefp-2.c scan-assembler minsd

So what's missing is simplification of 

Trying 8 -> 9:
    8: r87:DF=r85:DF<r82:DF
    9: r84:DF=unspec[r85:DF,r82:DF,r87:DF] 105
      REG_DEAD r87:DF
      REG_DEAD r85:DF
      REG_DEAD r82:DF
Failed to match this instruction:
(set (reg:DF 84)
    (unspec:DF [
            (reg:DF 85)
            (reg:DF 82 [ x.1_1 ])
            (lt:DF (reg:DF 85)
                (reg:DF 82 [ x.1_1 ]))
        ] UNSPEC_BLENDV))

to UNSPEC_MIN/MAX I guess?
Comment 1 Richard Biener 2020-05-12 13:42:27 UTC
Needs https://gcc.gnu.org/pipermail/gcc-patches/2020-May/545588.html to reproduce.
Comment 2 Uroš Bizjak 2020-05-13 14:13:25 UTC
It looks to me that a couple of (scalar) splitters are missing in sse.md.

There is vector

(define_insn_and_split "*<sse4_1>_blendv<ssemodesuffix><avxsizesuffix>_lt"

Defined as:

  [(set (match_operand:VF_128_256 0 "register_operand" "=Yr,*x,x")
	(unspec:VF_128_256
	  [(match_operand:VF_128_256 1 "register_operand" "0,0,x")
	   (match_operand:VF_128_256 2 "vector_operand" "YrBm,*xBm,xm")
	   (lt:VF_128_256
	     (match_operand:<sseintvecmode> 3 "register_operand" "Yz,Yz,x")
	     (match_operand:<sseintvecmode> 4 "const0_operand" "C,C,C"))]
	  UNSPEC_BLENDV))]

(please note const0 operand 4).

Probably similar pattern is missing that would degrade to MIN/MAX, for vector and scalar versions.
Comment 3 Richard Biener 2023-07-20 08:42:18 UTC
Fixed with the fix for PR61747.  Since min/max requires equal constants and they are now pushed to a common reg I'm not sure we need any such new patterns.  Maybe with integer min/max.