Hi In aarch64 backend of google/4.9 branch, the split pattern for insn aarch64_lshr_sisd_or_int_<mode>3 destroys one of the source operands, causes the later usage of the operand get a wrong value (google bug 17907351).
The bug has been fixed in trunk by r220860. This patch backports it to google/4.9 branch. It passed regression test on aarch64-qemu. OK for google/4.9? thanks Guozhi Wei Index: config/aarch64/aarch64.md =================================================================== --- config/aarch64/aarch64.md (revision 224524) +++ config/aarch64/aarch64.md (working copy) @@ -2786,7 +2786,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>")))] @@ -2805,11 +2805,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 @@ -2818,11 +2820,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 Index: testsuite/gcc.target/aarch64/sisd-shft-neg_1.c =================================================================== --- testsuite/gcc.target/aarch64/sisd-shft-neg_1.c (revision 0) +++ testsuite/gcc.target/aarch64/sisd-shft-neg_1.c (working copy) @@ -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; +} +