Hi!

I think 2/3 operand GIMPLE_ASSIGN is the most widely used gimple type,
and 128 bytes + 16/24 bytes in separate allocation for it is a lot
(though, we'd need a separate extra_order_size_table for such GIMPLE_ASSIGNs
if we decrease it a little bit).  The low hanging fruit on 64-bit arches is
moving uid right after plf (saves 8 bytes), moving modified:1 bit from
gimple_statement_with_ops to gimple_statement_base (I think all users just
use the accessor inlines, so where exactly it lives is gimple.h
implementation detail, can have comment etc.; saves another 8 bytes) and
moving has_volatile_ops:1 and references_memory_p:1 to base too (saves
another 8 bytes).  All this needs just minimal changes in gimple.h.
To get rid of the separate with_ops.op allocation, we can either keep the
current num_ops/op fields and just special case allocation, GC
and gimple_copy of the 2/3 operand GIMPLE_ASSIGN - put the 16/24 byte
op array into the place we just freed, so GIMPLE_ASSIGN will be
back to 128 bytes, but without a separate allocation for the ops.
Or, if gimple_ops, gimple_op, gimple_op_ptr, gimple_set_op and
gimple_num_ops are special cased, then 16 further bytes can be
saved by eliminating num_ops and the tree *op; pointer by putting the
3 operands inline - tree op[3];.  This is complicated by
gimple_statement_with_memory_ops containing with_ops as first field
- the 4 above inlines would then need to handle
GIMPLE_{COND,GOTO,LABEL,SWITCH} as one case, GIMPLE_ASSIGN
(and possible GIMPLE_RETURN) as another case and GIMPLE_CALL as yet another
case.

BTW, we still need just 3 flag bits and there are 3 unused bits,
so that for now we are ok, but in the future gimple_statement_base
has still 32 bits hole on 64-bit arches.  If all code uses inline
accessors, then perhaps gimple.h could use #ifdefs to differentiate
between 32-bit and 64-bit hosts, use 32-bits of flags in
gimple_statement_base for 64-bit hosts and for 32-bit hosts put a flag
word wherever they will be actually used.  I know that's ugly, but if it
is all hidden in gimple.h and not otherwise exposed, then memory savings
could be more important, if we still care about 32-bit hosts.

struct gimple_statement_base {
        enum gimple_code           code:16;              /*     0:16  4 */
        unsigned int               subcode:8;            /*     0: 8  4 */
        unsigned int               no_warning:1;         /*     0: 7  4 */
        unsigned int               visited:1;            /*     0: 6  4 */
        unsigned int               nontemporal_move:1;   /*     0: 5  4 */
        unsigned int               unused_1:1;           /*     0: 4  4 */
        unsigned int               unused_2:1;           /*     0: 3  4 */
        unsigned int               unused_3:1;           /*     0: 2  4 */
        unsigned int               plf:2;                /*     0: 0  4 */

        /* XXX 4 bytes hole, try to pack */

        struct basic_block_def *   bb;                   /*     8     8 */
        location_t                 location;             /*    16     4 */

        /* XXX 4 bytes hole, try to pack */

        tree                       block;                /*    24     8 */
        unsigned int               uid;                  /*    32     4 */

        /* size: 40, cachelines: 1 */
        /* sum members: 28, holes: 2, sum holes: 8 */
        /* padding: 4 */
        /* last cacheline: 40 bytes */
};      /* definitions: 1 */

struct gimple_statement_with_ops {
        struct gimple_statement_base gsbase;             /*     0    40 */

        /* XXX last struct has 4 bytes of padding */

        unsigned int               modified:1;           /*    40:31  4 */

        /* XXX 31 bits hole, try to pack */
        /* XXX 4 bytes hole, try to pack */

        bitmap                     addresses_taken;      /*    48     8 */
        struct def_optype_d *      def_ops;              /*    56     8 */
        /* --- cacheline 1 boundary (64 bytes) --- */
        struct use_optype_d *      use_ops;              /*    64     8 */
        size_t                     num_ops;              /*    72     8 */
        tree *                     op;                   /*    80     8 */

        /* size: 88, cachelines: 2 */
        /* sum members: 84, holes: 1, sum holes: 4 */
        /* bit holes: 1, sum bit holes: 31 bits */
        /* paddings: 1, sum paddings: 4 */
        /* last cacheline: 24 bytes */
};      /* definitions: 1 */

struct gimple_statement_with_memory_ops {
        struct gimple_statement_with_ops with_ops;       /*     0    88 */
        /* --- cacheline 1 boundary (64 bytes) was 24 bytes ago --- */
        unsigned int               has_volatile_ops:1;   /*    88:31  4 */
        unsigned int               references_memory_p:1; /*    88:30  4 */

        /* XXX 30 bits hole, try to pack */
        /* XXX 4 bytes hole, try to pack */

        struct voptype_d *         vdef_ops;             /*    96     8 */
        struct voptype_d *         vuse_ops;             /*   104     8 */
        bitmap                     stores;               /*   112     8 */
        bitmap                     loads;                /*   120     8 */
        /* --- cacheline 2 boundary (128 bytes) --- */

        /* size: 128, cachelines: 2 */
        /* sum members: 124, holes: 1, sum holes: 4 */
        /* bit holes: 1, sum bit holes: 30 bits */
};      /* definitions: 1 */

        Jakub

Reply via email to