From 5a1be5742466996037b478057239abf9672f499e Mon Sep 17 00:00:00 2001 From: sayle Date: Fri, 7 Jan 2005 00:47:13 +0000 Subject: [PATCH] * simplify-rtx.c (simplify_subreg): Simplify truncations of shifts of sign or zero extended values. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@93022 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 5 +++++ gcc/simplify-rtx.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 44ef9c7cb30..965fe599e17 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2005-01-06 Roger Sayle + + * simplify-rtx.c (simplify_subreg): Simplify truncations of shifts + of sign or zero extended values. + 2005-01-06 Geoffrey Keating * c-cppbuiltin.c (builtin_define_float_constants): Set __*_EPSILON__ diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index 6e208aa9d9a..0aa1e9576aa 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -3829,6 +3829,55 @@ simplify_subreg (enum machine_mode outermode, rtx op, return CONST0_RTX (outermode); } + /* Simplify (subreg:QI (lshiftrt:SI (sign_extend:SI (x:QI)) C), 0) into + to (ashiftrt:QI (x:QI) C), where C is a suitable small constant and + the outer subreg is effectively a truncation to the original mode. */ + if ((GET_CODE (op) == LSHIFTRT + || GET_CODE (op) == ASHIFTRT) + && SCALAR_INT_MODE_P (outermode) + /* Ensure that OUTERMODE is at least twice as wide as the INNERMODE + to avoid the possibility that an outer LSHIFTRT shifts by more + than the sign extension's sign_bit_copies and introduces zeros + into the high bits of the result. */ + && (2 * GET_MODE_BITSIZE (outermode)) <= GET_MODE_BITSIZE (innermode) + && GET_CODE (XEXP (op, 1)) == CONST_INT + && GET_CODE (XEXP (op, 0)) == SIGN_EXTEND + && GET_MODE (XEXP (XEXP (op, 0), 0)) == outermode + && INTVAL (XEXP (op, 1)) < GET_MODE_BITSIZE (outermode) + && subreg_lsb_1 (outermode, innermode, byte) == 0) + return simplify_gen_binary (ASHIFTRT, outermode, + XEXP (XEXP (op, 0), 0), XEXP (op, 1)); + + /* Likewise (subreg:QI (lshiftrt:SI (zero_extend:SI (x:QI)) C), 0) into + to (lshiftrt:QI (x:QI) C), where C is a suitable small constant and + the outer subreg is effectively a truncation to the original mode. */ + if ((GET_CODE (op) == LSHIFTRT + || GET_CODE (op) == ASHIFTRT) + && SCALAR_INT_MODE_P (outermode) + && GET_MODE_BITSIZE (outermode) < GET_MODE_BITSIZE (innermode) + && GET_CODE (XEXP (op, 1)) == CONST_INT + && GET_CODE (XEXP (op, 0)) == ZERO_EXTEND + && GET_MODE (XEXP (XEXP (op, 0), 0)) == outermode + && INTVAL (XEXP (op, 1)) < GET_MODE_BITSIZE (outermode) + && subreg_lsb_1 (outermode, innermode, byte) == 0) + return simplify_gen_binary (LSHIFTRT, outermode, + XEXP (XEXP (op, 0), 0), XEXP (op, 1)); + + /* Likewise (subreg:QI (ashift:SI (zero_extend:SI (x:QI)) C), 0) into + to (ashift:QI (x:QI) C), where C is a suitable small constant and + the outer subreg is effectively a truncation to the original mode. */ + if (GET_CODE (op) == ASHIFT + && SCALAR_INT_MODE_P (outermode) + && GET_MODE_BITSIZE (outermode) < GET_MODE_BITSIZE (innermode) + && GET_CODE (XEXP (op, 1)) == CONST_INT + && (GET_CODE (XEXP (op, 0)) == ZERO_EXTEND + || GET_CODE (XEXP (op, 0)) == SIGN_EXTEND) + && GET_MODE (XEXP (XEXP (op, 0), 0)) == outermode + && INTVAL (XEXP (op, 1)) < GET_MODE_BITSIZE (outermode) + && subreg_lsb_1 (outermode, innermode, byte) == 0) + return simplify_gen_binary (ASHIFT, outermode, + XEXP (XEXP (op, 0), 0), XEXP (op, 1)); + return NULL_RTX; } -- 2.11.4.GIT