This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Some middle-end improvements for bitfield handling (followup)


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]