diff options
author | Jakub Jelinek <jakub@redhat.com> | 2014-11-19 09:18:53 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2014-11-19 09:18:53 +0100 |
commit | 05f9c67507bd614e1fa1e5184a855a8257bc04fe (patch) | |
tree | add405212855dc07bdc60d4afe8c74e3fe7767ca /gcc | |
parent | 26c87b1a648dce3764f9efdb56c75dcf953413c5 (diff) | |
download | gcc-05f9c67507bd614e1fa1e5184a855a8257bc04fe.zip gcc-05f9c67507bd614e1fa1e5184a855a8257bc04fe.tar.gz gcc-05f9c67507bd614e1fa1e5184a855a8257bc04fe.tar.bz2 |
re PR rtl-optimization/63843 (wrong code generation at -O1 and higher)
PR rtl-optimization/63843
* simplify-rtx.c (simplify_binary_operation_1) <case ASHIFTRT>: For
optimization of ashiftrt of subreg of lshiftrt, check that code
is ASHIFTRT.
* gcc.c-torture/execute/pr63843.c: New test.
From-SVN: r217753
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/simplify-rtx.c | 73 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/pr63843.c | 31 |
4 files changed, 79 insertions, 37 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7dcfba3..b1bb78f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2014-11-19 Jakub Jelinek <jakub@redhat.com> + + PR rtl-optimization/63843 + * simplify-rtx.c (simplify_binary_operation_1) <case ASHIFTRT>: For + optimization of ashiftrt of subreg of lshiftrt, check that code + is ASHIFTRT. + 2014-11-18 Andrew MacLeod <amacleod@redhat.com> * attribs.c (decl_attributes): Remove always true condition, diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index 8094c75..022e36f 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -3105,43 +3105,42 @@ simplify_binary_operation_1 (enum rtx_code code, machine_mode mode, && ! side_effects_p (op1)) return op0; /* Given: - scalar modes M1, M2 - scalar constants c1, c2 - size (M2) > size (M1) - c1 == size (M2) - size (M1) - optimize: - (ashiftrt:M1 (subreg:M1 (lshiftrt:M2 (reg:M2) - (const_int <c1>)) - <low_part>) - (const_int <c2>)) - to: - (subreg:M1 (ashiftrt:M2 (reg:M2) - (const_int <c1 + c2>)) - <low_part>). */ - if (!VECTOR_MODE_P (mode) - && SUBREG_P (op0) - && CONST_INT_P (op1) - && (GET_CODE (SUBREG_REG (op0)) == LSHIFTRT) - && !VECTOR_MODE_P (GET_MODE (SUBREG_REG (op0))) - && CONST_INT_P (XEXP (SUBREG_REG (op0), 1)) - && (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (op0))) - > GET_MODE_BITSIZE (mode)) - && (INTVAL (XEXP (SUBREG_REG (op0), 1)) - == (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (op0))) - - GET_MODE_BITSIZE (mode))) - && subreg_lowpart_p (op0)) - { - rtx tmp = GEN_INT (INTVAL (XEXP (SUBREG_REG (op0), 1)) - + INTVAL (op1)); - machine_mode inner_mode = GET_MODE (SUBREG_REG (op0)); - tmp = simplify_gen_binary (ASHIFTRT, - GET_MODE (SUBREG_REG (op0)), - XEXP (SUBREG_REG (op0), 0), - tmp); - return simplify_gen_subreg (mode, tmp, inner_mode, - subreg_lowpart_offset (mode, - inner_mode)); - } + scalar modes M1, M2 + scalar constants c1, c2 + size (M2) > size (M1) + c1 == size (M2) - size (M1) + optimize: + (ashiftrt:M1 (subreg:M1 (lshiftrt:M2 (reg:M2) (const_int <c1>)) + <low_part>) + (const_int <c2>)) + to: + (subreg:M1 (ashiftrt:M2 (reg:M2) (const_int <c1 + c2>)) + <low_part>). */ + if (code == ASHIFTRT + && !VECTOR_MODE_P (mode) + && SUBREG_P (op0) + && CONST_INT_P (op1) + && GET_CODE (SUBREG_REG (op0)) == LSHIFTRT + && !VECTOR_MODE_P (GET_MODE (SUBREG_REG (op0))) + && CONST_INT_P (XEXP (SUBREG_REG (op0), 1)) + && (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (op0))) + > GET_MODE_BITSIZE (mode)) + && (INTVAL (XEXP (SUBREG_REG (op0), 1)) + == (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (op0))) + - GET_MODE_BITSIZE (mode))) + && subreg_lowpart_p (op0)) + { + rtx tmp = GEN_INT (INTVAL (XEXP (SUBREG_REG (op0), 1)) + + INTVAL (op1)); + machine_mode inner_mode = GET_MODE (SUBREG_REG (op0)); + tmp = simplify_gen_binary (ASHIFTRT, + GET_MODE (SUBREG_REG (op0)), + XEXP (SUBREG_REG (op0), 0), + tmp); + return simplify_gen_subreg (mode, tmp, inner_mode, + subreg_lowpart_offset (mode, + inner_mode)); + } canonicalize_shift: if (SHIFT_COUNT_TRUNCATED && CONST_INT_P (op1)) { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 1a56e1a..118805c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2014-11-19 Jakub Jelinek <jakub@redhat.com> + + PR rtl-optimization/63843 + * gcc.c-torture/execute/pr63843.c: New test. + 2014-11-18 James Greenhalgh <james.greenhalgh@arm.com> PR target/63937 diff --git a/gcc/testsuite/gcc.c-torture/execute/pr63843.c b/gcc/testsuite/gcc.c-torture/execute/pr63843.c new file mode 100644 index 0000000..9f6c7b0 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr63843.c @@ -0,0 +1,31 @@ +/* PR rtl-optimization/63843 */ + +static inline __attribute__ ((always_inline)) +unsigned short foo (unsigned short v) +{ + return (v << 8) | (v >> 8); +} + +unsigned short __attribute__ ((noinline, noclone, hot)) +bar (unsigned char *x) +{ + unsigned int a; + unsigned short b; + __builtin_memcpy (&a, &x[0], sizeof (a)); + a ^= 0x80808080U; + __builtin_memcpy (&x[0], &a, sizeof (a)); + __builtin_memcpy (&b, &x[2], sizeof (b)); + return foo (b); +} + +int +main () +{ + unsigned char x[8] = { 0x01, 0x01, 0x01, 0x01 }; + if (__CHAR_BIT__ == 8 + && sizeof (short) == 2 + && sizeof (int) == 4 + && bar (x) != 0x8181U) + __builtin_abort (); + return 0; +} |