diff options
author | Oleg Endo <olegendo@gcc.gnu.org> | 2012-10-12 00:41:23 +0000 |
---|---|---|
committer | Oleg Endo <olegendo@gcc.gnu.org> | 2012-10-12 00:41:23 +0000 |
commit | b4eca9c8df76d36dc7bb909424e0cc5a0d52d095 (patch) | |
tree | 962653c07a00c814ead771a9568becdae982ddb7 /gcc/testsuite | |
parent | 76a2a3f738f94ff070c2e4179951f8579f70555e (diff) | |
download | gcc-b4eca9c8df76d36dc7bb909424e0cc5a0d52d095.zip gcc-b4eca9c8df76d36dc7bb909424e0cc5a0d52d095.tar.gz gcc-b4eca9c8df76d36dc7bb909424e0cc5a0d52d095.tar.bz2 |
re PR target/51244 ([SH] Inefficient conditional branch and code around T bit)
PR target/51244
* config/sh/sh.md (negsi_cond, negdi_cond, stack_protect_test): Remove
get_t_reg_rtx when invoking gen_branch_true or gen_branch_false.
(*zero_extend<mode>si2_compact): Convert to insn_and_split. Convert
zero extensions of T bit stores to reg moves in splitter. Remove
obsolete unnamed peephole2 that caught zero extensions after negc T bit
stores.
(*branch_true_eq, *branch_false_ne): Delete.
(branch_true, branch_false): Convert insn to expander. Move actual
insn logic to...
(*cbranch_t): ...this new insn_and_split. Try to find preceding
redundant T bit stores and tests and combine them with the conditional
branch if possible in the splitter.
(movrt_xor, *movt_movrt): New insn_and_split.
* config/sh/predicates.md (cbranch_treg_value): New predicate.
* config/sh/sh-protos.h (sh_eval_treg_value): Forward declare...
* config/sh/sh.c (sh_eval_treg_value): ...this new function.
(expand_cbranchsi4, expand_cbranchdi4): Remove get_t_reg_rtx
when invoking gen_branch_true or gen_branch_false.
PR target/51244
* gcc.target/sh/pr51244-13.c: New.
* gcc.target/sh/pr51244-14.c: New.
* gcc.target/sh/pr51244-15.c: New.
* gcc.target/sh/pr51244-16.c: New.
From-SVN: r192387
Diffstat (limited to 'gcc/testsuite')
-rw-r--r-- | gcc/testsuite/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/sh/pr51244-13.c | 85 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/sh/pr51244-14.c | 107 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/sh/pr51244-15.c | 71 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/sh/pr51244-16.c | 11 |
5 files changed, 282 insertions, 0 deletions
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6923335..b35fe71 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2012-10-12 Oleg Endo <olegendo@gcc.gnu.org> + + PR target/51244 + * gcc.target/sh/pr51244-13.c: New. + * gcc.target/sh/pr51244-14.c: New. + * gcc.target/sh/pr51244-15.c: New. + * gcc.target/sh/pr51244-16.c: New. + 2012-10-11 Paolo Carlini <paolo.carlini@oracle.com> PR c++/51878 diff --git a/gcc/testsuite/gcc.target/sh/pr51244-13.c b/gcc/testsuite/gcc.target/sh/pr51244-13.c new file mode 100644 index 0000000..7e823dc --- /dev/null +++ b/gcc/testsuite/gcc.target/sh/pr51244-13.c @@ -0,0 +1,85 @@ +/* This is a case extracted from CSiBE which contained the following + sequence: + shll r0 + movt r0 + tst r0,r0 + bf .L11 + where the 'tst r0,r0' before the branch can be omitted by inverting the + branch condition. The tested function contains two other tst insns. If + everything goes as expected we will be seeing only those other two tst + insns. */ +/* { dg-do compile { target "sh*-*-*" } } */ +/* { dg-options "-O2" } */ +/* { dg-skip-if "" { "sh*-*-*" } { "-m5*" } { "" } } */ +/* { dg-final { scan-assembler-times "tst" 2 } } */ + +static __inline__ int +__test_bit (unsigned long nr, volatile void * addr) +{ + /* This is on purpose. */ + int oldbit; + return oldbit & 1; +} + +static __inline__ int +__constant_test_bit (unsigned long nr, volatile void * addr) +{ + return (((volatile char *) addr)[(nr>>3)^7] & (1<<(nr&7))) != 0; +} + +struct list_head +{ + struct list_head *next, *prev; +}; + +static inline void +__list_del (struct list_head *prev, struct list_head *next) +{ + next->prev = prev; + prev->next = next; +} + +static inline void +list_del (struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + entry->next = 0; + entry->prev = 0; +} + +extern int nr_active_pages; +extern int nr_inactive_pages; +extern struct list_head active_list; + +typedef struct page +{ + unsigned long flags; + struct list_head lru; +} mem_map_t; + +void +activate_page_nolock (struct page * page) +{ + if ((__builtin_constant_p((6)) + ? __constant_test_bit((6),(&(page)->flags)) + : __test_bit((6),(&(page)->flags)) ) + && !(__builtin_constant_p((7)) + ? __constant_test_bit((7),(&(page)->flags)) + : __test_bit((7),(&(page)->flags)) )) + { + list_del(&(page)->lru); + nr_inactive_pages--; + if (!(__builtin_constant_p(6) ? __constant_test_bit((6),(&(page)->flags)) + : __test_bit((6),(&(page)->flags)))) + printk("", "", 43); + + if ((__builtin_constant_p(7) ? __constant_test_bit((7),(&(page)->flags)) + : __test_bit((7),(&(page)->flags)))) + printk("", "", 43); + + (__builtin_constant_p(7) ? __constant_set_bit((7),(&(page)->flags)) + : __set_bit((7),(&(page)->flags)) ); + list_add(&(page)->lru, &active_list); + nr_active_pages++; + } +} diff --git a/gcc/testsuite/gcc.target/sh/pr51244-14.c b/gcc/testsuite/gcc.target/sh/pr51244-14.c new file mode 100644 index 0000000..0ff7008 --- /dev/null +++ b/gcc/testsuite/gcc.target/sh/pr51244-14.c @@ -0,0 +1,107 @@ +/* This is a case extracted from CSiBE which would sometimes contain the + following sequence: + cmp/eq r12,r13 + movt r0 + xor #1,r0 + extu.b r0,r0 + movt r3 + tst r0,r0 + bf/s .L35 + where the negated T bit store did not combine properly. Since there are + other movt insns we only check for the xor and the extu. */ +/* { dg-do compile { target "sh*-*-*" } } */ +/* { dg-options "-O2" } */ +/* { dg-skip-if "" { "sh*-*-*" } { "-m5*" } { "" } } */ +/* { dg-final { scan-assembler-not "xor|extu" } } */ + +typedef struct transaction_s transaction_t; + +struct journal_head +{ + transaction_t * b_transaction; + struct journal_head *b_cpnext, *b_cpprev; +}; + +struct transaction_s +{ + struct journal_head * t_checkpoint_list; + transaction_t *t_cpnext, *t_cpprev; +}; + +struct journal_s +{ + transaction_t * j_checkpoint_transactions; + unsigned long j_first, j_last; +}; + +typedef struct journal_s journal_t; + +extern int __try_to_free_cp_buf (struct journal_head *jh); +extern int __cleanup_transaction (journal_t *journal, transaction_t *transaction); +extern void __flush_batch (void **bhs, int *batch_count); +extern void* jh2bh (void*); + +static int +__flush_buffer (journal_t *journal, struct journal_head *jh, + void **bhs, int *batch_count, int *drop_count) +{ + void *bh = jh2bh (jh); + int ret = 0; + if (bh) + { + bhs[*batch_count] = bh; + (*batch_count)++; + if (*batch_count == 64) + ret = 1; + } + else + { + int last_buffer = 0; + if (jh->b_cpnext == jh) + last_buffer = 1; + if (__try_to_free_cp_buf (jh)) + { + (*drop_count)++; + ret = last_buffer; + } + } + return ret; +} + +int +log_do_checkpoint (journal_t *journal, int nblocks) +{ + transaction_t *transaction, *last_transaction, *next_transaction; + int batch_count = 0; + void *bhs[64]; + +repeat: + transaction = journal->j_checkpoint_transactions; + if (transaction == ((void *)0)) + return 0; + last_transaction = transaction->t_cpprev; + next_transaction = transaction; + do + { + struct journal_head *jh, *last_jh, *next_jh; + int drop_count = 0; + int cleanup_ret, retry = 0; + transaction = next_transaction; + next_transaction = transaction->t_cpnext; + jh = transaction->t_checkpoint_list; + last_jh = jh->b_cpprev; + next_jh = jh; + do + { + jh = next_jh; + next_jh = jh->b_cpnext; + retry = __flush_buffer(journal, jh, bhs, &batch_count, &drop_count); + } while (jh != last_jh && !retry); + + if (retry) + goto repeat; + + cleanup_ret = __cleanup_transaction(journal, transaction); + goto repeat; + } while (transaction != last_transaction); +} diff --git a/gcc/testsuite/gcc.target/sh/pr51244-15.c b/gcc/testsuite/gcc.target/sh/pr51244-15.c new file mode 100644 index 0000000..ec98d5e --- /dev/null +++ b/gcc/testsuite/gcc.target/sh/pr51244-15.c @@ -0,0 +1,71 @@ +/* Check that the redundant test removal code in the *cbranch_t split works + as expected on non-SH2A targets. Because on SH2A the movrt instruction + is used, this test is re-used and checked differently in pr51244-16.c. */ +/* { dg-do compile { target "sh*-*-*" } } */ +/* { dg-options "-O2" } */ +/* { dg-skip-if "" { "sh*-*-*" } { "-m5*" "-m2a*" } { "" } } */ +/* { dg-final { scan-assembler-times "tst" 6 } } */ +/* { dg-final { scan-assembler-times "movt" 6 } } */ +/* { dg-final { scan-assembler-times "xor" 3 } } */ +/* { dg-final { scan-assembler-not "extu|exts|negc" } } */ + +typedef char bool; + +int +test_0 (int a, int b, int c, int* d) +{ + /* non SH2A: 1x tst, 1x movt, 1x xor + SH2A: 1x tst, 1x movrt */ + bool x = a == 0; + d[2] = !x; + return x ? b : c; +} + +int +test_1 (int a, int b, int c, int* d) +{ + /* 1x tst, 1x movt */ + bool x = a != 0; + d[2] = !x; + return x ? b : c; +} + +int +test_2 (int a, int b, int c, char* d) +{ + /* Check that there is no sign/zero-extension before the store. + non SH2A: 1x tst, 1x movt, 1x xor + SH2A: 1x tst, 1x movrt */ + bool x = a == 0; + d[2] = !x; + return x ? b : c; +} + +int +test_3 (int a, int b, int c, char* d) +{ + /* Check that there is no sign/zero-extension before the store. + 1x tst, 1x movt */ + bool x = a != 0; + d[2] = !x; + return x ? b : c; +} + +int +test_4 (int a, int b, int c, char* d) +{ + /* 1x tst, 1x movt */ + bool x = a != 0; + d[2] = !x; + return !x ? b : c; +} + +int +test_5 (int a, int b, int c, char* d) +{ + /* non SH2A: 1x tst, 1x movt, 1x xor + SH2A: 1x tst, 1x movrt */ + bool x = a == 0; + d[2] = !x; + return !x ? b : c; +} diff --git a/gcc/testsuite/gcc.target/sh/pr51244-16.c b/gcc/testsuite/gcc.target/sh/pr51244-16.c new file mode 100644 index 0000000..8717df7 --- /dev/null +++ b/gcc/testsuite/gcc.target/sh/pr51244-16.c @@ -0,0 +1,11 @@ +/* Check that the redundant test removal code in the *cbranch_t split works + as expected on SH2A targets. */ +/* { dg-do compile { target "sh*-*-*" } } */ +/* { dg-options "-O2" } */ +/* { dg-skip-if "" { "sh*-*-*" } { "*" } { "-m2a*" } } */ +/* { dg-final { scan-assembler-times "tst" 6 } } */ +/* { dg-final { scan-assembler-times "movt" 3 } } */ +/* { dg-final { scan-assembler-times "movrt" 3 } } */ +/* { dg-final { scan-assembler-not "extu|exts|negc" } } */ + +#include "pr51244-15.c" |