From b229ab2a712ccd44126bcbcaed2da8b998e7366c Mon Sep 17 00:00:00 2001
From: Michael Matz <matz@suse.de>
Date: Tue, 15 Nov 2016 14:02:28 +0000
Subject: [PATCH] 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
---
 gcc/ChangeLog                           |  8 ++++++
 gcc/combine.c                           | 35 +++++++++++++++++++++++++
 gcc/testsuite/ChangeLog                 |  5 ++++
 gcc/testsuite/gcc.target/i386/pr77881.c | 12 +++++++++
 4 files changed, 60 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/i386/pr77881.c

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 1e422d2a844c..c4a660f0cff6 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 6b7bdd0f687d..2de2a3ef8a27 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 fce6f8d1b8f0..dcb220d036ab 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 000000000000..80d143f2bc50
--- /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" } } */
-- 
GitLab