Hi, > -----Original Message----- > From: Segher Boessenkool [mailto:[email protected]] > Sent: Tuesday, May 26, 2020 11:32 PM > To: Yangfei (Felix) <[email protected]> > Cc: [email protected]; Zhanghaijian (A) <[email protected]> > Subject: Re: [PATCH PR94026] combine missed opportunity to simplify > comparisons with zero
Snip...
>
> Yes, please try to get this sorted somehow. Maybe you can ask other people
> in your company that have this same problem?
Will try and see.
> > > > + new_rtx = gen_rtx_AND (mode, new_rtx,
> > > > + gen_int_mode (mask << real_pos, mode));
> > > > + }
> > >
> > > So this changes
> > > ((X >> C) & M) == ...
> > > to
> > > (X & (M << C)) == ...
> > > ?
> > >
> > > Where then does it check what ... is? This is only valid like this if
> > > that is
> zero.
> > >
> > > Why should this go in combine and not in simplify-rtx instead?
> >
> > True. This is only valid when ... is zero.
> > That's why we need the "&& equality_comparison " condition here.
>
> But that doesn't test if the other side of the comparison is 0.
Well, the caller has ensured that.
Here, local variable "equality_comparison" in make_compound_operation_int
depends on parameter "in_code":
8088 if (in_code == EQ)
8089 {
8090 equality_comparison = true;
8091 in_code = COMPARE;
8092 }
The only caller of make_compound_operation_int is make_compound_operation.
The comment of the caller says something about " in_code ":
8512 IN_CODE says what kind of expression we are processing. Normally, it
is
8513 SET. In a memory address it is MEM. When processing the arguments of
8514 a comparison or a COMPARE against zero, it is COMPARE, or EQ if more
8515 precisely it is an equality comparison against zero. */
For the given test case, we have a call trace of:
(gdb) bt
#0 make_compound_operation_int (mode=..., x_ptr=0xffffffffbd08,
in_code=COMPARE, next_code_ptr=0xffffffffbd1c) at
../../gcc-git/gcc/combine.c:8248
#1 0x000000000208983c in make_compound_operation (x=0xffffb211c768,
in_code=EQ) at ../../gcc-git/gcc/combine.c:8539
#2 0x00000000020970fc in simplify_comparison (code=NE, pop0=0xffffffffc1e8,
pop1=0xffffffffc1e0) at ../../gcc-git/gcc/combine.c:13032
#3 0x0000000002084544 in simplify_set (x=0xffffb211c240) at
../../gcc-git/gcc/combine.c:6932
#4 0x0000000002082688 in combine_simplify_rtx (x=0xffffb211c240,
op0_mode=E_VOIDmode, in_dest=0, in_cond=0) at ../../gcc-git/gcc/combine.c:6445
#5 0x000000000208025c in subst (x=0xffffb211c240, from=0xffffb211c138,
to=0xffffb211c150, in_dest=0, in_cond=0, unique_copy=0)
at ../../gcc-git/gcc/combine.c:5724
#6 0x0000000002079110 in try_combine (i3=0xffffb22cc3c0, i2=0xffffb22cc340,
i1=0x0, i0=0x0, new_direct_jump_p=0xffffffffceb4,
last_combined_insn=0xffffb22cc3c0) at ../../gcc-git/gcc/combine.c:3413
#7 0x0000000002073004 in combine_instructions (f=0xffffb211d038, nregs=103) at
../../gcc-git/gcc/combine.c:1305
#8 0x000000000209cc50 in rest_of_handle_combine () at
../../gcc-git/gcc/combine.c:15088
In simplify_comparison (combine.c:13032):
13028 rtx_code op0_mco_code = SET;
13029 if (op1 == const0_rtx)
13030 op0_mco_code = code == NE || code == EQ ? EQ : COMPARE;
13031
13032 op0 = make_compound_operation (op0, op0_mco_code);
13033 op1 = make_compound_operation (op1, SET);
> > > > --- /dev/null
> > > > +++ b/gcc/testsuite/gcc.dg/pr94026.c
> > > > @@ -0,0 +1,21 @@
> > > > +/* { dg-do compile { target aarch64*-*-* i?86-*-* x86_64-*-* } }
> > > > +*/
> > >
> > > Why restrict this to only some targets?
> >
> > That's because I only have these targets for verification.
> > But I think this can work on other targets. Removed from the v4 patch.
> > Could you please help check the other ports?
>
> In general, you should never restrict anything to some targets simply
> because you haven't tested it on other targets.
>
> If it is a good test it will just work on those other targets. Traffic on
> gcc-
> testresults@ will show you if it actually does.
OK. Thanks for pointing this out :-)
> > > > +/* { dg-options "-O2 -fdump-rtl-combine" } */
> > > > +
> > > > +int
> > > > +foo (int c)
> > > > +{
> > > > + int a = (c >> 8) & 7;
> > > > +
> > > > + if (a >= 2) {
> > > > + return 1;
> > > > + }
> > > > +
> > > > + return 0;
> > > > +}
> > > > +
> > > > +/* The combine phase should transform (compare (and (lshiftrt x 8) 6)
> 0)
> > > > + to (compare (and (x 1536)) 0). We look for the *attempt* to match
> this
> > > > + RTL pattern, regardless of whether an actual insn may be found on
> the
> > > > + platform. */
> > > > +
> > > > +/* { dg-final { scan-rtl-dump "\\(const_int 1536" "combine" } }
> > > > +*/
> > >
> > > That is a very fragile test.
> >
> > For this specific test case, (const_int 1536) is calculated from
> > subexpression
> (M << C) in (X & (M << C)).
> > I also see some similar checkings in gcc.dg/asr_div1.c. Suggesions?
>
> Maybe it is better to test that the non-optimal code you saw before is not
> generated anymore? That could be a target-specific test of course.
> The advantage is that the test will not break for all kinds of unrelated
> reasons
> (like this test) -- that simply does not scale with the number of tests we
> have.
Good suggestion.
The v5 patch checks for the redundant "asr" instruction on aarch64.
Newly add test fail without the fix and pass otherwise.
gcc/ChangeLog
+2020-05-27 Felix Yang <[email protected]>
+
+ PR rtl-optimization/94026
+ * combine.c (make_compound_operation_int): If we have (and
+ (lshiftrt X C) M) and M is a constant that would select a field
+ of bits within an item, but not the entire word, fold this into
+ a simple AND if we are in an equality comparison.
gcc/testsuite/ChangeLog
+2020-05-27 Felix Yang <[email protected]>
+
+ PR rtl-optimization/94026
+ * gcc.dg/pr94026.c: New test.
pr94026-v5.diff
Description: pr94026-v5.diff
