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