Patchwork [AArch64] Optimise comparison where intermediate result not used

login
register
mail settings
Submitter Ian Bolton
Date Nov. 6, 2012, 6:49 p.m.
Message ID <000001cdbc4f$6f66aa90$4e33ffb0$@bolton@arm.com>
Download mbox | patch
Permalink /patch/197535/
State New
Headers show

Comments

Ian Bolton - Nov. 6, 2012, 6:49 p.m.
Hi all,

When we perform an addition but only use the result for a comparison,
we can save an instruction.

Consider this function:

int foo (int a, int b) {
  return ((a + b) == 0) ? 1 : 7;
}


Here is the original output:

foo:
        add w0, w0, w1
        cmp w0, wzr
        mov w1, 7
        mov w0, 1
        csel w0, w1, w0, ne
        ret

Now we get this:

foo:
        cmn     w0, w1
        mov     w1, 7
        mov     w0, 1
        csel    w0, w1, w0, ne
        ret

:)


I added other testcases for this and also some for adds and subs, which
were investigated as part of this work.


OK for trunk?

Cheers,
Ian


2012-11-06  Ian Bolton  <ian.bolton@arm.com>

      * gcc/config/aarch64/aarch64.md (*compare_neg<mode>): New pattern.
      * gcc/testsuite/gcc.target/aarch64/cmn.c: New test.
      * gcc/testsuite/gcc.target/aarch64/adds.c: New test.
      * gcc/testsuite/gcc.target/aarch64/subs.c: New test.


------------------------------------------------
Marcus Shawcroft - Nov. 12, 2012, 9:05 a.m.
On 06/11/12 18:49, Ian Bolton wrote:

>
> OK for trunk?
>
> Cheers,
> Ian
>
>
> 2012-11-06  Ian Bolton  <ian.bolton@arm.com>
>
>        * gcc/config/aarch64/aarch64.md (*compare_neg<mode>): New pattern.
>        * gcc/testsuite/gcc.target/aarch64/cmn.c: New test.
>        * gcc/testsuite/gcc.target/aarch64/adds.c: New test.
>        * gcc/testsuite/gcc.target/aarch64/subs.c: New test.
>

OK, please back port to ARM/aarch64-4.7-branch.

/Marcus

Patch

diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index e6086a9..6935192 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -1310,6 +1310,17 @@ 
    (set_attr "mode" "<MODE>")]
 )
 
+(define_insn "*compare_neg<mode>"
+  [(set (reg:CC CC_REGNUM)
+	(compare:CC
+	 (match_operand:GPI 0 "register_operand" "r")
+	 (neg:GPI (match_operand:GPI 1 "register_operand" "r"))))]
+  ""
+  "cmn\\t%<w>0, %<w>1"
+  [(set_attr "v8type" "alus")
+   (set_attr "mode" "<MODE>")]
+)
+
 (define_insn "*add_<shift>_<mode>"
   [(set (match_operand:GPI 0 "register_operand" "=rk")
 	(plus:GPI (ASHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
diff --git a/gcc/testsuite/gcc.target/aarch64/adds.c
b/gcc/testsuite/gcc.target/aarch64/adds.c
new file mode 100644
index 0000000..aa42321
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/adds.c
@@ -0,0 +1,30 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+int z;
+int
+foo (int x, int y)
+{
+  int l = x + y;
+  if (l == 0)
+    return 5;
+
+  /* { dg-final { scan-assembler "adds\tw\[0-9\]" } } */
+  z = l ;
+  return 25;
+}
+
+typedef long long s64;
+
+s64 zz;
+s64
+foo2 (s64 x, s64 y)
+{
+  s64 l = x + y;
+  if (l < 0)
+    return 5;
+
+  /* { dg-final { scan-assembler "adds\tx\[0-9\]" } } */
+  zz = l ;
+  return 25;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/cmn.c
b/gcc/testsuite/gcc.target/aarch64/cmn.c
new file mode 100644
index 0000000..1f06f57
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/cmn.c
@@ -0,0 +1,24 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+int
+foo (int a, int b)
+{
+  if (a + b)
+    return 5;
+  else
+    return 2;
+  /* { dg-final { scan-assembler "cmn\tw\[0-9\]" } } */
+}
+
+typedef long long s64;
+
+s64
+foo2 (s64 a, s64 b)
+{
+  if (a + b)
+    return 5;
+  else
+    return 2;
+  /* { dg-final { scan-assembler "cmn\tx\[0-9\]" } } */
+}  
diff --git a/gcc/testsuite/gcc.target/aarch64/subs.c
b/gcc/testsuite/gcc.target/aarch64/subs.c
new file mode 100644
index 0000000..2bf1975
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/subs.c
@@ -0,0 +1,30 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+int z;
+int
+foo (int x, int y)
+{
+  int l = x - y;
+  if (l == 0)
+    return 5;
+
+  /* { dg-final { scan-assembler "subs\tw\[0-9\]" } } */
+  z = l ;
+  return 25;
+}
+
+typedef long long s64;
+
+s64 zz;
+s64
+foo2 (s64 x, s64 y)
+{
+  s64 l = x - y;
+  if (l < 0)
+    return 5;
+
+  /* { dg-final { scan-assembler "subs\tx\[0-9\]" } } */
+  zz = l ;
+  return 25;
+}