This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH, AArch64] Negate and set flags in shift mode
- From: "Hurugalawadi, Naveen" <Naveen dot Hurugalawadi at caviumnetworks dot com>
- To: "gcc-patches at gcc dot gnu dot org" <gcc-patches at gcc dot gnu dot org>
- Date: Wed, 10 Apr 2013 10:32:55 +0000
- Subject: [PATCH, AArch64] Negate and set flags in shift mode
Hi,
Please find attached the patch that implements negs instruction
with shift for aarch64 target.
Testcase have been added for negs instruction.
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-10 Naveen H.S <Naveen.Hurugalawadi@caviumnetworks.com>
* config/aarch64/aarch64.c (aarch64_select_cc_mode): Allow NEG
code in CC_NZ mode.
* config/aarch64/aarch64.md (*neg_<shift><mode>3_compare0): New
pattern.
gcc/testsuite/
2013-04-10 Naveen H.S <Naveen.Hurugalawadi@caviumnetworks.com>
* gcc.target/aarch64/negs.c: New.
--- gcc/config/aarch64/aarch64.c 2013-04-09 11:58:48.650789435 +0530
+++ gcc/config/aarch64/aarch64.c 2013-04-10 15:42:42.493294822 +0530
@@ -3087,7 +3087,8 @@ aarch64_select_cc_mode (RTX_CODE code, r
if ((GET_MODE (x) == SImode || GET_MODE (x) == DImode)
&& y == const0_rtx
&& (code == EQ || code == NE || code == LT || code == GE)
- && (GET_CODE (x) == PLUS || GET_CODE (x) == MINUS || GET_CODE (x) == AND))
+ && (GET_CODE (x) == PLUS || GET_CODE (x) == MINUS || GET_CODE (x) == AND
+ || GET_CODE (x) == NEG))
return CC_NZmode;
/* A compare with a shifted operand. Because of canonicalization,
--- gcc/config/aarch64/aarch64.md 2013-04-09 11:58:48.646789435 +0530
+++ gcc/config/aarch64/aarch64.md 2013-04-10 15:43:31.213294725 +0530
@@ -1901,6 +1901,21 @@
(set_attr "mode" "SI")]
)
+(define_insn "*neg_<shift><mode>3_compare0"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ
+ (neg:GPI (ASHIFT:GPI
+ (match_operand:GPI 1 "register_operand" "r")
+ (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
+ (const_int 0)))
+ (set (match_operand:GPI 0 "register_operand" "=r")
+ (neg:GPI (ASHIFT:GPI (match_dup 1) (match_dup 2))))]
+ ""
+ "negs\\t%<w>0, %<w>1, <shift> %2"
+ [(set_attr "v8type" "alus_shift")
+ (set_attr "mode" "<MODE>")]
+)
+
(define_insn "*neg_<shift>_<mode>2"
[(set (match_operand:GPI 0 "register_operand" "=r")
(neg:GPI (ASHIFT:GPI
--- gcc/testsuite/gcc.target/aarch64/negs.c 1970-01-01 05:30:00.000000000 +0530
+++ gcc/testsuite/gcc.target/aarch64/negs.c 2013-04-10 15:44:28.981294610 +0530
@@ -0,0 +1,108 @@
+/* { dg-do run } */
+/* { dg-options "-O2 --save-temps" } */
+
+extern void abort (void);
+int z;
+
+int
+negs_si_test1 (int a, int b, int c)
+{
+ int d = -b;
+
+ /* { dg-final { scan-assembler "negs\tw\[0-9\]+, w\[0-9\]+" } } */
+ if (d < 0)
+ return a + c;
+
+ z = d;
+ return b + c + d;
+}
+
+int
+negs_si_test3 (int a, int b, int c)
+{
+ int d = -(b) << 3;
+
+ /* { dg-final { scan-assembler "negs\tw\[0-9\]+, w\[0-9\]+, lsl 3" } } */
+ if (d == 0)
+ return a + c;
+
+ z = d;
+ return b + c + d;
+}
+
+typedef long long s64;
+s64 zz;
+
+s64
+negs_di_test1 (s64 a, s64 b, s64 c)
+{
+ s64 d = -b;
+
+ /* { dg-final { scan-assembler "negs\tx\[0-9\]+, x\[0-9\]+" } } */
+ if (d < 0)
+ return a + c;
+
+ zz = d;
+ return b + c + d;
+}
+
+s64
+negs_di_test3 (s64 a, s64 b, s64 c)
+{
+ s64 d = -(b) << 3;
+
+ /* { dg-final { scan-assembler "negs\tx\[0-9\]+, x\[0-9\]+, lsl 3" } } */
+ if (d == 0)
+ return a + c;
+
+ zz = d;
+ return b + c + d;
+}
+
+int main ()
+{
+ int x;
+ s64 y;
+
+ x = negs_si_test1 (2, 12, 5);
+ if (x != 7)
+ abort ();
+
+ x = negs_si_test1 (1, 2, 32);
+ if (x != 33)
+ abort ();
+
+ x = negs_si_test3 (13, 14, 5);
+ if (x != -93)
+ abort ();
+
+ x = negs_si_test3 (15, 21, 2);
+ if (x != -145)
+ abort ();
+
+ y = negs_di_test1 (0x20202020ll,
+ 0x65161611ll,
+ 0x42434243ll);
+ if (y != 0x62636263ll)
+ abort ();
+
+ y = negs_di_test1 (0x1010101010101ll,
+ 0x123456789abcdll,
+ 0x5555555555555ll);
+ if (y != 0x6565656565656ll)
+ abort ();
+
+ y = negs_di_test3 (0x62523781ll,
+ 0x64234978ll,
+ 0x12345123ll);
+ if (y != 0xfffffffd553d4edbll)
+ abort ();
+
+ y = negs_di_test3 (0x763526268ll,
+ 0x101010101ll,
+ 0x222222222ll);
+ if (y != 0xfffffffb1b1b1b1bll)
+ abort ();
+
+ return 0;
+}