This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Some middle-end improvements for bitfield handling (followup)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Roger Sayle <roger at eyesopen dot com>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Thu, 1 Jul 2004 05:41:22 -0400
- Subject: [PATCH] Some middle-end improvements for bitfield handling (followup)
- References: <20040630104321.GT21264@devserv.devel.redhat.com> <Pine.LNX.4.44.0406300616020.27406-100000@www.eyesopen.com>
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
On Wed, Jun 30, 2004 at 06:26:49AM -0600, Roger Sayle wrote:
> > Looking through the mails which lead to PR 15310, your one-bit
> > bitfield handling could be doable with a smallish change to
> > expand_assignment too. Just handle bitsize == 1 with constant
> > TREE_OPERAND (from, 1) in addition to count + bitsize == GET_MODE_BITSIZE ().
> > Shall I prepare a patch for that?
>
> That would be great! This has been on my TODO list for a while.
Here it is. In addition to handling single bit additions/subtractions
it also STRIP_NOPS, so that it optimizes even more cases than it used
to do before, e.g. current CVS only optimizes test2
struct { unsigned int i : 6, j : 11, k : 15; } b;
void test (void)
{
b.k += 3;
}
void test2 (void)
{
b.k += 3U;
}
while with this patch both are optimized.
Bootstrapped/regtested on i386-redhat-linux, ok to commit?
2004-07-01 Jakub Jelinek <jakub@redhat.com>
* expr.c (expand_assignment): Optimize bitfld += cst for 1 bit
bitfields as well. STRIP_NOPS from src operand and PLUS_EXPR's
first operand. Don't optimize if the bitfield is volatile.
--- gcc/expr.c 2004-06-30 12:08:54.949601282 +0200
+++ gcc/expr.c 2004-07-01 09:38:11.138727585 +0200
@@ -3858,23 +3858,36 @@ expand_assignment (tree to, tree from, i
MEM_KEEP_ALIAS_SET_P (to_rtx) = 1;
}
- if (mode1 == VOIDmode && !want_value
- && bitpos + bitsize <= BITS_PER_WORD
- && bitsize < BITS_PER_WORD
- && GET_MODE_BITSIZE (GET_MODE (to_rtx)) <= BITS_PER_WORD
- && !TREE_SIDE_EFFECTS (to)
- && TREE_CODE (TREE_TYPE (from)) == INTEGER_TYPE
- && TREE_CODE_CLASS (TREE_CODE (from)) == '2'
- && operand_equal_p (to, TREE_OPERAND (from, 0), 0))
+ while (mode1 == VOIDmode && !want_value
+ && bitpos + bitsize <= BITS_PER_WORD
+ && bitsize < BITS_PER_WORD
+ && GET_MODE_BITSIZE (GET_MODE (to_rtx)) <= BITS_PER_WORD
+ && !TREE_SIDE_EFFECTS (to)
+ && !TREE_THIS_VOLATILE (to))
{
+ tree src, op0, op1;
rtx value;
HOST_WIDE_INT count = bitpos;
+ optab binop;
+
+ src = from;
+ STRIP_NOPS (src);
+ if (TREE_CODE (TREE_TYPE (src)) != INTEGER_TYPE
+ || TREE_CODE_CLASS (TREE_CODE (src)) != '2')
+ break;
+
+ op0 = TREE_OPERAND (src, 0);
+ op1 = TREE_OPERAND (src, 1);
+ STRIP_NOPS (op0);
+
+ if (! operand_equal_p (to, op0, 0))
+ break;
if (BYTES_BIG_ENDIAN)
count = GET_MODE_BITSIZE (GET_MODE (to_rtx)) - bitpos - bitsize;
/* Special case some bitfield op= exp. */
- switch (TREE_CODE (from))
+ switch (TREE_CODE (src))
{
case PLUS_EXPR:
case MINUS_EXPR:
@@ -3882,22 +3895,29 @@ expand_assignment (tree to, tree from, i
break;
/* For now, just optimize the case of the topmost bitfield
- where we don't need to do any masking.
+ where we don't need to do any masking and also
+ 1 bit bitfields where xor can be used.
We might win by one instruction for the other bitfields
too if insv/extv instructions aren't used, so that
can be added later. */
- if (count + bitsize != GET_MODE_BITSIZE (GET_MODE (to_rtx)))
+ if (count + bitsize != GET_MODE_BITSIZE (GET_MODE (to_rtx))
+ && (bitsize != 1 || TREE_CODE (op1) != INTEGER_CST))
break;
- value = expand_expr (TREE_OPERAND (from, 1), NULL_RTX,
- VOIDmode, 0);
+ value = expand_expr (op1, NULL_RTX, VOIDmode, 0);
value = protect_from_queue (value, 0);
to_rtx = protect_from_queue (to_rtx, 1);
+ binop = TREE_CODE (src) == PLUS_EXPR ? add_optab : sub_optab;
+ if (bitsize == 1
+ && count + bitsize != GET_MODE_BITSIZE (GET_MODE (to_rtx)))
+ {
+ value = expand_and (GET_MODE (to_rtx), value, const1_rtx,
+ NULL_RTX);
+ binop = xor_optab;
+ }
value = expand_shift (LSHIFT_EXPR, GET_MODE (to_rtx),
value, build_int_2 (count, 0),
NULL_RTX, 1);
- result = expand_binop (GET_MODE (to_rtx),
- TREE_CODE (from) == PLUS_EXPR
- ? add_optab : sub_optab, to_rtx,
+ result = expand_binop (GET_MODE (to_rtx), binop, to_rtx,
value, to_rtx, 1, OPTAB_WIDEN);
if (result != to_rtx)
emit_move_insn (to_rtx, result);
@@ -3907,6 +3927,8 @@ expand_assignment (tree to, tree from, i
default:
break;
}
+
+ break;
}
result = store_field (to_rtx, bitsize, bitpos, mode1, from,
Jakub