static void emit_mfence_after_loop (struct loop *loop) { VEC (edge, heap) *exits = get_loop_exit_edges (loop); edge exit; gimple call; gimple_stmt_iterator bsi; unsigned i; for (i = 0; VEC_iterate (edge, exits, i, exit); i++) { call = gimple_build_call (FENCE_FOLLOWING_MOVNT, 0); if (!single_pred_p (exit->dest) /* If possible, we prefer not to insert the fence on other paths in cfg. */ && !(exit->flags & EDGE_ABNORMAL)) split_loop_exit_edge (exit); bsi = gsi_after_labels (exit->dest); gsi_insert_before (&bsi, call, GSI_NEW_STMT); mark_virtual_ops_for_renaming (call); } VEC_free (edge, heap, exits); update_ssa (TODO_update_ssa_only_virtuals); }
static bool may_use_storent_in_loop_p (struct loop *loop) { bool ret = true; if (loop->inner != NULL) return false; /* If we must issue a mfence insn after using storent, check that there is a suitable place for it at each of the loop exits. */ if (FENCE_FOLLOWING_MOVNT != NULL_TREE) { VEC (edge, heap) *exits = get_loop_exit_edges (loop); unsigned i; edge exit; for (i = 0; VEC_iterate (edge, exits, i, exit); i++) if ((exit->flags & EDGE_ABNORMAL) && exit->dest == EXIT_BLOCK_PTR) ret = false; VEC_free (edge, heap, exits); } return ret; }
static edge loop_edge_to_cancel (struct loop *loop) { vec<edge> exits; unsigned i; edge edge_to_cancel; gimple_stmt_iterator gsi; /* We want only one predecestor of the loop. */ if (EDGE_COUNT (loop->latch->preds) > 1) return NULL; exits = get_loop_exit_edges (loop); FOR_EACH_VEC_ELT (exits, i, edge_to_cancel) { /* Find the other edge than the loop exit leaving the conditoinal. */ if (EDGE_COUNT (edge_to_cancel->src->succs) != 2) continue; if (EDGE_SUCC (edge_to_cancel->src, 0) == edge_to_cancel) edge_to_cancel = EDGE_SUCC (edge_to_cancel->src, 1); else edge_to_cancel = EDGE_SUCC (edge_to_cancel->src, 0); /* We only can handle conditionals. */ if (!(edge_to_cancel->flags & (EDGE_TRUE_VALUE | EDGE_FALSE_VALUE))) continue; /* We should never have conditionals in the loop latch. */ gcc_assert (edge_to_cancel->dest != loop->header); /* Check that it leads to loop latch. */ if (edge_to_cancel->dest != loop->latch) continue; exits.release (); /* Verify that the code in loop latch does nothing that may end program execution without really reaching the exit. This may include non-pure/const function calls, EH statements, volatile ASMs etc. */ for (gsi = gsi_start_bb (loop->latch); !gsi_end_p (gsi); gsi_next (&gsi)) if (gimple_has_side_effects (gsi_stmt (gsi))) return NULL; return edge_to_cancel; } exits.release (); return NULL; }