as discussed here https://gcc.gnu.org/ml/gcc-patches/2015-01/msg00563.html
the problem is aarch64 hardware only support left shift truncation for SI/DI, while SHIFT_COUNT_TRUNCATED is enabled for all mode including QI/HI, which is inconsistent with hardware feature. there are two patterns defined for ashift:QI/HI, one for shift amount in register, one for shift amount as constant. this patch only remove the pattern for shift amount in register which cause the trouble. no regression on bare metal test. bootstrap OK. ok for trunk? 2015-01-15 Jiong. Wang (jiong.w...@arm.com) gcc/ PR64304 * config/aarch64/aarch64.md (define_insn "*ashl<mode>3_insn"): Deleted. (ashl<mode>3): Don't expand if operands[2] is not constant. gcc/testsuite/ * gcc.target/aarch64/pr64304.c: New testcase.
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index 597ff8c..49d6690 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -3091,6 +3091,8 @@ DONE; } } + else + DONE; } ) @@ -3315,15 +3317,6 @@ [(set_attr "type" "shift_reg")] ) -(define_insn "*ashl<mode>3_insn" - [(set (match_operand:SHORT 0 "register_operand" "=r") - (ashift:SHORT (match_operand:SHORT 1 "register_operand" "r") - (match_operand:QI 2 "aarch64_reg_or_shift_imm_si" "rUss")))] - "" - "lsl\\t%<w>0, %<w>1, %<w>2" - [(set_attr "type" "shift_reg")] -) - (define_insn "*<optab><mode>3_insn" [(set (match_operand:SHORT 0 "register_operand" "=r") (ASHIFT:SHORT (match_operand:SHORT 1 "register_operand" "r") diff --git a/gcc/testsuite/gcc.target/aarch64/pr64304.c b/gcc/testsuite/gcc.target/aarch64/pr64304.c new file mode 100644 index 0000000..5423bb3 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/pr64304.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 --save-temps" } */ + +unsigned char byte = 0; + +void +set_bit (unsigned int bit, unsigned char value) +{ + unsigned char mask = (unsigned char) (1 << (bit & 7)); + + if (! value) + byte &= (unsigned char)~mask; + else + byte |= mask; + /* { dg-final { scan-assembler "and\tw\[0-9\]+, w\[0-9\]+, 7" } } */ +} + +/* { dg-final { cleanup-saved-temps } } */