コード例 #1
0
ファイル: Delaunay.cpp プロジェクト: benmyb/OFEC_v0.4.2
static void divide(point * p_sorted[], int l, int r,
                   edge ** l_ccw, edge ** r_cw)
{
    int n;
    edge *l_ccw_l, *r_cw_l, *l_ccw_r, *r_cw_r, *l_tangent;
    edge *a, *b, *c;

    n = r - l + 1;
    if (n == 2) {
        /* Bottom of the recursion. Make an edge */
        *l_ccw = *r_cw = make_edge(p_sorted[l], p_sorted[r]);
    } else if (n == 3) {
        /* Bottom of the recursion. Make a triangle or two edges */
        double c_p;
        a = make_edge(p_sorted[l], p_sorted[l + 1]);
        b = make_edge(p_sorted[l + 1], p_sorted[r]);
        splice(a, b, p_sorted[l + 1]);
        c_p = Cross_product_3p(p_sorted[l], p_sorted[l + 1], p_sorted[r]);

        if (c_p > 0.0) {
            /* Make a triangle */
            c = join(a, p_sorted[l], b, p_sorted[r], side::right);
            *l_ccw = a;
            *r_cw = b;
        } else if (c_p < 0.0) {
            /* Make a triangle */
            c = join(a, p_sorted[l], b, p_sorted[r], side::left);
            *l_ccw = c;
            *r_cw = c;
        } else {
            /* Points are collinear,  no triangle */
            *l_ccw = a;
            *r_cw = b;
        }
    } else if (n > 3) {
        /* Continue to divide */

        /* Calculate the split point */
        int split = (l + r) / 2;

        /* Divide */
        divide(p_sorted, l, split, &l_ccw_l, &r_cw_l);
        divide(p_sorted, split + 1, r, &l_ccw_r, &r_cw_r);

        /* Merge */
        merge(r_cw_l, p_sorted[split], l_ccw_r, p_sorted[split + 1],
              &l_tangent);

        /* The lower tangent added by merge may have invalidated 
           l_ccw_l or r_cw_r. Update them if necessary. */
        if (Org(l_tangent) == p_sorted[l])
            l_ccw_l = l_tangent;
        if (Dest(l_tangent) == p_sorted[r])
            r_cw_r = l_tangent;

        /* Update edge refs to be passed back */
        *l_ccw = l_ccw_l;
        *r_cw = r_cw_r;
    }
}
コード例 #2
0
ファイル: gif_c.c プロジェクト: cran/gap
int main(int argc, char **argv)
{
  char    *progname = argv[0], *line, *newline();
  int     i, j, k, n_prob, got_opt();
  double  total_kinship();
  vertex  *top, *bot;
  blankline = &whereblank;
  line_no=0;
  for (line=newline(); line && line != blankline; line = newline())
  {
    if (sscanf(line,"%d%d%d",&i,&j,&k) != 3)
    {
      error("\n %s(%d): cannot read triplet",progname,line_no);
    }
    if (i > 0) bot = find_vertex(i);
    if (j > 0)
    {
      top = find_vertex(j);
      if (!connected(bot,top)) make_edge(bot,top);
    }
    if (k > 0)
    {
      top = find_vertex(k);
      if (!connected(bot,top)) make_edge(bot,top);
    }
  }

  for ( ; line; line=newline())
  {
    while (line && line == blankline) line=newline();
    for (no_probands(),n_prob=0 ; line && line != blankline; line=newline())
    {
      if (sscanf(line,"%d",&i) != 1)
      {
        error("\n %s(%d): cannot read integer",progname,line_no);
      }
      if (i > 0)
      {
        bot=find_vertex(i);
        if (new_proband(bot)) n_prob +=1;
      }
    }
    Rprintf("%9.3f",100000.0*total_kinship()/n_prob/(n_prob-1)*2.0);
    Rprintf("\n\n");
    R_FlushConsole();
  }
  R_ClearerrConsole();
  return(0);
}
コード例 #3
0
ファイル: Delaunay.cpp プロジェクト: benmyb/OFEC_v0.4.2
/* 
 * Creates a new edge and adds it to two rings of edges.
 */
static edge *join(edge * a, point * u, edge * b, point * v, side s)
{
    edge *e;

    /* u and v are the two vertices which are being joined.
       a and b are the two edges associated with u and v res. */

    e = make_edge(u, v);

    if (s == side::left) {
        if (Org(a) == u)
            splice(Oprev(a), e, u);
        else
            splice(Dprev(a), e, u);
        splice(b, e, v);
    } else {
        splice(a, e, u);
        if (Org(b) == v)
            splice(Oprev(b), e, v);
        else
            splice(Dprev(b), e, v);
    }

    return e;
}
コード例 #4
0
ファイル: cfg.c プロジェクト: BoxianLai/moxiedev
edge
cached_make_edge (sbitmap edge_cache, basic_block src, basic_block dst, int flags)
{
  if (edge_cache == NULL
      || src == ENTRY_BLOCK_PTR
      || dst == EXIT_BLOCK_PTR)
    return make_edge (src, dst, flags);

  /* Does the requested edge already exist?  */
  if (! TEST_BIT (edge_cache, dst->index))
    {
      /* The edge does not exist.  Create one and update the
	 cache.  */
      SET_BIT (edge_cache, dst->index);
      return unchecked_make_edge (src, dst, flags);
    }

  /* At this point, we know that the requested edge exists.  Adjust
     flags if necessary.  */
  if (flags)
    {
      edge e = find_edge (src, dst);
      e->flags |= flags;
    }

  return NULL;
}
コード例 #5
0
ファイル: quadedge.cpp プロジェクト: axiao/delaunay
// connects the a.dst to b.org through a new edge
edge connect(edge a, edge b) {
    Edge_Record er = make_edge();
    er.get_qr().v = a.dst();
    er.sym().get_qr().v = b.org();
    splice(er, a.lnext());
    splice(er.sym(), b);
    return er;
}
コード例 #6
0
static edge_ref connect(edge_ref a, edge_ref b)
{
    edge_ref e = make_edge();
    ODATA(e) = DEST(a);
    DDATA(e) = ORG(b);
    splice(e, LNEXT(a));
    splice(SYM(e), b);
    return e;
}
コード例 #7
0
ファイル: rtl-factoring.c プロジェクト: AhmadTux/DragonFlyBSD
static void
erase_matching_seqs (void)
{
  seq_block sb;
  matching_seq mseq;
  rtx insn;
  basic_block bb;
  rtx retlabel, saveinsn, callinsn;
  int i;

  for (sb = seq_blocks; sb; sb = sb->next_seq_block)
    {
      for (mseq = sb->matching_seqs; mseq; mseq = mseq->next_matching_seq)
        {
          insn = mseq->insn;
          bb = BLOCK_FOR_INSN (insn);

          /* Get the label after the sequence. This will be the return
             address. The label will be referenced using a symbol_ref so
             protect it from deleting.  */
          retlabel = block_label_after (insn);
          LABEL_PRESERVE_P (retlabel) = 1;

          /* Delete the insns of the sequence.  */
          for (i = 0; i < sb->length; i++)
            insn = prev_insn_in_block (insn);
          delete_basic_block (split_block_and_df_analyze (bb, insn));

          /* Emit an insn saving the return address to the link register
             before the deleted sequence.  */
          saveinsn = emit_insn_after (gen_move_insn (pattern_seqs->link_reg,
                                      gen_symbol_ref_rtx_for_label
                                      (retlabel)),
                                      BB_END (bb));
          BLOCK_FOR_INSN (saveinsn) = bb;

          /* Emit a jump to the appropriate part of the pattern sequence
             after the save insn. Also update the basic block.  */
          callinsn = emit_jump_insn_after (gen_jump (sb->label), saveinsn);
          JUMP_LABEL (callinsn) = sb->label;
          LABEL_NUSES (sb->label)++;
          BLOCK_FOR_INSN (callinsn) = bb;
          BB_END (bb) = callinsn;

          /* Maintain control flow and liveness information.  */
          SET_REGNO_REG_SET (df_get_live_out (bb),
                             REGNO (pattern_seqs->link_reg));
          emit_barrier_after (BB_END (bb));
          make_single_succ_edge (bb, BLOCK_FOR_INSN (sb->label), 0);
          IOR_REG_SET (df_get_live_out (bb),
		       df_get_live_in (BLOCK_FOR_INSN (sb->label)));

          make_edge (BLOCK_FOR_INSN (seq_blocks->label),
                     BLOCK_FOR_INSN (retlabel), EDGE_ABNORMAL);
        }
    }
}
コード例 #8
0
ファイル: cfg.c プロジェクト: BoxianLai/moxiedev
edge
make_single_succ_edge (basic_block src, basic_block dest, int flags)
{
  edge e = make_edge (src, dest, flags);

  e->probability = REG_BR_PROB_BASE;
  e->count = src->count;
  return e;
}
コード例 #9
0
ファイル: node2edge.c プロジェクト: Bioinfo-Tools/PANGEA-plus
void kmer2edges ( char * outfile )
{
	FILE * fp;
	char temp[256];
	sprintf ( temp, "%s.edge", outfile );
	fp = ckopen ( temp, "w" );
	make_edge ( fp );
	fclose ( fp );
	num_ed = edge_c;
}
コード例 #10
0
ファイル: cfgexpand.c プロジェクト: seguljac/higpu
static basic_block
construct_init_block (void)
{
  basic_block init_block, first_block;
  edge e = NULL;
  int flags;

  /* Multiple entry points not supported yet.  */
  gcc_assert (EDGE_COUNT (ENTRY_BLOCK_PTR->succs) == 1);

  e = EDGE_SUCC (ENTRY_BLOCK_PTR, 0);

  /* When entry edge points to first basic block, we don't need jump,
     otherwise we have to jump into proper target.  */
  if (e && e->dest != ENTRY_BLOCK_PTR->next_bb)
    {
      tree label = tree_block_label (e->dest);

      emit_jump (label_rtx (label));
      flags = 0;
    }
  else
    flags = EDGE_FALLTHRU;

  init_block = create_basic_block (NEXT_INSN (get_insns ()),
				   get_last_insn (),
				   ENTRY_BLOCK_PTR);
  init_block->frequency = ENTRY_BLOCK_PTR->frequency;
  init_block->count = ENTRY_BLOCK_PTR->count;
  if (e)
    {
      first_block = e->dest;
      redirect_edge_succ (e, init_block);
      e = make_edge (init_block, first_block, flags);
    }
  else
    e = make_edge (init_block, EXIT_BLOCK_PTR, EDGE_FALLTHRU);
  e->probability = REG_BR_PROB_BASE;
  e->count = ENTRY_BLOCK_PTR->count;

  update_bb_for_insn (init_block);
  return init_block;
}
コード例 #11
0
ファイル: som_graph.cpp プロジェクト: ElaraFX/tbb
// build a set of SPECULATION_CNT graphs, each of which consists of a broadcast_node,
//    xranges x yranges function_nodes, and one queue_node for output.
//    once speculation starts, if i % SPECULATION_CNT is the current graph, (i+1) % SPECULATION_CNT
//    is the first speculation, and so on.
void
build_BMU_graph(SOMap &map1) {
    // build current graph
    xsize = ((int)map1.size() + xranges - 1) / xranges;
    ysize = ((int)map1[0].size() + yranges - 1) / yranges;
    function_node_execs.clear();
    function_node_execs.reserve(xranges*yranges+1);
    for(int ii = 0; ii < xranges*yranges+1;++ii) function_node_execs.push_back(0);

    for(int scnt = 0; scnt < SPECULATION_CNT; ++scnt) {
        g[scnt] = new graph;
        send_to[scnt] = new b_node(*(g[scnt]));  // broadcast node to the function_nodes
        q[scnt] = new queue_node<search_result_type>(*(g[scnt]));  // output queue

        // create the function_nodes, tie to the graph
        s_array[scnt] = new search_node_array_type;
        s_array[scnt]->reserve(xranges);
        g_array[scnt] = new graph_array_type;
        g_array[scnt]->reserve(xranges);
        for(int i = 0; i < (int)map1.size(); i += xsize) {
            int xindex = i / xsize;
            s_array[scnt]->push_back(search_node_vector_type());
            (*s_array[scnt])[xindex].reserve(yranges);
            g_array[scnt]->push_back(graph_vector_type());
            (*g_array[scnt])[xindex].reserve(yranges);
            for( int j = 0; j < (int)map1[0].size(); j += ysize) {
                int offset = (i/xsize)*yranges + (j / ysize);
                int xmax = (i + xsize) > (int)map1.size() ? (int)map1.size() : i + xsize;
                int ymax = (j + ysize) > (int)map1[0].size() ? (int)map1[0].size() : j + ysize;
                subsquare_type sst(i,xmax,1,j,ymax,1);
                BMU_search_body bb(map1,sst,function_node_execs[offset]);
                graph *g_local = new graph;
                search_node *s = new search_node(*g_local, serial, bb); // copies Body
                (*g_array[scnt])[xindex].push_back(g_local);
                (*s_array[scnt])[xindex].push_back(s);
                make_edge(*(send_to[scnt]), *s);  // broadcast_node -> function_node
                make_edge(*s, *(q[scnt]));   // function_node -> queue_node
            }
        }
    }
}
コード例 #12
0
ファイル: edge.c プロジェクト: gosom/Dinic-Algorithm
edges_list read_edges() {
  guint first = 0, last = 0, capacity = 0;
  edge e = NULL;
  edges_list edges = NULL;

  edges = queue_new();
  while(scanf("%u %u %u\n", 
	      &first, &last, &capacity) != EOF){
    e = make_edge(first, last, capacity, 0, false);
    queue_push_tail(edges, e);
  }
  return edges;
}
コード例 #13
0
ファイル: gif_c.c プロジェクト: cran/gap
void gif_c(int *data, int *famsize, int *gifset, int *giflen, double *gifval)
{
  int     id, i, j, k, n_prob;
  double  total_kinship();
  vertex  *top, *bot;

  top=bot=NULL;
  for (id=0; id<*famsize; id++)
  {
    i=data[id*3];
    j=data[id*3+1];
    k=data[id*3+2];
    if (i > 0) bot = find_vertex(i);
    if (j > 0)
    {
      top = find_vertex(j);
      if (!connected(bot,top)) make_edge(bot,top);
    }
    if (k > 0)
    {
      top = find_vertex(k);
      if (!connected(bot,top)) make_edge(bot,top);
    }
  }
  no_probands();
  n_prob=0;
  for (id=0;id<*giflen;id++)
  {
    i=gifset[id];
    if (i > 0)
    {
      bot=find_vertex(i);
      if (new_proband(bot)) n_prob +=1;
    }
  }
  *gifval=100000.0*total_kinship()/n_prob/(n_prob-1)*2.0;

}
コード例 #14
0
ファイル: rtl-factoring.c プロジェクト: AhmadTux/DragonFlyBSD
static void
split_pattern_seq (void)
{
  rtx insn;
  basic_block bb;
  rtx retlabel, retjmp, saveinsn;
  int i;
  seq_block sb;

  insn = pattern_seqs->insn;
  bb = BLOCK_FOR_INSN (insn);

  /* Get the label after the sequence. This will be the return address. The
     label will be referenced using a symbol_ref so protect it from
     deleting.  */
  retlabel = block_label_after (insn);
  LABEL_PRESERVE_P (retlabel) = 1;

  /* Emit an indirect jump via the link register after the sequence acting
     as the return insn.  Also emit a barrier and update the basic block.  */
  if (!find_reg_note (BB_END (bb), REG_NORETURN, NULL))
    retjmp = emit_jump_insn_after (gen_indirect_jump (pattern_seqs->link_reg),
                                   BB_END (bb));
  emit_barrier_after (BB_END (bb));

  /* Replace all outgoing edges with a new one to the block of RETLABEL.  */
  while (EDGE_COUNT (bb->succs) != 0)
    remove_edge (EDGE_SUCC (bb, 0));
  make_edge (bb, BLOCK_FOR_INSN (retlabel), EDGE_ABNORMAL);

  /* Split the sequence according to SEQ_BLOCKS and cache the label of the
     resulting basic blocks.  */
  i = 0;
  for (sb = seq_blocks; sb; sb = sb->next_seq_block)
    {
      for (; i < sb->length; i++)
        insn = prev_insn_in_block (insn);

      sb->label = block_label (split_block_and_df_analyze (bb, insn));
    }

  /* Emit an insn saving the return address to the link register before the
     sequence.  */
  saveinsn = emit_insn_after (gen_move_insn (pattern_seqs->link_reg,
                              gen_symbol_ref_rtx_for_label
                              (retlabel)), BB_END (bb));
  /* Update liveness info.  */
  SET_REGNO_REG_SET (df_get_live_out (bb),
                     REGNO (pattern_seqs->link_reg));
}
コード例 #15
0
static void
unloop_loops (bitmap loop_closed_ssa_invalidated,
	      bool *irred_invalidated)
{
  while (loops_to_unloop.length ())
    {
      struct loop *loop = loops_to_unloop.pop ();
      int n_unroll = loops_to_unloop_nunroll.pop ();
      basic_block latch = loop->latch;
      edge latch_edge = loop_latch_edge (loop);
      int flags = latch_edge->flags;
      location_t locus = latch_edge->goto_locus;
      gcall *stmt;
      gimple_stmt_iterator gsi;

      remove_exits_and_undefined_stmts (loop, n_unroll);

      /* Unloop destroys the latch edge.  */
      unloop (loop, irred_invalidated, loop_closed_ssa_invalidated);

      /* Create new basic block for the latch edge destination and wire
	 it in.  */
      stmt = gimple_build_call (builtin_decl_implicit (BUILT_IN_UNREACHABLE), 0);
      latch_edge = make_edge (latch, create_basic_block (NULL, NULL, latch), flags);
      latch_edge->probability = 0;
      latch_edge->count = 0;
      latch_edge->flags |= flags;
      latch_edge->goto_locus = locus;

      latch_edge->dest->loop_father = current_loops->tree_root;
      latch_edge->dest->count = 0;
      latch_edge->dest->frequency = 0;
      set_immediate_dominator (CDI_DOMINATORS, latch_edge->dest, latch_edge->src);

      gsi = gsi_start_bb (latch_edge->dest);
      gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
    }
  loops_to_unloop.release ();
  loops_to_unloop_nunroll.release ();

  /* Remove edges in peeled copies.  */
  unsigned i;
  edge e;
  FOR_EACH_VEC_ELT (edges_to_remove, i, e)
    {
      bool ok = remove_path (e);
      gcc_assert (ok);
    }
コード例 #16
0
ファイル: build_edge.cpp プロジェクト: Buttonwood/SOAPdenovo2
/*************************************************
Function:
    kmer2edges
Description:
    This is the main function for building edges by compacting the linear nodes.
Input:
    1. ht:      the graph hashtable
    2. K_size:      kmer size
    3. out_file:    the name of output file containing edges sequence
Output:
    None.
Return:
    None.
*************************************************/
void kmer2edges ( hashtable2 * ht, int K_size, char * outfile )
{
	FILE * fp;
	char temp[256];
	sprintf ( temp, "%s", outfile );
	fp = fopen ( temp, "w" );

	if ( fp == NULL )
	{
		fprintf ( stderr, "ERROR: Can't create file %s. \n", temp );
		exit ( -1 );
	}

	make_edge ( ht, K_size, fp );
	fclose ( fp );
}
コード例 #17
0
ファイル: time_split_node.cpp プロジェクト: artog/Raytracer
//! Dummy executing broadcast_node; "nIter" calls; Returns time in seconds.
double bm_broadcast_node(tbb::flow::graph& g, int nIter)
{
    tbb::flow::queue_node<my_type> my_queue(g);
    tbb::flow::broadcast_node<my_type> my_broadcast_node(g);
    make_edge(my_broadcast_node, my_queue);

    my_type v(nSize);

    const tbb::tick_count t0 = tbb::tick_count::now();

    //using broadcast_node
    for (int i = 0; i < nIter; ++i)
        my_broadcast_node.try_put(v);
    //barrier sync
    g.wait_for_all();

    return (tbb::tick_count::now() - t0).seconds();
}
コード例 #18
0
ファイル: time_split_node.cpp プロジェクト: artog/Raytracer
//! Dummy executing split_node, "nIter" calls; Returns time in seconds.
double bm_split_node(tbb::flow::graph& g, int nIter)
{
    my_type v1(nSize);

    tbb::flow::queue_node<my_type> my_queue1(g);
    tbb::flow::tuple<my_type> my_tuple(1);

    tbb::flow::split_node< tbb::flow::tuple<my_type> > my_split_node(g);
    make_edge(tbb::flow::get<0>(my_split_node.output_ports()), my_queue1);

    const tbb::tick_count t0 = tbb::tick_count::now();

    //using split_node
    for (int i = 0; i < nIter; ++i)
        my_split_node.try_put(my_tuple); 

    //barrier sync
    g.wait_for_all();

    return (tbb::tick_count::now() - t0).seconds();
}
コード例 #19
0
ファイル: test_function_node.cpp プロジェクト: adiog/tbb
void test_extract() {
    int my_count = 0;
    int cm;
    tbb::flow::graph g;
    tbb::flow::broadcast_node<int> b0(g);
    tbb::flow::broadcast_node<int> b1(g);
    tbb::flow::function_node<int, int, FTYPE> f0(g, tbb::flow::unlimited, add_to_counter(my_count));
    tbb::flow::queue_node<int> q0(g);

    tbb::flow::make_edge(b0, f0);
    tbb::flow::make_edge(b1, f0);
    tbb::flow::make_edge(f0, q0);
    for( int i = 0; i < 2; ++i ) {
        ASSERT(b0.predecessor_count() == 0 && b0.successor_count() == 1, "b0 has incorrect counts");
        ASSERT(b1.predecessor_count() == 0 && b1.successor_count() == 1, "b1 has incorrect counts");
        ASSERT(f0.predecessor_count() == 2 && f0.successor_count() == 1, "f0 has incorrect counts");
        ASSERT(q0.predecessor_count() == 1 && q0.successor_count() == 0, "q0 has incorrect counts");

        /* b0         */
        /*   \        */
        /*    f0 - q0 */
        /*   /        */
        /* b1         */

        b0.try_put(1);
        g.wait_for_all();
        ASSERT(my_count == 1, "function_node didn't fire");
        ASSERT(q0.try_get(cm), "function_node didn't forward");
        b1.try_put(1);
        g.wait_for_all();
        ASSERT(my_count == 2, "function_node didn't fire");
        ASSERT(q0.try_get(cm), "function_node didn't forward");

        b0.extract();

        /* b0         */
        /*            */
        /*    f0 - q0 */
        /*   /        */
        /* b1         */

        ASSERT(b0.predecessor_count() == 0 && b0.successor_count() == 0, "b0 has incorrect counts");
        ASSERT(b1.predecessor_count() == 0 && b1.successor_count() == 1, "b1 has incorrect counts");
        ASSERT(f0.predecessor_count() == 1 && f0.successor_count() == 1, "f0 has incorrect counts");
        ASSERT(q0.predecessor_count() == 1 && q0.successor_count() == 0, "q0 has incorrect counts");
        b0.try_put(1);
        b0.try_put(1);
        g.wait_for_all();
        ASSERT(my_count == 2, "b0 messages being forwarded to function_node even though it is disconnected");
        b1.try_put(1);
        g.wait_for_all();
        ASSERT(my_count == 3, "function_node didn't fire though it has only one predecessor");
        ASSERT(q0.try_get(cm), "function_node didn't forward second time");

        f0.extract();

        /* b0         */
        /*            */
        /*    f0   q0 */
        /*            */
        /* b1         */

        ASSERT(b0.predecessor_count() == 0 && b0.successor_count() == 0, "b0 has incorrect counts");
        ASSERT(b1.predecessor_count() == 0 && b1.successor_count() == 0, "b1 has incorrect counts");
        ASSERT(f0.predecessor_count() == 0 && f0.successor_count() == 0, "f0 has incorrect counts");
        ASSERT(q0.predecessor_count() == 0 && q0.successor_count() == 0, "q0 has incorrect counts");
        b0.try_put(1);
        b0.try_put(1);
        b1.try_put(1);
        b1.try_put(1);
        g.wait_for_all();
        ASSERT(my_count == 3, "function_node didn't fire though it has only one predecessor");
        ASSERT(!q0.try_get(cm), "function_node forwarded though it shouldn't");
        make_edge(b0, f0);

        /* b0         */
        /*   \        */
        /*    f0   q0 */
        /*            */
        /* b1         */

        ASSERT(b0.predecessor_count() == 0 && b0.successor_count() == 1, "b0 has incorrect counts");
        ASSERT(b1.predecessor_count() == 0 && b1.successor_count() == 0, "b1 has incorrect counts");
        ASSERT(f0.predecessor_count() == 1 && f0.successor_count() == 0, "f0 has incorrect counts");
        ASSERT(q0.predecessor_count() == 0 && q0.successor_count() == 0, "q0 has incorrect counts");

        b0.try_put(int());
        g.wait_for_all();

        ASSERT(my_count == 4, "function_node didn't fire though it has only one predecessor");
        ASSERT(!q0.try_get(cm), "function_node forwarded though it shouldn't");

        tbb::flow::make_edge(b1, f0);
        tbb::flow::make_edge(f0, q0);
        my_count = 0;
    }
}
コード例 #20
0
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;
}
コード例 #21
0
ファイル: tree-call-cdce.c プロジェクト: acoxepochlabs/gcc
static bool
shrink_wrap_one_built_in_call (gimple bi_call)
{
  gimple_stmt_iterator bi_call_bsi;
  basic_block bi_call_bb, join_tgt_bb, guard_bb, guard_bb0;
  edge join_tgt_in_edge_from_call, join_tgt_in_edge_fall_thru;
  edge bi_call_in_edge0, guard_bb_in_edge;
  unsigned tn_cond_stmts, nconds;
  unsigned ci;
  gimple cond_expr = NULL;
  gimple cond_expr_start;
  tree bi_call_label_decl;
  gimple bi_call_label;

  auto_vec<gimple, 12> conds;
  gen_shrink_wrap_conditions (bi_call, conds, &nconds);

  /* This can happen if the condition generator decides
     it is not beneficial to do the transformation.  Just
     return false and do not do any transformation for
     the call.  */
  if (nconds == 0)
    return false;

  bi_call_bb = gimple_bb (bi_call);

  /* Now find the join target bb -- split bi_call_bb if needed.  */
  if (stmt_ends_bb_p (bi_call))
    {
      /* If the call must be the last in the bb, don't split the block,
	 it could e.g. have EH edges.  */
      join_tgt_in_edge_from_call = find_fallthru_edge (bi_call_bb->succs);
      if (join_tgt_in_edge_from_call == NULL)
        return false;
    }
  else
    join_tgt_in_edge_from_call = split_block (bi_call_bb, bi_call);

  bi_call_bsi = gsi_for_stmt (bi_call);

  join_tgt_bb = join_tgt_in_edge_from_call->dest;

  /* Now it is time to insert the first conditional expression
     into bi_call_bb and split this bb so that bi_call is
     shrink-wrapped.  */
  tn_cond_stmts = conds.length ();
  cond_expr = NULL;
  cond_expr_start = conds[0];
  for (ci = 0; ci < tn_cond_stmts; ci++)
    {
      gimple c = conds[ci];
      gcc_assert (c || ci != 0);
      if (!c)
        break;
      gsi_insert_before (&bi_call_bsi, c, GSI_SAME_STMT);
      cond_expr = c;
    }
  nconds--;
  ci++;
  gcc_assert (cond_expr && gimple_code (cond_expr) == GIMPLE_COND);

  /* Now the label.  */
  bi_call_label_decl = create_artificial_label (gimple_location (bi_call));
  bi_call_label = gimple_build_label (bi_call_label_decl);
  gsi_insert_before (&bi_call_bsi, bi_call_label, GSI_SAME_STMT);

  bi_call_in_edge0 = split_block (bi_call_bb, cond_expr);
  bi_call_in_edge0->flags &= ~EDGE_FALLTHRU;
  bi_call_in_edge0->flags |= EDGE_TRUE_VALUE;
  guard_bb0 = bi_call_bb;
  bi_call_bb = bi_call_in_edge0->dest;
  join_tgt_in_edge_fall_thru = make_edge (guard_bb0, join_tgt_bb,
                                          EDGE_FALSE_VALUE);

  bi_call_in_edge0->probability = REG_BR_PROB_BASE * ERR_PROB;
  bi_call_in_edge0->count =
      apply_probability (guard_bb0->count,
			 bi_call_in_edge0->probability);
  join_tgt_in_edge_fall_thru->probability =
      inverse_probability (bi_call_in_edge0->probability);
  join_tgt_in_edge_fall_thru->count =
      guard_bb0->count - bi_call_in_edge0->count;

  /* Code generation for the rest of the conditions  */
  guard_bb = guard_bb0;
  while (nconds > 0)
    {
      unsigned ci0;
      edge bi_call_in_edge;
      gimple_stmt_iterator guard_bsi = gsi_for_stmt (cond_expr_start);
      ci0 = ci;
      cond_expr_start = conds[ci0];
      for (; ci < tn_cond_stmts; ci++)
        {
          gimple c = conds[ci];
          gcc_assert (c || ci != ci0);
          if (!c)
            break;
          gsi_insert_before (&guard_bsi, c, GSI_SAME_STMT);
          cond_expr = c;
        }
      nconds--;
      ci++;
      gcc_assert (cond_expr && gimple_code (cond_expr) == GIMPLE_COND);
      guard_bb_in_edge = split_block (guard_bb, cond_expr);
      guard_bb_in_edge->flags &= ~EDGE_FALLTHRU;
      guard_bb_in_edge->flags |= EDGE_FALSE_VALUE;

      bi_call_in_edge = make_edge (guard_bb, bi_call_bb, EDGE_TRUE_VALUE);

      bi_call_in_edge->probability = REG_BR_PROB_BASE * ERR_PROB;
      bi_call_in_edge->count =
	  apply_probability (guard_bb->count,
			     bi_call_in_edge->probability);
      guard_bb_in_edge->probability =
          inverse_probability (bi_call_in_edge->probability);
      guard_bb_in_edge->count = guard_bb->count - bi_call_in_edge->count;
    }

  if (dump_file && (dump_flags & TDF_DETAILS))
    {
      location_t loc;
      loc = gimple_location (bi_call);
      fprintf (dump_file,
               "%s:%d: note: function call is shrink-wrapped"
               " into error conditions.\n",
               LOCATION_FILE (loc), LOCATION_LINE (loc));
    }

  return true;
}
コード例 #22
0
static struct loop *
unswitch_loop (struct loop *loop, basic_block unswitch_on, rtx cond, rtx cinsn)
{
  edge entry, latch_edge, true_edge, false_edge, e;
  basic_block switch_bb, unswitch_on_alt;
  struct loop *nloop;
  int irred_flag, prob;
  rtx seq;

  /* Some sanity checking.  */
  gcc_assert (flow_bb_inside_loop_p (loop, unswitch_on));
  gcc_assert (EDGE_COUNT (unswitch_on->succs) == 2);
  gcc_assert (just_once_each_iteration_p (loop, unswitch_on));
  gcc_assert (!loop->inner);
  gcc_assert (flow_bb_inside_loop_p (loop, EDGE_SUCC (unswitch_on, 0)->dest));
  gcc_assert (flow_bb_inside_loop_p (loop, EDGE_SUCC (unswitch_on, 1)->dest));

  entry = loop_preheader_edge (loop);

  /* Make a copy.  */
  irred_flag = entry->flags & EDGE_IRREDUCIBLE_LOOP;
  entry->flags &= ~EDGE_IRREDUCIBLE_LOOP;
  if (!duplicate_loop_to_header_edge (loop, entry, 1,
			      	      NULL, NULL, NULL, 0))
    return NULL;
  entry->flags |= irred_flag;

  /* Record the block with condition we unswitch on.  */
  unswitch_on_alt = get_bb_copy (unswitch_on);
  true_edge = BRANCH_EDGE (unswitch_on_alt);
  false_edge = FALLTHRU_EDGE (unswitch_on);
  latch_edge = single_succ_edge (get_bb_copy (loop->latch));

  /* Create a block with the condition.  */
  prob = true_edge->probability;
  switch_bb = create_empty_bb (EXIT_BLOCK_PTR->prev_bb);
  seq = compare_and_jump_seq (XEXP (cond, 0), XEXP (cond, 1), GET_CODE (cond),
			      block_label (true_edge->dest),
			      prob, cinsn);
  emit_insn_after (seq, BB_END (switch_bb));
  e = make_edge (switch_bb, true_edge->dest, 0);
  e->probability = prob;
  e->count = latch_edge->count * prob / REG_BR_PROB_BASE;
  e = make_edge (switch_bb, FALLTHRU_EDGE (unswitch_on)->dest, EDGE_FALLTHRU);
  e->probability = false_edge->probability;
  e->count = latch_edge->count * (false_edge->probability) / REG_BR_PROB_BASE;

  if (irred_flag)
    {
      switch_bb->flags |= BB_IRREDUCIBLE_LOOP;
      EDGE_SUCC (switch_bb, 0)->flags |= EDGE_IRREDUCIBLE_LOOP;
      EDGE_SUCC (switch_bb, 1)->flags |= EDGE_IRREDUCIBLE_LOOP;
    }
  else
    {
      switch_bb->flags &= ~BB_IRREDUCIBLE_LOOP;
      EDGE_SUCC (switch_bb, 0)->flags &= ~EDGE_IRREDUCIBLE_LOOP;
      EDGE_SUCC (switch_bb, 1)->flags &= ~EDGE_IRREDUCIBLE_LOOP;
    }

  /* Loopify from the copy of LOOP body, constructing the new loop.  */
  nloop = loopify (latch_edge,
		   single_pred_edge (get_bb_copy (loop->header)), switch_bb,
		   BRANCH_EDGE (switch_bb), FALLTHRU_EDGE (switch_bb), true,
		   prob, REG_BR_PROB_BASE - prob);

  copy_loop_info (loop, nloop);
  /* Remove branches that are now unreachable in new loops.  */
  remove_path (true_edge);
  remove_path (false_edge);

  /* Preserve the simple loop preheaders.  */
  split_edge (loop_preheader_edge (loop));
  split_edge (loop_preheader_edge (nloop));

  return nloop;
}
コード例 #23
0
ファイル: cfgexpand.c プロジェクト: seguljac/higpu
static void
construct_exit_block (void)
{
  rtx head = get_last_insn ();
  rtx end;
  basic_block exit_block;
  edge e, e2;
  unsigned ix;
  edge_iterator ei;

  /* Make sure the locus is set to the end of the function, so that
     epilogue line numbers and warnings are set properly.  */
#ifdef USE_MAPPED_LOCATION
  if (cfun->function_end_locus != UNKNOWN_LOCATION)
#else
  if (cfun->function_end_locus.file)
#endif
    input_location = cfun->function_end_locus;

  /* The following insns belong to the top scope.  */
  record_block_change (DECL_INITIAL (current_function_decl));

  /* Generate rtl for function exit.  */
  expand_function_end ();

  end = get_last_insn ();
  if (head == end)
    return;
  while (NEXT_INSN (head) && NOTE_P (NEXT_INSN (head)))
    head = NEXT_INSN (head);
  exit_block = create_basic_block (NEXT_INSN (head), end,
				   EXIT_BLOCK_PTR->prev_bb);
  exit_block->frequency = EXIT_BLOCK_PTR->frequency;
  exit_block->count = EXIT_BLOCK_PTR->count;

  ix = 0;
  while (ix < EDGE_COUNT (EXIT_BLOCK_PTR->preds))
    {
      e = EDGE_I (EXIT_BLOCK_PTR->preds, ix);
      if (!(e->flags & EDGE_ABNORMAL))
	redirect_edge_succ (e, exit_block);
      else
	ix++;
    }

  e = make_edge (exit_block, EXIT_BLOCK_PTR, EDGE_FALLTHRU);
  e->probability = REG_BR_PROB_BASE;
  e->count = EXIT_BLOCK_PTR->count;
  FOR_EACH_EDGE (e2, ei, EXIT_BLOCK_PTR->preds)
    if (e2 != e)
      {
        e->count -= e2->count;
	exit_block->count -= e2->count;
	exit_block->frequency -= EDGE_FREQUENCY (e2);
      }
  if (e->count < 0)
    e->count = 0;
  if (exit_block->count < 0)
    exit_block->count = 0;
  if (exit_block->frequency < 0)
    exit_block->frequency = 0;
  update_bb_for_insn (exit_block);
}
コード例 #24
0
ファイル: test_all.cpp プロジェクト: bubuker/cpp_compute
int main(int argc, char *argv[]) {
#if __TBB_FLOW_GRAPH_CPP11_FEATURES
    try {
        utility::thread_number_range threads(get_default_num_threads);
        utility::parse_cli_arguments(argc, argv,
                                     utility::cli_argument_pack()
                                     //"-h" option for displaying help is present implicitly
                                     .positional_arg(threads,"#threads",utility::thread_number_range_desc)
                                     .arg(verbose,"verbose","   print diagnostic output to screen")
                                     .arg(silent,"silent","    limits output to timing info; overrides verbose")
                                    );

        if (silent) verbose = false;  // make silent override verbose

        tick_count start = tick_count::now();
        for(int p = threads.first; p <= threads.last; p = threads.step(p)) {
            task_scheduler_init init(p);
            if (!silent)  cout << "graph test running on " << p << " threads.\n";

            graph g;

            {   // test buffer: 0, 1
                buffer b(g);
                toggle input(g);
                led output(g, "OUTPUT", false); // false means we will explicitly call display to see LED

                make_edge(input.get_out(), input_port<0>(b));
                make_edge(output_port<0>(b), output.get_in());

                if (!silent) printf("Testing buffer...\n");
                input.activate(); // 0
                g.wait_for_all();
                if (!silent) output.display();
                assert(output.get_value() == low);
                input.flip(); // 1
                g.wait_for_all();
                if (!silent) output.display();
                assert(output.get_value() == high);
            }

            {   // test not_gate: 0, 1
                not_gate n(g);
                toggle input(g);
                led output(g, "OUTPUT", false);

                make_edge(input.get_out(), input_port<0>(n));
                make_edge(output_port<0>(n), output.get_in());

                if (!silent) printf("Testing not_gate...\n");
                input.activate(); // 0
                g.wait_for_all();
                if (!silent) output.display();
                assert(output.get_value() == high);
                input.flip(); // 1
                g.wait_for_all();
                if (!silent) output.display();
                assert(output.get_value() == low);
            }

            {   // test two-input and_gate: 00, 01, 10, 11
                and_gate<2> a(g);
                toggle input0(g);
                toggle input1(g);
                led output(g, "OUTPUT", false);

                make_edge(input0.get_out(), input_port<0>(a));
                make_edge(input1.get_out(), input_port<1>(a));
                make_edge(output_port<0>(a), output.get_in());

                if (!silent) printf("Testing and_gate...\n");
                input1.activate();
                input0.activate();  // 0 0
                g.wait_for_all();
                if (!silent) output.display();
                assert(output.get_value() == low);
                input0.flip();  // 0 1
                g.wait_for_all();
                if (!silent) output.display();
                assert(output.get_value() == low);
                input1.flip();
                input0.flip();  // 1 0
                g.wait_for_all();
                if (!silent) output.display();
                assert(output.get_value() == low);
                input0.flip();  // 1 1
                g.wait_for_all();
                if (!silent) output.display();
                assert(output.get_value() == high);
            }

            {   // test three-input or_gate: 000, 001, 010, 100, 011, 101, 110, 111
                or_gate<3> o(g);
                toggle input0(g);
                toggle input1(g);
                toggle input2(g);
                led output(g, "OUTPUT", false);

                make_edge(input0.get_out(), input_port<0>(o));
                make_edge(input1.get_out(), input_port<1>(o));
                make_edge(input2.get_out(), input_port<2>(o));
                make_edge(output_port<0>(o), output.get_in());

                if (!silent) printf("Testing or_gate...\n");
                input2.activate();
                input1.activate();
                input0.activate();  // 0 0 0
                g.wait_for_all();
                if (!silent) output.display();
                assert(output.get_value() == low);
                input0.flip();  // 0 0 1
                g.wait_for_all();
                if (!silent) output.display();
                assert(output.get_value() == high);
                input1.flip();
                input0.flip();  // 0 1 0
                g.wait_for_all();
                if (!silent) output.display();
                assert(output.get_value() == high);
                input2.flip();
                input1.flip();  // 1 0 0
                g.wait_for_all();
                if (!silent) output.display();
                assert(output.get_value() == high);
                input2.flip();
                input1.flip();
                input0.flip();  // 0 1 1
                g.wait_for_all();
                if (!silent) output.display();
                assert(output.get_value() == high);
                input2.flip();
                input1.flip();  // 1 0 1
                g.wait_for_all();
                if (!silent) output.display();
                assert(output.get_value() == high);
                input1.flip();
                input0.flip();  // 1 1 0
                g.wait_for_all();
                if (!silent) output.display();
                assert(output.get_value() == high);
                input0.flip();  // 1 1 1
                g.wait_for_all();
                if (!silent) output.display();
                assert(output.get_value() == high);
            }

            {   // test two-input xor_gate: 00, 01, 10, 11
                xor_gate<2> x(g);
                toggle input0(g);
                toggle input1(g);
                led output(g, "OUTPUT", false);

                make_edge(input0.get_out(), input_port<0>(x));
                make_edge(input1.get_out(), input_port<1>(x));
                make_edge(output_port<0>(x), output.get_in());

                if (!silent) printf("Testing xor_gate...\n");
                input1.activate();
                input0.activate();  // 0 0
                g.wait_for_all();
                if (!silent) output.display();
                assert(output.get_value() == low);
                input0.flip();  // 0 1
                g.wait_for_all();
                if (!silent) output.display();
                assert(output.get_value() == high);
                input1.flip();
                input0.flip();  // 1 0
                g.wait_for_all();
                if (!silent) output.display();
                assert(output.get_value() == high);
                input0.flip();  // 1 1
                g.wait_for_all();
                if (!silent) output.display();
                assert(output.get_value() == low);
            }


            {   // test two-input nor_gate: 00, 01, 10, 11
                nor_gate<2> n(g);
                toggle input0(g);
                toggle input1(g);
                led output(g, "OUTPUT", false);

                make_edge(input0.get_out(), input_port<0>(n));
                make_edge(input1.get_out(), input_port<1>(n));
                make_edge(output_port<0>(n), output.get_in());

                if (!silent) printf("Testing nor_gate...\n");
                input1.activate();
                input0.activate();  // 0 0
                g.wait_for_all();
                if (!silent) output.display();
                assert(output.get_value() == high);
                input0.flip();  // 0 1
                g.wait_for_all();
                if (!silent) output.display();
                assert(output.get_value() == low);
                input1.flip();
                input0.flip();  // 1 0
                g.wait_for_all();
                if (!silent) output.display();
                assert(output.get_value() == low);
                input0.flip();  // 1 1
                g.wait_for_all();
                if (!silent) output.display();
                assert(output.get_value() == low);
            }

            {   // test steady_signal and digit
                steady_signal input0(g, high);
                steady_signal input1(g, low);
                and_gate<2> a(g);
                or_gate<2> o(g);
                xor_gate<2> x(g);
                nor_gate<2> n(g);
                digit output(g, "OUTPUT", false);

                make_edge(input0.get_out(), input_port<0>(a));
                make_edge(input1.get_out(), input_port<1>(a));
                make_edge(output_port<0>(a), input_port<0>(output));

                make_edge(input0.get_out(), input_port<0>(o));
                make_edge(input1.get_out(), input_port<1>(o));
                make_edge(output_port<0>(o), input_port<1>(output));

                make_edge(input0.get_out(), input_port<0>(x));
                make_edge(input1.get_out(), input_port<1>(x));
                make_edge(output_port<0>(x), input_port<2>(output));

                make_edge(input0.get_out(), input_port<0>(n));
                make_edge(input1.get_out(), input_port<1>(n));
                make_edge(output_port<0>(n), input_port<3>(output));

                if (!silent) printf("Testing steady_signal...\n");
                input0.activate();  // 1
                input1.activate();  // 0
                g.wait_for_all();
                if (!silent) output.display();
                assert(output.get_value() == 6);
            }

            {   // test push_button
                push_button p(g);
                buffer b(g);
                led output(g, "OUTPUT", !silent); // true means print all LED state changes

                make_edge(p.get_out(), input_port<0>(b));
                make_edge(output_port<0>(b), output.get_in());

                if (!silent) printf("Testing push_button...\n");
                p.press();
                p.release();
                p.press();
                p.release();
                g.wait_for_all();
            }

            {   // test one_bit_adder
                one_bit_adder my_adder(g);
                toggle A(g);
                toggle B(g);
                toggle CarryIN(g);
                led Sum(g, "SUM");
                led CarryOUT(g, "CarryOUT");

                make_edge(A.get_out(), input_port<P::A0>(my_adder));
                make_edge(B.get_out(), input_port<P::B0>(my_adder));
                make_edge(CarryIN.get_out(), input_port<P::CI>(my_adder));
                make_edge(output_port<P::S0>(my_adder), Sum.get_in());
                make_edge(output_port<1>(my_adder), CarryOUT.get_in());

                A.activate();
                B.activate();
                CarryIN.activate();

                if (!silent) printf("A on\n");
                A.flip();
                g.wait_for_all();
                if (!silent) Sum.display();
                if (!silent) CarryOUT.display();
                assert((Sum.get_value() == high) && (CarryOUT.get_value() == low));

                if (!silent) printf("A off\n");
                A.flip();
                g.wait_for_all();
                if (!silent) Sum.display();
                if (!silent) CarryOUT.display();
                assert((Sum.get_value() == low) && (CarryOUT.get_value() == low));

                if (!silent) printf("B on\n");
                B.flip();
                g.wait_for_all();
                if (!silent) Sum.display();
                if (!silent) CarryOUT.display();
                assert((Sum.get_value() == high) && (CarryOUT.get_value() == low));
                if (!silent) printf("B off\n");
                B.flip();
                g.wait_for_all();
                if (!silent) Sum.display();
                if (!silent) CarryOUT.display();
                assert((Sum.get_value() == low) && (CarryOUT.get_value() == low));

                if (!silent) printf("CarryIN on\n");
                CarryIN.flip();
                g.wait_for_all();
                if (!silent) Sum.display();
                if (!silent) CarryOUT.display();
                assert((Sum.get_value() == high) && (CarryOUT.get_value() == low));
                if (!silent) printf("CarryIN off\n");
                CarryIN.flip();
                g.wait_for_all();
                if (!silent) Sum.display();
                if (!silent) CarryOUT.display();
                assert((Sum.get_value() == low) && (CarryOUT.get_value() == low));

                if (!silent) printf("A&B on\n");
                A.flip();
                B.flip();
                g.wait_for_all();
                if (!silent) Sum.display();
                if (!silent) CarryOUT.display();
                assert((Sum.get_value() == low) && (CarryOUT.get_value() == high));
                if (!silent) printf("A&B off\n");
                A.flip();
                B.flip();
                g.wait_for_all();
                if (!silent) Sum.display();
                if (!silent) CarryOUT.display();
                assert((Sum.get_value() == low) && (CarryOUT.get_value() == low));

                if (!silent) printf("A&CarryIN on\n");
                A.flip();
                CarryIN.flip();
                g.wait_for_all();
                if (!silent) Sum.display();
                if (!silent) CarryOUT.display();
                assert((Sum.get_value() == low) && (CarryOUT.get_value() == high));
                if (!silent) printf("A&CarryIN off\n");
                A.flip();
                CarryIN.flip();
                g.wait_for_all();
                if (!silent) Sum.display();
                if (!silent) CarryOUT.display();
                assert((Sum.get_value() == low) && (CarryOUT.get_value() == low));

                if (!silent) printf("B&CarryIN on\n");
                B.flip();
                CarryIN.flip();
                g.wait_for_all();
                if (!silent) Sum.display();
                if (!silent) CarryOUT.display();
                assert((Sum.get_value() == low) && (CarryOUT.get_value() == high));
                if (!silent) printf("B&CarryIN off\n");
                B.flip();
                CarryIN.flip();
                g.wait_for_all();
                if (!silent) Sum.display();
                if (!silent) CarryOUT.display();
                assert((Sum.get_value() == low) && (CarryOUT.get_value() == low));

                if (!silent) printf("A&B&CarryIN on\n");
                A.flip();
                B.flip();
                CarryIN.flip();
                g.wait_for_all();
                if (!silent) Sum.display();
                if (!silent) CarryOUT.display();
                assert((Sum.get_value() == high) && (CarryOUT.get_value() == high));
                if (!silent) printf("A&B&CarryIN off\n");
                A.flip();
                B.flip();
                CarryIN.flip();
                g.wait_for_all();
                if (!silent) Sum.display();
                if (!silent) CarryOUT.display();
                assert((Sum.get_value() == low) && (CarryOUT.get_value() == low));
            }

#if USE_TWO_BIT_FULL_ADDER
            {   // test two_bit_adder
                if (!silent) printf("testing two_bit adder\n");
                two_bit_adder two_adder(g);
                std::vector<toggle> A(2, toggle(g));
                std::vector<toggle> B(2, toggle(g));
                toggle CarryIN(g);
                digit Sum(g, "SUM");
                led CarryOUT(g, "CarryOUT");

                make_edge(A[0].get_out(), input_port<P::A0>(two_adder));
                make_edge(B[0].get_out(), input_port<P::B0>(two_adder));
                make_edge(output_port<P::S0>(two_adder), input_port<0>(Sum));

                make_edge(A[1].get_out(), input_port<P::A1>(two_adder));
                make_edge(B[1].get_out(), input_port<P::B1>(two_adder));
                make_edge(output_port<P::S1>(two_adder), input_port<1>(Sum));

                make_edge(CarryIN.get_out(), input_port<P::CI>(two_adder));
                make_edge(output_port<P::CO>(two_adder), CarryOUT.get_in());

                // Activate all switches at low state
                for (int i=0; i<2; ++i) {
                    A[i].activate();
                    B[i].activate();
                }
                CarryIN.activate();

                if (!silent) printf("1+0\n");
                A[0].flip();
                g.wait_for_all();
                if (!silent) Sum.display();
                if (!silent) CarryOUT.display();
                assert((Sum.get_value() == 1) && (CarryOUT.get_value() == low));

                if (!silent) printf("0+1\n");
                A[0].flip();
                B[0].flip();
                g.wait_for_all();
                if (!silent) Sum.display();
                if (!silent) CarryOUT.display();
                assert((Sum.get_value() == 1) && (CarryOUT.get_value() == low));
            }
#else
            {   // test four_bit_adder
                four_bit_adder four_adder(g);
                std::vector<toggle> A(4, toggle(g));
                std::vector<toggle> B(4, toggle(g));
                toggle CarryIN(g);
                digit Sum(g, "SUM");
                led CarryOUT(g, "CarryOUT");

                make_edge(A[0].get_out(), input_port<P::A0>(four_adder));
                make_edge(B[0].get_out(), input_port<P::B0>(four_adder));
                make_edge(output_port<P::S0>(four_adder), input_port<0>(Sum));

                make_edge(A[1].get_out(), input_port<P::A1>(four_adder));
                make_edge(B[1].get_out(), input_port<P::B1>(four_adder));
                make_edge(output_port<P::S1>(four_adder), input_port<1>(Sum));

                make_edge(A[2].get_out(), input_port<P::A2>(four_adder));
                make_edge(B[2].get_out(), input_port<P::B2>(four_adder));
                make_edge(output_port<P::S2>(four_adder), input_port<2>(Sum));

                make_edge(A[3].get_out(), input_port<P::A3>(four_adder));
                make_edge(B[3].get_out(), input_port<P::B3>(four_adder));
                make_edge(output_port<P::S3>(four_adder), input_port<3>(Sum));

                make_edge(CarryIN.get_out(), input_port<P::CI>(four_adder));
                make_edge(output_port<P::CO>(four_adder), CarryOUT.get_in());

                // Activate all switches at low state
                for (int i=0; i<4; ++i) {
                    A[i].activate();
                    B[i].activate();
                }
                CarryIN.activate();

                if (!silent) printf("1+0\n");
                A[0].flip();
                g.wait_for_all();
                if (!silent) Sum.display();
                if (!silent) CarryOUT.display();
                assert((Sum.get_value() == 1) && (CarryOUT.get_value() == low));

                if (!silent) printf("0+1\n");
                A[0].flip();
                B[0].flip();
                g.wait_for_all();
                if (!silent) Sum.display();
                if (!silent) CarryOUT.display();
                assert((Sum.get_value() == 1) && (CarryOUT.get_value() == low));

                if (!silent) printf("3+4\n");
                A[0].flip();
                A[1].flip();
                B[0].flip();
                B[2].flip();
                g.wait_for_all();
                if (!silent) Sum.display();
                if (!silent) CarryOUT.display();
                assert((Sum.get_value() == 7) && (CarryOUT.get_value() == low));

                if (!silent) printf("6+1\n");
                A[0].flip();
                A[2].flip();
                B[0].flip();
                B[2].flip();
                g.wait_for_all();
                if (!silent) Sum.display();
                if (!silent) CarryOUT.display();
                assert((Sum.get_value() == 7) && (CarryOUT.get_value() == low));

                if (!silent) printf("0+0+carry\n");
                A[1].flip();
                A[2].flip();
                B[0].flip();
                CarryIN.flip();
                g.wait_for_all();
                if (!silent) Sum.display();
                if (!silent) CarryOUT.display();
                assert((Sum.get_value() == 1) && (CarryOUT.get_value() == low));

                if (!silent) printf("15+15+carry\n");
                A[0].flip();
                A[1].flip();
                A[2].flip();
                A[3].flip();
                B[0].flip();
                B[1].flip();
                B[2].flip();
                B[3].flip();
                g.wait_for_all();
                if (!silent) Sum.display();
                if (!silent) CarryOUT.display();
                assert((Sum.get_value() == 0xf) && (CarryOUT.get_value() == high));

                if (!silent) printf("8+8\n");
                A[0].flip();
                A[1].flip();
                A[2].flip();
                B[0].flip();
                B[1].flip();
                B[2].flip();
                CarryIN.flip();
                g.wait_for_all();
                if (!silent) Sum.display();
                if (!silent) CarryOUT.display();
                assert((Sum.get_value() == 0) && (CarryOUT.get_value() == high));

                if (!silent) printf("0+0\n");
                A[3].flip();
                B[3].flip();
                g.wait_for_all();
                if (!silent) Sum.display();
                if (!silent) CarryOUT.display();
                assert((Sum.get_value() == 0) && (CarryOUT.get_value() == low));
            }
#endif

            {   // test D_latch
                D_latch my_d_latch(g);
                toggle D(g);
                pulse E(g, 500, 4); // clock changes every 500ms; stops after 4 changes
                led Q(g, " Q", verbose); // if true, LEDs print at every state change
                led notQ(g, "~Q", verbose);

                make_edge(D.get_out(), input_port<0>(my_d_latch));
                make_edge(E.get_out(), input_port<1>(my_d_latch));
                make_edge(output_port<0>(my_d_latch), Q.get_in());
                make_edge(output_port<1>(my_d_latch), notQ.get_in());

                D.activate();

                if (!silent) printf("Toggling D\n");
                E.activate();
                D.flip();
                g.wait_for_all();
                if (!silent && !verbose) {
                    Q.display();
                    notQ.display();
                }
                assert((Q.get_value() == high) && (notQ.get_value() == low));
                E.reset();

                if (!silent) printf("Toggling D\n");
                E.activate();
                D.flip();
                g.wait_for_all();
                if (!silent && !verbose) {
                    Q.display();
                    notQ.display();
                }
                assert((Q.get_value() == low) && (notQ.get_value() == high));
                E.reset();

                if (!silent) printf("Toggling D\n");
                E.activate();
                D.flip();
                g.wait_for_all();
                if (!silent && !verbose) {
                    Q.display();
                    notQ.display();
                }
                assert((Q.get_value() == high) && (notQ.get_value() == low));
                E.reset();

                if (!silent) printf("Toggling D\n");
                E.activate();
                D.flip();
                g.wait_for_all();
                if (!silent && !verbose) {
                    Q.display();
                    notQ.display();
                }
                assert((Q.get_value() == low) && (notQ.get_value() == high));
                E.reset();

                if (!silent) printf("Toggling D\n");
                E.activate();
                D.flip();
                g.wait_for_all();
                if (!silent && !verbose) {
                    Q.display();
                    notQ.display();
                }
                assert((Q.get_value() == high) && (notQ.get_value() == low));
            }
        }
        utility::report_elapsed_time((tbb::tick_count::now() - start).seconds());
        return 0;
    } catch(std::exception& e) {
        cerr<<"error occurred. error text is :\"" <<e.what()<<"\"\n";
        return 1;
    }
#else
    utility::report_skipped();
    return 0;
#endif // __TBB_FLOW_GRAPH_CPP11_FEATURES
}
コード例 #25
0
ファイル: cfgexpand.c プロジェクト: seguljac/higpu
static basic_block
expand_gimple_tailcall (basic_block bb, tree stmt, bool *can_fallthru)
{
  rtx last2, last;
  edge e;
  edge_iterator ei;
  int probability;
  gcov_type count;

  last2 = last = get_last_insn ();

  expand_expr_stmt (stmt);

  for (last = NEXT_INSN (last); last; last = NEXT_INSN (last))
    if (CALL_P (last) && SIBLING_CALL_P (last))
      goto found;

  maybe_dump_rtl_for_tree_stmt (stmt, last2);

  *can_fallthru = true;
  return NULL;

 found:
  /* ??? Wouldn't it be better to just reset any pending stack adjust?
     Any instructions emitted here are about to be deleted.  */
  do_pending_stack_adjust ();

  /* Remove any non-eh, non-abnormal edges that don't go to exit.  */
  /* ??? I.e. the fallthrough edge.  HOWEVER!  If there were to be
     EH or abnormal edges, we shouldn't have created a tail call in
     the first place.  So it seems to me we should just be removing
     all edges here, or redirecting the existing fallthru edge to
     the exit block.  */

  probability = 0;
  count = 0;

  for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
    {
      if (!(e->flags & (EDGE_ABNORMAL | EDGE_EH)))
	{
	  if (e->dest != EXIT_BLOCK_PTR)
	    {
	      e->dest->count -= e->count;
	      e->dest->frequency -= EDGE_FREQUENCY (e);
	      if (e->dest->count < 0)
	        e->dest->count = 0;
	      if (e->dest->frequency < 0)
	        e->dest->frequency = 0;
	    }
	  count += e->count;
	  probability += e->probability;
	  remove_edge (e);
	}
      else
	ei_next (&ei);
    }

  /* This is somewhat ugly: the call_expr expander often emits instructions
     after the sibcall (to perform the function return).  These confuse the
     find_sub_basic_blocks code, so we need to get rid of these.  */
  last = NEXT_INSN (last);
  gcc_assert (BARRIER_P (last));

  *can_fallthru = false;
  while (NEXT_INSN (last))
    {
      /* For instance an sqrt builtin expander expands if with
	 sibcall in the then and label for `else`.  */
      if (LABEL_P (NEXT_INSN (last)))
	{
	  *can_fallthru = true;
	  break;
	}
      delete_insn (NEXT_INSN (last));
    }

  e = make_edge (bb, EXIT_BLOCK_PTR, EDGE_ABNORMAL | EDGE_SIBCALL);
  e->probability += probability;
  e->count += count;
  BB_END (bb) = last;
  update_bb_for_insn (bb);

  if (NEXT_INSN (last))
    {
      bb = create_basic_block (NEXT_INSN (last), get_last_insn (), bb);

      last = BB_END (bb);
      if (BARRIER_P (last))
	BB_END (bb) = PREV_INSN (last);
    }

  maybe_dump_rtl_for_tree_stmt (stmt, last2);

  return bb;
}
コード例 #26
0
ファイル: cfgexpand.c プロジェクト: seguljac/higpu
static basic_block
expand_gimple_cond_expr (basic_block bb, tree stmt)
{
  basic_block new_bb, dest;
  edge new_edge;
  edge true_edge;
  edge false_edge;
  tree pred = COND_EXPR_COND (stmt);
  tree then_exp = COND_EXPR_THEN (stmt);
  tree else_exp = COND_EXPR_ELSE (stmt);
  rtx last2, last;

  last2 = last = get_last_insn ();

  extract_true_false_edges_from_block (bb, &true_edge, &false_edge);
  if (EXPR_LOCUS (stmt))
    {
      emit_line_note (*(EXPR_LOCUS (stmt)));
      record_block_change (TREE_BLOCK (stmt));
    }

  /* These flags have no purpose in RTL land.  */
  true_edge->flags &= ~EDGE_TRUE_VALUE;
  false_edge->flags &= ~EDGE_FALSE_VALUE;

  /* We can either have a pure conditional jump with one fallthru edge or
     two-way jump that needs to be decomposed into two basic blocks.  */
  if (TREE_CODE (then_exp) == GOTO_EXPR && IS_EMPTY_STMT (else_exp))
    {
      jumpif (pred, label_rtx (GOTO_DESTINATION (then_exp)));
      add_reg_br_prob_note (dump_file, last, true_edge->probability);
      maybe_dump_rtl_for_tree_stmt (stmt, last);
      if (EXPR_LOCUS (then_exp))
	emit_line_note (*(EXPR_LOCUS (then_exp)));
      return NULL;
    }
  if (TREE_CODE (else_exp) == GOTO_EXPR && IS_EMPTY_STMT (then_exp))
    {
      jumpifnot (pred, label_rtx (GOTO_DESTINATION (else_exp)));
      add_reg_br_prob_note (dump_file, last, false_edge->probability);
      maybe_dump_rtl_for_tree_stmt (stmt, last);
      if (EXPR_LOCUS (else_exp))
	emit_line_note (*(EXPR_LOCUS (else_exp)));
      return NULL;
    }
  gcc_assert (TREE_CODE (then_exp) == GOTO_EXPR
	      && TREE_CODE (else_exp) == GOTO_EXPR);

  jumpif (pred, label_rtx (GOTO_DESTINATION (then_exp)));
  add_reg_br_prob_note (dump_file, last, true_edge->probability);
  last = get_last_insn ();
  expand_expr (else_exp, const0_rtx, VOIDmode, 0);

  BB_END (bb) = last;
  if (BARRIER_P (BB_END (bb)))
    BB_END (bb) = PREV_INSN (BB_END (bb));
  update_bb_for_insn (bb);

  new_bb = create_basic_block (NEXT_INSN (last), get_last_insn (), bb);
  dest = false_edge->dest;
  redirect_edge_succ (false_edge, new_bb);
  false_edge->flags |= EDGE_FALLTHRU;
  new_bb->count = false_edge->count;
  new_bb->frequency = EDGE_FREQUENCY (false_edge);
  new_edge = make_edge (new_bb, dest, 0);
  new_edge->probability = REG_BR_PROB_BASE;
  new_edge->count = new_bb->count;
  if (BARRIER_P (BB_END (new_bb)))
    BB_END (new_bb) = PREV_INSN (BB_END (new_bb));
  update_bb_for_insn (new_bb);

  maybe_dump_rtl_for_tree_stmt (stmt, last2);
  
  if (EXPR_LOCUS (else_exp))
    emit_line_note (*(EXPR_LOCUS (else_exp)));

  return new_bb;
}
コード例 #27
0
ファイル: ubsan.c プロジェクト: acoxepochlabs/gcc
void
ubsan_expand_null_ifn (gimple_stmt_iterator gsi)
{
  gimple stmt = gsi_stmt (gsi);
  location_t loc = gimple_location (stmt);
  gcc_assert (gimple_call_num_args (stmt) == 2);
  tree ptr = gimple_call_arg (stmt, 0);
  tree ckind = gimple_call_arg (stmt, 1);

  basic_block cur_bb = gsi_bb (gsi);

  /* Split the original block holding the pointer dereference.  */
  edge e = split_block (cur_bb, stmt);

  /* Get a hold on the 'condition block', the 'then block' and the
     'else block'.  */
  basic_block cond_bb = e->src;
  basic_block fallthru_bb = e->dest;
  basic_block then_bb = create_empty_bb (cond_bb);
  add_bb_to_loop (then_bb, cond_bb->loop_father);
  loops_state_set (LOOPS_NEED_FIXUP);

  /* Make an edge coming from the 'cond block' into the 'then block';
     this edge is unlikely taken, so set up the probability accordingly.  */
  e = make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
  e->probability = PROB_VERY_UNLIKELY;

  /* Connect 'then block' with the 'else block'.  This is needed
     as the ubsan routines we call in the 'then block' are not noreturn.
     The 'then block' only has one outcoming edge.  */
  make_single_succ_edge (then_bb, fallthru_bb, EDGE_FALLTHRU);

  /* Set up the fallthrough basic block.  */
  e = find_edge (cond_bb, fallthru_bb);
  e->flags = EDGE_FALSE_VALUE;
  e->count = cond_bb->count;
  e->probability = REG_BR_PROB_BASE - PROB_VERY_UNLIKELY;

  /* Update dominance info for the newly created then_bb; note that
     fallthru_bb's dominance info has already been updated by
     split_bock.  */
  if (dom_info_available_p (CDI_DOMINATORS))
    set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);

  /* Put the ubsan builtin call into the newly created BB.  */
  gimple g;
  if (flag_sanitize_undefined_trap_on_error)
    g = gimple_build_call (builtin_decl_implicit (BUILT_IN_TRAP), 0);
  else
    {
      enum built_in_function bcode
	= flag_sanitize_recover
	  ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH
	  : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_ABORT;
      tree fn = builtin_decl_implicit (bcode);
      const struct ubsan_mismatch_data m
	= { build_zero_cst (pointer_sized_int_node), ckind };
      tree data
	= ubsan_create_data ("__ubsan_null_data", &loc, &m,
			     ubsan_type_descriptor (TREE_TYPE (ptr),
						    UBSAN_PRINT_POINTER),
			     NULL_TREE);
      data = build_fold_addr_expr_loc (loc, data);
      g = gimple_build_call (fn, 2, data,
			     build_zero_cst (pointer_sized_int_node));
    }
  gimple_set_location (g, loc);
  gimple_stmt_iterator gsi2 = gsi_start_bb (then_bb);
  gsi_insert_after (&gsi2, g, GSI_NEW_STMT);

  /* Unlink the UBSAN_NULLs vops before replacing it.  */
  unlink_stmt_vdef (stmt);

  g = gimple_build_cond (EQ_EXPR, ptr, build_int_cst (TREE_TYPE (ptr), 0),
			 NULL_TREE, NULL_TREE);
  gimple_set_location (g, loc);

  /* Replace the UBSAN_NULL with a GIMPLE_COND stmt.  */
  gsi_replace (&gsi, g, false);
}
コード例 #28
0
ファイル: cube_show.c プロジェクト: kimhc6028/cube
void display(void)
{  
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
  glMatrixMode(GL_MODELVIEW);    
 
  glLoadIdentity();   
    gluLookAt(0.0,0.0,distance,0.0,0.0,0.0,0.0,1.0,0.0);

  glRotatef(-pitch,1.0,0.0,0.0);
  glRotatef(-yaw,0.0,1.0,0.0);

  /////////////////////////////////////////////////////////









  //////////////////////////////////////////////////////
  glPushMatrix();
  {
    glRotatef(gDrawRotateAngle,0.0,1.0,0.0);
    glRotatef(gDrawRotateAngle,1.0,0.0,0.0);

    make_corner(corner_permu[0],corner_ori[0],W,O,G,K,K,K);
    make_corner(corner_permu[1],corner_ori[1],W,B,O,K,K,K);
    make_corner(corner_permu[2],corner_ori[2],W,R,B,K,K,K);
    make_corner(corner_permu[3],corner_ori[3],W,G,R,K,K,K);
    make_corner(corner_permu[4],corner_ori[4],Y,G,O,K,K,K);
    make_corner(corner_permu[5],corner_ori[5],Y,O,B,K,K,K);
    make_corner(corner_permu[6],corner_ori[6],Y,B,R,K,K,K);
    make_corner(corner_permu[7],corner_ori[7],Y,R,G,K,K,K);

    make_edge(edge_permu[0],edge_ori[0],W,O,K,K,K,K);
    make_edge(edge_permu[1],edge_ori[1],W,B,K,K,K,K);
    make_edge(edge_permu[2],edge_ori[2],W,R,K,K,K,K);
    make_edge(edge_permu[3],edge_ori[3],W,G,K,K,K,K);
    make_edge(edge_permu[4],edge_ori[4],O,G,K,K,K,K);
    make_edge(edge_permu[5],edge_ori[5],O,B,K,K,K,K);
    make_edge(edge_permu[6],edge_ori[6],R,B,K,K,K,K);
    make_edge(edge_permu[7],edge_ori[7],R,G,K,K,K,K);
    make_edge(edge_permu[8],edge_ori[8],Y,O,K,K,K,K);
    make_edge(edge_permu[9],edge_ori[9],Y,B,K,K,K,K);
    make_edge(edge_permu[10],edge_ori[10],Y,R,K,K,K,K);
    make_edge(edge_permu[11],edge_ori[11],Y,G,K,K,K,K);

    make_center();
    
  }
  glPopMatrix();

 
  glPopMatrix();
  glutSwapBuffers();
}
コード例 #29
0
ファイル: tree-mudflap.c プロジェクト: ChaosJohn/gcc
static void
mf_build_check_statement_for (tree base, tree limit,
                              gimple_stmt_iterator *instr_gsi,
                              location_t location, tree dirflag)
{
  gimple_stmt_iterator gsi;
  basic_block cond_bb, then_bb, join_bb;
  edge e;
  tree cond, t, u, v;
  tree mf_base;
  tree mf_elem;
  tree mf_limit;
  gimple g;
  gimple_seq seq, stmts;

  /* We first need to split the current basic block, and start altering
     the CFG.  This allows us to insert the statements we're about to
     construct into the right basic blocks.  */

  cond_bb = gimple_bb (gsi_stmt (*instr_gsi));
  gsi = *instr_gsi;
  gsi_prev (&gsi);
  if (! gsi_end_p (gsi))
    e = split_block (cond_bb, gsi_stmt (gsi));
  else
    e = split_block_after_labels (cond_bb);
  cond_bb = e->src;
  join_bb = e->dest;

  /* A recap at this point: join_bb is the basic block at whose head
     is the gimple statement for which this check expression is being
     built.  cond_bb is the (possibly new, synthetic) basic block the
     end of which will contain the cache-lookup code, and a
     conditional that jumps to the cache-miss code or, much more
     likely, over to join_bb.  */

  /* Create the bb that contains the cache-miss fallback block (mf_check).  */
  then_bb = create_empty_bb (cond_bb);
  make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
  make_single_succ_edge (then_bb, join_bb, EDGE_FALLTHRU);

  /* Mark the pseudo-fallthrough edge from cond_bb to join_bb.  */
  e = find_edge (cond_bb, join_bb);
  e->flags = EDGE_FALSE_VALUE;
  e->count = cond_bb->count;
  e->probability = REG_BR_PROB_BASE;

  /* Update dominance info.  Note that bb_join's data was
     updated by split_block.  */
  if (dom_info_available_p (CDI_DOMINATORS))
    {
      set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
      set_immediate_dominator (CDI_DOMINATORS, join_bb, cond_bb);
    }

  /* Update loop info.  */
  if (current_loops)
    add_bb_to_loop (then_bb, cond_bb->loop_father);

  /* Build our local variables.  */
  mf_elem = create_tmp_reg (mf_cache_structptr_type, "__mf_elem");
  mf_base = create_tmp_reg (mf_uintptr_type, "__mf_base");
  mf_limit = create_tmp_reg (mf_uintptr_type, "__mf_limit");

  /* Build: __mf_base = (uintptr_t) <base address expression>.  */
  seq = NULL;
  t = fold_convert_loc (location, mf_uintptr_type,
			unshare_expr (base));
  t = force_gimple_operand (t, &stmts, false, NULL_TREE);
  gimple_seq_add_seq (&seq, stmts);
  g = gimple_build_assign (mf_base, t);
  gimple_set_location (g, location);
  gimple_seq_add_stmt (&seq, g);

  /* Build: __mf_limit = (uintptr_t) <limit address expression>.  */
  t = fold_convert_loc (location, mf_uintptr_type,
			unshare_expr (limit));
  t = force_gimple_operand (t, &stmts, false, NULL_TREE);
  gimple_seq_add_seq (&seq, stmts);
  g = gimple_build_assign (mf_limit, t);
  gimple_set_location (g, location);
  gimple_seq_add_stmt (&seq, g);

  /* Build: __mf_elem = &__mf_lookup_cache [(__mf_base >> __mf_shift)
                                            & __mf_mask].  */
  t = build2 (RSHIFT_EXPR, mf_uintptr_type, mf_base,
              flag_mudflap_threads ? mf_cache_shift_decl
	       : mf_cache_shift_decl_l);
  t = build2 (BIT_AND_EXPR, mf_uintptr_type, t,
              flag_mudflap_threads ? mf_cache_mask_decl
	       : mf_cache_mask_decl_l);
  t = build4 (ARRAY_REF,
              TREE_TYPE (TREE_TYPE (mf_cache_array_decl)),
              mf_cache_array_decl, t, NULL_TREE, NULL_TREE);
  t = build1 (ADDR_EXPR, mf_cache_structptr_type, t);
  t = force_gimple_operand (t, &stmts, false, NULL_TREE);
  gimple_seq_add_seq (&seq, stmts);
  g = gimple_build_assign (mf_elem, t);
  gimple_set_location (g, location);
  gimple_seq_add_stmt (&seq, g);

  /* Quick validity check.

     if (__mf_elem->low > __mf_base
         || (__mf_elem_high < __mf_limit))
        {
          __mf_check ();
          ... and only if single-threaded:
          __mf_lookup_shift_1 = f...;
          __mf_lookup_mask_l = ...;
        }

     It is expected that this body of code is rarely executed so we mark
     the edge to the THEN clause of the conditional jump as unlikely.  */

  /* Construct t <-- '__mf_elem->low  > __mf_base'.  */
  t = build3 (COMPONENT_REF, mf_uintptr_type,
              build1 (INDIRECT_REF, mf_cache_struct_type, mf_elem),
              TYPE_FIELDS (mf_cache_struct_type), NULL_TREE);
  t = build2 (GT_EXPR, boolean_type_node, t, mf_base);

  /* Construct '__mf_elem->high < __mf_limit'.

     First build:
        1) u <--  '__mf_elem->high'
        2) v <--  '__mf_limit'.

     Then build 'u <-- (u < v).  */

  u = build3 (COMPONENT_REF, mf_uintptr_type,
              build1 (INDIRECT_REF, mf_cache_struct_type, mf_elem),
              DECL_CHAIN (TYPE_FIELDS (mf_cache_struct_type)), NULL_TREE);

  v = mf_limit;

  u = build2 (LT_EXPR, boolean_type_node, u, v);

  /* Build the composed conditional: t <-- 't || u'.  Then store the
     result of the evaluation of 't' in a temporary variable which we
     can use as the condition for the conditional jump.  */
  t = build2 (TRUTH_OR_EXPR, boolean_type_node, t, u);
  t = force_gimple_operand (t, &stmts, false, NULL_TREE);
  gimple_seq_add_seq (&seq, stmts);
  cond = create_tmp_reg (boolean_type_node, "__mf_unlikely_cond");
  g = gimple_build_assign  (cond, t);
  gimple_set_location (g, location);
  gimple_seq_add_stmt (&seq, g);

  /* Build the conditional jump.  'cond' is just a temporary so we can
     simply build a void COND_EXPR.  We do need labels in both arms though.  */
  g = gimple_build_cond (NE_EXPR, cond, boolean_false_node, NULL_TREE,
			 NULL_TREE);
  gimple_set_location (g, location);
  gimple_seq_add_stmt (&seq, g);

  /* At this point, after so much hard work, we have only constructed
     the conditional jump,

     if (__mf_elem->low > __mf_base
         || (__mf_elem_high < __mf_limit))

     The lowered GIMPLE tree representing this code is in the statement
     list starting at 'head'.

     We can insert this now in the current basic block, i.e. the one that
     the statement we're instrumenting was originally in.  */
  gsi = gsi_last_bb (cond_bb);
  gsi_insert_seq_after (&gsi, seq, GSI_CONTINUE_LINKING);

  /*  Now build up the body of the cache-miss handling:

     __mf_check();
     refresh *_l vars.

     This is the body of the conditional.  */

  seq = NULL;
  /* u is a string, so it is already a gimple value.  */
  u = mf_file_function_line_tree (location);
  /* NB: we pass the overall [base..limit] range to mf_check.  */
  v = fold_build2_loc (location, PLUS_EXPR, mf_uintptr_type,
		   fold_build2_loc (location,
				MINUS_EXPR, mf_uintptr_type, mf_limit, mf_base),
		   build_int_cst (mf_uintptr_type, 1));
  v = force_gimple_operand (v, &stmts, true, NULL_TREE);
  gimple_seq_add_seq (&seq, stmts);
  g = gimple_build_call (mf_check_fndecl, 4, mf_base, v, dirflag, u);
  gimple_seq_add_stmt (&seq, g);

  if (! flag_mudflap_threads)
    {
      if (stmt_ends_bb_p (g))
	{
	  gsi = gsi_start_bb (then_bb);
	  gsi_insert_seq_after (&gsi, seq, GSI_CONTINUE_LINKING);
	  e = split_block (then_bb, g);
	  then_bb = e->dest;
	  seq = NULL;
	}

      g = gimple_build_assign (mf_cache_shift_decl_l, mf_cache_shift_decl);
      gimple_seq_add_stmt (&seq, g);

      g = gimple_build_assign (mf_cache_mask_decl_l, mf_cache_mask_decl);
      gimple_seq_add_stmt (&seq, g);
    }

  /* Insert the check code in the THEN block.  */
  gsi = gsi_start_bb (then_bb);
  gsi_insert_seq_after (&gsi, seq, GSI_CONTINUE_LINKING);

  *instr_gsi = gsi_start_bb (join_bb);
}
コード例 #30
0
static void
shrink_wrap_one_built_in_call_with_conds (gcall *bi_call, vec <gimple *> conds,
					  unsigned int nconds)
{
  gimple_stmt_iterator bi_call_bsi;
  basic_block bi_call_bb, join_tgt_bb, guard_bb;
  edge join_tgt_in_edge_from_call, join_tgt_in_edge_fall_thru;
  edge bi_call_in_edge0, guard_bb_in_edge;
  unsigned tn_cond_stmts;
  unsigned ci;
  gimple *cond_expr = NULL;
  gimple *cond_expr_start;

  /* The cfg we want to create looks like this:

	   [guard n-1]         <- guard_bb (old block)
	     |    \
	     | [guard n-2]                   }
	     |    / \                        }
	     |   /  ...                      } new blocks
	     |  /  [guard 0]                 }
	     | /    /   |                    }
	    [ call ]    |     <- bi_call_bb  }
	     | \        |
	     |  \       |
	     |   [ join ]     <- join_tgt_bb (old iff call must end bb)
	     |
	 possible EH edges (only if [join] is old)

     When [join] is new, the immediate dominators for these blocks are:

     1. [guard n-1]: unchanged
     2. [call]: [guard n-1]
     3. [guard m]: [guard m+1] for 0 <= m <= n-2
     4. [join]: [guard n-1]

     We punt for the more complex case case of [join] being old and
     simply free the dominance info.  We also punt on postdominators,
     which aren't expected to be available at this point anyway.  */
  bi_call_bb = gimple_bb (bi_call);

  /* Now find the join target bb -- split bi_call_bb if needed.  */
  if (stmt_ends_bb_p (bi_call))
    {
      /* We checked that there was a fallthrough edge in
	 can_guard_call_p.  */
      join_tgt_in_edge_from_call = find_fallthru_edge (bi_call_bb->succs);
      gcc_assert (join_tgt_in_edge_from_call);
      /* We don't want to handle PHIs.  */
      if (EDGE_COUNT (join_tgt_in_edge_from_call->dest->preds) > 1)
	join_tgt_bb = split_edge (join_tgt_in_edge_from_call);
      else
	{
	  join_tgt_bb = join_tgt_in_edge_from_call->dest;
	  /* We may have degenerate PHIs in the destination.  Propagate
	     those out.  */
	  for (gphi_iterator i = gsi_start_phis (join_tgt_bb); !gsi_end_p (i);)
	    {
	      gphi *phi = i.phi ();
	      replace_uses_by (gimple_phi_result (phi),
			       gimple_phi_arg_def (phi, 0));
	      remove_phi_node (&i, true);
	    }
	}
    }
  else
    {
      join_tgt_in_edge_from_call = split_block (bi_call_bb, bi_call);
      join_tgt_bb = join_tgt_in_edge_from_call->dest;
    }

  bi_call_bsi = gsi_for_stmt (bi_call);

  /* Now it is time to insert the first conditional expression
     into bi_call_bb and split this bb so that bi_call is
     shrink-wrapped.  */
  tn_cond_stmts = conds.length ();
  cond_expr = NULL;
  cond_expr_start = conds[0];
  for (ci = 0; ci < tn_cond_stmts; ci++)
    {
      gimple *c = conds[ci];
      gcc_assert (c || ci != 0);
      if (!c)
        break;
      gsi_insert_before (&bi_call_bsi, c, GSI_SAME_STMT);
      cond_expr = c;
    }
  ci++;
  gcc_assert (cond_expr && gimple_code (cond_expr) == GIMPLE_COND);

  typedef std::pair<edge, edge> edge_pair;
  auto_vec<edge_pair, 8> edges;

  bi_call_in_edge0 = split_block (bi_call_bb, cond_expr);
  bi_call_in_edge0->flags &= ~EDGE_FALLTHRU;
  bi_call_in_edge0->flags |= EDGE_FALSE_VALUE;
  guard_bb = bi_call_bb;
  bi_call_bb = bi_call_in_edge0->dest;
  join_tgt_in_edge_fall_thru = make_edge (guard_bb, join_tgt_bb,
                                          EDGE_TRUE_VALUE);

  edges.reserve (nconds);
  edges.quick_push (edge_pair (bi_call_in_edge0, join_tgt_in_edge_fall_thru));

  /* Code generation for the rest of the conditions  */
  for (unsigned int i = 1; i < nconds; ++i)
    {
      unsigned ci0;
      edge bi_call_in_edge;
      gimple_stmt_iterator guard_bsi = gsi_for_stmt (cond_expr_start);
      ci0 = ci;
      cond_expr_start = conds[ci0];
      for (; ci < tn_cond_stmts; ci++)
        {
	  gimple *c = conds[ci];
          gcc_assert (c || ci != ci0);
          if (!c)
            break;
          gsi_insert_before (&guard_bsi, c, GSI_SAME_STMT);
          cond_expr = c;
        }
      ci++;
      gcc_assert (cond_expr && gimple_code (cond_expr) == GIMPLE_COND);
      guard_bb_in_edge = split_block (guard_bb, cond_expr);
      guard_bb_in_edge->flags &= ~EDGE_FALLTHRU;
      guard_bb_in_edge->flags |= EDGE_TRUE_VALUE;

      bi_call_in_edge = make_edge (guard_bb, bi_call_bb, EDGE_FALSE_VALUE);
      edges.quick_push (edge_pair (bi_call_in_edge, guard_bb_in_edge));
    }

  /* Now update the probability and profile information, processing the
     guards in order of execution.

     There are two approaches we could take here.  On the one hand we
     could assign a probability of X to the call block and distribute
     that probability among its incoming edges.  On the other hand we
     could assign a probability of X to each individual call edge.

     The choice only affects calls that have more than one condition.
     In those cases, the second approach would give the call block
     a greater probability than the first.  However, the difference
     is only small, and our chosen X is a pure guess anyway.

     Here we take the second approach because it's slightly simpler
     and because it's easy to see that it doesn't lose profile counts.  */
  bi_call_bb->count = profile_count::zero ();
  while (!edges.is_empty ())
    {
      edge_pair e = edges.pop ();
      edge call_edge = e.first;
      edge nocall_edge = e.second;
      basic_block src_bb = call_edge->src;
      gcc_assert (src_bb == nocall_edge->src);

      call_edge->probability = profile_probability::very_unlikely ();
      nocall_edge->probability = profile_probability::always ()
				 - call_edge->probability;

      bi_call_bb->count += call_edge->count ();

      if (nocall_edge->dest != join_tgt_bb)
	nocall_edge->dest->count = src_bb->count - bi_call_bb->count;
    }

  if (dom_info_available_p (CDI_DOMINATORS))
    {
      /* The split_blocks leave [guard 0] as the immediate dominator
	 of [call] and [call] as the immediate dominator of [join].
	 Fix them up.  */
      set_immediate_dominator (CDI_DOMINATORS, bi_call_bb, guard_bb);
      set_immediate_dominator (CDI_DOMINATORS, join_tgt_bb, guard_bb);
    }

  if (dump_file && (dump_flags & TDF_DETAILS))
    {
      location_t loc;
      loc = gimple_location (bi_call);
      fprintf (dump_file,
               "%s:%d: note: function call is shrink-wrapped"
               " into error conditions.\n",
               LOCATION_FILE (loc), LOCATION_LINE (loc));
    }
}