On 07/28/11 06:40, Richard Guenther wrote:
Looking at the C++ memory model what you need is indeed simple enough
to recover here. Still this loop does quadratic work for a struct with
N bitfield members and a function which stores into all of them.
And that with a big constant factor as you build a component-ref
and even unshare trees (which isn't necessary here anyway). In fact
you could easily manually keep track of bitpos when walking adjacent
bitfield members. An initial call to get_inner_reference on
TREE_OPERAND (exp, 0) would give you the starting position of the record.
That would still be quadratic of course.
Actually, we don't need to call get_inner_reference at all. It seems
DECL_FIELD_BIT_OFFSET has all the information we need.
How about we simplify things further as in the attached patch?
Tested on x86-64 Linux.
OK for mainline?
* expr.c (get_bit_range): Get field bit offset from
DECL_FIELD_BIT_OFFSET.
Index: expr.c
===================================================================
--- expr.c (revision 176891)
+++ expr.c (working copy)
@@ -4179,18 +4179,10 @@ get_bit_range (unsigned HOST_WIDE_INT *b
prev_field_is_bitfield = true;
for (fld = TYPE_FIELDS (record_type); fld; fld = DECL_CHAIN (fld))
{
- tree t, offset;
- enum machine_mode mode;
- int unsignedp, volatilep;
-
if (TREE_CODE (fld) != FIELD_DECL)
continue;
- t = build3 (COMPONENT_REF, TREE_TYPE (exp),
- unshare_expr (TREE_OPERAND (exp, 0)),
- fld, NULL_TREE);
- get_inner_reference (t, &bitsize, &bitpos, &offset,
- &mode, &unsignedp, &volatilep, true);
+ bitpos = TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (fld));
if (field == fld)
found_field = true;