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" } } */