Tuple representation#
GIMPLE instructions are tuples of variable size divided in two groups: a header describing the instruction and its locations, and a variable length body with all the operands. Tuples are organized into a hierarchy with 3 main classes of tuples.
gimple (gsbase)#
This is the root of the hierarchy, it holds basic information needed by most GIMPLE statements. There are some fields that may not be relevant to every GIMPLE statement, but those were moved into the base structure to take advantage of holes left by other fields (thus making the structure more compact). The structure takes 4 words (32 bytes) on 64 bit hosts:
Field |
Size (bits) |
|
8 |
|
16 |
|
1 |
|
1 |
|
1 |
|
2 |
|
1 |
|
1 |
|
1 |
|
32 |
|
32 |
|
32 |
|
64 |
|
63 |
Total size |
32 bytes |
codeMain identifier for a GIMPLE instruction.subcodeUsed to distinguish different variants of the same basic instruction or provide flags applicable to a given code. Thesubcodeflags field has different uses depending on the code of the instruction, but mostly it distinguishes instructions of the same family. The most prominent use of this field is in assignments, where subcode indicates the operation done on the RHS of the assignment. For example, a = b + c is encoded asGIMPLE_ASSIGN <PLUS_EXPR, a, b, c>.no_warningBitflag to indicate whether a warning has already been issued on this statement.visitedGeneral purpose ‘visited’ marker. Set and cleared by each pass when needed.nontemporal_moveBitflag used in assignments that represent non-temporal moves. Although this bitflag is only used in assignments, it was moved into the base to take advantage of the bit holes left by the previous fields.plfPass Local Flags. This 2-bit mask can be used as general purpose markers by any pass. Passes are responsible for clearing and setting these two flags accordingly.modifiedBitflag to indicate whether the statement has been modified. Used mainly by the operand scanner to determine when to re-scan a statement for operands.has_volatile_opsBitflag to indicate whether this statement contains operands that have been marked volatile.references_memory_pBitflag to indicate whether this statement contains memory references (i.e., its operands are either global variables, or pointer dereferences or anything that must reside in memory).uidThis is an unsigned integer used by passes that want to assign IDs to every statement. These IDs must be assigned and used by each pass.locationThis is alocation_tidentifier to specify source code location for this statement. It is inherited from the front end.num_opsNumber of operands that this statement has. This specifies the size of the operand vector embedded in the tuple. Only used in some tuples, but it is declared in the base tuple to take advantage of the 32-bit hole left by the previous fields.bbBasic block holding the instruction.blockLexical block holding this statement. Also used for debug information generation.
gimple_statement_with_ops#
This tuple is actually split in two:
gimple_statement_with_ops_base and
gimple_statement_with_ops. This is needed to accommodate the
way the operand vector is allocated. The operand vector is
defined to be an array of 1 element. So, to allocate a dynamic
number of operands, the memory allocator (gimple_alloc) simply
allocates enough memory to hold the structure itself plus N
- 1 operands which run ‘off the end’ of the structure. For
example, to allocate space for a tuple with 3 operands,
gimple_alloc reserves sizeof (struct
gimple_statement_with_ops) + 2 * sizeof (tree) bytes.
On the other hand, several fields in this tuple need to be shared
with the gimple_statement_with_memory_ops tuple. So, these
common fields are placed in gimple_statement_with_ops_base which
is then inherited from the other two tuples.
|
256 |
|
64 |
|
64 |
|
|
Total size |
48 + 8 * |
gsbaseInherited fromstruct gimple.def_opsArray of pointers into the operand array indicating all the slots that contain a variable written-to by the statement. This array is also used for immediate use chaining. Note that it would be possible to not rely on this array, but the changes required to implement this are pretty invasive.use_opsSimilar todef_opsbut for variables read by the statement.opArray of trees withnum_opsslots.
gimple_statement_with_memory_ops#
This tuple is essentially identical to gimple_statement_with_ops,
except that it contains 4 additional fields to hold vectors
related memory stores and loads. Similar to the previous case,
the structure is split in two to accommodate for the operand
vector (gimple_statement_with_memory_ops_base and
gimple_statement_with_memory_ops).
Field |
Size (bits) |
|
256 |
|
64 |
|
64 |
|
64 |
|
64 |
|
64 |
|
64 |
|
|
Total size |
80 + 8 * |
vdef_opsSimilar todef_opsbut forVDEFoperators. There is one entry per memory symbol written by this statement. This is used to maintain the memory SSA use-def and def-def chains.vuse_opsSimilar touse_opsbut forVUSEoperators. There is one entry per memory symbol loaded by this statement. This is used to maintain the memory SSA use-def chains.storesBitset with all the UIDs for the symbols written-to by the statement. This is different thanvdef_opsin that all the affected symbols are mentioned in this set. If memory partitioning is enabled, thevdef_opsvector will refer to memory partitions. Furthermore, no SSA information is stored in this set.loadsSimilar tostores, but for memory loads. (Note that there is some amount of redundancy here, it should be possible to reduce memory utilization further by removing these sets).
All the other tuples are defined in terms of these three basic ones. Each tuple will add some fields.