From: Jakub Jelinek Date: Wed, 19 Nov 2014 08:18:53 +0000 (+0100) Subject: re PR rtl-optimization/63843 (wrong code generation at -O1 and higher) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=05f9c67507bd614e1fa1e5184a855a8257bc04fe;p=gcc.git re PR rtl-optimization/63843 (wrong code generation at -O1 and higher) PR rtl-optimization/63843 * simplify-rtx.c (simplify_binary_operation_1) : For optimization of ashiftrt of subreg of lshiftrt, check that code is ASHIFTRT. * gcc.c-torture/execute/pr63843.c: New test. From-SVN: r217753 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7dcfba38c5a..b1bb78ffb0e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2014-11-19 Jakub Jelinek + + PR rtl-optimization/63843 + * simplify-rtx.c (simplify_binary_operation_1) : For + optimization of ashiftrt of subreg of lshiftrt, check that code + is ASHIFTRT. + 2014-11-18 Andrew MacLeod * attribs.c (decl_attributes): Remove always true condition, diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index 8094c7584ac..022e36fe7c0 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 )) - ) - (const_int )) - to: - (subreg:M1 (ashiftrt:M2 (reg:M2) - (const_int )) - ). */ - 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 )) + ) + (const_int )) + to: + (subreg:M1 (ashiftrt:M2 (reg:M2) (const_int )) + ). */ + 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 1a56e1ac9ed..118805c26e1 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2014-11-19 Jakub Jelinek + + PR rtl-optimization/63843 + * gcc.c-torture/execute/pr63843.c: New test. + 2014-11-18 James Greenhalgh 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 00000000000..9f6c7b06c39 --- /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; +}