Hi,
Please find attached the patch that implements addition and Subtraction
by setting flags instructions in extend and shift_extend mode for
aarch64 target.
The patch for Add/Sub instructions by setting flags in shift mode is
already posted.
Testcase have been added for these instructions.
Please review the same and let me know if there should be any
modifications in the patch.
Build and tested on aarch64-thunder-elf (using Cavium's internal
simulator). No new regressions.
Thanks,
Naveen
gcc/
2013-04-12 Naveen H.S <[email protected]>
* config/aarch64/aarch64.md (*adds_<optab><mode>_multp2):
New pattern.
(*subs_<optab><mode>_multp2): New pattern.
(*adds_<optab><ALLX:mode>_<GPI:mode>): New pattern.
(*subs_<optab><ALLX:mode>_<GPI:mode>): New pattern.
gcc/testsuite/
2013-04-12 Naveen H.S <[email protected]>
* gcc.target/aarch64/adds3.c: New.
* gcc.target/aarch64/subs3.c: New.--- gcc/config/aarch64/aarch64.md 2013-04-12 10:03:11.924990662 +0530
+++ gcc/config/aarch64/aarch64.md 2013-04-12 14:31:58.368958483 +0530
@@ -1291,6 +1291,78 @@
(set_attr "mode" "SI")]
)
+(define_insn "*adds_<optab><ALLX:mode>_<GPI:mode>"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ
+ (plus:GPI
+ (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r"))
+ (match_operand:GPI 2 "register_operand" "r"))
+ (const_int 0)))
+ (set (match_operand:GPI 0 "register_operand" "=r")
+ (plus:GPI (ANY_EXTEND:GPI (match_dup 1)) (match_dup 2)))]
+ ""
+ "adds\\t%<GPI:w>0, %<GPI:w>2, %<GPI:w>1, <su>xt<ALLX:size>"
+ [(set_attr "v8type" "alus_ext")
+ (set_attr "mode" "<GPI:MODE>")]
+)
+
+(define_insn "*subs_<optab><ALLX:mode>_<GPI:mode>"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ
+ (minus:GPI (match_operand:GPI 1 "register_operand" "r")
+ (ANY_EXTEND:GPI
+ (match_operand:ALLX 2 "register_operand" "r")))
+ (const_int 0)))
+ (set (match_operand:GPI 0 "register_operand" "=r")
+ (minus:GPI (match_dup 1) (ANY_EXTEND:GPI (match_dup 2))))]
+ ""
+ "subs\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size>"
+ [(set_attr "v8type" "alus_ext")
+ (set_attr "mode" "<GPI:MODE>")]
+)
+
+(define_insn "*adds_<optab><mode>_multp2"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ
+ (plus:GPI (ANY_EXTRACT:GPI
+ (mult:GPI (match_operand:GPI 1 "register_operand" "r")
+ (match_operand 2 "aarch64_pwr_imm3" "Up3"))
+ (match_operand 3 "const_int_operand" "n")
+ (const_int 0))
+ (match_operand:GPI 4 "register_operand" "r"))
+ (const_int 0)))
+ (set (match_operand:GPI 0 "register_operand" "=r")
+ (plus:GPI (ANY_EXTRACT:GPI (mult:GPI (match_dup 1) (match_dup 2))
+ (match_dup 3)
+ (const_int 0))
+ (match_dup 4)))]
+ "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
+ "adds\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
+ [(set_attr "v8type" "alus_ext")
+ (set_attr "mode" "<MODE>")]
+)
+
+(define_insn "*subs_<optab><mode>_multp2"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ
+ (minus:GPI (match_operand:GPI 4 "register_operand" "r")
+ (ANY_EXTRACT:GPI
+ (mult:GPI (match_operand:GPI 1 "register_operand" "r")
+ (match_operand 2 "aarch64_pwr_imm3" "Up3"))
+ (match_operand 3 "const_int_operand" "n")
+ (const_int 0)))
+ (const_int 0)))
+ (set (match_operand:GPI 0 "register_operand" "=r")
+ (minus:GPI (match_dup 4) (ANY_EXTRACT:GPI
+ (mult:GPI (match_dup 1) (match_dup 2))
+ (match_dup 3)
+ (const_int 0))))]
+ "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
+ "subs\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
+ [(set_attr "v8type" "alus_ext")
+ (set_attr "mode" "<MODE>")]
+)
+
(define_insn "*add<mode>3nr_compare0"
[(set (reg:CC_NZ CC_REGNUM)
(compare:CC_NZ
--- gcc/testsuite/gcc.target/aarch64/adds3.c 1970-01-01 05:30:00.000000000 +0530
+++ gcc/testsuite/gcc.target/aarch64/adds3.c 2013-04-12 16:18:29.472945730 +0530
@@ -0,0 +1,61 @@
+/* { dg-do run } */
+/* { dg-options "-O2 --save-temps" } */
+
+extern void abort (void);
+typedef long long s64;
+
+int
+adds_ext (s64 a, int b, int c)
+{
+ s64 d = a + b;
+
+ /* { dg-final { scan-assembler "adds\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+, sxtw" } } */
+ if (d == 0)
+ return a + c;
+ else
+ return b + d + c;
+}
+
+int
+adds_shift_ext (s64 a, int b, int c)
+{
+ s64 d = (a + ((s64)b << 3));
+
+ /* { dg-final { scan-assembler "adds\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+, sxtw 3" } } */
+ if (d == 0)
+ return a + c;
+ else
+ return b + d + c;
+}
+
+int main ()
+{
+ int x;
+ s64 y;
+
+ x = adds_ext (0x13000002ll, 41, 15);
+ if (x != 318767203)
+ abort ();
+
+ x = adds_ext (0x50505050ll, 29, 4);
+ if (x != 1347440782)
+ abort ();
+
+ x = adds_ext (0x12121212121ll, 2, 14);
+ if (x != 555819315)
+ abort ();
+
+ x = adds_shift_ext (0x123456789ll, 4, 12);
+ if (x != 591751097)
+ abort ();
+
+ x = adds_shift_ext (0x02020202ll, 9, 8);
+ if (x != 33686107)
+ abort ();
+
+ x = adds_shift_ext (0x987987987987ll, 23, 41);
+ if (x != -2020050305)
+ abort ();
+
+ return 0;
+}
--- gcc/testsuite/gcc.target/aarch64/subs3.c 1970-01-01 05:30:00.000000000 +0530
+++ gcc/testsuite/gcc.target/aarch64/subs3.c 2013-04-12 16:18:40.404945709 +0530
@@ -0,0 +1,61 @@
+/* { dg-do run } */
+/* { dg-options "-O2 --save-temps" } */
+
+extern void abort (void);
+typedef long long s64;
+
+int
+subs_ext (s64 a, int b, int c)
+{
+ s64 d = a - b;
+
+ /* { dg-final { scan-assembler "subs\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+, sxtw" } } */
+ if (d == 0)
+ return a + c;
+ else
+ return b + d + c;
+}
+
+int
+subs_shift_ext (s64 a, int b, int c)
+{
+ s64 d = (a - ((s64)b << 3));
+
+ /* { dg-final { scan-assembler "subs\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+, sxtw 3" } } */
+ if (d == 0)
+ return a + c;
+ else
+ return b + d + c;
+}
+
+int main ()
+{
+ int x;
+ s64 y;
+
+ x = subs_ext (0x13000002ll, 41, 15);
+ if (x != 318767121)
+ abort ();
+
+ x = subs_ext (0x50505050ll, 29, 4);
+ if (x != 1347440724)
+ abort ();
+
+ x = subs_ext (0x12121212121ll, 2, 14);
+ if (x != 555819311)
+ abort ();
+
+ x = subs_shift_ext (0x123456789ll, 4, 12);
+ if (x != 591751033)
+ abort ();
+
+ x = subs_shift_ext (0x02020202ll, 9, 8);
+ if (x != 33685963)
+ abort ();
+
+ x = subs_shift_ext (0x987987987987ll, 23, 41);
+ if (x != -2020050673)
+ abort ();
+
+ return 0;
+}