From 55e79aef81371abf4c07885fbbd748078d695209 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 26 Jan 2005 12:29:25 -0800 Subject: [PATCH] re PR middle-end/18008 (Duplicate mask on bitfield insertion) PR middle-end/18008 * combine.c (make_field_assignment): Simplify store to zero_extract from a source with an overlapping mask. From-SVN: r94282 --- gcc/ChangeLog | 6 ++++++ gcc/combine.c | 53 ++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 48 insertions(+), 11 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4255c8e48b2..630dfac2abe 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2005-01-26 Richard Henderson + + PR middle-end/18008 + * combine.c (make_field_assignment): Simplify store to zero_extract + from a source with an overlapping mask. + 2005-01-26 Aldy Hernandez 2004-11-11 Eric Christopher diff --git a/gcc/combine.c b/gcc/combine.c index 0baeb981500..7fe0a5f702e 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -7815,14 +7815,14 @@ make_field_assignment (rtx x) return x; } - else if (GET_CODE (src) == AND && GET_CODE (XEXP (src, 0)) == SUBREG - && subreg_lowpart_p (XEXP (src, 0)) - && (GET_MODE_SIZE (GET_MODE (XEXP (src, 0))) - < GET_MODE_SIZE (GET_MODE (SUBREG_REG (XEXP (src, 0))))) - && GET_CODE (SUBREG_REG (XEXP (src, 0))) == ROTATE - && GET_CODE (XEXP (SUBREG_REG (XEXP (src, 0)), 0)) == CONST_INT - && INTVAL (XEXP (SUBREG_REG (XEXP (src, 0)), 0)) == -2 - && rtx_equal_for_field_assignment_p (dest, XEXP (src, 1))) + if (GET_CODE (src) == AND && GET_CODE (XEXP (src, 0)) == SUBREG + && subreg_lowpart_p (XEXP (src, 0)) + && (GET_MODE_SIZE (GET_MODE (XEXP (src, 0))) + < GET_MODE_SIZE (GET_MODE (SUBREG_REG (XEXP (src, 0))))) + && GET_CODE (SUBREG_REG (XEXP (src, 0))) == ROTATE + && GET_CODE (XEXP (SUBREG_REG (XEXP (src, 0)), 0)) == CONST_INT + && INTVAL (XEXP (SUBREG_REG (XEXP (src, 0)), 0)) == -2 + && rtx_equal_for_field_assignment_p (dest, XEXP (src, 1))) { assign = make_extraction (VOIDmode, dest, 0, XEXP (SUBREG_REG (XEXP (src, 0)), 1), @@ -7834,9 +7834,9 @@ make_field_assignment (rtx x) /* If SRC is (ior (ashift (const_int 1) POS) DEST), this is a set of a one-bit field. */ - else if (GET_CODE (src) == IOR && GET_CODE (XEXP (src, 0)) == ASHIFT - && XEXP (XEXP (src, 0), 0) == const1_rtx - && rtx_equal_for_field_assignment_p (dest, XEXP (src, 1))) + if (GET_CODE (src) == IOR && GET_CODE (XEXP (src, 0)) == ASHIFT + && XEXP (XEXP (src, 0), 0) == const1_rtx + && rtx_equal_for_field_assignment_p (dest, XEXP (src, 1))) { assign = make_extraction (VOIDmode, dest, 0, XEXP (XEXP (src, 0), 1), 1, 1, 1, 0); @@ -7845,6 +7845,37 @@ make_field_assignment (rtx x) return x; } + /* If DEST is already a field assignment, i.e. ZERO_EXTRACT, and the + SRC is an AND with all bits of that field set, then we can discard + the AND. */ + if (GET_CODE (dest) == ZERO_EXTRACT + && GET_CODE (XEXP (dest, 1)) == CONST_INT + && GET_CODE (src) == AND + && GET_CODE (XEXP (src, 1)) == CONST_INT) + { + HOST_WIDE_INT width = INTVAL (XEXP (dest, 1)); + unsigned HOST_WIDE_INT and_mask = INTVAL (XEXP (src, 1)); + unsigned HOST_WIDE_INT ze_mask; + + if (width >= HOST_BITS_PER_WIDE_INT) + ze_mask = -1; + else + ze_mask = ((unsigned HOST_WIDE_INT)1 << width) - 1; + + /* Complete overlap. We can remove the source AND. */ + if ((and_mask & ze_mask) == ze_mask) + return gen_rtx_SET (VOIDmode, dest, XEXP (src, 0)); + + /* Partial overlap. We can reduce the source AND. */ + if ((and_mask & ze_mask) != and_mask) + { + mode = GET_MODE (src); + src = gen_rtx_AND (mode, XEXP (src, 0), + gen_int_mode (mode, and_mask & ze_mask)); + return gen_rtx_SET (VOIDmode, dest, src); + } + } + /* The other case we handle is assignments into a constant-position field. They look like (ior/xor (and DEST C1) OTHER). If C1 represents a mask that has all one bits except for a group of zero bits and -- 2.30.2