Hi,

On Sat, 12 Nov 2016, Segher Boessenkool wrote:

> Hi Michael,
> 
> On Thu, Oct 20, 2016 at 04:20:09PM +0200, Michael Matz wrote:
> >     PR missed-optimization/77881
> >     * combine.c (simplify_comparison): Remove useless subregs
> >     also inside the loop, not just after it.
> > 
> > testsuite/
> >     * gcc.target/i386/pr77881.c: New test.
> 
> This isn't checked in yet, do you still want it?

Gnah, fell through the cracks.  I had to fix something else in combine to 
make it not regress in the testsuite.  The problem is that removing the 
subregs enables further simplifications which in turn might not be 
expected down-stream.  The particular problem was that originally the loop 
was left with an (subreg:QI (and:SI (lrshift X 24) 255) 0), whose inner op 
in turn was recognized by make_compound_operation and transformed into an 
extract.

With the patch we leave the loop now with essentially
  (subreg:QI (lrshift X 24) 0)
which of course is just the same masking and hence extract, but 
make_compound_operation didn't know.  With the amended patch it does.  I 
didn't come around making the AND and SUBREG handling a bit more common 
(which I initially wanted to do before posting), so for now I'm handling 
only the specific case I hit.

With this patch there are now no regressions on x86-64-linux (bootstrapped 
with all languages+ada).  Okay for trunk?


Ciao,
Michael.
        PR missed-optimization/77881
        * combine.c (simplify_comparison): Remove useless subregs
        also inside the loop, not just after it.
        (make_compound_operation): Recognize some subregs as being
        masking as well.

testsuite/
        * gcc.target/i386/pr77881.c: New test.

diff --git a/gcc/combine.c b/gcc/combine.c
index 6ffa387..0210685 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -8102,6 +8102,18 @@ make_compound_operation (rtx x, enum rtx_code in_code)
        rtx inner = SUBREG_REG (x), simplified;
        enum rtx_code subreg_code = in_code;
 
+       /* If the SUBREG is masking of a logical right shift,
+          make an extraction.  */
+       if (GET_CODE (inner) == LSHIFTRT
+           && GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (inner))
+           && subreg_lowpart_p (x))
+         {
+           new_rtx = make_compound_operation (XEXP (inner, 0), next_code);
+           new_rtx = make_extraction (mode, new_rtx, 0, XEXP (inner, 1),
+                                      mode_width, 1, 0, in_code == COMPARE);
+           break;
+         }
+
        /* If in_code is COMPARE, it isn't always safe to pass it through
           to the recursive make_compound_operation call.  */
        if (subreg_code == COMPARE
@@ -11994,6 +12006,29 @@ simplify_comparison (enum rtx_code code, rtx *pop0, 
rtx *pop1)
          if (subreg_lowpart_p (op0)
              && GET_MODE_PRECISION (GET_MODE (SUBREG_REG (op0))) < mode_width)
            ;
+         else if (subreg_lowpart_p (op0)
+                  && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT
+                  && GET_MODE_CLASS (GET_MODE (SUBREG_REG (op0))) == MODE_INT
+                  && (code == NE || code == EQ)
+                  && (GET_MODE_PRECISION (GET_MODE (SUBREG_REG (op0)))
+                      <= HOST_BITS_PER_WIDE_INT)
+                  && !paradoxical_subreg_p (op0)
+                  && (nonzero_bits (SUBREG_REG (op0),
+                                    GET_MODE (SUBREG_REG (op0)))
+                      & ~GET_MODE_MASK (GET_MODE (op0))) == 0)
+           {
+             /* Remove outer subregs that don't do anything.  */
+             tem = gen_lowpart (GET_MODE (SUBREG_REG (op0)), op1);
+ 
+             if ((nonzero_bits (tem, GET_MODE (SUBREG_REG (op0)))
+                  & ~GET_MODE_MASK (GET_MODE (op0))) == 0)
+               {
+                 op0 = SUBREG_REG (op0);
+                 op1 = tem;
+                 continue;
+               }
+             break;
+           }
          else
            break;
 
diff --git a/gcc/testsuite/gcc.target/i386/pr77881.c 
b/gcc/testsuite/gcc.target/i386/pr77881.c
new file mode 100644
index 0000000..80d143f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr77881.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target pie } */
+/* { dg-options "-O2" } */
+extern void baz(void);
+int
+foo (long long int a, long long int a2, int b)
+{
+    if (a < 0 || b)
+          baz ();
+}
+/* { dg-final { scan-assembler "js\[ \t\]\.L" } } */
+/* { dg-final { scan-assembler "jne\[ \t\]\.L" } } */

Reply via email to