diff options
author | Oleg Endo <olegendo@gcc.gnu.org> | 2016-02-22 13:33:31 +0000 |
---|---|---|
committer | Oleg Endo <olegendo@gcc.gnu.org> | 2016-02-22 13:33:31 +0000 |
commit | f88d45dc171e59e120817912115550b943c30b22 (patch) | |
tree | edb2f6b914dc2e288c537e24bcb365233f139a86 /gcc | |
parent | bddb7adb4411ec4c9653e61accb3db25e3b2c405 (diff) | |
download | gcc-f88d45dc171e59e120817912115550b943c30b22.zip gcc-f88d45dc171e59e120817912115550b943c30b22.tar.gz gcc-f88d45dc171e59e120817912115550b943c30b22.tar.bz2 |
re PR rtl-optimization/69806 ([SH] Combine doesn't see constant)
gcc/
PR target/69806
PR target/54089
* config/sh/sh.c (sh_lshrsi_clobbers_t_reg_p, sh_dynamicalize_shift_p):
Handle negative shift counts.
* config/sh/sh.md (ashlsi3, lshrsi3_n, lshrsi3_n_clobbers_t): Don't use
force_reg on the shift constant.
(lshrsi3): Likewise. Expand into lshrsi3_n* instead of lshrsi3_d.
(lshrsi3_d): Handle negative shift counts.
gcc/testsuite/
PR target/69806
PR target/54089
* gcc.target/sh/pr54089-10.c: New.
From-SVN: r233601
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/config/sh/sh.c | 6 | ||||
-rw-r--r-- | gcc/config/sh/sh.md | 24 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/sh/pr54089-10.c | 153 |
5 files changed, 190 insertions, 10 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3e4273b..14e3adb 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2016-02-22 Oleg Endo <olegendo@gcc.gnu.org> + + PR target/69806 + PR target/54089 + * config/sh/sh.c (sh_lshrsi_clobbers_t_reg_p, sh_dynamicalize_shift_p): + Handle negative shift counts. + * config/sh/sh.md (ashlsi3, lshrsi3_n, lshrsi3_n_clobbers_t): Don't use + force_reg on the shift constant. + (lshrsi3): Likewise. Expand into lshrsi3_n* instead of lshrsi3_d. + (lshrsi3_d): Handle negative shift counts. + 2016-02-22 Richard Biener <rguenther@suse.de> Tom de Vries <tom@codesourcery.com> diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index 0b18ce5..8c8fe3c 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -3259,7 +3259,8 @@ sh_lshrsi_clobbers_t_reg_p (rtx shift_amount) { gcc_assert (CONST_INT_P (shift_amount)); - const int shift_amount_i = INTVAL (shift_amount) & 31; + /* For right shifts the constant might be negative. */ + const int shift_amount_i = std::abs (INTVAL (shift_amount)) & 31; /* Special case for shift count of 31: use shll-movt sequence. */ if (shift_amount_i == 31) @@ -3278,7 +3279,8 @@ sh_dynamicalize_shift_p (rtx count) { gcc_assert (CONST_INT_P (count)); - const int shift_amount_i = INTVAL (count) & 31; + /* For right shifts the constant might be negative. */ + const int shift_amount_i = std::abs (INTVAL (count)) & 31; int insn_count; /* For left and right shifts, there are shorter 2 insn sequences for diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md index 9fa835b..c0a9249c 100644 --- a/gcc/config/sh/sh.md +++ b/gcc/config/sh/sh.md @@ -5011,7 +5011,10 @@ label: } if (TARGET_DYNSHIFT && CONST_INT_P (operands[2]) && sh_dynamicalize_shift_p (operands[2])) - operands[2] = force_reg (SImode, operands[2]); + { + /* Don't force the constant into a reg yet. Some other optimizations + might not see through the reg that holds the shift count. */ + } /* If the ashlsi3_* insn is going to clobber the T_REG it must be expanded here. */ @@ -5567,9 +5570,12 @@ label: if (TARGET_DYNSHIFT && CONST_INT_P (operands[2]) && sh_dynamicalize_shift_p (operands[2])) { - rtx neg_count = force_reg (SImode, - gen_int_mode (- INTVAL (operands[2]), SImode)); - emit_insn (gen_lshrsi3_d (operands[0], operands[1], neg_count)); + /* Don't force the constant into a reg yet. Some other optimizations + might not see through the reg that holds the shift count. */ + if (sh_lshrsi_clobbers_t_reg_p (operands[2])) + emit_insn (gen_lshrsi3_n_clobbers_t (operands[0], operands[1], operands[2])); + else + emit_insn (gen_lshrsi3_n (operands[0], operands[1], operands[2])); DONE; } @@ -5621,6 +5627,10 @@ label: && ! sh_lshrsi_clobbers_t_reg_p (operands[2])" [(const_int 0)] { + /* The shift count const_int is a negative value for all dynamic + right shift insns. */ + operands[2] = GEN_INT (- INTVAL (operands[2])); + if (satisfies_constraint_P27 (operands[2])) { /* This will not be done for a shift amount of 1, because it would @@ -5679,8 +5689,7 @@ label: { /* If this pattern was picked and dynamic shifts are supported, switch to dynamic shift pattern before reload. */ - operands[2] = force_reg (SImode, - gen_int_mode (- INTVAL (operands[2]), SImode)); + operands[2] = GEN_INT (- INTVAL (operands[2])); emit_insn (gen_lshrsi3_d (operands[0], operands[1], operands[2])); } else @@ -5711,8 +5720,7 @@ label: { /* If this pattern was picked and dynamic shifts are supported, switch to dynamic shift pattern before reload. */ - operands[2] = force_reg (SImode, - gen_int_mode (- INTVAL (operands[2]), SImode)); + operands[2] = GEN_INT (- INTVAL (operands[2])); emit_insn (gen_lshrsi3_d (operands[0], operands[1], operands[2])); } else diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6c73051..927af63 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2016-02-22 Oleg Endo <olegendo@gcc.gnu.org> + + PR target/69806 + PR target/54089 + * gcc.target/sh/pr54089-10.c: New. + 2016-02-20 Paul Thomas <pault@gcc.gnu.org> PR fortran/69423 diff --git a/gcc/testsuite/gcc.target/sh/pr54089-10.c b/gcc/testsuite/gcc.target/sh/pr54089-10.c new file mode 100644 index 0000000..85aeabd --- /dev/null +++ b/gcc/testsuite/gcc.target/sh/pr54089-10.c @@ -0,0 +1,153 @@ +/* Check that there are no redundant zero extensions around logical right + shifts. */ +/* { dg-do compile } */ +/* { dg-options "-O1" } */ +/* { dg-final { scan-assembler-times "extu" 20 } } */ + +/* { dg-final { scan-assembler-times "shll" 2 { target { "! sh2a" && has_dyn_shift } } } } */ +/* { dg-final { scan-assembler-times "shll" 3 { target { "! sh2a" && "! has_dyn_shift" } } } } */ +/* { dg-final { scan-assembler-times "movt" 2 { target { ! sh2a } } } } */ + +/* { dg-final { scan-assembler-times "bld" 1 { target { sh2a } } } } */ +/* { dg-final { scan-assembler-times "movt" 1 { target { sh2a } } } } */ +/* { dg-final { scan-assembler-times "movrt" 1 { target { sh2a } } } } */ +/* { dg-final { scan-assembler-times "cmp/pz" 1 { target { sh2a } } } } */ + +/* { dg-final { scan-assembler-times "shld" 9 { target { has_dyn_shift } } } } */ + +void +test_0 (unsigned char* x, unsigned int* y) +{ + y[0] = x[1] >> 1; +} + +void +test_1 (unsigned char* x, unsigned int* y) +{ + y[0] = x[1] >> 2; +} + +void +test_2 (unsigned char* x, unsigned int* y) +{ + y[0] = x[1] >> 3; +} + +void +test_3 (unsigned char* x, unsigned int* y) +{ + y[0] = x[1] >> 4; +} + +void +test_4 (unsigned char* x, unsigned int* y) +{ + y[0] = x[1] >> 5; +} + +void +test_5 (unsigned char* x, unsigned int* y) +{ + y[0] = x[1] >> 6; +} + +void +test_6 (unsigned char* x, unsigned int* y) +{ + /* non-SH2A: shll, movt + SH2A: bld, movt */ + y[0] = x[1] >> 7; +} + + +void +test_100 (unsigned short* x, unsigned int* y) +{ + y[0] = x[1] >> 1; +} + +void +test_101 (unsigned short* x, unsigned int* y) +{ + y[0] = x[1] >> 2; +} + +void +test_102 (unsigned short* x, unsigned int* y) +{ + y[0] = x[1] >> 3; +} + +void +test_103 (unsigned short* x, unsigned int* y) +{ + y[0] = x[1] >> 4; +} + +void +test_104 (unsigned short* x, unsigned int* y) +{ + y[0] = x[1] >> 5; +} + +void +test_105 (unsigned short* x, unsigned int* y) +{ + y[0] = x[1] >> 6; +} + +void +test_106 (unsigned short* x, unsigned int* y) +{ + y[0] = x[1] >> 7; +} + +void +test_107 (unsigned short* x, unsigned int* y) +{ + y[0] = x[1] >> 8; +} + +void +test_108 (unsigned short* x, unsigned int* y) +{ + y[0] = x[1] >> 9; +} + +void +test_109 (unsigned short* x, unsigned int* y) +{ + y[0] = x[1] >> 10; +} + +void +test_110 (unsigned short* x, unsigned int* y) +{ + y[0] = x[1] >> 11; +} + +void +test_111 (unsigned short* x, unsigned int* y) +{ + y[0] = x[1] >> 12; +} + +void +test_112 (unsigned short* x, unsigned int* y) +{ + y[0] = x[1] >> 13; +} + +void +test_113 (unsigned short* x, unsigned int* y) +{ + y[0] = x[1] >> 14; +} + +void +test_114 (unsigned short* x, unsigned int* y) +{ + /* non-SH2A: shll, movt + SH2A: cmp/pz, movrt */ + y[0] = x[1] >> 15; +} |