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