Previous:Conditional Expressions, Up:Operands [Contents][Index]
Except when they appear in the condition operand of aGIMPLE_COND, logical ‘and’ and ‘or’ operators are simplifiedas follows:a = b && c becomes
T1 = (bool)b;if (T1 == true) T1 = (bool)c;a = T1;
Note thatT1 in this example cannot be an expression temporary,because it has two different assignments.
All gimple operands are of typetree. But only certaintypes of trees are allowed to be used as operand tuples. Basicvalidation is controlled by the functionget_gimple_rhs_class, which given a tree code, returns anenum with the following values of typeenumgimple_rhs_class
GIMPLE_INVALID_RHSThe tree cannot be used as a GIMPLE operand.GIMPLE_TERNARY_RHSThe tree is a valid GIMPLE ternary operation.GIMPLE_BINARY_RHSThe tree is a valid GIMPLE binary operation.GIMPLE_UNARY_RHSThe tree is a valid GIMPLE unary operation.GIMPLE_SINGLE_RHSThe tree is a single object, that cannot be split into simpleroperands (for instance,SSA_NAME,VAR_DECL,COMPONENT_REF, etc).This operand class also acts as an escape hatch for tree nodesthat may be flattened out into the operand vector, but would needmore than two slots on the RHS. For instance, aCOND_EXPRexpression of the form(a op b) ? x : y could be flattenedout on the operand vector using 4 slots, but it would alsorequire additional processing to distinguishc = a op bfromc = a op b ? x : y. In time, these special case treeexpressions should be flattened into the operand vector.
For tree nodes in the categoriesGIMPLE_TERNARY_RHS,GIMPLE_BINARY_RHS andGIMPLE_UNARY_RHS, they cannot bestored inside tuples directly. They first need to be flattened andseparated into individual components. For instance, given the GENERICexpression
a = b + c
its tree representation is:
MODIFY_EXPR <VAR_DECL <a>, PLUS_EXPR <VAR_DECL <b>, VAR_DECL <c>>>
In this case, the GIMPLE form for this statement is logicallyidentical to its GENERIC form but in GIMPLE, thePLUS_EXPRon the RHS of the assignment is not represented as a tree,instead the two operands are taken out of thePLUS_EXPR sub-treeand flattened into the GIMPLE tuple as follows:
GIMPLE_ASSIGN <PLUS_EXPR, VAR_DECL <a>, VAR_DECL <b>, VAR_DECL <c>>
The operand vector is stored at the bottom of the three tuplestructures that accept operands. This means, that depending onthe code of a given statement, its operand vector will be atdifferent offsets from the base of the structure. To accesstuple operands use the following accessors
unsignedgimple_num_ops(gimple g) ¶Returns the number of operands in statement G.
treegimple_op(gimple g, unsigned i) ¶Returns operandI from statementG.
tree *gimple_ops(gimple g) ¶Returns a pointer into the operand vector for statementG. Thisis computed using an internal table calledgimple_ops_offset_[].This table is indexed by the gimple code ofG.
When the compiler is built, this table is filled-in using thesizes of the structures used by each statement code defined ingimple.def. Since the operand vector is at the bottom of thestructure, for a gimple codeC the offset is computed as sizeof(struct-ofC) - sizeof (tree).
This mechanism adds one memory indirection to every access whenusinggimple_op(), if this becomes a bottleneck, a pass canchoose to memoize the result fromgimple_ops() and use that toaccess the operands.
When adding a new operand to a gimple statement, the operand willbe validated according to what each tuple accepts in its operandvector. These predicates are called by thegimple_name_set_...(). Each tuple will use one of thefollowing predicates (Note, this list is not exhaustive):
boolis_gimple_val(tree t) ¶Returns true if t is a "GIMPLE value", which are all thenon-addressable stack variables (variables for whichis_gimple_reg returns true) and constants (expressions for whichis_gimple_min_invariant returns true).
boolis_gimple_addressable(tree t) ¶Returns true if t is a symbol or memory reference whose addresscan be taken.
boolis_gimple_asm_val(tree t) ¶Similar tois_gimple_val but it also accepts hard registers.
boolis_gimple_call_addr(tree t) ¶Return true if t is a valid expression to use as the functioncalled by aGIMPLE_CALL.
boolis_gimple_mem_ref_addr(tree t) ¶Return true if t is a valid expression to use as first operandof aMEM_REF expression.
boolis_gimple_constant(tree t) ¶Return true if t is a valid gimple constant.
boolis_gimple_min_invariant(tree t) ¶Return true if t is a valid minimal invariant. This is differentfrom constants, in that the specific value of t may not be knownat compile time, but it is known that it doesn’t change (e.g.,the address of a function local variable).
boolis_gimple_ip_invariant(tree t) ¶Return true if t is an interprocedural invariant. This means that tis a valid invariant in all functions (e.g. it can be an address of aglobal variable but not of a local one).
boolis_gimple_ip_invariant_address(tree t) ¶Return true if t is anADDR_EXPR that does not change once theprogram is running (and which is valid in all functions).
boolis_gimple_assign(gimple g) ¶Return true if the code of g isGIMPLE_ASSIGN.
boolis_gimple_call(gimple g) ¶Return true if the code of g isGIMPLE_CALL.
boolis_gimple_debug(gimple g) ¶Return true if the code of g isGIMPLE_DEBUG.
boolgimple_assign_cast_p(const_gimple g) ¶Return true if g is aGIMPLE_ASSIGN that performs a type castoperation.
boolgimple_debug_bind_p(gimple g) ¶Return true if g is aGIMPLE_DEBUG that binds the value of anexpression to a variable.
boolis_gimple_omp(gimple g) ¶Return true if g is any of the OpenMP codes.
boolgimple_debug_begin_stmt_p(gimple g) ¶Return true if g is aGIMPLE_DEBUG that marks the beginning ofa source statement.
boolgimple_debug_inline_entry_p(gimple g) ¶Return true if g is aGIMPLE_DEBUG that marks the entrypoint of an inlined function.
boolgimple_debug_nonbind_marker_p(gimple g) ¶Return true if g is aGIMPLE_DEBUG that marks a program location,without any variable binding.
Previous:Conditional Expressions, Up:Operands [Contents][Index]