GCC Middle and Back End API Reference

Data Structures  
struct  name_to_bb 
struct  ssa_names_hasher 
class  nontrapping_dom_walker 
Variables  
static unsigned int  nt_call_phase 
static hash_table < ssa_names_hasher >  seen_ssa_names 

static 
The function absolute_replacement does the main work of doing the absolute replacement. Return true if the replacement is done. Otherwise return false. bb is the basic block where the replacement is going to be done on. arg0 is argument 0 from the phi. Likewise for arg1.
If the type says honor signed zeros we cannot do this optimization.
OTHER_BLOCK must have only one executable statement which must have the form arg0 = arg1 or arg1 = arg0.
If we did not find the proper negation assignment, then we can not optimize.
If we got here, then we have found the only executable statement in OTHER_BLOCK. If it is anything other than arg = arg1 or arg1 = arg0, then we can not optimize.
The assignment has to be arg0 = arg1 or arg1 = arg0.
Only relationals comparing arg[01] against zero are interesting.
Make sure the conditional is arg[01] OP y.
We need to know which is the true edge and which is the false edge so that we know if have abs or negative abs.
For GT_EXPR/GE_EXPR, if the true edge goes to OTHER_BLOCK, then we will need to negate the result. Similarly for LT_EXPR/LE_EXPR if the false edge goes to OTHER_BLOCK.
Build the modify expression with abs expression.
Get the right GSI. We want to insert after the recently added ABS_EXPR statement (which we know is the first statement in the block.
Note that we optimized this PHI.

static 
We see the expression EXP in basic block BB. If it's an interesting expression (an MEM_REF through an SSA_NAME) possibly insert the expression into the set NONTRAP or the hash table of seen expressions. STORE is true if this expression is on the LHS, otherwise it's on the RHS.
Try to find the last seen MEM_REF through the same SSA_NAME, which can trap.
If we've found a trapping MEM_REF, _and_ it dominates EXP (it's in a basic block on the path from us to the dominator root) then we can't trap.
EXP might trap, so insert it into the hash table.

static 
Conditional store replacement. We already know that the recognized pattern looks like so: split: if (cond) goto THEN_BB; else goto ELSE_BB (edge E1) THEN_BB: ... X = Y; ... goto JOIN_BB; ELSE_BB: ... X = Z; ... fallthrough (edge E0) JOIN_BB: some more We check that it is safe to sink the store to JOIN_BB by verifying that there are no readafterwrite or writeafterwrite dependencies in THEN_BB and ELSE_BB.
Handle the case with single statement in THEN_BB and ELSE_BB.
Find data references.
Find pairs of stores with equal LHS.
No pairs of stores found.
Compute and check data dependencies in both basic blocks.
Check that there are no readafterwrite or writeafterwrite dependencies in THEN_BB.
Check that there are no readafterwrite or writeafterwrite dependencies in ELSE_BB.
Sink stores with same LHS.

static 
Do the main work of conditional store replacement.
Now we've checked the constraints, so do the transformation: 1) Remove the stores.
2) Create a PHI node at the join block, with one argument holding the old RHS, and the other holding the temporary where we stored the old memory contents.
3) Insert that PHI node.
References free_data_refs().

static 
Do the main work of conditional store replacement. We already know that the recognized pattern looks like so: split: if (cond) goto MIDDLE_BB; else goto JOIN_BB (edge E1) MIDDLE_BB: something fallthrough (edge E0) JOIN_BB: some more We check that MIDDLE_BB contains only one store, that that store doesn't trap (not via NOTRAP, but via checking if an access to the same memory location dominates us) and that the store has a "simple" RHS.
Check if middle_bb contains of only one store.
Prove that we can move the store down. We could also check TREE_THIS_NOTRAP here, but in that case we also could move stores, whose value is not available readily, which we want to avoid.
Now we've checked the constraints, so do the transformation: 1) Remove the single store.
2) Insert a load from the memory of the store to the temporary on the edge which did not contain the store.
3) Create a PHI node at the join block, with one argument holding the old RHS, and the other holding the temporary where we stored the old memory contents.
4) Insert that PHI node.

static 
The function conditional_replacement does the main work of doing the conditional replacement. Return true if the replacement is done. Otherwise return false. BB is the basic block where the replacement is going to be done on. ARG0 is argument 0 from PHI. Likewise for ARG1.
FIXME: Gimplification of complex type is too hard for now.
We aren't prepared to handle vectors either (and it is a question if it would be worthwhile anyway).
The PHI arguments have the constants 0 and 1, or 0 and 1, then convert it to the conditional.
At this point we know we have a GIMPLE_COND with two successors. One successor is BB, the other successor is an empty block which falls through into BB. There is a single PHI node at the join point (BB) and its arguments are constants (0, 1) or (0, 1). So, given the condition COND, and the two PHI arguments, we can rewrite this PHI into nonbranching code: dest = (COND) or dest = COND' We use the condition asis if the argument associated with the true edge has the value one or the argument associated with the false edge as the value zero. Note that those conditions are not the same since only one of the outgoing edges from the GIMPLE_COND will directly reach BB and thus be associated with an argument.
To handle special cases like floating point comparison, it is easier and less errorprone to build a tree and gimplify it on the fly though it is less efficient.
We need to know which is the true edge and which is the false edge so that we know when to invert the condition below.
Insert our new statements at the end of conditional block before the COND_STMT.
Set the locus to the first argument, unless is doesn't have one.
Note that we optimized this PHI.

static 

static 
Determine whether we should attempt to hoist adjacent loads out of diamond patterns in pass_phiopt. Always hoist loads if fhoistadjacentloads is specified and the target machine has both a conditional move instruction and a defined cache line size.

static 
Always do these optimizations if we have SSA trees to work on.

staticread 
This is the entry point of gathering non trapping memory accesses. It will do a dominator walk over the whole function, and it will make use of the bb>aux pointers. It returns a set of trees (the MEM_REFs itself) which can't trap.
We're going to do a dominator walk, so ensure that we have dominance information.

static 
Given a "diamond" controlflow pattern where BB0 tests a condition, BB1 and BB2 are "then" and "else" blocks dependent on this test, and BB3 rejoins control flow following BB1 and BB2, look for opportunities to hoist loads as follows. If BB3 contains a PHI of two loads, one each occurring in BB1 and BB2, and the loads are provably of adjacent fields in the same structure, then move both loads into BB0. Of course this can only be done if there are no dependencies preventing such motion. One of the hoisted loads will always be speculative, so the transformation is currently conservative:  The fields must be strictly adjacent.  The two fields must occupy a single memory block that is guaranteed to not cross a page boundary. The last is difficult to prove, as such memory blocks should be aligned on the minimum of the stack alignment boundary and the alignment guaranteed by heap allocation interfaces. Thus we rely on a parameter for the alignment value. Provided a good value is used for the last case, the first restriction could possibly be relaxed.
Walk the phis in bb3 looking for an opportunity. We are looking for phis of two SSA names, one each of which is defined in bb1 and bb2.
Check the mode of the arguments to be sure a conditional move can be generated for it.
Both statements must be assignments whose RHS is a COMPONENT_REF.
The zeroth operand of the two component references must be identical. It is not sufficient to compare get_base_address of the two references, because this could allow for different elements of the same array in the two trees. It is not safe to assume that the existence of one array element implies the existence of a different one.
Check for field adjacency, and ensure field1 comes first.
Check for proper alignment of the first field.
For profitability, the two field references should fit within a single cache line.
The two expressions cannot be dependent upon vdefs defined in bb1/bb2.
The conditions are satisfied; hoist the loads from bb1 and bb2 into bb0. We hoist the first one first so that a cache miss is handled efficiently regardless of hardware cachefill policy.

static 
Update *ARG which is defined in STMT so that it contains the computed value if that seems profitable. Return true if the statement is made dead by that rewriting.
For arg = &p>i transform it to p, if possible.
TODO: Much like IPACP jumpfunctions we want to handle constant additions symbolically here, and we'd need to update the comparison code that compares the arg + cst tuples in our caller. For now the code above exactly handles the VEC_BASE pattern from vec.h.
References gimple_assign_rhs1(), gimple_assign_rhs2(), gimple_assign_rhs_code(), is_gimple_assign(), and operand_equal_for_phi_arg_p().
Referenced by operand_equal_for_value_replacement().

static 
Return TRUE if STMT has a VUSE whose corresponding VDEF is in BB.
gimple_opt_pass* make_pass_cselim  (  ) 
gimple_opt_pass* make_pass_phiopt  (  ) 

static 
The function minmax_replacement does the main work of doing the minmax replacement. Return true if the replacement is done. Otherwise return false. BB is the basic block where the replacement is going to be done on. ARG0 is argument 0 from the PHI. Likewise for ARG1.
The optimization may be unsafe due to NaNs.
This transformation is only valid for order comparisons. Record which operand is smaller/larger if the result of the comparison is true.
We need to know which is the true edge and which is the false edge so that we know if have abs or negative abs.
Forward the edges over the middle basic block.
Case if (smaller < larger) rslt = smaller; else rslt = larger;
Recognize the following case, assuming d <= u: if (a <= u) b = MAX (a, d); x = PHI <b, u> This is equivalent to b = MAX (a, d); x = MIN (b, u);
We got here if the condition is true, i.e., SMALLER < LARGER.
Case if (smaller < larger) { r' = MAX_EXPR (smaller, bound) } r = PHI <r', larger> > to be turned to MIN_EXPR.
We need BOUND <= LARGER.
Case if (smaller < larger) { r' = MIN_EXPR (larger, bound) } r = PHI <r', smaller> > to be turned to MAX_EXPR.
We need BOUND >= SMALLER.
We got here if the condition is false, i.e., SMALLER > LARGER.
Case if (smaller > larger) { r' = MIN_EXPR (smaller, bound) } r = PHI <r', larger> > to be turned to MAX_EXPR.
We need BOUND >= LARGER.
Case if (smaller > larger) { r' = MAX_EXPR (larger, bound) } r = PHI <r', smaller> > to be turned to MIN_EXPR.
We need BOUND <= SMALLER.
Move the statement from the middle block.
Emit the statement to compute min/max.

static 
Return TRUE if arg0/arg1 are equal to the rhs/lhs or lhs/rhs of COND. Also return TRUE if arg0/arg1 are equal to the source arguments of a an EQ comparison feeding a BIT_AND_EXPR which feeds COND. Return FALSE otherwise.
Now handle more complex case where we have an EQ comparison which feeds a BIT_AND_EXPR which feeds COND. First verify that COND is of the form SSA_NAME NE 0.
Now ensure that SSA_NAME is set by a BIT_AND_EXPR.
Now verify arg0/arg1 correspond to the source arguments of an EQ comparison feeding the BIT_AND_EXPR.
References extract_true_false_edges_from_block(), gimple_assign_lhs(), gimple_cond_code(), gsi_after_labels(), gsi_end_p(), gsi_next_nondebug(), gsi_stmt(), is_gimple_assign(), is_gimple_debug(), jump_function_from_stmt(), and last_stmt().

static 
Replace PHI node element whose edge is E in block BB with variable NEW. Remove the edge from COND_BLOCK which does not lead to BB (COND_BLOCK is known to have two edges, one of which must reach BB).
Change the PHI argument to new.
Remove the empty basic block.
Eliminate the COND_EXPR at the end of COND_BLOCK.
Referenced by value_replacement().

static 
RHS is a source argument in a BIT_AND_EXPR which feeds a conditional of the form SSA_NAME NE 0. If RHS is fed by a simple EQ_EXPR comparison of two values, see if the two input values of the EQ_EXPR match arg0 and arg1. If so update *code and return TRUE. Otherwise return FALSE.
Obviously if RHS is not an SSA_NAME, we can't look at the defining statement.
Verify the defining statement has an EQ_EXPR on the RHS.
Finally verify the source operands of the EQ_EXPR are equal to arg0 and arg1.
We will perform the optimization.

static 
Return the singleton PHI in the SEQ of PHIs for edges E0 and E1.
If the PHI arguments are equal then we can skip this PHI.
If we already have a PHI that has the two edge arguments are different, then return it is not a singleton for these PHIs.
Referenced by value_replacement().

static 
This pass tries to transform conditional stores into unconditional ones, enabling further simplifications with the simpler then and else blocks. In particular it replaces this: bb0: if (cond) goto bb2; else goto bb1; bb1: *p = RHS; bb2: with bb0: if (cond) goto bb1; else goto bb2; bb1: condtmp' = *p; bb2: condtmp = PHI <RHS, condtmp'> *p = condtmp; This transformation can only be done under several constraints, documented below. It also replaces: bb0: if (cond) goto bb2; else goto bb1; bb1: *p = RHS1; goto bb3; bb2: *p = RHS2; bb3: with bb0: if (cond) goto bb3; else goto bb1; bb1: bb3: condtmp = PHI <RHS1, RHS2> *p = condtmp;
??? We are not interested in loop related info, but the following will create it, ICEing as we didn't init loops with preheaders. An interfacing issue of find_data_references_in_bb.

static 
This pass tries to replaces an ifthenelse block with an assignment. We have four kinds of transformations. Some of these transformations are also performed by the ifcvt RTL optimizer. Conditional Replacement  This transformation, implemented in conditional_replacement, replaces bb0: if (cond) goto bb2; else goto bb1; bb1: bb2: x = PHI <0 (bb1), 1 (bb0), ...>; with bb0: x' = cond; goto bb2; bb2: x = PHI <x' (bb0), ...>; We remove bb1 as it becomes unreachable. This occurs often due to gimplification of conditionals. Value Replacement  This transformation, implemented in value_replacement, replaces bb0: if (a != b) goto bb2; else goto bb1; bb1: bb2: x = PHI <a (bb1), b (bb0), ...>; with bb0: bb2: x = PHI <b (bb0), ...>; This opportunity can sometimes occur as a result of other optimizations. Another case caught by value replacement looks like this: bb0: t1 = a == CONST; t2 = b > c; t3 = t1 & t2; if (t3 != 0) goto bb1; else goto bb2; bb1: bb2: x = PHI (CONST, a) Gets replaced with: bb0: bb2: t1 = a == CONST; t2 = b > c; t3 = t1 & t2; x = a; ABS Replacement  This transformation, implemented in abs_replacement, replaces bb0: if (a >= 0) goto bb2; else goto bb1; bb1: x = a; bb2: x = PHI <x (bb1), a (bb0), ...>; with bb0: x' = ABS_EXPR< a >; bb2: x = PHI <x' (bb0), ...>; MIN/MAX Replacement  This transformation, minmax_replacement replaces bb0: if (a <= b) goto bb2; else goto bb1; bb1: bb2: x = PHI <b (bb1), a (bb0), ...>; with bb0: x' = MIN_EXPR (a, b) bb2: x = PHI <x' (bb0), ...>; A similar transformation is done for MAX_EXPR. This pass also performs a fifth transformation of a slightly different flavor. Adjacent Load Hoisting  This transformation replaces bb0: if (...) goto bb2; else goto bb1; bb1: x1 = (<expr>).field1; goto bb3; bb2: x2 = (<expr>).field2; bb3: # x = PHI <x1, x2>; with bb0: x1 = (<expr>).field1; x2 = (<expr>).field2; if (...) goto bb2; else goto bb1; bb1: goto bb3; bb2: bb3: # x = PHI <x1, x2>; The purpose of this transformation is to enable generation of conditional move instructions such as Intel CMOVE or PowerPC ISEL. Because one of the loads is speculative, the transformation is restricted to very specific cases to avoid introducing a page fault. We are looking for the common idiom: if (...) x = y>left; else x = y>right; where left and right are typically adjacent pointers in a tree structure.

static 

static 
The core routine of conditional store replacement and normal phi optimizations. Both share much of the infrastructure in how to match applicable basic block patterns. DO_STORE_ELIM is true when we want to do conditional store replacement, false otherwise. DO_HOIST_LOADS is true when we want to hoist adjacent loads out of diamond control flow patterns, false otherwise.
Calculate the set of nontrapping memory accesses.
Search every basic block for COND_EXPR we may be able to optimize. We walk the blocks in order that guarantees that a block with a single predecessor is processed before the predecessor. This ensures that we collapse inner ifs before visiting the outer ones, and also that we do not try to visit a removed block.
Check to see if the last statement is a GIMPLE_COND.
We cannot do the optimization on abnormal edges.
If either bb1's succ or bb2 or bb2's succ is non NULL.
Find the bb which is the fall through to the other.
If one edge or the other is dominant, a conditional move is likely to perform worse than the wellpredicted branch.
Make sure that bb1 is just a fall through.
Also make sure that bb1 only have one predecessor and that it is bb.
bb1 is the middle block, bb2 the join block, bb the split block, e1 the fallthrough edge from bb1 to bb2. We can't do the optimization if the join block has more than two predecessors.
Value replacement can work with more than one PHI so try that first.
Something is wrong if we cannot find the arguments in the PHI node.
Do the replacement of conditional if it can be done.
If the CFG has changed, we should cleanup the CFG.
In condstore replacement we have added some loads on edges and new VOPS (as we moved the store, and created a load).

static 
The function value_replacement does the main work of doing the value replacement. Return nonzero if the replacement is done. Otherwise return 0. If we remove the middle basic block, return 2. BB is the basic block where the replacement is going to be done on. ARG0 is argument 0 from the PHI. Likewise for ARG1.
If the type says honor signed zeros we cannot do this optimization.
If there is a statement in MIDDLE_BB that defines one of the PHI arguments, then adjust arg0 or arg1.
Now try to adjust arg0 or arg1 according to the computation in the statement.
This transformation is only valid for equality comparisons.
We need to know which is the true edge and which is the false edge so that we know if have abs or negative abs.
At this point we know we have a COND_EXPR with two successors. One successor is BB, the other successor is an empty block which falls through into BB. The condition for the COND_EXPR is known to be NE_EXPR or EQ_EXPR. There is a single PHI node at the join point (BB) with two arguments. We now need to verify that the two arguments in the PHI node match the two arguments to the equality comparison.
For NE_EXPR, we want to build an assignment result = arg where arg is the PHI argument associated with the true edge. For EQ_EXPR we want the PHI argument associated with the false edge.
Unfortunately, E may not reach BB (it may instead have gone to OTHER_BLOCK). If that is the case, then we want the single outgoing edge from OTHER_BLOCK which reaches BB and represents the desired path from COND_BLOCK.
Now we know the incoming edge to BB that has the argument for the RHS of our new assignment statement.
If the middle basic block was empty or is defining the PHI arguments and this is a single phi where the args are different for the edges e0 and e1 then we can remove the middle basic block.
Note that we optimized this PHI.
Replace the PHI arguments with arg.
References edge_def::dest, edge_def::dest_idx, dump_file, dump_flags, gimple_phi_result(), basic_block_def::index, phi_nodes(), print_generic_expr(), replace_phi_edge_with_variable(), single_non_singleton_phi_for_edges(), and single_succ_edge().

static 
Used for quick clearing of the hashtable when we see calls. Hash entries with phase < nt_call_phase are invalid.

static 
The hash table for remembering what we've seen.