Hi, Since a recent change to the tree optimizers https://gcc.gnu.org/ml/gcc-patches/2015-05/msg00089.html some related SH patterns stopped working. The attached patch fixes this.
Tested briefly with 'make all' and with make -k check-gcc RUNTESTFLAGS="sh.exp=pr54236* --target_board=sh-sim \{-m2/-ml,-m2/-mb,-m2a/-mb,-m4/-ml,-m4/-mb,-m4a/-ml,-m4a/-mb}" Committed as r223346. Cheers, Oleg gcc/ChangeLog: PR target/54236 * config/sh/sh.md (*round_int_even): New insn_and_split and accompanying new unnamed split. gcc/testsuite/ChangeLog: PR target/54236 * gcc.target/sh/pr54236-2.c: Adjust expected insn counts.
Index: gcc/testsuite/gcc.target/sh/pr54236-2.c =================================================================== --- gcc/testsuite/gcc.target/sh/pr54236-2.c (revision 223273) +++ gcc/testsuite/gcc.target/sh/pr54236-2.c (working copy) @@ -4,12 +4,19 @@ /* { dg-do compile } */ /* { dg-options "-O1" } */ /* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */ -/* { dg-final { scan-assembler-times "addc" 37 } } */ -/* { dg-final { scan-assembler-times "shlr" 23 } } */ +/* { dg-final { scan-assembler-times "addc" 36 } } */ +/* { dg-final { scan-assembler-times "shlr" 22 } } */ /* { dg-final { scan-assembler-times "shll" 14 } } */ -/* { dg-final { scan-assembler-times "add\t" 12 } } */ +/* { dg-final { scan-assembler-times "add\tr" 12 } } */ /* { dg-final { scan-assembler-not "movt" } } */ +/* { dg-final { scan-assembler-times "add\t#1" 1 } } */ + +/* { dg-final { scan-assembler-times "mov\t#-2" 1 { target { ! sh2a } } } } */ +/* { dg-final { scan-assembler-times "and\tr" 1 { target { ! sh2a } } } } */ + +/* { dg-final { scan-assembler-times "bclr\t#0" 1 { target { sh2a } } } } */ + int test_000 (int a, int c, int b, int d) { @@ -125,7 +132,8 @@ int test_016 (int a, int b, int c, int d) { - // 1x shlr, 1x addc + // non-SH2A: 1x add #1, 1x mov #-2, 1x and + // SH2A: 1x add #1, 1x blcr #0 return a + (a & 1); } Index: gcc/config/sh/sh.md =================================================================== --- gcc/config/sh/sh.md (revision 223274) +++ gcc/config/sh/sh.md (working copy) @@ -1998,6 +1998,44 @@ [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2))) (set (match_dup 0) (plus:SI (match_dup 0) (const_int 1)))]) + +;; The tree optimiziers canonicalize +;; reg + (reg & 1) +;; into +;; (reg + 1) & -2 +;; +;; On SH2A an add-bclr sequence will be used to handle this. +;; On non-SH2A re-emit the add-and sequence to improve register utilization. +(define_insn_and_split "*round_int_even" + [(set (match_operand:SI 0 "arith_reg_dest") + (and:SI (plus:SI (match_operand:SI 1 "arith_reg_operand") + (const_int 1)) + (const_int -2)))] + "TARGET_SH1 && !TARGET_SH2A && can_create_pseudo_p ()" + "#" + "&& 1" + [(set (match_dup 0) (const_int -2)) + (set (match_dup 2) (plus:SI (match_dup 1) (const_int 1))) + (set (match_dup 0) (and:SI (match_dup 0) (match_dup 2)))] +{ + operands[2] = gen_reg_rtx (SImode); +}) + +;; If the *round_int_even pattern is combined with another plus, +;; convert it into an addc pattern to emit an shlr-addc sequence. +;; This split is taken by combine on non-SH2A and SH2A. +(define_split + [(set (match_operand:SI 0 "arith_reg_dest") + (plus:SI (and:SI (plus:SI (match_operand:SI 1 "arith_reg_operand") + (const_int 1)) + (const_int -2)) + (match_operand:SI 2 "arith_reg_operand")))] + "TARGET_SH1 && can_create_pseudo_p ()" + [(parallel [(set (match_dup 0) + (plus:SI (plus:SI (match_dup 1) (match_dup 2)) + (and:SI (match_dup 1) (const_int 1)))) + (clobber (reg:SI T_REG))])]) + ;; Split 'reg + T' into 'reg + 0 + T' to utilize the addc insn. ;; If the 0 constant can be CSE-ed, this becomes a one instruction ;; operation, as opposed to sequences such as