GCC Middle and Back End API Reference
|
Data Structures | |
struct | prop_value_d |
Typedefs | |
typedef struct prop_value_d | prop_value_t |
typedef hash_table < pointer_hash < gimple_statement_base > > | gimple_htab |
Enumerations | |
enum | ccp_lattice_t { UNINITIALIZED, UNDEFINED, CONSTANT, VARYING } |
Variables | |
static prop_value_t * | const_val |
static unsigned | n_const_val |
typedef hash_table<pointer_hash <gimple_statement_base> > gimple_htab |
typedef struct prop_value_d prop_value_t |
enum ccp_lattice_t |
@verbatim
Conditional constant propagation pass for the GNU compiler. Copyright (C) 2000-2013 Free Software Foundation, Inc. Adapted from original RTL SSA-CCP by Daniel Berlin dberl Adapted to GIMPLE trees by Diego Novillo in@d berli n.or gdnovi llo@ redha t.co m
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with GCC; see the file COPYING3. If not see http://www.gnu.org/licenses/.
Conditional constant propagation (CCP) is based on the SSA propagation engine (tree-ssa-propagate.c). Constant assignments of the form VAR = CST are propagated from the assignments into uses of VAR, which in turn may generate new constants. The simulation uses a four level lattice to keep track of constant values associated with SSA names. Given an SSA name V_i, it may take one of the following values: UNINITIALIZED -> the initial state of the value. This value is replaced with a correct initial value the first time the value is used, so the rest of the pass does not need to care about it. Using this value simplifies initialization of the pass, and prevents us from needlessly scanning statements that are never reached. UNDEFINED -> V_i is a local variable whose definition has not been processed yet. Therefore we don't yet know if its value is a constant or not. CONSTANT -> V_i has been found to hold a constant value C. VARYING -> V_i cannot take a constant value, or if it does, it is not possible to determine it at compile time. The core of SSA-CCP is in ccp_visit_stmt and ccp_visit_phi_node: 1- In ccp_visit_stmt, we are interested in assignments whose RHS evaluates into a constant and conditional jumps whose predicate evaluates into a boolean true or false. When an assignment of the form V_i = CONST is found, V_i's lattice value is set to CONSTANT and CONST is associated with it. This causes the propagation engine to add all the SSA edges coming out the assignment into the worklists, so that statements that use V_i can be visited. If the statement is a conditional with a constant predicate, we mark the outgoing edges as executable or not executable depending on the predicate's value. This is then used when visiting PHI nodes to know when a PHI argument can be ignored. 2- In ccp_visit_phi_node, if all the PHI arguments evaluate to the same constant C, then the LHS of the PHI is set to C. This evaluation is known as the "meet operation". Since one of the goals of this evaluation is to optimistically return constant values as often as possible, it uses two main short cuts: - If an argument is flowing in through a non-executable edge, it is ignored. This is useful in cases like this: if (PRED) a_9 = 3; else a_10 = 100; a_11 = PHI (a_9, a_10) If PRED is known to always evaluate to false, then we can assume that a_11 will always take its value from a_10, meaning that instead of consider it VARYING (a_9 and a_10 have different values), we can consider it CONSTANT 100. - If an argument has an UNDEFINED value, then it does not affect the outcome of the meet operation. If a variable V_i has an UNDEFINED value, it means that either its defining statement hasn't been visited yet or V_i has no defining statement, in which case the original symbol 'V' is being used uninitialized. Since 'V' is a local variable, the compiler may assume any initial value for it. After propagation, every variable V_i that ends up with a lattice value of CONSTANT will have the associated constant value in the array CONST_VAL[i].VALUE. That is fed into substitute_and_fold for final substitution and folding. References: Constant propagation with conditional branches, Wegman and Zadeck, ACM TOPLAS 13(2):181-210. Building an Optimizing Compiler, Robert Morgan, Butterworth-Heinemann, 1998, Section 8.9. Advanced Compiler Design and Implementation, Steven Muchnick, Morgan Kaufmann, 1997, Section 12.6
Possible lattice values.
|
static |
Return the propagation value when applying __builtin_assume_aligned to its arguments.
??? Delay building trees here.
|
static |
Referenced by evaluate_stmt().
|
static |
Return the propagation value when applying the operation CODE to the values RHS1 and RHS2 yielding type TYPE.
??? Delay building trees here.
References ccp_fold(), CONSTANT, dump_file, dump_flags, fold_defer_overflow_warnings(), fold_undefer_overflow_warnings(), is_gimple_min_invariant(), prop_value_d::lattice_val, likely_value(), prop_value_d::mask, UNDEFINED, prop_value_d::value, and VARYING.
|
static |
Apply the operation CODE in type TYPE to the value, mask pairs R1VAL, R1MASK and R2VAL, R2MASK representing a values of type R1TYPE and R2TYPE and set the value, mask pair *VAL and *MASK to the result.
Assume we'll get a constant result. Use an initial varying value, we fall back to varying in the end if necessary.
The mask is constant where there is a known not set bit, (m1 | m2) & ((v1 | m1) & (v2 | m2))
The mask is constant where there is a known set bit, (m1 | m2) & ~((v1 & ~m1) | (v2 & ~m2)).
m1 | m2
??? We can handle partially known shift counts if we know its sign. That way we can tell that (x << (y | 8)) & 255 is zero.
We need to know if we are doing a left or a right shift to properly shift in zeros for left shift and unsigned right shifts and the sign bit for signed right shifts. For signed right shifts we shift in varying in case the sign bit was varying.
Do the addition with unknown bits set to zero, to give carry-ins of zero wherever possible.
Do the addition with unknown bits set to one, to give carry-ins of one wherever possible.
Each bit in the result is known if (a) the corresponding bits in both inputs are known, and (b) the carry-in to that bit position is known. We can check condition (b) by seeing if we got the same result with minimised carries as with maximised carries.
It shouldn't matter whether we choose lo or hi here.
Just track trailing zeros in both operands and transfer them to the other.
We know the result of a comparison is always one or zero.
Fallthru.
If the most significant bits are not known we know nothing.
For comparisons the signedness is in the comparison operands.
If we know the most significant bits we know the values value ranges by means of treating varying bits as zero or one. Do a cross comparison of the max/min pairs.
This probably should never happen as we'd have folded the thing during fully constant value folding.
We know the result of a comparison is always one or zero.
References double_int::and_not(), and double_int::ext().
|
static |
Return the propagation value when applying the operation CODE to the value RHS yielding type TYPE.
??? Delay building trees here.
References gimple_call_arg(), host_integerp(), and tree_low_cst().
|
static |
Apply the operation CODE in type TYPE to the value, mask pair RVAL and RMASK representing a value of type RTYPE and set the value, mask pair *VAL and *MASK to the result.
Return ~rval + 1.
First extend mask and value according to the original type.
Then extend mask and value according to the target type.
References HOST_WIDE_INT, double_int::lrotate(), and shift.
|
static |
Referenced by get_value_from_alignment().
|
static |
For float types, modify the value of VAL to make ccp work correctly for non-standard values (-0, NaN): If HONOR_SIGNED_ZEROS is false, and VAL = -0, we canonicalize it to 0. If HONOR_NANS is false, and VAL is NaN, we canonicalize it to UNDEFINED. This is to fix the following problem (see PR 29921): Suppose we have x = 0.0 * y and we set value of y to NaN. This causes value of x to be set to NaN. When we later determine that y is in fact VARYING, fold uses the fact that HONOR_NANS is false, and we try to change the value of x to 0, causing an ICE. With HONOR_NANS being false, the real appearance of NaN would cause undefined behavior, though, so claiming that y (and x) are UNDEFINED initially is correct.
|
static |
Do final substitution of propagated values, cleanup the flowgraph and free allocated storage. Return TRUE when something was optimized.
Derive alignment and misalignment information from partially constant pointers in the lattice.
Trailing constant bits specify the alignment, trailing value bits the misalignment.
Perform substitutions based on the known constant values.
Referenced by visit_assignment().
|
static |
CCP specific front-end to the non-destructive constant folding routines. Attempt to simplify the RHS of STMT knowing that one or more operands are constants. If simplification is possible, return the simplified RHS, otherwise return the original RHS or NULL_TREE.
Handle comparison operators that can appear in GIMPLE form.
Return the constant switch index.
Referenced by bit_value_binop().
|
static |
|
static |
Fold the stmt at *GSI with CCP specific information that propagating and regular folding does not catch.
Statement evaluation will handle type mismatches in constants more gracefully than the final propagation. This allows us to fold more conditionals here.
If the call was folded into a constant make sure it goes away even if we cannot propagate into all uses because of type issues.
Don't optimize away calls that have side-effects.
Internal calls provide no argument types, so the extra laxity for normal calls does not apply.
The heuristic of fold_builtin_alloca_with_align differs before and after inlining, so we don't require the arg to be changed into a constant for folding, but just to be constant.
Propagate into the call arguments. Compared to replace_uses_in this can use the argument slot types for type verification instead of the current argument type. We also can safely drop qualifiers here as we are dealing with constants anyway.
If we have a load that turned out to be constant replace it as we cannot propagate into all uses in all cases.
|
static |
Initialize local data structures for CCP.
Initialize simulation flags for PHI nodes and statements.
If the statement is a control insn, then we do not want to avoid simulating the statement once. Failure to do so means that those edges will never get added.
If the statement will not produce a constant, mark all its outputs VARYING.
Now process PHI nodes. We never clear the simulate_again flag on phi nodes, since we do not know which edges are executable yet, except for phi nodes for virtual operands when we do not do store ccp.
Referenced by visit_assignment().
|
static |
Compute the meet operator between *VAL1 and *VAL2. Store the result in VAL1. any M UNDEFINED = any any M VARYING = VARYING Ci M Cj = Ci if (i == j) Ci M Cj = VARYING if (i != j)
UNDEFINED M any = any
any M UNDEFINED = any Nothing to do. VAL1 already contains the value we want.
any M VARYING = VARYING.
Ci M Cj = Ci if (i == j) Ci M Cj = VARYING if (i != j) For INTEGER_CSTs mask unequal bits. If no equal bits remain, drop to varying.
Ci M Cj = Ci if (i == j) Ci M Cj = VARYING if (i != j) VAL1 already contains the value we want for equivalent values.
When not equal addresses are involved try meeting for alignment.
Any other combination is VARYING.
|
static |
Loop through the PHI_NODE's parameters for BLOCK and compare their lattice values to determine PHI_NODE's lattice value. The value of a PHI node is determined calling ccp_lattice_meet with all the arguments of the PHI node that are incoming via executable edges.
Compute the meet operator over all the PHI arguments flowing through executable edges.
If the incoming edge is executable, Compute the meet operator for the existing value of the PHI node and the current PHI argument.
Make the transition to the new value.
Referenced by visit_assignment().
|
static |
Evaluate statement STMT. If the statement produces an output value and its evaluation changes the lattice value of its output, return SSA_PROP_INTERESTING and set *OUTPUT_P to the SSA_NAME holding the output value. If STMT is a conditional branch and we can determine its truth value, set *TAKEN_EDGE_P accordingly. If STMT produces a varying value, return SSA_PROP_VARYING.
If the statement is an assignment that produces a single output value, evaluate its RHS to see if the lattice value of its output has changed.
A value-returning call also performs an assignment.
If STMT is a conditional branch, see if we can determine which branch will be taken.
FIXME. It appears that we should be able to optimize computed GOTOs here as well.
Any other kind of statement is not interesting for constant propagation and, therefore, not worth simulating.
Definitions made by statements other than assignments to SSA_NAMEs represent unknown modifications to their outputs. Mark them VARYING.
Referenced by visit_assignment().
void debug_lattice_value | ( | prop_value_t | val | ) |
Print lattice value VAL to stderr.
DEBUG_FUNCTION void debug_lattice_value | ( | ) |
References gimple_nop_p(), and UNINITIALIZED.
|
static |
Debug count support. Reset the values of ssa names VARYING when the total number ssa names analyzed is beyond the debug count specified.
|
static |
Main entry point for SSA Conditional Constant Propagation.
References gimple_location().
Referenced by visit_cond_stmt().
|
static |
Dump constant propagation value VAL to file OUTF prefixed by PREFIX.
Referenced by set_lattice_value().
|
static |
Evaluate statement STMT. Valid only for assignments, calls, conditionals, and switches.
If the statement is likely to have a CONSTANT result, then try to fold the statement to determine the constant value.
FIXME. This is the only place that we call ccp_fold. Since likely_value never returns CONSTANT for calls, we will not attempt to fold them, including builtins that may profit.
The statement produced a constant value.
If the statement is likely to have a VARYING result, then do not bother folding the statement.
Other cases cannot satisfy is_gimple_min_invariant without folding.
These cannot satisfy is_gimple_min_invariant without folding.
The statement produced a constant value.
Resort to simplification for bitwise tracking.
These builtins return their first argument, unmodified.
The statement produced a nonconstant value. If the statement had UNDEFINED operands, then the result of the statement should be UNDEFINED. Otherwise, the statement is VARYING.
References bit_value_binop(), gimple_assign_lhs(), and gimple_assign_rhs2().
|
static |
A simple pass that attempts to fold all builtin functions. This pass is run after we've propagated as many constants as we can.
Remove all *ssaname_N ={v} {CLOBBER}; stmts, after the last GIMPLE DSE they aren't needed and might unnecessarily keep the SSA_NAMEs live.
Resolve __builtin_constant_p. If it hasn't been folded to integer_one_node by now, it's fairly certain that the value simply isn't constant.
Remove __builtin_assume_aligned.
These shouldn't be folded before pass_stdarg.
FALLTHRU
Retry the same statement if it changed into another builtin, there might be new opportunities now.
Delete unreachable blocks.
References opt_pass::clone(), opt_pass::execute(), and gimple_opt_pass::gimple_opt_pass().
|
static |
Detects a __builtin_alloca_with_align with constant size argument. Declares fixed-size array and returns the address, if found, otherwise returns NULL_TREE.
Get lhs.
Detect constant argument.
Heuristic: don't fold large allocas.
In case the alloca is located at function entry, it has the same lifetime as a declared array, so we allow a larger size.
Declare array.
Fold alloca to the address of the array.
References insert_clobbers_for_var(), and update_call_from_tree().
|
static |
References targetm.
|
inlinestatic |
Return the constant tree value associated with VAR.
|
static |
Compute a default value for variable VAR and store it in the CONST_VAL array. The following rules are used to get default values: 1- Global and static variables that are declared constant are considered CONSTANT. 2- Any other value is considered UNDEFINED. This is useful when considering PHI nodes. PHI arguments that are undefined do not change the constant value of the PHI node, which allows for more constants to be propagated. 3- Variables defined by statements other than assignments and PHI nodes are considered VARYING. 4- Initial values of variables that are not GIMPLE registers are considered VARYING.
Variables defined by an empty statement are those used before being initialized. If VAR is a local variable, we can assume initially that it is UNDEFINED, otherwise we must consider it VARYING.
Any other variable defined by an assignment is considered UNDEFINED.
A variable defined by a call or a PHI node is considered UNDEFINED.
Otherwise, VAR will never take on a constant value.
References prop_value_d::lattice_val, prop_value_d::mask, and VARYING.
|
inlinestatic |
Get the constant value associated with variable VAR.
Referenced by get_value_for_expr(), and get_value_from_alignment().
|
static |
|
static |
Return the value for the tree operand EXPR. If FOR_BITS_P is true return constant bits extracted from alignment information for invariant addresses.
References get_value(), gimple_has_volatile_ops(), prop_value_d::lattice_val, UNDEFINED, and VARYING.
|
static |
Return the value for the address expression EXPR based on alignment information.
References canonicalize_float_value(), CONSTANT, get_value(), is_gimple_min_invariant(), prop_value_d::lattice_val, prop_value_d::mask, prop_value_d::value, and VARYING.
|
inlinestatic |
Advance the iterator to the previous non-debug gimple statement in the same or dominating basic block.
|
static |
Given a BUILT_IN_STACK_SAVE value SAVED_VAL, insert a clobber of VAR before each matching BUILT_IN_STACK_RESTORE. Mark visited phis in VISITED.
|
static |
Find a BUILT_IN_STACK_SAVE dominating gsi_stmt (I), and insert a clobber of VAR before each matching BUILT_IN_STACK_RESTORE. It is possible that BUILT_IN_STACK_SAVE cannot be find in a dominator when a previous pass (such as DOM) duplicated it along multiple paths to a BB. In that case the function gives up without inserting the clobbers.
Referenced by fold_builtin_alloca_with_align().
|
static |
Return the likely CCP lattice value for STMT. If STMT has no operands, then return CONSTANT. Else if undefinedness of operands of STMT cause its value to be undefined, then return UNDEFINED. Else if any operands of STMT are constants, then return CONSTANT. Else return VARYING.
This function appears to be called only for assignments, calls, conditionals, and switches, due to the logic in visit_stmt.
If the statement has volatile operands, it won't fold to a constant value.
Arrive here for more complex cases.
There may be constants in regular rhs operands. For calls we have to ignore lhs, fndecl and static chain, otherwise only the lhs.
These 3 builtins use the first argument just as a magic way how to find out a decl uid.
If the operation combines operands like COMPLEX_EXPR make sure to not mark the result UNDEFINED if only one part of the result is undefined.
Unary operators are handled with all_undefined_operands.
Not MIN_EXPR, MAX_EXPR. One VARYING operand may be selected. Not bitwise operators, one VARYING operand may specify the result completely. Not logical operators for the same reason. Not COMPLEX_EXPR as one VARYING operand makes the result partly not UNDEFINED. Not *DIV_EXPR, comparisons and shifts because the undefined operand may be promoted.
If any part of an address is UNDEFINED, like the index of an ARRAY_EXPR, then treat the result as UNDEFINED.
If there was an UNDEFINED operand but the result may be not UNDEFINED fall back to CONSTANT. During iteration UNDEFINED may still drop to CONSTANT.
We do not consider virtual operands here -- load from read-only memory may have only VARYING virtual operands, but still be constant.
Referenced by bit_value_binop().
gimple_opt_pass* make_pass_ccp | ( | ) |
gimple_opt_pass* make_pass_fold_builtins | ( | ) |
|
static |
Try to optimize out __builtin_stack_restore. Optimize it out if there is another __builtin_stack_restore in the same basic block and no calls or ASM_EXPRs are in between, or if this block's only outgoing edge is to EXIT_BLOCK and there are no calls or ASM_EXPRs after this __builtin_stack_restore.
All regular builtins are ok, just obviously not alloca.
Allow one successor of the exit block, or zero successors.
If there's exactly one use, then zap the call to __builtin_stack_save. If there are multiple uses, then the last one should remove the call. In any case, whether the call to __builtin_stack_save can be removed or not is irrelevant to removing the call to __builtin_stack_restore.
No effect, so the statement will be deleted.
|
static |
If va_list type is a simple pointer and nothing special is needed, optimize __builtin_va_start (&ap, 0) into ap = __builtin_next_arg (0), __builtin_va_end (&ap) out as NOP and __builtin_va_copy into a simple pointer assignment.
No effect, so the statement will be deleted.
|
static |
Attemp to make the block of __builtin_unreachable I unreachable by changing the incoming jumps. Return true if at least one jump was changed.
Verify we do not need to preserve the label.
Only handle the case that __builtin_unreachable is the first statement in the block. We rely on DCE to remove stmts without side-effects before __builtin_unreachable.
Todo: handle other cases, f.i. switch statement.
References dump_file, dump_flags, and print_gimple_stmt().
|
static |
Set the value for variable VAR to NEW_VAL. Return true if the new value is different from VAR's previous value.
We can deal with old UNINITIALIZED values just fine here.
We have to be careful to not go up the bitwise lattice represented by the mask. ??? This doesn't seem to be the best place to enforce this.
If *OLD_VAL and NEW_VAL are the same, return false to inform the caller that this was a non-transition.
??? We would like to delay creation of INTEGER_CSTs from partially constants here.
References dump_file, dump_flags, dump_lattice_value(), prop_value_d::lattice_val, and UNINITIALIZED.
|
inlinestatic |
Sets the value associated with VAR to VARYING.
References build_real(), CONSTANT, dconst0, prop_value_d::lattice_val, type(), and prop_value_d::value.
Referenced by surely_varying_stmt_p().
|
static |
Returns true if STMT cannot be constant.
If the statement has operands that we cannot handle, it cannot be constant.
If it is a call and does not return a value or is not a builtin and not an indirect call, it is varying.
Any other store operation is not interesting.
Anything other than assignments and conditional jumps are not interesting for CCP.
References gsi_end_p(), gsi_next(), gsi_start_bb(), gsi_stmt(), prop_set_simulate_again(), set_value_varying(), and stmt_ends_bb_p().
|
static |
Return whether the lattice transition is valid.
Lattice transitions must always be monotonically increasing in value.
Now both lattice values are CONSTANT.
Allow transitioning from PHI <&x, not executable> == &x to PHI <&x, &y> == common alignment.
Bit-lattices have to agree in the still valid bits.
Otherwise constant values have to agree.
|
static |
Return a double_int that can be used for bitwise simplifications from VAL.
|
static |
Return the constant value for OP or OP otherwise.
|
static |
Visit the assignment statement STMT. Set the value of its LHS to the value computed by the RHS and store LHS in *OUTPUT_P. If STMT creates virtual definitions, set the value of each new name to that of the RHS (if we can derive a constant out of the RHS). Value-returning call statements also perform an assignment, and are handled here.
For a simple copy operation, we copy the lattice values.
Evaluate the statement, which could be either a GIMPLE_ASSIGN or a GIMPLE_CALL.
Set the lattice value of the statement's output.
If STMT is an assignment to an SSA_NAME, we only have one value to set.
References calculate_dominance_info(), ccp_finalize(), ccp_initialize(), ccp_visit_phi_node(), ccp_visit_stmt(), CDI_DOMINATORS, free_dominance_info(), and ssa_propagate().
|
static |
Visit the conditional statement STMT. Return SSA_PROP_INTERESTING if it can determine which edge will be taken. Otherwise, return SSA_PROP_VARYING.
Find which edge out of the conditional block will be taken and add it to the worklist. If no single edge can be determined statically, return SSA_PROP_VARYING to feed all the outgoing edges to the propagation engine.
References do_ssa_ccp().
|
static |
Array of propagated constant values. After propagation, CONST_VAL[I].VALUE holds the constant value for SSA_NAME(I). If the constant is held in an SSA name representing a memory store (i.e., a VDEF), CONST_VAL[I].MEM_REF will contain the actual memory reference used to store (i.e., the LHS of the assignment doing the store).
|
static |