summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Matz <matz@suse.de>2016-11-15 14:02:28 +0000
committerMichael Matz <matz@gcc.gnu.org>2016-11-15 14:02:28 +0000
commitb229ab2a712ccd44126bcbcaed2da8b998e7366c (patch)
tree6332e06f8a024d08d976fc3a4dcd33711ea2e615
parentaa806c3be702a6bcd72cad5c329024ee68e29e3a (diff)
downloadgcc-b229ab2a712ccd44126bcbcaed2da8b998e7366c.tar.gz
re PR target/77881 (Non-optimal signed comparison on x86_64 since r146817)
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. From-SVN: r242414
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/combine.c35
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.target/i386/pr77881.c12
4 files changed, 60 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 1e422d2a844..c4a660f0cff 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2016-11-15 Michael Matz <matz@suse.de>
+
+ 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.
+
2016-11-15 Richard Sandiford <richard.sandiford@arm.com>
Alan Hayward <alan.hayward@arm.com>
David Sherwood <david.sherwood@arm.com>
diff --git a/gcc/combine.c b/gcc/combine.c
index 6b7bdd0f687..2de2a3ef8a2 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/ChangeLog b/gcc/testsuite/ChangeLog
index fce6f8d1b8f..dcb220d036a 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2016-11-15 Michael Matz <matz@suse.de>
+
+ PR missed-optimization/77881
+ * gcc.target/i386/pr77881.c: New test.
+
2016-11-15 Jakub Jelinek <jakub@redhat.com>
PR middle-end/78295
diff --git a/gcc/testsuite/gcc.target/i386/pr77881.c b/gcc/testsuite/gcc.target/i386/pr77881.c
new file mode 100644
index 00000000000..80d143f2bc5
--- /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" } } */