void backprop::optimize_phi (gphi *phi, tree var, const usage_info *info) { /* If the sign of the result doesn't matter, try to strip sign operations from arguments. */ if (info->flags.ignore_sign) { basic_block bb = gimple_bb (phi); use_operand_p use; ssa_op_iter oi; bool replaced = false; FOR_EACH_PHI_ARG (use, phi, oi, SSA_OP_USE) { /* Propagating along abnormal edges is delicate, punt for now. */ const int index = PHI_ARG_INDEX_FROM_USE (use); if (EDGE_PRED (bb, index)->flags & EDGE_ABNORMAL) continue; tree new_arg = strip_sign_op (USE_FROM_PTR (use)); if (new_arg) { if (!replaced) prepare_change (var); if (dump_file && (dump_flags & TDF_DETAILS)) note_replacement (phi, USE_FROM_PTR (use), new_arg); replace_exp (use, new_arg); replaced = true; } } }
static void sese_build_liveouts_bb (sese region, bitmap liveouts, basic_block bb) { edge e; edge_iterator ei; ssa_op_iter iter; use_operand_p use_p; FOR_EACH_EDGE (e, ei, bb->succs) for (gphi_iterator bsi = gsi_start_phis (e->dest); !gsi_end_p (bsi); gsi_next (&bsi)) sese_build_liveouts_use (region, liveouts, bb, PHI_ARG_DEF_FROM_EDGE (bsi.phi (), e)); for (gimple_stmt_iterator bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi)) { gimple *stmt = gsi_stmt (bsi); if (is_gimple_debug (stmt)) continue; FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_ALL_USES) sese_build_liveouts_use (region, liveouts, bb, USE_FROM_PTR (use_p)); } }
void dump_immediate_uses_for (FILE *file, tree var) { imm_use_iterator iter; use_operand_p use_p; gcc_assert (var && TREE_CODE (var) == SSA_NAME); print_generic_expr (file, var, TDF_SLIM); fprintf (file, " : -->"); if (has_zero_uses (var)) fprintf (file, " no uses.\n"); else if (has_single_use (var)) fprintf (file, " single use.\n"); else fprintf (file, "%d uses.\n", num_imm_uses (var)); FOR_EACH_IMM_USE_FAST (use_p, iter, var) { if (use_p->loc.stmt == NULL && use_p->use == NULL) fprintf (file, "***end of stmt iterator marker***\n"); else if (!is_gimple_reg (USE_FROM_PTR (use_p))) print_gimple_stmt (file, USE_STMT (use_p), 0, TDF_VOPS|TDF_MEMSYMS); else print_gimple_stmt (file, USE_STMT (use_p), 0, TDF_SLIM); } fprintf(file, "\n"); }
void backprop::optimize_phi (gphi *phi, tree var, const usage_info *info) { /* If the sign of the result doesn't matter, strip sign operations from all arguments. */ if (info->flags.ignore_sign) { use_operand_p use; ssa_op_iter oi; bool replaced = false; FOR_EACH_PHI_ARG (use, phi, oi, SSA_OP_USE) { tree new_arg = strip_sign_op (USE_FROM_PTR (use)); if (new_arg) { if (!replaced) prepare_change (var); if (dump_file && (dump_flags & TDF_DETAILS)) note_replacement (phi, USE_FROM_PTR (use), new_arg); replace_exp (use, new_arg); replaced = true; } }
static void replace_exp_1 (use_operand_p op_p, tree val, bool for_propagation ATTRIBUTE_UNUSED) { #if defined ENABLE_CHECKING tree op = USE_FROM_PTR (op_p); gcc_assert (!(for_propagation && TREE_CODE (op) == SSA_NAME && TREE_CODE (val) == SSA_NAME && !may_propagate_copy (op, val))); #endif if (TREE_CODE (val) == SSA_NAME) SET_USE (op_p, val); else SET_USE (op_p, unsave_expr_now (val)); }
static bool can_propagate_from (gimple def_stmt) { use_operand_p use_p; ssa_op_iter iter; gcc_assert (is_gimple_assign (def_stmt)); /* If the rhs has side-effects we cannot propagate from it. */ if (gimple_has_volatile_ops (def_stmt)) return false; /* If the rhs is a load we cannot propagate from it. */ if (TREE_CODE_CLASS (gimple_assign_rhs_code (def_stmt)) == tcc_reference || TREE_CODE_CLASS (gimple_assign_rhs_code (def_stmt)) == tcc_declaration) return false; /* Constants can be always propagated. */ if (gimple_assign_single_p (def_stmt) && is_gimple_min_invariant (gimple_assign_rhs1 (def_stmt))) return true; /* We cannot propagate ssa names that occur in abnormal phi nodes. */ FOR_EACH_SSA_USE_OPERAND (use_p, def_stmt, iter, SSA_OP_USE) if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (USE_FROM_PTR (use_p))) return false; /* If the definition is a conversion of a pointer to a function type, then we can not apply optimizations as some targets require function pointers to be canonicalized and in this case this optimization could eliminate a necessary canonicalization. */ if (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt))) { tree rhs = gimple_assign_rhs1 (def_stmt); if (POINTER_TYPE_P (TREE_TYPE (rhs)) && TREE_CODE (TREE_TYPE (TREE_TYPE (rhs))) == FUNCTION_TYPE) return false; } return true; }
static void replace_exp_1 (use_operand_p op_p, tree val, bool for_propagation ATTRIBUTE_UNUSED) { tree op = USE_FROM_PTR (op_p); #if defined ENABLE_CHECKING gcc_assert (!(for_propagation && TREE_CODE (op) == SSA_NAME && TREE_CODE (val) == SSA_NAME && !may_propagate_copy (op, val))); #endif if (TREE_CODE (val) == SSA_NAME) { if (TREE_CODE (op) == SSA_NAME && POINTER_TYPE_P (TREE_TYPE (op))) merge_alias_info (op, val); SET_USE (op_p, val); } else SET_USE (op_p, unsave_expr_now (val)); }
static void sese_reset_debug_liveouts_bb (sese region, bitmap liveouts, basic_block bb) { gimple_stmt_iterator bsi; ssa_op_iter iter; use_operand_p use_p; for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi)) { gimple *stmt = gsi_stmt (bsi); if (!is_gimple_debug (stmt)) continue; FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_ALL_USES) if (sese_bad_liveouts_use (region, liveouts, bb, USE_FROM_PTR (use_p))) { gimple_debug_bind_reset_value (stmt); update_stmt (stmt); break; } } }
static bool verify_phi_args (tree phi, basic_block bb, basic_block *definition_block) { edge e; bool err = false; unsigned i, phi_num_args = PHI_NUM_ARGS (phi); if (EDGE_COUNT (bb->preds) != phi_num_args) { error ("incoming edge count does not match number of PHI arguments"); err = true; goto error; } for (i = 0; i < phi_num_args; i++) { use_operand_p op_p = PHI_ARG_DEF_PTR (phi, i); tree op = USE_FROM_PTR (op_p); e = EDGE_PRED (bb, i); if (op == NULL_TREE) { error ("PHI argument is missing for edge %d->%d", e->src->index, e->dest->index); err = true; goto error; } if (TREE_CODE (op) != SSA_NAME && !is_gimple_min_invariant (op)) { error ("PHI argument is not SSA_NAME, or invariant"); err = true; } if (TREE_CODE (op) == SSA_NAME) err = verify_use (e->src, definition_block[SSA_NAME_VERSION (op)], op_p, phi, e->flags & EDGE_ABNORMAL, !is_gimple_reg (PHI_RESULT (phi)), NULL); if (e->dest != bb) { error ("wrong edge %d->%d for PHI argument", e->src->index, e->dest->index); err = true; } if (err) { fprintf (stderr, "PHI argument\n"); print_generic_stmt (stderr, op, TDF_VOPS); goto error; } } error: if (err) { fprintf (stderr, "for PHI node\n"); print_generic_stmt (stderr, phi, TDF_VOPS); } return err; }
static bool verify_use (basic_block bb, basic_block def_bb, use_operand_p use_p, tree stmt, bool check_abnormal, bool is_virtual, bitmap names_defined_in_bb) { bool err = false; tree ssa_name = USE_FROM_PTR (use_p); err = verify_ssa_name (ssa_name, is_virtual); if (!TREE_VISITED (ssa_name)) if (verify_imm_links (stderr, ssa_name)) err = true; TREE_VISITED (ssa_name) = 1; if (IS_EMPTY_STMT (SSA_NAME_DEF_STMT (ssa_name)) && default_def (SSA_NAME_VAR (ssa_name)) == ssa_name) ; /* Default definitions have empty statements. Nothing to do. */ else if (!def_bb) { error ("missing definition"); err = true; } else if (bb != def_bb && !dominated_by_p (CDI_DOMINATORS, bb, def_bb)) { error ("definition in block %i does not dominate use in block %i", def_bb->index, bb->index); err = true; } else if (bb == def_bb && names_defined_in_bb != NULL && !bitmap_bit_p (names_defined_in_bb, SSA_NAME_VERSION (ssa_name))) { error ("definition in block %i follows the use", def_bb->index); err = true; } if (check_abnormal && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ssa_name)) { error ("SSA_NAME_OCCURS_IN_ABNORMAL_PHI should be set"); err = true; } /* Make sure the use is in an appropriate list by checking the previous element to make sure it's the same. */ if (use_p->prev == NULL) { error ("no immediate_use list"); err = true; } else { tree listvar ; if (use_p->prev->use == NULL) listvar = use_p->prev->stmt; else listvar = USE_FROM_PTR (use_p->prev); if (listvar != ssa_name) { error ("wrong immediate use list"); err = true; } } if (err) { fprintf (stderr, "for SSA_NAME: "); print_generic_expr (stderr, ssa_name, TDF_VOPS); fprintf (stderr, " in statement:\n"); print_generic_stmt (stderr, stmt, TDF_VOPS); } return err; }
DEBUG_FUNCTION bool verify_imm_links (FILE *f, tree var) { use_operand_p ptr, prev, list; int count; gcc_assert (TREE_CODE (var) == SSA_NAME); list = &(SSA_NAME_IMM_USE_NODE (var)); gcc_assert (list->use == NULL); if (list->prev == NULL) { gcc_assert (list->next == NULL); return false; } prev = list; count = 0; for (ptr = list->next; ptr != list; ) { if (prev != ptr->prev) goto error; if (ptr->use == NULL) goto error; /* 2 roots, or SAFE guard node. */ else if (*(ptr->use) != var) goto error; prev = ptr; ptr = ptr->next; /* Avoid infinite loops. 50,000,000 uses probably indicates a problem. */ if (count++ > 50000000) goto error; } /* Verify list in the other direction. */ prev = list; for (ptr = list->prev; ptr != list; ) { if (prev != ptr->next) goto error; prev = ptr; ptr = ptr->prev; if (count-- < 0) goto error; } if (count != 0) goto error; return false; error: if (ptr->loc.stmt && gimple_modified_p (ptr->loc.stmt)) { fprintf (f, " STMT MODIFIED. - <%p> ", (void *)ptr->loc.stmt); print_gimple_stmt (f, ptr->loc.stmt, 0, TDF_SLIM); } fprintf (f, " IMM ERROR : (use_p : tree - %p:%p)", (void *)ptr, (void *)ptr->use); print_generic_expr (f, USE_FROM_PTR (ptr), TDF_SLIM); fprintf(f, "\n"); return true; }