]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
[AArch64] Fix wrong-code bug in right-shift SISD patterns
authorKyrylo Tkachov <kyrylo.tkachov@arm.com>
Fri, 20 Feb 2015 14:23:02 +0000 (14:23 +0000)
committerKyrylo Tkachov <ktkachov@gcc.gnu.org>
Fri, 20 Feb 2015 14:23:02 +0000 (14:23 +0000)
Backport from mainline
2015-02-20  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>

* config/aarch64/aarch64.md (*aarch64_lshr_sisd_or_int_<mode>3):
Mark operand 0 as earlyclobber in 2nd alternative.
(1st define_split below *aarch64_lshr_sisd_or_int_<mode>3):
Write negated shift amount into QI lowpart operand 0 and use it
in the shift step.
(2nd define_split below *aarch64_lshr_sisd_or_int_<mode>3): Likewise.

* gcc.target/aarch64/sisd-shft-neg_1.c: New test.

From-SVN: r220863

gcc/ChangeLog
gcc/config/aarch64/aarch64.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/aarch64/sisd-shft-neg_1.c [new file with mode: 0644]

index 870044f241158d9281ec0955f1fce3fbebd8e448..098531d7952d22b2f72741d479db3f538d358e96 100644 (file)
@@ -1,3 +1,15 @@
+2015-02-20  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
+
+       Backport from mainline
+       2015-02-20  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
+
+       * config/aarch64/aarch64.md (*aarch64_lshr_sisd_or_int_<mode>3):
+       Mark operand 0 as earlyclobber in 2nd alternative.
+       (1st define_split below *aarch64_lshr_sisd_or_int_<mode>3):
+       Write negated shift amount into QI lowpart operand 0 and use it
+       in the shift step.
+       (2nd define_split below *aarch64_lshr_sisd_or_int_<mode>3): Likewise.
+
 2015-02-20  Georg-Johann Lay  <avr@gjlay.de>
 
        Backport from 2015-02-20 trunk r220847.
index 46d9e9f7b994e8ea740d8b276f3a3fa910042c1a..9c096c2c86aeaa30b568eced819495155d1f6b40 100644 (file)
 
 ;; Logical right shift using SISD or Integer instruction
 (define_insn "*aarch64_lshr_sisd_or_int_<mode>3"
-  [(set (match_operand:GPI 0 "register_operand" "=w,w,r")
+  [(set (match_operand:GPI 0 "register_operand" "=w,&w,r")
         (lshiftrt:GPI
           (match_operand:GPI 1 "register_operand" "w,w,r")
           (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,w,rUs<cmode>")))]
            (match_operand:DI 1 "aarch64_simd_register")
            (match_operand:QI 2 "aarch64_simd_register")))]
   "TARGET_SIMD && reload_completed"
-  [(set (match_dup 2)
+  [(set (match_dup 3)
         (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
    (set (match_dup 0)
-        (unspec:DI [(match_dup 1) (match_dup 2)] UNSPEC_SISD_USHL))]
-  ""
+        (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_SISD_USHL))]
+  {
+    operands[3] = gen_lowpart (QImode, operands[0]);
+  }
 )
 
 (define_split
            (match_operand:SI 1 "aarch64_simd_register")
            (match_operand:QI 2 "aarch64_simd_register")))]
   "TARGET_SIMD && reload_completed"
-  [(set (match_dup 2)
+  [(set (match_dup 3)
         (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
    (set (match_dup 0)
-        (unspec:SI [(match_dup 1) (match_dup 2)] UNSPEC_USHL_2S))]
-  ""
+        (unspec:SI [(match_dup 1) (match_dup 3)] UNSPEC_USHL_2S))]
+  {
+    operands[3] = gen_lowpart (QImode, operands[0]);
+  }
 )
 
 ;; Arithmetic right shift using SISD or Integer instruction
index 4f61162be080a44dc6e2830aabeb7fa5d28d3c07..db8b0827e7e73fd02a5eff69bf595550c6200ff0 100644 (file)
@@ -1,3 +1,10 @@
+2015-02-20  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
+
+       Backport from mainline
+       2015-02-20  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
+
+       * gcc.target/aarch64/sisd-shft-neg_1.c: New test.
+
 2015-02-20  Georg-Johann Lay  <avr@gjlay.de>
 
        Backport from 2015-02-20 trunk r220847.
diff --git a/gcc/testsuite/gcc.target/aarch64/sisd-shft-neg_1.c b/gcc/testsuite/gcc.target/aarch64/sisd-shft-neg_1.c
new file mode 100644 (file)
index 0000000..c091657
--- /dev/null
@@ -0,0 +1,38 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-inline" } */
+
+extern void abort (void);
+
+#define force_simd_si(v) asm volatile ("mov %s0, %1.s[0]" :"=w" (v) :"w" (v) :)
+
+unsigned int
+shft_add (unsigned int a, unsigned int b)
+{
+  unsigned int c;
+
+  force_simd_si (a);
+  force_simd_si (b);
+  c = a >> b;
+  force_simd_si (c);
+
+  return c + b;
+}
+
+int
+main (void)
+{
+  unsigned int i = 0;
+  unsigned int a = 0xdeadbeef;
+
+  for (i = 0; i < 32; i++)
+  {
+    unsigned int exp = (a / (1 << i) + i);
+    unsigned int got = shft_add (a, i);
+
+    if (exp != got)
+      abort ();
+  }
+
+  return 0;
+}
+