]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR target/59216 (ARM negdi*extendsidi regression)
authorRichard Earnshaw <rearnsha@arm.com>
Fri, 22 Nov 2013 15:43:11 +0000 (15:43 +0000)
committerRichard Earnshaw <rearnsha@gcc.gnu.org>
Fri, 22 Nov 2013 15:43:11 +0000 (15:43 +0000)
PR target/59216

gcc/
* arm.md (negdi_extendsidi): Fix invalid split.

gcc/testsuite/
* gcc.target/arm/negdi-4.c: Delete invalid test.
* gcc.dg/torture/pr59216.c: New test.

From-SVN: r205271

gcc/ChangeLog
gcc/config/arm/arm.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/torture/pr59216.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/negdi-4.c [deleted file]

index fcfae83e0cd4790a8400a1fa010645a0e42c4a83..c1320a5807b7d509a4f8d1c4468b7eefcb5b201b 100644 (file)
@@ -1,3 +1,8 @@
+2013-11-22  Richard Earnshaw  <rearnsha@arm.com>
+
+       PR target/59216
+       * arm.md (negdi_extendsidi): Fix invalid split.
+
 2013-11-22  Alex Velenko  <Alex.Velenko@arm.com>
 
        * config/aarch64/arm_neon.h (vmov_n_f32): Implemented in C.
index a26550a476a4d4693ec1a4d91f4fcb0ec7aac48f..8e52003af1cf150ab7f61b7784421f2a71b5f97c 100644 (file)
 
 ;; Negate an extended 32-bit value.
 (define_insn_and_split "*negdi_extendsidi"
-  [(set (match_operand:DI 0 "s_register_operand" "=r,&r,l,&l")
-       (neg:DI (sign_extend:DI (match_operand:SI 1 "s_register_operand" "0,r,0,l"))))
+  [(set (match_operand:DI 0 "s_register_operand" "=l,r")
+       (neg:DI (sign_extend:DI
+                (match_operand:SI 1 "s_register_operand" "l,r"))))
    (clobber (reg:CC CC_REGNUM))]
   "TARGET_32BIT"
-  "#" ; rsb\\t%Q0, %1, #0\;asr\\t%R0, %Q0, #31
+  "#"
   "&& reload_completed"
   [(const_int 0)]
   {
-     operands[2] = gen_highpart (SImode, operands[0]);
-     operands[0] = gen_lowpart (SImode, operands[0]);
-     rtx tmp = gen_rtx_SET (VOIDmode,
-                            operands[0],
-                            gen_rtx_MINUS (SImode,
-                                           const0_rtx,
-                                           operands[1]));
-     if (TARGET_ARM)
-       {
-         emit_insn (tmp);
-       }
-     else
-       {
-         /* Set the flags, to emit the short encoding in Thumb2.  */
-         rtx flags = gen_rtx_SET (VOIDmode,
-                                  gen_rtx_REG (CCmode, CC_REGNUM),
-                                  gen_rtx_COMPARE (CCmode,
-                                                   const0_rtx,
-                                                   operands[1]));
-         emit_insn (gen_rtx_PARALLEL (VOIDmode,
-                                      gen_rtvec (2,
-                                                 flags,
-                                                 tmp)));
-       }
-       emit_insn (gen_rtx_SET (VOIDmode,
-                              operands[2],
-                              gen_rtx_ASHIFTRT (SImode,
-                                                operands[0],
-                                                GEN_INT (31))));
-     DONE;
+    rtx low = gen_lowpart (SImode, operands[0]);
+    rtx high = gen_highpart (SImode, operands[0]);
+
+    if (reg_overlap_mentioned_p (low, operands[1]))
+      {
+       /* Input overlaps the low word of the output.  Use:
+               asr     Rhi, Rin, #31
+               rsbs    Rlo, Rin, #0
+               rsc     Rhi, Rhi, #0 (thumb2: sbc Rhi, Rhi, Rhi, lsl #1).  */
+       rtx cc_reg = gen_rtx_REG (CC_Cmode, CC_REGNUM);
+
+       emit_insn (gen_rtx_SET (VOIDmode, high,
+                               gen_rtx_ASHIFTRT (SImode, operands[1],
+                                                 GEN_INT (31))));
+
+       emit_insn (gen_subsi3_compare (low, const0_rtx, operands[1]));
+       if (TARGET_ARM)
+         emit_insn (gen_rtx_SET (VOIDmode, high,
+                                 gen_rtx_MINUS (SImode,
+                                                gen_rtx_MINUS (SImode,
+                                                               const0_rtx,
+                                                               high),
+                                                gen_rtx_LTU (SImode,
+                                                             cc_reg,
+                                                             const0_rtx))));
+       else
+         {
+           rtx two_x = gen_rtx_ASHIFT (SImode, high, GEN_INT (1));
+           emit_insn (gen_rtx_SET (VOIDmode, high,
+                                   gen_rtx_MINUS (SImode,
+                                                  gen_rtx_MINUS (SImode,
+                                                                 high,
+                                                                 two_x),
+                                                  gen_rtx_LTU (SImode,
+                                                               cc_reg,
+                                                               const0_rtx))));
+         }
+      }
+    else
+      {
+       /* No overlap, or overlap on high word.  Use:
+               rsb     Rlo, Rin, #0
+               bic     Rhi, Rlo, Rin
+               asr     Rhi, Rhi, #31
+          Flags not needed for this sequence.  */
+       emit_insn (gen_rtx_SET (VOIDmode, low,
+                               gen_rtx_NEG (SImode, operands[1])));
+       emit_insn (gen_rtx_SET (VOIDmode, high,
+                               gen_rtx_AND (SImode,
+                                            gen_rtx_NOT (SImode, operands[1]),
+                                            low)));
+       emit_insn (gen_rtx_SET (VOIDmode, high,
+                               gen_rtx_ASHIFTRT (SImode, high,
+                                                 GEN_INT (31))));
+      }
+    DONE;
   }
-  [(set_attr "length" "8,8,4,4")
-   (set_attr "arch" "a,a,t2,t2")
+  [(set_attr "length" "12")
+   (set_attr "arch" "t2,*")
    (set_attr "type" "multiple")]
 )
 
index 270c53cbc5bec236c6907c105524f54bd543f316..38c359e1fe0379be6f9497573c5376a2c51584c0 100644 (file)
@@ -1,3 +1,9 @@
+2013-11-22  Richard Earnshaw  <rearnsha@arm.com>
+
+       PR target/59216
+       * gcc.target/arm/negdi-4.c: Delete invalid test.
+       * gcc.dg/torture/pr59216.c: New test.
+
 2013-11-22  Alex Velenko  <Alex.Velenko@arm.com>
 
        * gcc.target/aarch64/vmov_n_1.c: New testcase.
diff --git a/gcc/testsuite/gcc.dg/torture/pr59216.c b/gcc/testsuite/gcc.dg/torture/pr59216.c
new file mode 100644 (file)
index 0000000..0de51ba
--- /dev/null
@@ -0,0 +1,32 @@
+/* { dg-do run } */
+
+#include <limits.h>
+
+extern void abort (void);
+extern void exit (int);
+
+long long __attribute__((noinline)) f(int a)
+{
+  return -(long long) a;
+}
+
+int
+main()
+{
+  if (f(0) != 0)
+    abort ();
+
+  if (f(1) != -(long long)1)
+    abort ();
+
+  if (f(-1) != -(long long)-1)
+    abort ();
+
+  if (f(INT_MIN) != -(long long)INT_MIN)
+    abort ();
+
+  if (f(INT_MAX) != -(long long)INT_MAX)
+    abort ();
+
+  exit (0);
+}
diff --git a/gcc/testsuite/gcc.target/arm/negdi-4.c b/gcc/testsuite/gcc.target/arm/negdi-4.c
deleted file mode 100644 (file)
index dc3deaa..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/* { dg-do compile } */
-/* { dg-require-effective-target arm32 } */
-/* { dg-options "-O2" } */
-
-signed long long negdi_extendsidi (signed int x)
-{
-  return -((signed long long) x);
-}
-/*
-Expected output:
-        rsbs    r0, r0, #0
-        mov     r1, r0, asr #31
-*/
-/* { dg-final { scan-assembler-times "rsb" 1 } } */
-/* { dg-final { scan-assembler-times "asr" 1 } } */
-/* { dg-final { scan-assembler-times "rsc" 0 } } */