diff options
author | Oleg Endo <olegendo@gcc.gnu.org> | 2012-11-03 12:01:01 +0000 |
---|---|---|
committer | Oleg Endo <olegendo@gcc.gnu.org> | 2012-11-03 12:01:01 +0000 |
commit | 4aaf79c2cfeed3c57e923995a02fbe25d592bf25 (patch) | |
tree | ef0d9e9173002423f55c425d4b7c49f155dccdfc /gcc | |
parent | 49503de9a9ccdfab8247742065896d59f48a9022 (diff) | |
download | gcc-4aaf79c2cfeed3c57e923995a02fbe25d592bf25.zip gcc-4aaf79c2cfeed3c57e923995a02fbe25d592bf25.tar.gz gcc-4aaf79c2cfeed3c57e923995a02fbe25d592bf25.tar.bz2 |
re PR target/51244 ([SH] Inefficient conditional branch and code around T bit)
PR target/51244
* config/sh/sh.md (*cbranch_t): Allow splitting after reload.
Allow going beyond current basic block before reload when looking for
the reg set insn.
* config/sh/sh.c (sh_find_set_of_reg): Don't stop at labels.
PR target/51244
* gcc.target/sh/pr51244-18.c: New.
* gcc.target/sh/pr51244-19.c: New.
From-SVN: r193119
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/config/sh/sh.c | 2 | ||||
-rw-r--r-- | gcc/config/sh/sh.md | 9 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/sh/pr51244-18.c | 102 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/sh/pr51244-19.c | 75 |
6 files changed, 199 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 59a51f3..8af3547 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2012-11-03 Oleg Endo <olegendo@gcc.gnu.org> + + PR target/51244 + * config/sh/sh.md (*cbranch_t): Allow splitting after reload. + Allow going beyond current basic block before reload when looking for + the reg set insn. + * config/sh/sh.c (sh_find_set_of_reg): Don't stop at labels. + 2012-11-02 Jan Hubicka <jh@suse.cz> * tree-ssa-loop-niter.c (discover_iteration_bound_by_body_walk): Add diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index 40afdb4..25573b3 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -13486,7 +13486,7 @@ sh_find_set_of_reg (rtx reg, rtx insn, rtx(*stepfunc)(rtx)) for (result.insn = stepfunc (insn); result.insn != NULL_RTX; result.insn = stepfunc (result.insn)) { - if (LABEL_P (result.insn) || BARRIER_P (result.insn)) + if (BARRIER_P (result.insn)) return result; if (!NONJUMP_INSN_P (result.insn)) continue; diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md index 6b1fdbe..a002304 100644 --- a/gcc/config/sh/sh.md +++ b/gcc/config/sh/sh.md @@ -8167,13 +8167,15 @@ label: { return output_branch (sh_eval_treg_value (operands[1]), insn, operands); } - "&& can_create_pseudo_p ()" + "&& 1" [(set (pc) (if_then_else (eq (reg:SI T_REG) (match_dup 2)) (label_ref (match_dup 0)) (pc)))] { /* Try to find missed test and branch combine opportunities which result in redundant T bit tests before conditional branches. + This is done not only after combine (and before reload) but in every + split pass, because some opportunities are formed also after combine. FIXME: Probably this would not be needed if CCmode was used together with TARGET_FIXED_CONDITION_CODE_REGS. */ @@ -8212,8 +8214,11 @@ label: while (true) { + /* It's not safe to go beyond the current basic block after reload. */ set_of_reg s1 = sh_find_set_of_reg (tested_reg, s0.insn, - prev_nonnote_insn_bb); + reload_completed + ? prev_nonnote_insn_bb + : prev_nonnote_insn); if (s1.set_src == NULL_RTX) break; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 8722826..2f5d1f7 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2012-11-03 Oleg Endo <olegendo@gcc.gnu.org> + + PR target/51244 + * gcc.target/sh/pr51244-18.c: New. + * gcc.target/sh/pr51244-19.c: New. + 2012-11-03 Richard Sandiford <rdsandiford@googlemail.com> * gcc.target/mips/octeon-exts-7.c (bar): Make sure the extraction of diff --git a/gcc/testsuite/gcc.target/sh/pr51244-18.c b/gcc/testsuite/gcc.target/sh/pr51244-18.c new file mode 100644 index 0000000..dbfb990 --- /dev/null +++ b/gcc/testsuite/gcc.target/sh/pr51244-18.c @@ -0,0 +1,102 @@ +/* Check that no unnecessary T bit stores are done before conditional + branches. + This case was extracted from the CSiBE set and contained the following + sequence: + cmp/hi r1,r0 + movt r1 + tst r1,r1 + bt .L12 + mov.l @r10,r1 + In this reduced code the movt and tst insns were only present in the + unwanted sequence. Thus, if we see any tst or movt insns, something is + not working as expected. This test requires -O2 because the T bit stores + in question will be eliminated in additional insn split passes after + reload. */ +/* { dg-do compile { target "sh*-*-*" } } */ +/* { dg-options "-O2" } */ +/* { dg-skip-if "" { "sh*-*-*" } { "-m5*" } { "" } } */ +/* { dg-final { scan-assembler-not "movt|tst" } } */ + +typedef char Char; +typedef unsigned char Bool; +typedef unsigned char UChar; +typedef int Int32; +typedef unsigned int UInt32; +typedef short Int16; +typedef unsigned short UInt16; + +static inline Bool +mainGtU (UInt32 i1, UInt32 i2, UChar* block, UInt16* quadrant, UInt32 nblock, + Int32* budget) +{ + Int32 k; + UChar c1, c2; + UInt16 s1, s2; + k = nblock + 8; + do + { + c1 = block[i1]; + c2 = block[i2]; + if (c1 != c2) + return (c1 > c2); + s1 = quadrant[i1]; + s2 = quadrant[i2]; + if (s1 != s2) + return (s1 > s2); + + i1++; i2++; + k -= 8; + } while (k >= 0); + + return 0; +} + +static inline void +mainSimpleSort (UInt32* ptr, UChar* block, UInt16* quadrant, Int32 nblock, + Int32 lo, Int32 hi, Int32 d, Int32* budget) +{ + Int32 i, j, h, bigN, hp; + UInt32 v; + bigN = hi - lo + 1; + hp = 0; + h = 1; + j = lo + h; + v = ptr[j]; + + while (mainGtU (ptr[j-h]+d, v+d, block, quadrant, nblock, budget)) + { + ptr[j] = ptr[j-h]; + j = j - h; + } +} + +static inline void +mainQSort3 (UInt32* ptr, UChar* block, UInt16* quadrant, Int32 nblock, + Int32 loSt, Int32 hiSt, Int32 dSt, Int32* budget) +{ + Int32 unLo, unHi, ltLo, gtHi; + Int32 sp, lo, hi, d; + + Int32 stackLo[100]; + Int32 stackHi[100]; + Int32 stackD [100]; + + sp = 0; + stackLo[sp] = loSt; + stackHi[sp] = hiSt; + stackD [sp] = dSt; + lo = stackLo[sp]; + hi = stackHi[sp]; + d = stackD [sp]; + mainSimpleSort (ptr, block, quadrant, nblock, lo, hi, d, budget); +} + +void +mainSort (UInt32* ptr, UChar* block, UInt16* quadrant, UInt32* ftab, + Int32 nblock, Int32 verb, Int32* budget) +{ + Int32 sb = 0; + Int32 lo = ftab[sb] & (~((1 << 21))); + Int32 hi = (ftab[sb+1] & (~((1 << 21)))) - 1; + mainQSort3 (ptr, block, quadrant, nblock, lo, hi, 2, budget); +} diff --git a/gcc/testsuite/gcc.target/sh/pr51244-19.c b/gcc/testsuite/gcc.target/sh/pr51244-19.c new file mode 100644 index 0000000..4d4f781 --- /dev/null +++ b/gcc/testsuite/gcc.target/sh/pr51244-19.c @@ -0,0 +1,75 @@ +/* Check that no unnecessary T bit stores are done before conditional + branches. + This case was extracted from the CSiBE set and contained the following + sequence: + mov.l @(8,r4),r2 + mov.l @(4,r4),r3 + cmp/gt r2,r3 + movt r2 +.L3: + tst r2,r2 + bt/s .L12 + mov #-1,r0 + + ..... + + mov.l @r4,r2 + tst r2,r2 + bra .L3 + movt r2 + + In this reduced code the movt insns were only present in the + unwanted sequences. Thus, if we see any movt insns, something is not + working as expected. This test requires -O2 because the T bit stores + in question will be eliminated in additional insn split passes after + reload. */ +/* { dg-do compile { target "sh*-*-*" } } */ +/* { dg-options "-O2" } */ +/* { dg-skip-if "" { "sh*-*-*" } { "-m5*" } { "" } } */ +/* { dg-final { scan-assembler-not "movt" } } */ + +struct request +{ + unsigned long nr_sectors; +}; + +struct request_list +{ + int count; +}; + +struct request_queue +{ + struct request_list rq; + volatile int nr_sectors; + int max_queue_sectors; + int can_throttle; + unsigned long bounce_pfn; +}; + +typedef struct request_queue request_queue_t; + +static inline int +blk_oversized_queue (request_queue_t* q) +{ + if (q->can_throttle) + return q->nr_sectors > q->max_queue_sectors; + return q->rq.count == 0; +} + +struct request* +get_request (request_queue_t* q, int rw) +{ + struct request* rq = ((void*)0); + struct request_list *rl = &q->rq; + + if (blk_oversized_queue (q)) + { + if ((rw == 1) || (rw == 0)) + return ((void*)0); + if (blk_oversized_queue (q)) + return ((void*)0); + } + + return (void*)-100; +} |