We couldn't generate SBC for AArch64 ... until now!

This really patch includes the main pattern, a zero_extend form
of it and a test.

Full regression testing for Linux and bare-metal passed.

OK for trunk stage-1?

Thanks,
Ian


2013-03-14  Ian Bolton  <ian.bol...@arm.com>

gcc/
        * config/aarch64/aarch64.md (*sub<mode>3_carryin): New pattern.
        (*subsi3_carryin_uxtw): Likewise.

testsuite/
        * gcc.target/aarch64/sbc.c: New test.

diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index 4358b44..c99e188 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -1790,6 +1790,34 @@
    (set_attr "mode" "SI")]
 )
 
+(define_insn "*sub<mode>3_carryin"
+  [(set
+    (match_operand:GPI 0 "register_operand" "=r")
+    (minus:GPI (minus:GPI
+               (match_operand:GPI 1 "register_operand" "r")
+               (ltu:GPI (reg:CC CC_REGNUM) (const_int 0)))
+              (match_operand:GPI 2 "register_operand" "r")))]
+   ""
+   "sbc\\t%<w>0, %<w>1, %<w>2"
+  [(set_attr "v8type" "adc")
+   (set_attr "mode" "<MODE>")]
+)
+
+;; zero_extend version of the above
+(define_insn "*subsi3_carryin_uxtw"
+  [(set
+    (match_operand:DI 0 "register_operand" "=r")
+    (zero_extend:DI
+     (minus:SI (minus:SI
+               (match_operand:SI 1 "register_operand" "r")
+               (ltu:SI (reg:CC CC_REGNUM) (const_int 0)))
+              (match_operand:SI 2 "register_operand" "r"))))]
+   ""
+   "sbc\\t%w0, %w1, %w2"
+  [(set_attr "v8type" "adc")
+   (set_attr "mode" "SI")]
+)
+
 (define_insn "*sub_uxt<mode>_multp2"
   [(set (match_operand:GPI 0 "register_operand" "=rk")
        (minus:GPI (match_operand:GPI 4 "register_operand" "r")
diff --git a/gcc/testsuite/gcc.target/aarch64/sbc.c 
b/gcc/testsuite/gcc.target/aarch64/sbc.c
new file mode 100644
index 0000000..e479910
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sbc.c
@@ -0,0 +1,41 @@
+/* { dg-do run } */
+/* { dg-options "-O2 --save-temps" } */
+
+extern void abort (void);
+
+typedef unsigned int u32int;
+typedef unsigned long long u64int;
+
+u32int
+test_si (u32int w1, u32int w2, u32int w3, u32int w4)
+{
+  u32int w0;
+  /* { dg-final { scan-assembler "sbc\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+\n" } } 
*/
+  w0 = w1 - w2 - (w3 < w4);
+  return w0;
+}
+
+u64int
+test_di (u64int x1, u64int x2, u64int x3, u64int x4)
+{
+  u64int x0;
+  /* { dg-final { scan-assembler "sbc\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+\n" } } 
*/
+  x0 = x1 - x2 - (x3 < x4);
+  return x0;
+}
+
+int
+main ()
+{
+  u32int x;
+  u64int y;
+  x = test_si (7, 8, 12, 15);
+  if (x != -2)
+    abort();
+  y = test_di (0x987654321ll, 0x123456789ll, 0x345345345ll, 0x123123123ll);
+  if (y != 0x8641fdb98ll)
+    abort();
+  return 0;
+}
+
+/* { dg-final { cleanup-saved-temps } } */

Reply via email to