> -----Original Message----- > From: Hu, Lin1 > Sent: Tuesday, September 3, 2024 2:05 PM > To: Jakub Jelinek <ja...@redhat.com>; Andrew Pinski <pins...@gmail.com>; > Liu, Hongtao <hongtao....@intel.com> > Cc: Jiang, Haochen <haochen.ji...@intel.com>; Richard Biener > <rguent...@suse.de>; gcc-patches@gcc.gnu.org; ubiz...@gmail.com > Subject: RE: [PATCH 2/8] i386: Optimize ordered and nonequal > > > -----Original Message----- > > From: Jakub Jelinek <ja...@redhat.com> > > Sent: Tuesday, September 3, 2024 2:56 AM > > To: Andrew Pinski <pins...@gmail.com> > > Cc: Jiang, Haochen <haochen.ji...@intel.com>; Richard Biener > > <rguent...@suse.de>; gcc-patches@gcc.gnu.org; Liu, Hongtao > > <hongtao....@intel.com>; ubiz...@gmail.com; Hu, Lin1 > > <lin1...@intel.com> > > Subject: Re: [PATCH 2/8] i386: Optimize ordered and nonequal > > > > On Mon, Sep 02, 2024 at 11:25:36AM -0700, Andrew Pinski wrote: > > > On Mon, Sep 2, 2024 at 11:20 AM Jakub Jelinek <ja...@redhat.com> wrote: > > > > > > > > On Mon, Aug 26, 2024 at 02:42:31PM +0800, Haochen Jiang wrote: > > > > > * match.pd: Optimize (and ordered non-equal) to > > > > > (not (or unordered equal)) > > > > > > > > > > gcc/testsuite/ChangeLog: > > > > > > > > > > * gcc.target/i386/optimize_one.c: New test. > > > > > > > > The testcase FAILs on i686-linux, because it uses -mfpmath=sse > > > > without enabling -msse2. > > > > > > > > I've committed the following fix as obvious to fix that. > > > > > > > > > --- a/gcc/match.pd > > > > > +++ b/gcc/match.pd > > > > > @@ -6636,6 +6636,9 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) > > > > > (ltgt @0 @0) > > > > > (if (!flag_trapping_math || !tree_expr_maybe_nan_p (@0)) > > > > > { constant_boolean_node (false, type); })) > > > > > +(simplify > > > > > + (bit_and (ordered @0 @1) (ne @0 @1)) (bit_not (uneq @0 @1))) > > > > > > > > I wonder whether there shouldn't be some :c (e.g. on bit_and and > > > > maybe ne too), because ordered is commutative and so is ne and so > > > > is bit_and, and perhaps you want to match also (bit_and (ne @0 @1) > > > > (ordered @1 @0)) etc. What about negation of this (bit_ior > > > > (unordered @0 > > @1) (eq @0 @1))? > > > > > > The :c is needed for bit_and for sure. BUT should not needed for > > > ordered/ne though because the canonicalization of the operations > > > should have the operands in the same order as `a ordered b` is the > > > same as `b ordered a`. > > > > Maybe. Also, isn't (bit_not (uneq @0 @1)) (ltgt @0 @1) ? > > > > Jakub > > I add some tests like: > 6 int is_ordered_and_nonequal_sh_1 (float a, float b) > 7 { > 8 return !__builtin_isunordered (a, b) && (a != b); > 9 } > 10 > 11 int is_ordered_and_nonequal_sh_2 (float a, float b) > 12 { > 13 return !__builtin_isunordered (a, b) && (b != a); > 14 } > 15 > 16 int is_ordered_and_nonequal_sh_3 (float a, float b) > 17 { > 18 return (b != a) && !__builtin_isunordered (a, b); > 19 } > 20 > 21 int is_ordered_and_nonequal_sh_4 (float a, float b) > 22 { > 23 return !__builtin_isunordered (a, b) && !(a == b); > 24 } > 25 > 26 int is_ordered_and_nonequal_sh_5 (float a, float b) > 27 { > 28 return !__builtin_isunordered (a, b) && !(b == a); > 29 } > 30 > 31 int is_ordered_and_nonequal_sh_6 (float a, float b) > 32 { > 33 return !(b == a) && !__builtin_isunordered (a, b); > 34 } > 35 > 36 int is_unordered_or_equal_sh_1 (float a, float b) > 37 { > 38 return __builtin_isunordered (a, b) || (a == b); > 39 } > 40 > 41 int is_unordered_or_equal_sh_2 (float a, float b) > 42 { > 43 return __builtin_isunordered (a, b) || (b == a); > 44 } > 45 > 46 int is_unordered_or_equal_sh_3 (float a, float b) > 47 { > 48 return (a == b) || __builtin_isunordered (b, a); > 49 } > 50 > 51 int is_ordered_and_ltgt_sh_1 (float a, float b) > 52 { > 53 return !__builtin_isunordered (a, b) && ((a < b) || (a > b)); > 54 } > 55 > 56 int is_ordered_and_ltgt_sh_2 (float a, float b) > 57 { > 58 return !__builtin_isunordered (a, b) && ((b > a) || (a > b)); > 59 } > 60 > 61 int is_ordered_and_ltgt_sh_3 (float a, float b) > 62 { > 63 return ((b > a) || (a > b)) && !__builtin_isunordered (a, b); > 64 } > > From the result, I get some conclusions or quesitions: > 1. We need to add :c to bit_and. > 2. We need to add (ltgt @0 @1). > But, in 006t.gimple !__builtin_isunordered (a, b) && ((b > a) || (a > b)) > will be > 126 > 127 if (a ord b) goto <D.2813>; else goto <D.2811>; > 128 <D.2813>: > 129 if (b <> a) goto <D.2814>; else goto <D.2811>; > 130 <D.2814>: > 131 iftmp.1 = 1; > GCC don't use bit_and like other testcases, looks like I can't just add a > simplify in > match.pd, do you have any idea to solve this question in the frontend (maybe > frontend)? > 3. After add these testcases, I consider to change the testcase's name to opt- > ucomi-1.c.
I made some mistakes for the previous comments. Some of the tests are not directly related to what we are discussing. I've written a patch like this diff --git a/gcc/match.pd b/gcc/match.pd index 4298e89dad6..621306213e4 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -6652,8 +6652,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (if (!flag_trapping_math || !tree_expr_maybe_nan_p (@0)) { constant_boolean_node (false, type); })) (simplify - (bit_and (ordered @0 @1) (ne @0 @1)) - (bit_not (uneq @0 @1))) + (bit_and:c (ordered @0 @1) (ne @0 @1)) + (ltgt @0 @1)) /* x == ~x -> false */ /* x != ~x -> true */ diff --git a/gcc/testsuite/gcc.target/i386/opt-comi-1.c b/gcc/testsuite/gcc.target/i386/opt-comi-1.c new file mode 100644 index 00000000000..fc7b8632004 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/opt-comi-1.c @@ -0,0 +1,49 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mfpmath=sse -msse2" } */ +/* { dg-final { scan-assembler-times "comiss" 9 } } */ +/* { dg-final { scan-assembler-times "set" 9 } } */ + +int is_ordered_and_nonequal_sh_1 (float a, float b) +{ + return !__builtin_isunordered (a, b) && (a != b); +} + +int is_ordered_and_nonequal_sh_2 (float a, float b) +{ + return !__builtin_isunordered (a, b) && (b != a); +} + +int is_ordered_and_nonequal_sh_3 (float a, float b) +{ + return (b != a) && !__builtin_isunordered (a, b); +} + +int is_ordered_and_nonequal_sh_4 (float a, float b) +{ + return !__builtin_isunordered (a, b) && !(a == b); +} + +int is_ordered_and_nonequal_sh_5 (float a, float b) +{ + return !__builtin_isunordered (a, b) && !(b == a); +} + +int is_ordered_and_nonequal_sh_6 (float a, float b) +{ + return !(b == a) && !__builtin_isunordered (a, b); +} + +int is_ordered_or_nonequal_sh_7 (float a, float b) +{ + return !(__builtin_isunordered (a, b) || (a == b)); +} + +int is_ordered_or_nonequal_sh_8 (float a, float b) +{ + return !(__builtin_isunordered (a, b) || (b == a)); +} will send it out after I test it out.