- /* Recursively value-numberize reference ops and tree lists. */
- if (REFERENCE_CLASS_P (op))
- {
- tree tempop = create_value_expr_from (op, block, vuses);
- op = tempop ? tempop : op;
- val = vn_lookup_or_add_with_vuses (op, vuses);
- set_expression_vuses (op, vuses);
- }
- else
- {
- val = vn_lookup_or_add (op);
- }
- if (TREE_CODE (op) != TREE_LIST)
- add_to_exp_gen (block, op);
-
- if (TREE_CODE (val) == VALUE_HANDLE)
- TREE_TYPE (val) = TREE_TYPE (TREE_OPERAND (vexpr, i));
-
- TREE_OPERAND (vexpr, i) = val;
- }
- efi = find_existing_value_expr (vexpr, vuses);
- if (efi)
- return efi;
- get_or_alloc_expression_id (vexpr);
- return vexpr;
-}
-
-/* Return a copy of NODE that is stored in the temporary alloc_pool's.
- This is made recursively true, so that the operands are stored in
- the pool as well. */
-
-static tree
-poolify_tree (tree node)
-{
- switch (TREE_CODE (node))
- {
- case INDIRECT_REF:
- {
- tree temp = (tree) pool_alloc (reference_node_pool);
- memcpy (temp, node, tree_size (node));
- TREE_OPERAND (temp, 0) = poolify_tree (TREE_OPERAND (temp, 0));
- return temp;
- }
- break;
- case GIMPLE_MODIFY_STMT:
- {
- tree temp = (tree) pool_alloc (modify_expr_node_pool);
- memcpy (temp, node, tree_size (node));
- GIMPLE_STMT_OPERAND (temp, 0) =
- poolify_tree (GIMPLE_STMT_OPERAND (temp, 0));
- GIMPLE_STMT_OPERAND (temp, 1) =
- poolify_tree (GIMPLE_STMT_OPERAND (temp, 1));
- return temp;
- }
- break;
- case SSA_NAME:
- case INTEGER_CST:
- case STRING_CST:
- case REAL_CST:
- case PARM_DECL:
- case VAR_DECL:
- case RESULT_DECL:
- return node;
- default:
- gcc_unreachable ();
- }
-}
-
-static tree modify_expr_template;
-
-/* Allocate a GIMPLE_MODIFY_STMT with TYPE, and operands OP1, OP2 in the
- alloc pools and return it. */
-static tree
-poolify_modify_stmt (tree op1, tree op2)
-{
- if (modify_expr_template == NULL)
- modify_expr_template = build_gimple_modify_stmt (op1, op2);
-
- GIMPLE_STMT_OPERAND (modify_expr_template, 0) = op1;
- GIMPLE_STMT_OPERAND (modify_expr_template, 1) = op2;
-
- return poolify_tree (modify_expr_template);
-}
-
-
-/* For each real store operation of the form
- *a = <value> that we see, create a corresponding fake store of the
- form storetmp_<version> = *a.
-
- This enables AVAIL computation to mark the results of stores as
- available. Without this, you'd need to do some computation to
- mark the result of stores as ANTIC and AVAIL at all the right
- points.
- To save memory, we keep the store
- statements pool allocated until we decide whether they are
- necessary or not. */
-
-static void
-insert_fake_stores (void)
-{
- basic_block block;
-
- FOR_ALL_BB (block)
- {
- block_stmt_iterator bsi;
- for (bsi = bsi_start (block); !bsi_end_p (bsi); bsi_next (&bsi))
- {
- tree stmt = bsi_stmt (bsi);
-
- /* We can't generate SSA names for stores that are complex
- or aggregate. We also want to ignore things whose
- virtual uses occur in abnormal phis. */
-
- if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT
- && TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 0)) == INDIRECT_REF
- && !AGGREGATE_TYPE_P (TREE_TYPE (GIMPLE_STMT_OPERAND (stmt, 0)))
- && TREE_CODE (TREE_TYPE (GIMPLE_STMT_OPERAND
- (stmt, 0))) != COMPLEX_TYPE)
- {
- ssa_op_iter iter;
- def_operand_p defp;
- tree lhs = GIMPLE_STMT_OPERAND (stmt, 0);
- tree rhs = GIMPLE_STMT_OPERAND (stmt, 1);
- tree new_tree;
- bool notokay = false;
-
- FOR_EACH_SSA_DEF_OPERAND (defp, stmt, iter, SSA_OP_VIRTUAL_DEFS)
- {
- tree defvar = DEF_FROM_PTR (defp);
- if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (defvar))
- {
- notokay = true;
- break;
- }
- }
-
- if (notokay)
- continue;
-
- if (!storetemp || TREE_TYPE (rhs) != TREE_TYPE (storetemp))
- {
- storetemp = create_tmp_var (TREE_TYPE (rhs), "storetmp");
- if (TREE_CODE (TREE_TYPE (storetemp)) == VECTOR_TYPE)
- DECL_GIMPLE_REG_P (storetemp) = 1;
- get_var_ann (storetemp);
- }
-
- new_tree = poolify_modify_stmt (storetemp, lhs);
-
- lhs = make_ssa_name (storetemp, new_tree);
- GIMPLE_STMT_OPERAND (new_tree, 0) = lhs;
- create_ssa_artificial_load_stmt (new_tree, stmt);
-
- NECESSARY (new_tree) = 0;
- VEC_safe_push (tree, heap, inserted_exprs, new_tree);
- VEC_safe_push (tree, heap, need_creation, new_tree);
- bsi_insert_after (&bsi, new_tree, BSI_NEW_STMT);
- }
- }
- }
-}
-
-/* Turn the pool allocated fake stores that we created back into real
- GC allocated ones if they turned out to be necessary to PRE some
- expressions. */
-
-static void
-realify_fake_stores (void)
-{
- unsigned int i;
- tree stmt;
-
- for (i = 0; VEC_iterate (tree, need_creation, i, stmt); i++)
- {
- if (NECESSARY (stmt))
- {
- block_stmt_iterator bsi;
- tree newstmt, tmp;
-
- /* Mark the temp variable as referenced */
- add_referenced_var (SSA_NAME_VAR (GIMPLE_STMT_OPERAND (stmt, 0)));
-
- /* Put the new statement in GC memory, fix up the
- SSA_NAME_DEF_STMT on it, and then put it in place of
- the old statement before the store in the IR stream
- as a plain ssa name copy. */
- bsi = bsi_for_stmt (stmt);
- bsi_prev (&bsi);
- tmp = GIMPLE_STMT_OPERAND (bsi_stmt (bsi), 1);
- newstmt = build_gimple_modify_stmt (GIMPLE_STMT_OPERAND (stmt, 0),
- tmp);
- SSA_NAME_DEF_STMT (GIMPLE_STMT_OPERAND (newstmt, 0)) = newstmt;
- bsi_insert_before (&bsi, newstmt, BSI_SAME_STMT);
- bsi = bsi_for_stmt (stmt);
- bsi_remove (&bsi, true);
- }
- else
- release_defs (stmt);
- }
-}
-
-/* Given an SSA_NAME, see if SCCVN has a value number for it, and if
- so, return the value handle for this value number, creating it if
- necessary.
- Return NULL if SCCVN has no info for us. */
-
-static tree
-get_sccvn_value (tree name)
-{
- if (TREE_CODE (name) == SSA_NAME
- && VN_INFO (name)->valnum != name
- && VN_INFO (name)->valnum != VN_TOP)
- {
- tree val = VN_INFO (name)->valnum;
- bool is_invariant = is_gimple_min_invariant (val);
- tree valvh = !is_invariant ? get_value_handle (val) : NULL_TREE;
-
- /* We may end up with situations where SCCVN has chosen a
- representative for the equivalence set that we have not
- visited yet. In this case, just create the value handle for
- it. */
- if (!valvh && !is_invariant)
- {
- tree defstmt = SSA_NAME_DEF_STMT (val);
-
- gcc_assert (VN_INFO (val)->valnum == val);
- /* PHI nodes can't have vuses and attempts to iterate over
- their VUSE operands will crash. */
- if (TREE_CODE (defstmt) == PHI_NODE || IS_EMPTY_STMT (defstmt))
- defstmt = NULL;
- {
- tree defstmt2 = SSA_NAME_DEF_STMT (name);
- if (TREE_CODE (defstmt2) != PHI_NODE &&
- !ZERO_SSA_OPERANDS (defstmt2, SSA_OP_ALL_VIRTUALS))
- gcc_assert (defstmt);
- }
- valvh = vn_lookup_or_add_with_stmt (val, defstmt);
- }
-
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "SCCVN says ");
- print_generic_expr (dump_file, name, 0);
- fprintf (dump_file, " value numbers to ");
- if (valvh && !is_invariant)
- {
- print_generic_expr (dump_file, val, 0);
- fprintf (dump_file, " (");
- print_generic_expr (dump_file, valvh, 0);
- fprintf (dump_file, ")\n");
- }
- else
- print_generic_stmt (dump_file, val, 0);
- }
- if (valvh)
- return valvh;
- else
- return val;
- }
- return NULL_TREE;
-}
-
-/* Create value handles for PHI in BLOCK. */
-
-static void
-make_values_for_phi (tree phi, basic_block block)
-{
- tree result = PHI_RESULT (phi);
- /* We have no need for virtual phis, as they don't represent
- actual computations. */
- if (is_gimple_reg (result))
- {
- tree sccvnval = get_sccvn_value (result);
- if (sccvnval)
- {
- vn_add (result, sccvnval);
- bitmap_insert_into_set (PHI_GEN (block), result);
- bitmap_value_insert_into_set (AVAIL_OUT (block), result);
- }
- else
- add_to_sets (result, result, NULL,
- PHI_GEN (block), AVAIL_OUT (block));
- }
-}
-
-/* Create value handles for STMT in BLOCK. Return true if we handled
- the statement. */
-
-static bool
-make_values_for_stmt (tree stmt, basic_block block)
-{
-
- tree lhs = GIMPLE_STMT_OPERAND (stmt, 0);
- tree rhs = GIMPLE_STMT_OPERAND (stmt, 1);
- tree valvh = NULL_TREE;
- tree lhsval;
- VEC (tree, gc) *vuses = NULL;
-
- valvh = get_sccvn_value (lhs);
-
- if (valvh)
- {
- vn_add (lhs, valvh);
- bitmap_value_insert_into_set (AVAIL_OUT (block), lhs);
- /* Shortcut for FRE. We have no need to create value expressions,
- just want to know what values are available where. */
- if (in_fre)
- return true;
-
- }
- else if (in_fre)
- {
- /* For FRE, if SCCVN didn't find anything, we aren't going to
- either, so just make up a new value number if necessary and
- call it a day */
- if (get_value_handle (lhs) == NULL)
- vn_lookup_or_add (lhs);
- bitmap_value_insert_into_set (AVAIL_OUT (block), lhs);
- return true;
- }
-
- lhsval = valvh ? valvh : get_value_handle (lhs);
- vuses = copy_vuses_from_stmt (stmt);
- STRIP_USELESS_TYPE_CONVERSION (rhs);
- if (can_value_number_operation (rhs)
- && (!lhsval || !is_gimple_min_invariant (lhsval)))
- {
- /* For value numberable operation, create a
- duplicate expression with the operands replaced
- with the value handles of the original RHS. */
- tree newt = create_value_expr_from (rhs, block, vuses);
- if (newt)
- {
- set_expression_vuses (newt, vuses);
- /* If we already have a value number for the LHS, reuse
- it rather than creating a new one. */
- if (lhsval)
- {
- set_value_handle (newt, lhsval);
- if (!is_gimple_min_invariant (lhsval))
- add_to_value (lhsval, newt);
- }
- else
- {
- tree val = vn_lookup_or_add_with_vuses (newt, vuses);
- vn_add (lhs, val);
- }
-
- add_to_exp_gen (block, newt);
- }
-
- bitmap_insert_into_set (TMP_GEN (block), lhs);
- bitmap_value_insert_into_set (AVAIL_OUT (block), lhs);
- return true;
- }
- else if ((TREE_CODE (rhs) == SSA_NAME
- && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs))
- || is_gimple_min_invariant (rhs)
- || TREE_CODE (rhs) == ADDR_EXPR
- || TREE_INVARIANT (rhs)
- || DECL_P (rhs))
- {
-
- if (lhsval)
- {
- set_expression_vuses (rhs, vuses);
- set_value_handle (rhs, lhsval);
- if (!is_gimple_min_invariant (lhsval))
- add_to_value (lhsval, rhs);
- bitmap_insert_into_set (TMP_GEN (block), lhs);
- bitmap_value_insert_into_set (AVAIL_OUT (block), lhs);
- }
- else
- {
- /* Compute a value number for the RHS of the statement
- and add its value to the AVAIL_OUT set for the block.
- Add the LHS to TMP_GEN. */
- set_expression_vuses (rhs, vuses);
- add_to_sets (lhs, rhs, vuses, TMP_GEN (block),
- AVAIL_OUT (block));
- }
- /* None of the rest of these can be PRE'd. */
- if (TREE_CODE (rhs) == SSA_NAME && !is_undefined_value (rhs))
- add_to_exp_gen (block, rhs);
- return true;
- }
- return false;
-
-}
-
-/* Compute the AVAIL set for all basic blocks.
-
- This function performs value numbering of the statements in each basic
- block. The AVAIL sets are built from information we glean while doing
- this value numbering, since the AVAIL sets contain only one entry per
- value.
-
- AVAIL_IN[BLOCK] = AVAIL_OUT[dom(BLOCK)].
- AVAIL_OUT[BLOCK] = AVAIL_IN[BLOCK] U PHI_GEN[BLOCK] U TMP_GEN[BLOCK]. */
-
-static void
-compute_avail (void)
-{
- basic_block block, son;
- basic_block *worklist;
- size_t sp = 0;
- tree param;
-
- /* For arguments with default definitions, we pretend they are
- defined in the entry block. */
- for (param = DECL_ARGUMENTS (current_function_decl);
- param;
- param = TREE_CHAIN (param))
- {
- if (gimple_default_def (cfun, param) != NULL)
- {
- tree def = gimple_default_def (cfun, param);
-
- vn_lookup_or_add (def);
- if (!in_fre)
- {
- bitmap_insert_into_set (TMP_GEN (ENTRY_BLOCK_PTR), def);
- bitmap_value_insert_into_set (maximal_set, def);
- }
- bitmap_value_insert_into_set (AVAIL_OUT (ENTRY_BLOCK_PTR), def);
- }
- }
-
- /* Likewise for the static chain decl. */
- if (cfun->static_chain_decl)
- {
- param = cfun->static_chain_decl;
- if (gimple_default_def (cfun, param) != NULL)
- {
- tree def = gimple_default_def (cfun, param);
-
- vn_lookup_or_add (def);
- if (!in_fre)
- {
- bitmap_insert_into_set (TMP_GEN (ENTRY_BLOCK_PTR), def);
- bitmap_value_insert_into_set (maximal_set, def);
- }
- bitmap_value_insert_into_set (AVAIL_OUT (ENTRY_BLOCK_PTR), def);
- }