diff options
author | Oleg Endo <olegendo@gcc.gnu.org> | 2012-03-05 23:12:20 +0000 |
---|---|---|
committer | Oleg Endo <olegendo@gcc.gnu.org> | 2012-03-05 23:12:20 +0000 |
commit | 9747719a9c9483c66daa25943dd4f9bebd8f23b3 (patch) | |
tree | 6ee019d6d59407d9f58c395a24e16b730c0a5c6b /gcc | |
parent | 5de724244f16e91b67997df6edab0faad7b2c97d (diff) | |
download | gcc-9747719a9c9483c66daa25943dd4f9bebd8f23b3.zip gcc-9747719a9c9483c66daa25943dd4f9bebd8f23b3.tar.gz gcc-9747719a9c9483c66daa25943dd4f9bebd8f23b3.tar.bz2 |
re PR target/51244 ([SH] Inefficient conditional branch and code around T bit)
PR target/51244
* config/sh/sh.c (sh_expand_t_scc): Remove SH2A special case
and use unified expansion logic.
* config/sh/sh.md (xorsi3_movrt): Rename to movrt. Move
closer to the existing movt insn.
(negc): Rename insn to *negc. Add new expander.
(movnegt): Use xor pattern for T bit negation. Reserve helper
constant for negc pattern.
(*movnegt): New insn and splitter.
PR target/51244
* gcc.target/sh/pr51244-1.c: New.
* gcc.target/sh/pr51244-2.c: New.
* gcc.target/sh/pr51244-3.c: New.
From-SVN: r184966
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/config/sh/sh.c | 9 | ||||
-rw-r--r-- | gcc/config/sh/sh.md | 95 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/sh/pr48596.c | 31 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/sh/pr51244-1.c | 32 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/sh/pr51244-2.c | 18 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/sh/pr51244-3.c | 16 |
8 files changed, 176 insertions, 44 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8897a63..2f10f58 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2012-03-06 Oleg Endo <olegendo@gcc.gnu.org> + + PR target/51244 + * config/sh/sh.c (sh_expand_t_scc): Remove SH2A special case + and use unified expansion logic. + * config/sh/sh.md (xorsi3_movrt): Rename to movrt. Move + closer to the existing movt insn. + (negc): Rename insn to *negc. Add new expander. + (movnegt): Use xor pattern for T bit negation. Reserve helper + constant for negc pattern. + (*movnegt): New insn and splitter. + 2012-03-05 Bernd Schmidt <bernds@codesourcery.com> * c-typeck.c (pointer_diff): Check for POINTER_PLUS_EXPR, not diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index 0bcebdf..4c2d710 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -11888,15 +11888,8 @@ sh_expand_t_scc (rtx operands[]) val = INTVAL (op1); if ((code == EQ && val == 1) || (code == NE && val == 0)) emit_insn (gen_movt (result)); - else if (TARGET_SH2A && ((code == EQ && val == 0) - || (code == NE && val == 1))) - emit_insn (gen_xorsi3_movrt (result)); else if ((code == EQ && val == 0) || (code == NE && val == 1)) - { - emit_clobber (result); - emit_insn (gen_subc (result, result, result)); - emit_insn (gen_addsi3 (result, result, const1_rtx)); - } + emit_insn (gen_movnegt (result)); else if (code == EQ || code == NE) emit_insn (gen_move_insn (result, GEN_INT (code == NE))); else diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md index 6a25b9d..eb1c852 100644 --- a/gcc/config/sh/sh.md +++ b/gcc/config/sh/sh.md @@ -3354,15 +3354,6 @@ label: xori %1, %2, %0" [(set_attr "type" "arith_media")]) -;; Store the complements of the T bit in a register. -(define_insn "xorsi3_movrt" - [(set (match_operand:SI 0 "arith_reg_dest" "=r") - (xor:SI (reg:SI T_REG) - (const_int 1)))] - "TARGET_SH2A" - "movrt\\t%0" - [(set_attr "type" "arith")]) - (define_insn "xordi3" [(set (match_operand:DI 0 "arith_reg_dest" "=r,r") (xor:DI (match_operand:DI 1 "arith_reg_operand" "%r,r") @@ -4387,7 +4378,17 @@ label: ;; Unary arithmetic ;; ------------------------------------------------------------------------- -(define_insn "negc" +(define_expand "negc" + [(parallel [(set (match_operand:SI 0 "arith_reg_dest" "") + (neg:SI (plus:SI (reg:SI T_REG) + (match_operand:SI 1 "arith_reg_operand" "")))) + (set (reg:SI T_REG) + (ne:SI (ior:SI (reg:SI T_REG) (match_dup 1)) + (const_int 0)))])] + "" + "") + +(define_insn "*negc" [(set (match_operand:SI 0 "arith_reg_dest" "=r") (neg:SI (plus:SI (reg:SI T_REG) (match_operand:SI 1 "arith_reg_operand" "r")))) @@ -9528,6 +9529,13 @@ mov.l\\t1f,r0\\n\\ "movt %0" [(set_attr "type" "arith")]) +(define_insn "movrt" + [(set (match_operand:SI 0 "arith_reg_dest" "=r") + (xor:SI (reg:SI T_REG) (const_int 1)))] + "TARGET_SH2A" + "movrt %0" + [(set_attr "type" "arith")]) + (define_expand "cstore4_media" [(set (match_operand:SI 0 "register_operand" "=r") (match_operator:SI 1 "sh_float_comparison_operator" @@ -9654,40 +9662,55 @@ mov.l\\t1f,r0\\n\\ DONE; ") -;; sne moves the complement of the T reg to DEST like this: -;; cmp/eq ... -;; mov #-1,temp -;; negc temp,dest -;; This is better than xoring compare result with 1 because it does -;; not require r0 and further, the -1 may be CSE-ed or lifted out of a -;; loop. +;; Move the complement of the T reg to a reg. +;; On SH2A the movrt insn can be used. +;; On anything else than SH2A this has to be done with multiple instructions. +;; One obvious way would be: +;; cmp/eq ... +;; movt r0 +;; xor #1,r0 +;; +;; However, this puts pressure on r0 in most cases and thus the following is +;; more appealing: +;; cmp/eq ... +;; mov #-1,temp +;; negc temp,dest +;; +;; If the constant -1 can be CSE-ed or lifted out of a loop it effectively +;; becomes a one instruction operation. Moreover, care must be taken that +;; the insn can still be combined with inverted compare and branch code +;; around it. +;; The expander will reserve the constant -1, the insn makes the whole thing +;; combinable, the splitter finally emits the insn if it was not combined +;; away. +;; Notice that when using the negc variant the T bit also gets inverted. (define_expand "movnegt" [(set (match_dup 1) (const_int -1)) - (parallel [(set (match_operand:SI 0 "" "") - (neg:SI (plus:SI (reg:SI T_REG) - (match_dup 1)))) - (set (reg:SI T_REG) - (ne:SI (ior:SI (reg:SI T_REG) (match_dup 1)) - (const_int 0)))])] + (parallel [(set (match_operand:SI 0 "arith_reg_dest" "") + (xor:SI (reg:SI T_REG) (const_int 1))) + (use (match_dup 1))])] "" - " { operands[1] = gen_reg_rtx (SImode); -}") - -;; Recognize mov #-1/negc/neg sequence, and change it to movt/add #-1. -;; This prevents a regression that occurred when we switched from xor to -;; mov/neg for sne. +}) -(define_split - [(set (match_operand:SI 0 "arith_reg_dest" "") - (plus:SI (reg:SI T_REG) - (const_int -1)))] +(define_insn_and_split "*movnegt" + [(set (match_operand:SI 0 "arith_reg_dest" "=r") + (xor:SI (reg:SI T_REG) (const_int 1))) + (use (match_operand:SI 1 "arith_reg_operand" "r"))] "TARGET_SH1" - [(set (match_dup 0) (eq:SI (reg:SI T_REG) (const_int 1))) - (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))] - "") + "#" + "&& 1" + [(const_int 0)] +{ + if (TARGET_SH2A) + emit_insn (gen_movrt (operands[0])); + else + emit_insn (gen_negc (operands[0], operands[1])); + DONE; +} + [(set_attr "type" "arith")]) (define_expand "cstoresf4" [(set (match_operand:SI 0 "register_operand" "=r") diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5ea082e..b6d68df 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2012-03-06 Oleg Endo <olegendo@gcc.gnu.org> + + PR target/51244 + * gcc.target/sh/pr51244-1.c: New. + * gcc.target/sh/pr51244-2.c: New. + * gcc.target/sh/pr51244-3.c: New. + 2012-03-05 Jason Merrill <jason@redhat.com> PR c++/51930 diff --git a/gcc/testsuite/gcc.target/sh/pr48596.c b/gcc/testsuite/gcc.target/sh/pr48596.c new file mode 100644 index 0000000..3026278 --- /dev/null +++ b/gcc/testsuite/gcc.target/sh/pr48596.c @@ -0,0 +1,31 @@ +/* Check that the following code compiles without errors. */ +/* { dg-do compile { target "sh*-*-*" } } */ +/* { dg-options "-O1" } */ + +enum { nrrdCenterUnknown, nrrdCenterNode, nrrdCenterCell, nrrdCenterLast }; +typedef struct { int size; int center; } NrrdAxis; +typedef struct { int dim; NrrdAxis axis[10]; } Nrrd; +typedef struct { } NrrdKernel; +typedef struct { const NrrdKernel *kernel[10]; int samples[10]; } Info; + +void +foo (Nrrd *nout, Nrrd *nin, const NrrdKernel *kernel, const double *parm, + const int *samples, const double *scalings) +{ + Info *info; + int d, p, np, center; + for (d=0; d<nin->dim; d++) + { + info->kernel[d] = kernel; + if (samples) + info->samples[d] = samples[d]; + else + { + center = _nrrdCenter(nin->axis[d].center); + if (nrrdCenterCell == center) + info->samples[d] = nin->axis[d].size*scalings[d]; + else + info->samples[d] = (nin->axis[d].size - 1)*scalings[d] + 1; + } + } +} diff --git a/gcc/testsuite/gcc.target/sh/pr51244-1.c b/gcc/testsuite/gcc.target/sh/pr51244-1.c new file mode 100644 index 0000000..57af104 --- /dev/null +++ b/gcc/testsuite/gcc.target/sh/pr51244-1.c @@ -0,0 +1,32 @@ +/* Check that inverted conditional branch logic does not generate + unnecessary explicit T bit extractions, inversions and + test instructions. */ +/* { dg-do compile { target "sh*-*-*" } } */ +/* { dg-options "-O1 -mbranch-cost=2" } */ +/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */ +/* { dg-final { scan-assembler-not "tst|negc|extu" } } */ + +int +testfunc_00 (int a, int b, int c, int d) +{ + return (a != b || a != d) ? b : c; +} + +int +testfunc_01 (int a, char* p, int b, int c) +{ + return (a == b && a == c) ? b : c; +} + +int +testfunc_02 (int a, char* p, int b, int c) +{ + return (a == b && a == c) ? b : c; +} + +int +testfunc_03 (int a, char* p, int b, int c) +{ + return (a != b && a != c) ? b : c; +} + diff --git a/gcc/testsuite/gcc.target/sh/pr51244-2.c b/gcc/testsuite/gcc.target/sh/pr51244-2.c new file mode 100644 index 0000000..d984676 --- /dev/null +++ b/gcc/testsuite/gcc.target/sh/pr51244-2.c @@ -0,0 +1,18 @@ +/* Check that when taking the complement of the T bit using the negc + instruction pattern, the constant -1 is loaded only once. + On SH2A this test is skipped because the movrt instruction is used + to get the complement of the T bit. */ +/* { dg-do compile { target "sh*-*-*" } } */ +/* { dg-options "-O1 -mbranch-cost=2" } */ +/* { dg-skip-if "" { "sh*-*-*" } { "-m5*" "-m2a*" } { "" } } */ +/* { dg-final { scan-assembler-times "mov\t#-1" 1 } } */ + +void +testfunc_00 (int* a, int* b, int c, int d) +{ + b[0] = a[0] != c; + b[1] = a[1] != d; + b[2] = a[2] != c; + b[3] = a[3] != d; +} + diff --git a/gcc/testsuite/gcc.target/sh/pr51244-3.c b/gcc/testsuite/gcc.target/sh/pr51244-3.c new file mode 100644 index 0000000..ebb3c3a --- /dev/null +++ b/gcc/testsuite/gcc.target/sh/pr51244-3.c @@ -0,0 +1,16 @@ +/* Check that when taking the complement of the T bit on SH2A, + the movrt instruction is being generated. */ +/* { dg-do compile { target "sh*-*-*" } } */ +/* { dg-options "-O1 -mbranch-cost=2" } */ +/* { dg-skip-if "" { "sh*-*-*" } { "*" } { "-m2a*" } } */ +/* { dg-final { scan-assembler-times "movrt" 4 } } */ + +void +testfunc_00 (int* a, int* b, int c, int d) +{ + b[0] = a[0] != c; + b[1] = a[1] != d; + b[2] = a[2] != c; + b[3] = a[3] != d; +} + |