Esempio n. 1
0
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);
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
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;
}