gccint: Logical Operators
1
1 12.6.4 Logical Operators
1 ------------------------
1
1 Except when they appear in the condition operand of a 'GIMPLE_COND',
1 logical 'and' and 'or' operators are simplified as follows: 'a = b && c'
1 becomes
1
1 T1 = (bool)b;
1 if (T1 == true)
1 T1 = (bool)c;
1 a = T1;
1
1 Note that 'T1' in this example cannot be an expression temporary,
1 because it has two different assignments.
1
1 12.6.5 Manipulating operands
1 ----------------------------
1
1 All gimple operands are of type 'tree'. But only certain types of trees
1 are allowed to be used as operand tuples. Basic validation is
1 controlled by the function 'get_gimple_rhs_class', which given a tree
1 code, returns an 'enum' with the following values of type 'enum
1 gimple_rhs_class'
1
1 * 'GIMPLE_INVALID_RHS' The tree cannot be used as a GIMPLE operand.
1
1 * 'GIMPLE_TERNARY_RHS' The tree is a valid GIMPLE ternary operation.
1
1 * 'GIMPLE_BINARY_RHS' The tree is a valid GIMPLE binary operation.
1
1 * 'GIMPLE_UNARY_RHS' The tree is a valid GIMPLE unary operation.
1
1 * 'GIMPLE_SINGLE_RHS' The tree is a single object, that cannot be
1 split into simpler operands (for instance, 'SSA_NAME', 'VAR_DECL',
1 'COMPONENT_REF', etc).
1
1 This operand class also acts as an escape hatch for tree nodes that
1 may be flattened out into the operand vector, but would need more
1 than two slots on the RHS. For instance, a 'COND_EXPR' expression
1 of the form '(a op b) ? x : y' could be flattened out on the
1 operand vector using 4 slots, but it would also require additional
1 processing to distinguish 'c = a op b' from 'c = a op b ? x : y'.
1 Something similar occurs with 'ASSERT_EXPR'. In time, these
1 special case tree expressions should be flattened into the operand
1 vector.
1
1 For tree nodes in the categories 'GIMPLE_TERNARY_RHS',
1 'GIMPLE_BINARY_RHS' and 'GIMPLE_UNARY_RHS', they cannot be stored inside
1 tuples directly. They first need to be flattened and separated into
1 individual components. For instance, given the GENERIC expression
1
1 a = b + c
1
1 its tree representation is:
1
1 MODIFY_EXPR <VAR_DECL <a>, PLUS_EXPR <VAR_DECL <b>, VAR_DECL <c>>>
1
1 In this case, the GIMPLE form for this statement is logically identical
1 to its GENERIC form but in GIMPLE, the 'PLUS_EXPR' on the RHS of the
1 assignment is not represented as a tree, instead the two operands are
1 taken out of the 'PLUS_EXPR' sub-tree and flattened into the GIMPLE
1 tuple as follows:
1
1 GIMPLE_ASSIGN <PLUS_EXPR, VAR_DECL <a>, VAR_DECL <b>, VAR_DECL <c>>
1
1 12.6.6 Operand vector allocation
1 --------------------------------
1
1 The operand vector is stored at the bottom of the three tuple structures
1 that accept operands. This means, that depending on the code of a given
1 statement, its operand vector will be at different offsets from the base
1 of the structure. To access tuple operands use the following accessors
1
1 -- GIMPLE function: unsigned gimple_num_ops (gimple g)
1 Returns the number of operands in statement G.
1
1 -- GIMPLE function: tree gimple_op (gimple g, unsigned i)
1 Returns operand 'I' from statement 'G'.
1
1 -- GIMPLE function: tree * gimple_ops (gimple g)
1 Returns a pointer into the operand vector for statement 'G'. This
1 is computed using an internal table called 'gimple_ops_offset_'[].
1 This table is indexed by the gimple code of 'G'.
1
1 When the compiler is built, this table is filled-in using the sizes
1 of the structures used by each statement code defined in
1 gimple.def. Since the operand vector is at the bottom of the
1 structure, for a gimple code 'C' the offset is computed as sizeof
1 (struct-of 'C') - sizeof (tree).
1
1 This mechanism adds one memory indirection to every access when
1 using 'gimple_op'(), if this becomes a bottleneck, a pass can
1 choose to memoize the result from 'gimple_ops'() and use that to
1 access the operands.
1
1 12.6.7 Operand validation
1 -------------------------
1
1 When adding a new operand to a gimple statement, the operand will be
1 validated according to what each tuple accepts in its operand vector.
1 These predicates are called by the 'gimple_NAME_set_...()'. Each tuple
1 will use one of the following predicates (Note, this list is not
1 exhaustive):
1
1 -- GIMPLE function: bool is_gimple_val (tree t)
1 Returns true if t is a "GIMPLE value", which are all the
1 non-addressable stack variables (variables for which
1 'is_gimple_reg' returns true) and constants (expressions for which
1 'is_gimple_min_invariant' returns true).
1
1 -- GIMPLE function: bool is_gimple_addressable (tree t)
1 Returns true if t is a symbol or memory reference whose address can
1 be taken.
1
1 -- GIMPLE function: bool is_gimple_asm_val (tree t)
1 Similar to 'is_gimple_val' but it also accepts hard registers.
1
1 -- GIMPLE function: bool is_gimple_call_addr (tree t)
1 Return true if t is a valid expression to use as the function
1 called by a 'GIMPLE_CALL'.
1
1 -- GIMPLE function: bool is_gimple_mem_ref_addr (tree t)
1 Return true if t is a valid expression to use as first operand of a
1 'MEM_REF' expression.
1
1 -- GIMPLE function: bool is_gimple_constant (tree t)
1 Return true if t is a valid gimple constant.
1
1 -- GIMPLE function: bool is_gimple_min_invariant (tree t)
1 Return true if t is a valid minimal invariant. This is different
1 from constants, in that the specific value of t may not be known at
1 compile time, but it is known that it doesn't change (e.g., the
1 address of a function local variable).
1
1 -- GIMPLE function: bool is_gimple_ip_invariant (tree t)
1 Return true if t is an interprocedural invariant. This means that
1 t is a valid invariant in all functions (e.g. it can be an address
1 of a global variable but not of a local one).
1
1 -- GIMPLE function: bool is_gimple_ip_invariant_address (tree t)
1 Return true if t is an 'ADDR_EXPR' that does not change once the
1 program is running (and which is valid in all functions).
1
1 12.6.8 Statement validation
1 ---------------------------
1
1 -- GIMPLE function: bool is_gimple_assign (gimple g)
1 Return true if the code of g is 'GIMPLE_ASSIGN'.
1
1 -- GIMPLE function: bool is_gimple_call (gimple g)
1 Return true if the code of g is 'GIMPLE_CALL'.
1
1 -- GIMPLE function: bool is_gimple_debug (gimple g)
1 Return true if the code of g is 'GIMPLE_DEBUG'.
1
1 -- GIMPLE function: bool gimple_assign_cast_p (const_gimple g)
1 Return true if g is a 'GIMPLE_ASSIGN' that performs a type cast
1 operation.
1
1 -- GIMPLE function: bool gimple_debug_bind_p (gimple g)
1 Return true if g is a 'GIMPLE_DEBUG' that binds the value of an
1 expression to a variable.
1
1 -- GIMPLE function: bool is_gimple_omp (gimple g)
1 Return true if g is any of the OpenMP codes.
1
1 -- GIMPLE function: gimple_debug_begin_stmt_p (gimple g)
1 Return true if g is a 'GIMPLE_DEBUG' that marks the beginning of a
1 source statement.
1
1 -- GIMPLE function: gimple_debug_inline_entry_p (gimple g)
1 Return true if g is a 'GIMPLE_DEBUG' that marks the entry point of
1 an inlined function.
1
1 -- GIMPLE function: gimple_debug_nonbind_marker_p (gimple g)
1 Return true if g is a 'GIMPLE_DEBUG' that marks a program location,
1 without any variable binding.
1