static bool generate_loops_for_partition (struct loop *loop, bitmap partition, bool copy_p) { unsigned i, x; gimple_stmt_iterator bsi; basic_block *bbs; if (copy_p) { loop = copy_loop_before (loop); create_preheader (loop, CP_SIMPLE_PREHEADERS); create_bb_after_loop (loop); } if (loop == NULL) return false; /* Remove stmts not in the PARTITION bitmap. The order in which we visit the phi nodes and the statements is exactly as in stmts_from_loop. */ bbs = get_loop_body_in_dom_order (loop); for (x = 0, i = 0; i < loop->num_nodes; i++) { basic_block bb = bbs[i]; for (bsi = gsi_start_phis (bb); !gsi_end_p (bsi);) if (!bitmap_bit_p (partition, x++)) { gimple phi = gsi_stmt (bsi); if (!is_gimple_reg (gimple_phi_result (phi))) mark_virtual_phi_result_for_renaming (phi); remove_phi_node (&bsi, true); } else gsi_next (&bsi); for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi);) { gimple stmt = gsi_stmt (bsi); if (gimple_code (gsi_stmt (bsi)) != GIMPLE_LABEL && !bitmap_bit_p (partition, x++)) { unlink_stmt_vdef (stmt); gsi_remove (&bsi, true); release_defs (stmt); } else gsi_next (&bsi); } } free (bbs); return true; }
static struct mem_ref_group * gather_memory_references (struct loop *loop, bool *no_other_refs) { basic_block *body = get_loop_body_in_dom_order (loop); basic_block bb; unsigned i; gimple_stmt_iterator bsi; gimple stmt; tree lhs, rhs; struct mem_ref_group *refs = NULL; *no_other_refs = true; /* Scan the loop body in order, so that the former references precede the later ones. */ for (i = 0; i < loop->num_nodes; i++) { bb = body[i]; if (bb->loop_father != loop) continue; for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi)) { stmt = gsi_stmt (bsi); if (gimple_code (stmt) != GIMPLE_ASSIGN) { if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS) || (is_gimple_call (stmt) && !(gimple_call_flags (stmt) & ECF_CONST))) *no_other_refs = false; continue; } lhs = gimple_assign_lhs (stmt); rhs = gimple_assign_rhs1 (stmt); if (REFERENCE_CLASS_P (rhs)) *no_other_refs &= gather_memory_references_ref (loop, &refs, rhs, false, stmt); if (REFERENCE_CLASS_P (lhs)) *no_other_refs &= gather_memory_references_ref (loop, &refs, lhs, true, stmt); } } free (body); return refs; }
static struct mem_ref_group * gather_memory_references (struct loop *loop, bool *no_other_refs) { basic_block *body = get_loop_body_in_dom_order (loop); basic_block bb; unsigned i; block_stmt_iterator bsi; tree stmt, lhs, rhs, call; struct mem_ref_group *refs = NULL; *no_other_refs = true; /* Scan the loop body in order, so that the former references precede the later ones. */ for (i = 0; i < loop->num_nodes; i++) { bb = body[i]; if (bb->loop_father != loop) continue; for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi)) { stmt = bsi_stmt (bsi); call = get_call_expr_in (stmt); if (call && !(call_expr_flags (call) & ECF_CONST)) *no_other_refs = false; if (TREE_CODE (stmt) != GIMPLE_MODIFY_STMT) { if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS)) *no_other_refs = false; continue; } lhs = GIMPLE_STMT_OPERAND (stmt, 0); rhs = GIMPLE_STMT_OPERAND (stmt, 1); if (REFERENCE_CLASS_P (rhs)) *no_other_refs &= gather_memory_references_ref (loop, &refs, rhs, false, stmt); if (REFERENCE_CLASS_P (lhs)) *no_other_refs &= gather_memory_references_ref (loop, &refs, lhs, true, stmt); } } free (body); return refs; }
static struct mem_ref_group * gather_memory_references (struct loop *loop) { basic_block *body = get_loop_body_in_dom_order (loop); basic_block bb; unsigned i; block_stmt_iterator bsi; tree stmt, lhs, rhs; struct mem_ref_group *refs = NULL; /* Scan the loop body in order, so that the former references precede the later ones. */ for (i = 0; i < loop->num_nodes; i++) { bb = body[i]; if (bb->loop_father != loop) continue; for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi)) { stmt = bsi_stmt (bsi); if (TREE_CODE (stmt) != MODIFY_EXPR) continue; lhs = TREE_OPERAND (stmt, 0); rhs = TREE_OPERAND (stmt, 1); if (REFERENCE_CLASS_P (rhs)) gather_memory_references_ref (loop, &refs, rhs, false, stmt); if (REFERENCE_CLASS_P (lhs)) gather_memory_references_ref (loop, &refs, lhs, true, stmt); } } free (body); return refs; }
static bool generate_builtin (struct loop *loop, bitmap partition, bool copy_p) { bool res = false; unsigned i, x = 0; basic_block *bbs; gimple write = NULL; tree op0, op1; gimple_stmt_iterator bsi; tree nb_iter = number_of_exit_cond_executions (loop); if (!nb_iter || nb_iter == chrec_dont_know) return false; bbs = get_loop_body_in_dom_order (loop); for (i = 0; i < loop->num_nodes; i++) { basic_block bb = bbs[i]; for (bsi = gsi_start_phis (bb); !gsi_end_p (bsi); gsi_next (&bsi)) x++; for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi)) { gimple stmt = gsi_stmt (bsi); if (bitmap_bit_p (partition, x++) && is_gimple_assign (stmt) && !is_gimple_reg (gimple_assign_lhs (stmt))) { /* Don't generate the builtins when there are more than one memory write. */ if (write != NULL) goto end; write = stmt; } } } if (!write) goto end; op0 = gimple_assign_lhs (write); op1 = gimple_assign_rhs1 (write); if (!(TREE_CODE (op0) == ARRAY_REF || TREE_CODE (op0) == INDIRECT_REF)) goto end; /* The new statements will be placed before LOOP. */ bsi = gsi_last_bb (loop_preheader_edge (loop)->src); if (gimple_assign_rhs_code (write) == INTEGER_CST && (integer_zerop (op1) || real_zerop (op1))) res = generate_memset_zero (write, op0, nb_iter, bsi); /* If this is the last partition for which we generate code, we have to destroy the loop. */ if (res && !copy_p) { unsigned nbbs = loop->num_nodes; basic_block src = loop_preheader_edge (loop)->src; basic_block dest = single_exit (loop)->dest; prop_phis (dest); make_edge (src, dest, EDGE_FALLTHRU); cancel_loop_tree (loop); for (i = 0; i < nbbs; i++) delete_basic_block (bbs[i]); set_immediate_dominator (CDI_DOMINATORS, dest, recompute_dominator (CDI_DOMINATORS, dest)); } end: free (bbs); return res; }
static bool generate_builtin (struct loop *loop, bitmap partition, bool copy_p) { bool res = false; unsigned i, x = 0; basic_block *bbs; gimple write = NULL; gimple_stmt_iterator bsi; tree nb_iter = number_of_exit_cond_executions (loop); if (!nb_iter || nb_iter == chrec_dont_know) return false; bbs = get_loop_body_in_dom_order (loop); for (i = 0; i < loop->num_nodes; i++) { basic_block bb = bbs[i]; for (bsi = gsi_start_phis (bb); !gsi_end_p (bsi); gsi_next (&bsi)) x++; for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi)) { gimple stmt = gsi_stmt (bsi); if (gimple_code (stmt) == GIMPLE_LABEL || is_gimple_debug (stmt)) continue; if (!bitmap_bit_p (partition, x++)) continue; /* If the stmt has uses outside of the loop fail. */ if (stmt_has_scalar_dependences_outside_loop (stmt)) goto end; if (is_gimple_assign (stmt) && !is_gimple_reg (gimple_assign_lhs (stmt))) { /* Don't generate the builtins when there are more than one memory write. */ if (write != NULL) goto end; write = stmt; if (bb == loop->latch) nb_iter = number_of_latch_executions (loop); } } } if (!stmt_with_adjacent_zero_store_dr_p (write)) goto end; /* The new statements will be placed before LOOP. */ bsi = gsi_last_bb (loop_preheader_edge (loop)->src); generate_memset_zero (write, gimple_assign_lhs (write), nb_iter, bsi); res = true; /* If this is the last partition for which we generate code, we have to destroy the loop. */ if (!copy_p) { unsigned nbbs = loop->num_nodes; edge exit = single_exit (loop); basic_block src = loop_preheader_edge (loop)->src, dest = exit->dest; redirect_edge_pred (exit, src); exit->flags &= ~(EDGE_TRUE_VALUE|EDGE_FALSE_VALUE); exit->flags |= EDGE_FALLTHRU; cancel_loop_tree (loop); rescan_loop_exit (exit, false, true); for (i = 0; i < nbbs; i++) delete_basic_block (bbs[i]); set_immediate_dominator (CDI_DOMINATORS, dest, recompute_dominator (CDI_DOMINATORS, dest)); } end: free (bbs); return res; }