aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKyrylo Tkachov <kyrylo.tkachov@arm.com>2015-02-20 14:05:51 +0000
committerKyrylo Tkachov <ktkachov@gcc.gnu.org>2015-02-20 14:05:51 +0000
commit498b13e24b8a995dd3bb6f0bb734f15b78ef89d1 (patch)
tree4cf8cd26b5ea9500187020a5b5fad34f124e8436
parent739b41ebb1350735fe3aa92c1978524204395df8 (diff)
downloadgcc-498b13e24b8a995dd3bb6f0bb734f15b78ef89d1.zip
gcc-498b13e24b8a995dd3bb6f0bb734f15b78ef89d1.tar.gz
gcc-498b13e24b8a995dd3bb6f0bb734f15b78ef89d1.tar.bz2
[AArch64] Fix wrong-code bug in right-shift SISD patterns
* 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: r220860
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/config/aarch64/aarch64.md18
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sisd-shft-neg_1.c38
4 files changed, 62 insertions, 7 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a899997..32cc757 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+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 Bernd Schmidt <bernds@codesourcery.com>
* cgraph.h (clone_function_name_1): Declare.
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index 1f4169e..8f157ce2 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -3360,7 +3360,7 @@
;; 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>")))]
@@ -3379,11 +3379,13 @@
(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
@@ -3392,11 +3394,13 @@
(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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 2409cfb..65310fd 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+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>
PR target/64452
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
index 0000000..c091657
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sisd-shft-neg_1.c
@@ -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;
+}
+