From 6ea007e447876a49b7ea271d0bdee721e6b98cef Mon Sep 17 00:00:00 2001
From: Bernd Schmidt <bernd.schmidt@codesourcery.com>
Date: Fri, 16 Apr 2010 09:42:32 +0000
Subject: [PATCH] re PR target/41514 (redundant compare instruction of
 consecutive conditional branches)

	PR target/41514
	* config/arm/arm.md (cbranchsi4_insn): Renamed from "*cbranchsi4_insn".
	If the previous insn is a cbranchsi4_insn with the same arguments,
	omit the compare instruction.

	PR target/41514
	gcc.target/arm/thumb-comparisons.c: New test.

From-SVN: r158404
---
 gcc/ChangeLog                                  |  5 +++++
 gcc/config/arm/arm.md                          | 17 +++++++++++++++--
 gcc/testsuite/ChangeLog                        |  5 +++++
 .../gcc.target/arm/thumb-comparisons.c         | 18 ++++++++++++++++++
 4 files changed, 43 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/arm/thumb-comparisons.c

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 79f4c59bcabf..0e384b57376e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -8,6 +8,11 @@
 	* reload.c (find_reloads): Use it rather than testing for an
 	empty constraint string.
 
+	PR target/41514
+	* config/arm/arm.md (cbranchsi4_insn): Renamed from "*cbranchsi4_insn".
+	If the previous insn is a cbranchsi4_insn with the same arguments,
+	omit the compare instruction.
+
 2010-04-16  Jakub Jelinek  <jakub@redhat.com>
 
 	* alias.c (memrefs_conflict_p): If x and y are the same VALUE,
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index c5e2a16e694c..1a07f36ef6ca 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -6705,7 +6705,7 @@
 				   operands[3])); DONE;"
 )
 
-(define_insn "*cbranchsi4_insn"
+(define_insn "cbranchsi4_insn"
   [(set (pc) (if_then_else
 	      (match_operator 0 "arm_comparison_operator"
 	       [(match_operand:SI 1 "s_register_operand" "l,*h")
@@ -6714,7 +6714,20 @@
 	      (pc)))]
   "TARGET_THUMB1"
   "*
-  output_asm_insn (\"cmp\\t%1, %2\", operands);
+  rtx t = prev_nonnote_insn (insn);
+  if (t != NULL_RTX
+      && INSN_P (t)
+      && INSN_CODE (t) == CODE_FOR_cbranchsi4_insn)
+    {
+      t = XEXP (SET_SRC (PATTERN (t)), 0);
+      if (!rtx_equal_p (XEXP (t, 0), operands[1])
+	  || !rtx_equal_p (XEXP (t, 1), operands[2]))
+	t = NULL_RTX;
+    }
+  else
+    t = NULL_RTX;
+  if (t == NULL_RTX)
+    output_asm_insn (\"cmp\\t%1, %2\", operands);
 
   switch (get_attr_length (insn))
     {
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index a029d982b25c..3f0fe2beab27 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2010-04-16  Bernd Schmidt  <bernd.schmidt@codesourcery.com>
+
+	PR target/41514
+	gcc.target/arm/thumb-comparisons.c: New test.
+
 2010-04-16  Christian Bruel  <christian.bruel@st.com>
 
 	* g++.dg/torture/pr36191.C: Enable for SH.
diff --git a/gcc/testsuite/gcc.target/arm/thumb-comparisons.c b/gcc/testsuite/gcc.target/arm/thumb-comparisons.c
new file mode 100644
index 000000000000..45be2cf74f07
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/thumb-comparisons.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-mthumb -Os" }  */
+/* { dg-require-effective-target arm_thumb1_ok } */
+
+int foo(char ch)
+{
+  switch (ch) {
+    case '-':
+    case '?':
+    case '/':
+    case 99:
+        return 1;
+    default:
+        return 0;
+  }
+}
+
+/* { dg-final { scan-assembler-times "cmp\[\\t \]*r.,\[\\t \]*#63" 1 } } */
-- 
GitLab