GCC Middle and Back End API Reference
|
Data Structures | |
struct | tailcall |
Variables | |
static tree | m_acc |
static tree | a_acc |
|
static |
Helper to insert PHI_ARGH to the phi of VAR in the destination of edge E.
|
static |
Adjust the accumulator values according to A and M after GSI, and update the phi nodes on edge BACK.
|
static |
Adjust value of the return at the end of BB according to M and A accumulators.
References cfun, is_gimple_reg(), and ssa_default_def().
|
static |
Creates a GIMPLE statement which computes the operation specified by CODE, ACC and OP1 to a new variable with name LABEL and inserts the statement in the position specified by GSI. Returns the tree node of the statement's result.
|
static |
Returns true if argument PARAM of the tail recursive call needs to be copied when the call is eliminated.
Parameters that are only defined but never used need not be copied.
|
static |
Creates a tail-call accumulator of the same type as the return type of the current function. LABEL is the name used to creating the temporary variable for the accumulator. The accumulator will be inserted in the phis of a basic block BB with single predecessor with an initial value INIT converted to the current function return type.
RET_TYPE can be a float when -ffast-maths is enabled.
|
static |
Subtract COUNT and FREQUENCY from the basic block and it's outgoing edge.
|
static |
|
static |
Eliminates tail call described by T. TMP_VARS is a list of temporary variables used to copy the function arguments.
Remove the code after call_gsi that will become unreachable. The possibly unreachable code in other blocks is removed later in cfg cleanup.
Do not remove the return statement, so that redirect_edge_and_branch sees how the block ends.
Number of executions of function has reduced by the tailcall.
Replace the call by a jump to the start of function.
Add phi node entries for arguments. The ordering of the phi nodes should be the same as the ordering of the arguments.
Update the values of accumulators.
Result of the call will no longer be defined. So adjust the SSA_NAME_DEF_STMT accordingly.
|
static |
|
static |
|
static |
|
static |
Finds tailcalls falling into basic block BB. The list of found tailcalls is added to the start of RET.
Ignore labels, returns, clobbers and debug stmts.
Check for a call.
If the statement references memory or volatile operands, fail.
Recurse to the predecessors.
If the LHS of our call is not just a simple register, we can't transform this into a tail or sibling call. This situation happens, in (e.g.) "*p = foo()" where foo returns a struct. In this case we won't have a temporary here, but we need to carry out the side effect anyway, so tailcall is impossible. ??? In some situations (when the struct is returned in memory via invisible argument) we could deal with this, e.g. by passing 'p' itself as that argument to foo, but it's too early to do this here, and expand_call() will not handle it anyway. If it ever can, then we need to revisit this here, to allow that situation.
We found the call, check whether it is suitable.
Make sure there are no problems with copying. The parameter have a copyable type and the two arguments must have reasonably equivalent types. The latter requirement could be relaxed if we emitted a suitable type conversion statement.
The parameter should be a real operand, so that phi node created for it at the start of the function has the meaning of copying the value. This test implies is_gimple_reg_type from the previous condition, however this one could be relaxed by being more careful with copying the new value of the parameter (emitting appropriate GIMPLE_ASSIGN and updating the virtual operands).
Make sure the tail invocation of this function does not refer to local variables.
Now check the statements after the call. None of them has virtual operands, so they may only depend on the call through its return value. The return value should also be dependent on each of them, since we are running after dce.
This is a gimple assign.
See if this is a tail call we can handle.
We may proceed if there either is no return value, or the return value is identical to the call's return.
If this is not a tail recursive call, we cannot handle addends or multiplicands.
For pointers only allow additions.
References gimple_call_lhs().
|
static |
|
static |
Checks whether the expression EXPR in stmt AT is independent of the statement pointed to by GSI (in a sense that we already know EXPR's value at GSI). We use the fact that we are only called from the chain of basic blocks that have only single successor. Returns the expression containing the value of EXPR at GSI.
Mark the blocks in the chain leading to the end.
The default definition or defined before the chain.
The value is a constant.
Unmark the blocks.
References basic_block_def::aux, gimple_bb(), gsi_end_p(), gsi_next(), gsi_stmt(), basic_block_def::preds, and edge_def::src.
gimple_opt_pass* make_pass_tail_calls | ( | ) |
gimple_opt_pass* make_pass_tail_recursion | ( | ) |
|
static |
|
static |
Optimizes the tailcall described by T. If OPT_TAILCALLS is true, also mark the tailcalls for the sibcall optimization.
|
static |
Simulates the effect of an assignment STMT on the return value of the tail recursive CALL passed in ASS_VAR. M and A are the multiplicative and the additive factor for the real return value.
See if this is a simple copy operation of an SSA name to the function result. In that case we may have a simple tail call. Ignore type conversions that can never produce extra code between the function call and the function return.
Reject a tailcall if the type conversion might need additional code.
Fall through.
Accumulator optimizations will reverse the order of operations. We can only do that for floating-point types if we're assuming that addition and multiplication are associative.
TODO -- Handle POINTER_PLUS_EXPR.
|
static |
Propagate VAR through phis on edge E.
|
static |
Returns false when the function is not suitable for tail call optimization from some reason (e.g. if it takes variable number of arguments). This test must pass in addition to suitable_for_tail_opt_p in order to make tail call discovery happen.
alloca (until we have stack slot life analysis) inhibits sibling call optimizations, but not tail recursion.
If we are using sjlj exceptions, we may need to add a call to _Unwind_SjLj_Unregister at exit of the function. Which means that we cannot do any sibcall transformations.
Any function that calls setjmp might have longjmp called from any called function. ??? We really should represent this properly in the CFG so that this needn't be special cased.
??? It is OK if the argument of a function is taken in some cases, but not in all cases. See PR15387 and PR19616. Revisit for 4.1.
|
static |
Returns false when the function is not suitable for tail call optimization from some reason (e.g. if it takes variable number of arguments).
References function::calls_alloca, and cfun.
|
static |
Optimizes tail calls in the function, turning the tail recursion into iteration.
Only traverse the normal exits, i.e. those that end with return statement.
Construct the phi nodes and accumulators if necessary.
Ensure that there is only one predecessor of the block or if there are existing degenerate PHI nodes.
Copy the args if needed.
When the tail call elimination using accumulators is performed, statements adding the accumulated value are inserted at all exits. This turns all other tail calls to non-tail ones.
Modify the remaining return statements.
We may have created new loops. Make them magically appear.
Add phi nodes for the virtual operands defined in the function to the header of the loop created by tail recursion elimination. Do so by triggering the SSA renamer.
|
static |
Creates a new GIMPLE statement that adjusts the value of accumulator ACC by the computation specified by CODE and OP1 and insert the statement at the position specified by GSI as a new statement. Returns new SSA name of updated accumulator.
|
static |
|
static |
The variables holding the value of multiplicative and additive accumulator.