예제 #1
0
파일: cilk.c 프로젝트: kito-cheng/gcc
tree
create_cilk_function_exit (tree frame, bool detaches, bool needs_sync)
{
  tree epi = alloc_stmt_list ();

  if (needs_sync) 
    append_to_statement_list (build_cilk_sync (), &epi);
  tree func_ptr = build1 (ADDR_EXPR, cilk_frame_ptr_type_decl, frame);
  tree pop_frame = build_call_expr (cilk_pop_fndecl, 1, func_ptr);
  tree worker = cilk_dot (frame, CILK_TI_FRAME_WORKER, 0);
  tree current = cilk_arrow (worker, CILK_TI_WORKER_CUR, 0);
  tree parent = cilk_dot (frame, CILK_TI_FRAME_PARENT, 0);
  tree set_current = build2 (MODIFY_EXPR, void_type_node, current, parent);
  append_to_statement_list (set_current, &epi);
  append_to_statement_list (pop_frame, &epi);
  tree call = build_call_expr (cilk_leave_fndecl, 1, func_ptr);
  if (!detaches)
    {
      tree flags = cilk_dot (frame, CILK_TI_FRAME_FLAGS, false);
      tree flags_cmp_expr = fold_build2 (NE_EXPR, TREE_TYPE (flags), flags, 
					 build_int_cst (TREE_TYPE (flags), 
							CILK_FRAME_VERSION));
      call = fold_build3 (COND_EXPR, void_type_node, flags_cmp_expr,
			  call, build_empty_stmt (EXPR_LOCATION (flags)));
    }
  append_to_statement_list (call, &epi);  
  return epi;
}
예제 #2
0
void
cilk_install_body_with_frame_cleanup (tree fndecl, tree orig_body, void *wd)
{
  tree frame = make_cilk_frame (fndecl);
  tree dtor = create_cilk_function_exit (frame, false, false);
  add_local_decl (cfun, frame);

  cfun->language = ggc_cleared_alloc<language_function> ();
  
  location_t loc = EXPR_LOCATION (orig_body);
  tree list = alloc_stmt_list ();
  DECL_SAVED_TREE (fndecl) = list;
  tree fptr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (frame)), frame);
  tree body = cilk_install_body_pedigree_operations (fptr);
  gcc_assert (TREE_CODE (body) == STATEMENT_LIST);
  tree detach_expr = build_call_expr (cilk_detach_fndecl, 1, fptr);
  append_to_statement_list (detach_expr, &body);
  cilk_outline (fndecl, &orig_body, (struct wrapper_data *) wd);
  append_to_statement_list (orig_body, &body);
  if (flag_exceptions)
    {
      tree except_flag = set_cilk_except_flag (frame);
      tree except_data = set_cilk_except_data (frame);
      tree catch_list = alloc_stmt_list ();
      append_to_statement_list (except_flag, &catch_list);
      append_to_statement_list (except_data, &catch_list);
      body = create_try_catch_expr (body, catch_list);
    }
  append_to_statement_list (build_stmt (loc, TRY_FINALLY_EXPR, body, dtor),
			    &list);
}
예제 #3
0
static void
add_expr_to_chain (tree* chain, tree expr, bool front)
{
  if (expr == NULL_TREE || IS_EMPTY_STMT (expr))
    return;

  if (*chain)
    {
      if (TREE_CODE (*chain) != STATEMENT_LIST)
	{
	  tree tmp;

	  tmp = *chain;
	  *chain = NULL_TREE;
	  append_to_statement_list (tmp, chain);
	}

      if (front)
	{
	  tree_stmt_iterator i;

	  i = tsi_start (*chain);
	  tsi_link_before (&i, expr, TSI_CONTINUE_LINKING);
	}
      else
	append_to_statement_list (expr, chain);
    }
  else
    *chain = expr;
}
예제 #4
0
파일: cp-gimplify.c 프로젝트: didemoto/gcc
static void
genericize_continue_stmt (tree *stmt_p)
{
  tree stmt_list = NULL;
  tree pred = build_predict_expr (PRED_CONTINUE, NOT_TAKEN);
  tree label = get_bc_label (bc_continue);
  location_t location = EXPR_LOCATION (*stmt_p);
  tree jump = build1_loc (location, GOTO_EXPR, void_type_node, label);
  append_to_statement_list (pred, &stmt_list);
  append_to_statement_list (jump, &stmt_list);
  *stmt_p = stmt_list;
}
예제 #5
0
static tree
build_gimple_eh_filter_tree (tree body, tree allowed, tree failure)
{
  tree t;

  /* FIXME should the allowed types go in TREE_TYPE?  */
  t = build2 (EH_FILTER_EXPR, void_type_node, allowed, NULL_TREE);
  append_to_statement_list (failure, &EH_FILTER_FAILURE (t));

  t = build2 (TRY_CATCH_EXPR, void_type_node, NULL_TREE, t);
  append_to_statement_list (body, &TREE_OPERAND (t, 0));

  return t;
}
예제 #6
0
static void
append_stmt (tree stmt)
{
  if (!EXPR_HAS_LOCATION (stmt))
    SET_EXPR_LOCATION (stmt, input_location);
  TREE_SIDE_EFFECTS (stmt) = true;
  append_to_statement_list (stmt, &cur_stmts);
}
예제 #7
0
파일: cp-gimplify.c 프로젝트: didemoto/gcc
static void
genericize_for_stmt (tree *stmt_p, int *walk_subtrees, void *data)
{
  tree stmt = *stmt_p;
  tree expr = NULL;
  tree loop;
  tree init = FOR_INIT_STMT (stmt);

  if (init)
    {
      cp_walk_tree (&init, cp_genericize_r, data, NULL);
      append_to_statement_list (init, &expr);
    }

  genericize_cp_loop (&loop, EXPR_LOCATION (stmt), FOR_COND (stmt),
		      FOR_BODY (stmt), FOR_EXPR (stmt), 1, walk_subtrees, data);
  append_to_statement_list (loop, &expr);
  *stmt_p = expr;
}
static tree
finish_bc_block (enum bc_t bc, tree label, tree body)
{
  gcc_assert (label == ctxp->current_label[bc]);

  if (TREE_USED (label))
    {
      tree t, sl = NULL;

      t = build1 (LABEL_EXPR, void_type_node, label);

      append_to_statement_list (body, &sl);
      append_to_statement_list (t, &sl);
      body = sl;
    }

  ctxp->current_label[bc] = TREE_CHAIN (label);
  TREE_CHAIN (label) = NULL_TREE;
  return body;
}
예제 #9
0
파일: cp-gimplify.c 프로젝트: didemoto/gcc
static void
finish_bc_block (tree *block, enum bc_t bc, tree label)
{
  gcc_assert (label == bc_label[bc]);

  if (TREE_USED (label))
    append_to_statement_list (build1 (LABEL_EXPR, void_type_node, label),
			      block);

  bc_label[bc] = DECL_CHAIN (label);
  DECL_CHAIN (label) = NULL_TREE;
}
예제 #10
0
파일: c-gimplify.c 프로젝트: aosm/gcc_40
static tree
finish_bc_block (tree label, tree body)
{
  gcc_assert (label == ctxp->current_bc_label);

  if (TREE_USED (label))
    {
      tree t, sl = NULL;

      /* Clear the name so flow can delete the label.  */
      DECL_NAME (label) = NULL_TREE;
      t = build1 (LABEL_EXPR, void_type_node, label);

      append_to_statement_list (body, &sl);
      append_to_statement_list (t, &sl);
      body = sl;
    }

  ctxp->current_bc_label = TREE_CHAIN (label);
  TREE_CHAIN (label) = NULL_TREE;
  return body;
}
예제 #11
0
void
gfc_add_expr_to_block (stmtblock_t * block, tree expr)
{
  gcc_assert (block);

  if (expr == NULL_TREE || IS_EMPTY_STMT (expr))
    return;

  if (block->head)
    {
      if (TREE_CODE (block->head) != STATEMENT_LIST)
	{
	  tree tmp;

	  tmp = block->head;
	  block->head = NULL_TREE;
	  append_to_statement_list (tmp, &block->head);
	}
      append_to_statement_list (expr, &block->head);
    }
  else
    /* Don't bother creating a list if we only have a single statement.  */
    block->head = expr;
}
예제 #12
0
/* parsing language hook */
static void slang_parse_file ()
{

    int i;
    for(i = 0; i<num_in_fnames; ++i) {
        parse_program(in_fnames[i]);
    } 
#if 0
  tree  char_p = build_pointer_type (char_type_node);
  tree  puts_type   = build_function_type_list (integer_type_node,
						char_p, NULL_TREE);
  tree  puts_fndecl = build_function_decl ("puts", true, puts_type);

  tree  main_type   = build_function_type_list (integer_type_node, NULL_TREE);
  tree  main_fndecl = build_function_decl ("main", false, main_type);

  const char *msg = "HelloWorld , ... This is pradeeps compiler";
  tree hello_str = build_string_literal (strlen(msg) + 1, msg);

  tree  call = build_call_expr (puts_fndecl,1, hello_str);
  tree block = make_node(BLOCK);
  tree       c1 = build_pointer_type (char_type_node);
  tree stmts = NULL_TREE ;//alloc_stmt_list ();
  append_to_statement_list (call, &stmts);

  build_function (main_fndecl, stmts, block);

  FILE *fd = fopen("/home/pradeep/Desktop/dump.txt","w");


  gimplify_function_tree (main_fndecl);

  dump_function_to_file (main_fndecl, fd, 0);

  fclose(fd);

  cgraph_finalize_function (main_fndecl, false);

  current_function_decl = NULL_TREE;
  pop_cfun();
#endif

}
예제 #13
0
static void
gimplify_must_not_throw_expr (tree *expr_p, tree *pre_p)
{
  tree stmt = *expr_p;
  tree temp = voidify_wrapper_expr (stmt, NULL);
  tree body = TREE_OPERAND (stmt, 0);

  gimplify_stmt (&body);

  stmt = gimple_build_eh_filter (body, NULL_TREE,
				 build_call (terminate_node, NULL_TREE));

  if (temp)
    {
      append_to_statement_list (stmt, pre_p);
      *expr_p = temp;
    }
  else
    *expr_p = stmt;
}
예제 #14
0
파일: tree-mudflap.c 프로젝트: 0mp/freebsd
static void
mudflap_register_call (tree obj, tree object_size, tree varname)
{
  tree arg, args, call_stmt;

  args = tree_cons (NULL_TREE, varname, NULL_TREE);

  arg = build_int_cst (NULL_TREE, 4); /* __MF_TYPE_STATIC */
  args = tree_cons (NULL_TREE, arg, args);

  arg = convert (size_type_node, object_size);
  args = tree_cons (NULL_TREE, arg, args);

  arg = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (obj)), obj);
  arg = convert (ptr_type_node, arg);
  args = tree_cons (NULL_TREE, arg, args);

  call_stmt = build_function_call_expr (mf_register_fndecl, args);

  append_to_statement_list (call_stmt, &enqueued_call_stmt_chain);
}
예제 #15
0
void
write_resource_constructor (tree *list_p)
{
  tree decl, t, register_resource_fn;
  unsigned ix;

  if (resources == NULL)
    return;

  t = build_function_type_list (void_type_node, ptr_type_node, NULL);
  t = build_decl (input_location,
		  FUNCTION_DECL, get_identifier ("_Jv_RegisterResource"), t);
  TREE_PUBLIC (t) = 1;
  DECL_EXTERNAL (t) = 1;
  register_resource_fn = t;

  /* Write out entries in the same order in which they were defined.  */
  FOR_EACH_VEC_ELT (tree, resources, ix, decl)
    {
      t = build_fold_addr_expr (decl);
      t = build_call_expr (register_resource_fn, 1, t);
      append_to_statement_list (t, list_p);
    }
void
write_resource_constructor (tree *list_p)
{
  tree iter, t, register_resource_fn;

  if (resources == NULL)
    return;

  t = build_function_type_list (void_type_node, ptr_type_node, NULL);
  t = build_decl (FUNCTION_DECL, get_identifier ("_Jv_RegisterResource"), t);
  TREE_PUBLIC (t) = 1;
  DECL_EXTERNAL (t) = 1;
  register_resource_fn = t;

  /* Write out entries in the same order in which they were defined.  */
  for (iter = nreverse (resources); iter ; iter = TREE_CHAIN (iter))
    {
      t = build_fold_addr_expr (TREE_VALUE (iter));
      t = tree_cons (NULL, t, NULL);
      t = build_function_call_expr (register_resource_fn, t);
      append_to_statement_list (t, list_p);
    }
}
예제 #17
0
static void
build_cdtor (bool ctor_p, tree *cdtors, size_t len)
{
  size_t i;

  i = 0;
  while (i < len)
    {
      tree body;
      tree fn;
      priority_type priority;

      priority = 0;
      body = NULL_TREE;
      /* Find the next batch of constructors/destructors with the same
	 initialization priority.  */
      do
	{
	  priority_type p;
	  fn = cdtors[i];
	  p = ctor_p ? DECL_INIT_PRIORITY (fn) : DECL_FINI_PRIORITY (fn);
	  if (!body)
	    priority = p;
	  else if (p != priority)
	    break;
	  append_to_statement_list (build_function_call_expr (fn, 0),
				    &body);
	  ++i;
	}
      while (i < len);
      gcc_assert (body != NULL_TREE);
      /* Generate a function to call all the function of like
	 priority.  */
      cgraph_build_static_cdtor (ctor_p ? 'I' : 'D', body, priority);
    }
}
예제 #18
0
static tree
pop_binding (void)
{
  tree res;
  struct binding_level *cur;

  cur = cur_binding_level;
  res = cur->bind;

  if (cur->save_stack)
    {
      tree tmp_var;
      tree save;
      tree save_call;
      tree restore;
      tree t;

      /* Create an artificial var to save the stack pointer.  */
      /* build_decl got a new parameter
       * http://www.mail-archive.com/[email protected]/msg01245.html
       */
      tmp_var = build_decl (UNKNOWN_LOCATION, VAR_DECL, NULL, ptr_type_node);
      DECL_ARTIFICIAL (tmp_var) = true;
      DECL_IGNORED_P (tmp_var) = true;
      TREE_USED (tmp_var) = true;
      push_decl (tmp_var);

      /*
       * The functions
       *   build_function_call_expr
       *
       * were eliminated in newer versions of GCC. See
       *   http://patchwork.ozlabs.org/patch/57555/
       *   http://patchwork.ozlabs.org/patch/57906/
       *   http://patchwork.ozlabs.org/patch/57911/
       *   http://patchwork.ozlabs.org/patch/57962/
       *
       *
       */

      /* Create the save stmt.  */
      /*
       * build_function_call_expr was removed with patch 57962
       *   http://patchwork.ozlabs.org/patch/57962/
       *
       * The signature was
       *   build_function_call_expr (location_t loc, tree fndecl, tree arglist)
       * A new function build_call_expr_loc_vec was introduced.
       * See examples in the patch how to replace that function.
       */
      save_call = build_call_expr_loc
    		  (UNKNOWN_LOCATION,
    		   implicit_built_in_decls[BUILT_IN_STACK_SAVE],
    		   0);
      save = build2 (MODIFY_EXPR, ptr_type_node, tmp_var, save_call);
      TREE_SIDE_EFFECTS (save) = true;

      /* Create the restore stmt.  */
      restore = build_call_expr_loc
    		  (UNKNOWN_LOCATION,
    		   implicit_built_in_decls[BUILT_IN_STACK_RESTORE],
    		   1,
    		   tmp_var);

      /* Build a try-finally block.
	 The statement list is the block of current statements.  */
      t = build2 (TRY_FINALLY_EXPR, void_type_node, cur_stmts, NULL_TREE);
      TREE_SIDE_EFFECTS (t) = true;

      /* The finally block is the restore stmt.  */
      append_to_statement_list (restore, &TREE_OPERAND (t, 1));

      /* The body of the BIND_BLOCK is the save stmt, followed by the
	 try block.  */
      BIND_EXPR_BODY (res) = NULL_TREE;
      append_to_statement_list (save, &BIND_EXPR_BODY (res));
      append_to_statement_list (t, &BIND_EXPR_BODY (res));
    }
  else
    {
      /* The body of the BIND_BLOCK is the statement block.  */
      BIND_EXPR_BODY (res) = cur_stmts;
    }
  BIND_EXPR_VARS (res) = cur->first_decl;

  BLOCK_SUBBLOCKS (cur->block) = cur->first_block;
  BLOCK_VARS (cur->block) = cur->first_decl;

  cur_binding_level = cur->prev;
  cur->prev = old_binding_levels;
  old_binding_levels = cur;

  return res;
}
예제 #19
0
파일: ortho-lang.c 프로젝트: Jonsba/ghdl
static tree
pop_binding (void)
{
  tree res;
  struct binding_level *cur;

  cur = cur_binding_level;
  res = cur->bind;

  if (cur->save_stack)
    {
      tree tmp_var;
      tree save;
      tree save_call;
      tree restore;
      tree t;

      /* Create an artificial var to save the stack pointer.  */
      tmp_var = build_decl (input_location, VAR_DECL, NULL, ptr_type_node);
      DECL_ARTIFICIAL (tmp_var) = true;
      DECL_IGNORED_P (tmp_var) = true;
      TREE_USED (tmp_var) = true;
      pushdecl (tmp_var);

      /* Create the save stmt.  */
      save_call = build_call_expr
	(builtin_decl_implicit (BUILT_IN_STACK_SAVE), 0);
      save = build2 (MODIFY_EXPR, ptr_type_node, tmp_var, save_call);
      TREE_SIDE_EFFECTS (save) = true;

      /* Create the restore stmt.  */
      restore = build_call_expr
	(builtin_decl_implicit (BUILT_IN_STACK_RESTORE), 1, tmp_var);

      /* Build a try-finally block.
	 The statement list is the block of current statements.  */
      t = build2 (TRY_FINALLY_EXPR, void_type_node, cur_stmts, NULL_TREE);
      TREE_SIDE_EFFECTS (t) = true;

      /* The finally block is the restore stmt.  */
      append_to_statement_list (restore, &TREE_OPERAND (t, 1));

      /* The body of the BIND_BLOCK is the save stmt, followed by the
	 try block.  */
      BIND_EXPR_BODY (res) = NULL_TREE;
      append_to_statement_list (save, &BIND_EXPR_BODY (res));
      append_to_statement_list (t, &BIND_EXPR_BODY (res));
    }
  else
    {
      /* The body of the BIND_BLOCK is the statement block.  */
      BIND_EXPR_BODY (res) = cur_stmts;
    }
  BIND_EXPR_VARS (res) = cur->first_decl;

  BLOCK_SUBBLOCKS (cur->block) = cur->first_block;
  BLOCK_VARS (cur->block) = cur->first_decl;

  /* Set current statements list and current binding.  */
  cur_stmts = cur->prev_stmts;
  cur_binding_level = cur->prev;

  /* Put removed binding to the recycle list.  */
  cur->prev = old_binding_levels;
  old_binding_levels = cur;

  return res;
}
예제 #20
0
static tree
cp_expand_cond_array_notations (tree orig_stmt)
{
  vec<tree, va_gc> *array_list = NULL, *array_operand = NULL;
  size_t list_size = 0;
  size_t rank = 0, ii = 0;
  tree an_init, body, stmt = NULL_TREE;
  tree builtin_loop, new_var = NULL_TREE;
  tree loop_with_init = alloc_stmt_list ();
  location_t location = UNKNOWN_LOCATION;
  vec<vec<an_parts> > an_info = vNULL;
  auto_vec<an_loop_parts> an_loop_info;

  if (TREE_CODE (orig_stmt) == COND_EXPR)
    {
      size_t cond_rank = 0, yes_rank = 0, no_rank = 0;
      tree yes_expr = COND_EXPR_THEN (orig_stmt);
      tree no_expr = COND_EXPR_ELSE (orig_stmt);
      tree cond = COND_EXPR_COND (orig_stmt);
      if (!find_rank (EXPR_LOCATION (cond), cond, cond, true, &cond_rank)
	  || !find_rank (EXPR_LOCATION (yes_expr), yes_expr, yes_expr, true,
			 &yes_rank)
	  || find_rank (EXPR_LOCATION (no_expr), no_expr, no_expr, true,
			&no_rank))
	return error_mark_node;
      /* If the condition has a zero rank, then handle array notations in body
	 separately.  */
      if (cond_rank == 0)
	return orig_stmt;
      if (cond_rank != yes_rank && yes_rank != 0)
	{
	  error_at (EXPR_LOCATION (yes_expr), "rank mismatch with controlling"
		    " expression of parent if-statement");
	  return error_mark_node;
	}
      else if (cond_rank != no_rank && no_rank != 0)
	{
	  error_at (EXPR_LOCATION (no_expr), "rank mismatch with controlling "
		    "expression of parent if-statement");
	  return error_mark_node;
	}
    }
  else if (TREE_CODE (orig_stmt) == IF_STMT)
    {
      size_t cond_rank = 0, yes_rank = 0, no_rank = 0;
      tree yes_expr = THEN_CLAUSE (orig_stmt);
      tree no_expr = ELSE_CLAUSE (orig_stmt);
      tree cond = IF_COND (orig_stmt);
      if (!find_rank (EXPR_LOCATION (cond), cond, cond, true, &cond_rank)
	  || (yes_expr
	      && !find_rank (EXPR_LOCATION (yes_expr), yes_expr, yes_expr, true,
			     &yes_rank))
	  || (no_expr
	      && !find_rank (EXPR_LOCATION (no_expr), no_expr, no_expr, true,
			     &no_rank)))
	return error_mark_node;

      /* Same reasoning as for COND_EXPR.  */
      if (cond_rank == 0)
	return orig_stmt;
      else if (cond_rank != yes_rank && yes_rank != 0)
	{
	  error_at (EXPR_LOCATION (yes_expr), "rank mismatch with controlling"
		    " expression of parent if-statement");
	  return error_mark_node;
	}
      else if (cond_rank != no_rank && no_rank != 0)
	{
	  error_at (EXPR_LOCATION (no_expr), "rank mismatch with controlling "
		    "expression of parent if-statement");
	  return error_mark_node;
	}
    }
  else if (truth_value_p (TREE_CODE (orig_stmt)))
    {
      size_t left_rank = 0, right_rank = 0;
      tree left_expr = TREE_OPERAND (orig_stmt, 0);
      tree right_expr = TREE_OPERAND (orig_stmt, 1);
      if (!find_rank (EXPR_LOCATION (left_expr), left_expr, left_expr, true,
		      &left_rank)
	  || !find_rank (EXPR_LOCATION (right_expr), right_expr, right_expr,
			 true, &right_rank))
	return error_mark_node;
      if (right_rank == 0 && left_rank == 0)
	return orig_stmt;
    }

  if (!find_rank (EXPR_LOCATION (orig_stmt), orig_stmt, orig_stmt, true,
		  &rank))
    return error_mark_node;
  if (rank == 0)
    return orig_stmt;

  extract_array_notation_exprs (orig_stmt, false, &array_list);
  stmt = alloc_stmt_list ();
  for (ii = 0; ii < vec_safe_length (array_list); ii++)
    {
      tree array_node = (*array_list)[ii];
      if (TREE_CODE (array_node) == CALL_EXPR
	  || TREE_CODE (array_node) == AGGR_INIT_EXPR)
	{
	  builtin_loop = expand_sec_reduce_builtin (array_node, &new_var);
	  if (builtin_loop == error_mark_node)
	    finish_expr_stmt (error_mark_node);
	  else if (new_var)
	    {
	      vec<tree, va_gc> *sub_list = NULL, *new_var_list = NULL;
	      vec_safe_push (sub_list, array_node);
	      vec_safe_push (new_var_list, new_var);
	      replace_array_notations (&orig_stmt, false, sub_list,
				       new_var_list);
	      append_to_statement_list (builtin_loop, &stmt);
	    }
	}
    }
  append_to_statement_list (orig_stmt, &stmt);
  rank = 0;
  array_list = NULL;
  if (!find_rank (EXPR_LOCATION (stmt), stmt, stmt, true, &rank))
    return error_mark_node;
  if (rank == 0)
    return stmt;
  
  extract_array_notation_exprs (stmt, true, &array_list);
  list_size = vec_safe_length (array_list);
  if (list_size == 0)
    return stmt;

  location = EXPR_LOCATION (orig_stmt);
  list_size = vec_safe_length (array_list);
  an_loop_info.safe_grow_cleared (rank);
  
  an_init = push_stmt_list ();

  /* Assign the array notation components to variable so that they can
     satisfy the exec-once rule.  */
  for (ii = 0; ii < list_size; ii++)
    {
      tree anode = (*array_list)[ii];
      make_triplet_val_inv (&ARRAY_NOTATION_START (anode));
      make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (anode));
      make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (anode));
    }
  cilkplus_extract_an_triplets (array_list, list_size, rank, &an_info);

  for (ii = 0; ii < rank; ii++) 
    {
      tree typ = ptrdiff_type_node;
      an_loop_info[ii].var = create_temporary_var (typ);
      add_decl_expr (an_loop_info[ii].var);
      an_loop_info[ii].ind_init =
	build_x_modify_expr (location, an_loop_info[ii].var, INIT_EXPR,
			     build_zero_cst (typ), tf_warning_or_error);
    }
  array_operand = create_array_refs (location, an_info, an_loop_info,
				     list_size, rank);
  replace_array_notations (&stmt, true, array_list, array_operand);
  create_cmp_incr (location, &an_loop_info, rank, an_info, tf_warning_or_error);
  
  an_init = pop_stmt_list (an_init);
  append_to_statement_list (an_init, &loop_with_init);
  body = stmt;

  for (ii = 0; ii < rank; ii++)
    {
      tree new_loop = push_stmt_list ();
      create_an_loop (an_loop_info[ii].ind_init, an_loop_info[ii].cmp,
		      an_loop_info[ii].incr, body);
      body = pop_stmt_list (new_loop);
    }
  append_to_statement_list (body, &loop_with_init);

  release_vec_vec (an_info);
  
  return loop_with_init;
}
예제 #21
0
static tree
expand_unary_array_notation_exprs (tree orig_stmt)
{
  vec<tree, va_gc> *array_list = NULL, *array_operand = NULL;
  size_t list_size = 0, rank = 0, ii = 0;
  tree body;
  tree builtin_loop, stmt = NULL_TREE, new_var = NULL_TREE;
  location_t location = EXPR_LOCATION (orig_stmt);
  tree an_init, loop_with_init = alloc_stmt_list ();
  vec<vec<an_parts> > an_info = vNULL;
  auto_vec<an_loop_parts> an_loop_info;
  
  if (!find_rank (location, orig_stmt, orig_stmt, true, &rank))
    return error_mark_node;
  if (rank == 0)
    return orig_stmt;  
  
  extract_array_notation_exprs (orig_stmt, false, &array_list);
  list_size = vec_safe_length (array_list);
  location = EXPR_LOCATION (orig_stmt);
  stmt = NULL_TREE;
  for (ii = 0; ii < list_size; ii++)
    if (TREE_CODE ((*array_list)[ii]) == CALL_EXPR
	|| TREE_CODE ((*array_list)[ii]) == AGGR_INIT_EXPR)
      {
	tree list_node = (*array_list)[ii];
	builtin_loop = expand_sec_reduce_builtin (list_node, &new_var);
	if (builtin_loop == error_mark_node)
	  return error_mark_node;
	else if (builtin_loop)
	  {
	    vec<tree, va_gc> *sub_list = NULL, *new_var_list = NULL;
	    stmt = alloc_stmt_list ();
	    append_to_statement_list (builtin_loop, &stmt);
	    vec_safe_push (sub_list, list_node);
	    vec_safe_push (new_var_list, new_var);
	    replace_array_notations (&orig_stmt, false, sub_list, new_var_list);
	  }	
      }
  if (stmt != NULL_TREE)
    append_to_statement_list (finish_expr_stmt (orig_stmt), &stmt);
  else
    stmt = orig_stmt;
  rank = 0;
  list_size = 0;
  array_list = NULL;
  extract_array_notation_exprs (stmt, true, &array_list);
  list_size = vec_safe_length (array_list);

  if (!find_rank (EXPR_LOCATION (stmt), stmt, stmt, true, &rank))
    return error_mark_node;
  if (rank == 0 || list_size == 0)
    return stmt;
  an_loop_info.safe_grow_cleared (rank);
  an_init = push_stmt_list ();  
    /* Assign the array notation components to variable so that they can satisfy
     the exec-once rule.  */
  for (ii = 0; ii < list_size; ii++)
    {
      tree array_node = (*array_list)[ii];
      make_triplet_val_inv (&ARRAY_NOTATION_START (array_node));
      make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (array_node));
      make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (array_node));
    }
  cilkplus_extract_an_triplets (array_list, list_size, rank, &an_info);
  
  for (ii = 0; ii < rank; ii++)
    {
      tree typ = ptrdiff_type_node;
      an_loop_info[ii].var = create_temporary_var (typ);
      add_decl_expr (an_loop_info[ii].var);
      an_loop_info[ii].ind_init = build_x_modify_expr
	(location, an_loop_info[ii].var, INIT_EXPR, build_zero_cst (typ), 
	 tf_warning_or_error);
    }
  array_operand = create_array_refs (location, an_info, an_loop_info,
				     list_size, rank);
  replace_array_notations (&stmt, true, array_list, array_operand);
  create_cmp_incr (location, &an_loop_info, rank, an_info, tf_warning_or_error);
  
  an_init = pop_stmt_list (an_init);
  append_to_statement_list (an_init, &loop_with_init);
  body = stmt;
  
  for (ii = 0; ii < rank; ii++)
    {
      tree new_loop = push_stmt_list ();
      create_an_loop (an_loop_info[ii].ind_init, an_loop_info[ii].cmp,
		      an_loop_info[ii].incr, body);
      body = pop_stmt_list (new_loop);
    }
  append_to_statement_list (body, &loop_with_init);

  release_vec_vec (an_info);

  return loop_with_init;
}
예제 #22
0
static tree
expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
{
  tree new_var_type = NULL_TREE, func_parm, new_yes_expr, new_no_expr;
  tree array_ind_value = NULL_TREE, new_no_ind, new_yes_ind, new_no_list;
  tree new_yes_list, new_cond_expr, new_expr = NULL_TREE; 
  vec<tree, va_gc> *array_list = NULL, *array_operand = NULL;
  size_t list_size = 0, rank = 0, ii = 0;
  tree  body, an_init, loop_with_init = alloc_stmt_list ();
  tree array_op0, comp_node = NULL_TREE;
  tree call_fn = NULL_TREE, identity_value = NULL_TREE;
  tree init = NULL_TREE, cond_init = NULL_TREE;
  enum tree_code code = NOP_EXPR;
  location_t location = UNKNOWN_LOCATION;
  vec<vec<an_parts> > an_info = vNULL;
  auto_vec<an_loop_parts> an_loop_info;
  enum built_in_function an_type =
    is_cilkplus_reduce_builtin (CALL_EXPR_FN (an_builtin_fn));
  vec <tree, va_gc> *func_args;
  
  if (an_type == BUILT_IN_NONE)
    return NULL_TREE;

  if (an_type != BUILT_IN_CILKPLUS_SEC_REDUCE
      && an_type != BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING)
    func_parm = CALL_EXPR_ARG (an_builtin_fn, 0);
  else
    {
      call_fn = CALL_EXPR_ARG (an_builtin_fn, 2);

      /* We need to do this because we are "faking" the builtin function types,
	 so the compiler does a bunch of typecasts and this will get rid of
	 all that!  */
      STRIP_NOPS (call_fn);
      if (TREE_CODE (call_fn) != OVERLOAD
	  && TREE_CODE (call_fn) != FUNCTION_DECL)
	call_fn = TREE_OPERAND (call_fn, 0);
      identity_value = CALL_EXPR_ARG (an_builtin_fn, 0);
      func_parm = CALL_EXPR_ARG (an_builtin_fn, 1);
      STRIP_NOPS (identity_value);
    }
  STRIP_NOPS (func_parm);
  
  location = EXPR_LOCATION (an_builtin_fn);
  
  /* Note about using find_rank (): If find_rank returns false, then it must
     have already reported an error, thus we just return an error_mark_node
     without any doing any error emission.  */  
  if (!find_rank (location, an_builtin_fn, an_builtin_fn, true, &rank))
      return error_mark_node;
  if (rank == 0)
    {
      error_at (location, "Invalid builtin arguments");
      return error_mark_node;
    }
  else if (rank > 1 
	   && (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
	       || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND))
    { 
      error_at (location, "__sec_reduce_min_ind or __sec_reduce_max_ind cannot "
		"have arrays with dimension greater than 1");
      return error_mark_node;
    }
  
  extract_array_notation_exprs (func_parm, true, &array_list);
  list_size = vec_safe_length (array_list);
  switch (an_type)
    {
    case BUILT_IN_CILKPLUS_SEC_REDUCE_ADD:
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MUL:
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX:
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN:
      new_var_type = TREE_TYPE ((*array_list)[0]);
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO:
    case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO:
    case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_NONZERO:
    case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO:
      new_var_type = boolean_type_node;
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND:
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND:
      new_var_type = size_type_node;
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE:
      if (call_fn && identity_value)
	new_var_type = TREE_TYPE ((*array_list)[0]);
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING:
      new_var_type = NULL_TREE;
      break;
    default:
      gcc_unreachable ();
    }
    
  if (new_var_type && TREE_CODE (new_var_type) == ARRAY_TYPE)
    new_var_type = TREE_TYPE (new_var_type);
  an_loop_info.safe_grow_cleared (rank);

  an_init = push_stmt_list ();

  /* Assign the array notation components to variable so that they can satisfy
     the exec-once rule.  */
  for (ii = 0; ii < list_size; ii++)
    if (TREE_CODE ((*array_list)[ii]) == ARRAY_NOTATION_REF)
      {
	tree anode = (*array_list)[ii];
	make_triplet_val_inv (&ARRAY_NOTATION_START (anode));
	make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (anode));
	make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (anode));
      }
  cilkplus_extract_an_triplets (array_list, list_size, rank, &an_info);
  for (ii = 0; ii < rank; ii++)
    {
      tree typ = ptrdiff_type_node;

      /* In this place, we are using get_temp_regvar instead of 
	 create_temporary_var if an_type is SEC_REDUCE_MAX/MIN_IND because
	 the array_ind_value depends on this value being initalized to 0.  */
      if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
	  || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND) 
	an_loop_info[ii].var = get_temp_regvar (typ, build_zero_cst (typ));
      else
	{
	  an_loop_info[ii].var = create_temporary_var (typ);
	  add_decl_expr (an_loop_info[ii].var);
	}
      an_loop_info[ii].ind_init = 
	build_x_modify_expr (location, an_loop_info[ii].var, INIT_EXPR,
			     build_zero_cst (typ), tf_warning_or_error);
    }
  array_operand = create_array_refs (location, an_info, an_loop_info,
				      list_size, rank);
  replace_array_notations (&func_parm, true, array_list, array_operand);
  
  if (!TREE_TYPE (func_parm))      
    TREE_TYPE (func_parm) = TREE_TYPE ((*array_list)[0]);
  
  create_cmp_incr (location, &an_loop_info, rank, an_info, tf_warning_or_error);
  if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
      || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND) 
    array_ind_value = get_temp_regvar (TREE_TYPE (func_parm), func_parm);

  array_op0 = (*array_operand)[0];
  if (INDIRECT_REF_P (array_op0))
    array_op0 = TREE_OPERAND (array_op0, 0);
  switch (an_type)
    {
    case BUILT_IN_CILKPLUS_SEC_REDUCE_ADD:
      code = PLUS_EXPR;
      init = build_zero_cst (new_var_type);
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MUL:
      code = MULT_EXPR;
      init = build_one_cst (new_var_type);
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO:
    case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_NONZERO:
      code = ((an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO) ? EQ_EXPR
	: NE_EXPR);
      init = build_zero_cst (new_var_type);
      cond_init = build_one_cst (new_var_type);
      comp_node = build_zero_cst (TREE_TYPE (func_parm));
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO:
    case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO:
      code = ((an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO) ? NE_EXPR
	: EQ_EXPR);
      init = build_one_cst (new_var_type);
      cond_init = build_zero_cst (new_var_type);
      comp_node = build_zero_cst (TREE_TYPE (func_parm));
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX:
      code = MAX_EXPR;
      init = (TYPE_MIN_VALUE (new_var_type) ? TYPE_MIN_VALUE (new_var_type)
	: func_parm);
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN:
      code = MIN_EXPR;
      init = (TYPE_MAX_VALUE (new_var_type) ? TYPE_MAX_VALUE (new_var_type)
	: func_parm);
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND:
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND:
      code = (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND ? LE_EXPR
	: GE_EXPR);
      init = an_loop_info[0].var;
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE:
      init = identity_value;
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING:
      init = NULL_TREE;
      break;
    default:
      gcc_unreachable ();
    }

  if (an_type != BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING)
    *new_var = get_temp_regvar (new_var_type, init);
  else
    *new_var = NULL_TREE;

  switch (an_type)
    {
    case BUILT_IN_CILKPLUS_SEC_REDUCE_ADD:
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MUL:      
      new_expr = build_x_modify_expr (location, *new_var, code, func_parm,
				      tf_warning_or_error);
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO:
    case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO:
    case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO:
    case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_NONZERO:
      /* In all these cases, assume the false case is true and as soon as
	 we find a true case,  set the true flag on and latch it in.  */
      new_yes_expr = build_x_modify_expr (location, *new_var, NOP_EXPR,
					  cond_init, tf_warning_or_error);
      new_no_expr = build_x_modify_expr (location, *new_var, NOP_EXPR,
					 *new_var, tf_warning_or_error);
      new_cond_expr = build_x_binary_op
	(location, code, func_parm, TREE_CODE (func_parm), comp_node,
	 TREE_CODE (comp_node), NULL, tf_warning_or_error);
      new_expr = build_x_conditional_expr (location, new_cond_expr,
					   new_yes_expr, new_no_expr,
					   tf_warning_or_error);
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX:
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN:
      new_cond_expr = build_x_binary_op
	(location, code, *new_var, TREE_CODE (*new_var), func_parm,
	 TREE_CODE (func_parm), NULL, tf_warning_or_error);
      new_expr = build_x_modify_expr (location, *new_var, NOP_EXPR, func_parm,
				      tf_warning_or_error);
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND:
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND:
      new_yes_expr = build_x_modify_expr (location, array_ind_value, NOP_EXPR,
					  func_parm, tf_warning_or_error);
      new_no_expr = build_x_modify_expr (location, array_ind_value, NOP_EXPR,
					 array_ind_value, tf_warning_or_error);
      if (list_size > 1)
	new_yes_ind = build_x_modify_expr (location, *new_var, NOP_EXPR,
					   an_loop_info[0].var,
					   tf_warning_or_error);
      else
	new_yes_ind = build_x_modify_expr (location, *new_var, NOP_EXPR,
					   TREE_OPERAND (array_op0, 1),
					   tf_warning_or_error);
      new_no_ind = build_x_modify_expr (location, *new_var, NOP_EXPR, *new_var,
					tf_warning_or_error);
      new_yes_list = alloc_stmt_list ();
      append_to_statement_list (new_yes_ind, &new_yes_list);
      append_to_statement_list (new_yes_expr, &new_yes_list);

      new_no_list = alloc_stmt_list ();
      append_to_statement_list (new_no_ind, &new_no_list);
      append_to_statement_list (new_no_expr, &new_no_list);

      new_cond_expr = build_x_binary_op (location, code, array_ind_value,
					 TREE_CODE (array_ind_value), func_parm,
					 TREE_CODE (func_parm), NULL,
					 tf_warning_or_error);
      new_expr = build_x_conditional_expr (location, new_cond_expr,
					   new_yes_list, new_no_list,
					   tf_warning_or_error);
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE:
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING:
      func_args = make_tree_vector ();
      if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE)
	vec_safe_push (func_args, *new_var);
      else
	vec_safe_push (func_args, identity_value);
      vec_safe_push (func_args, func_parm);

      new_expr = finish_call_expr (call_fn, &func_args, false, true,
				   tf_warning_or_error);
      if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE)
	new_expr = build_x_modify_expr (location, *new_var, NOP_EXPR, new_expr,
					tf_warning_or_error);
      release_tree_vector (func_args);
      break;
    default:
      gcc_unreachable ();
    }
  an_init = pop_stmt_list (an_init);
  append_to_statement_list (an_init, &loop_with_init);
  body = new_expr;

  for (ii = 0; ii < rank; ii++)
    {
      tree new_loop = push_stmt_list ();
      create_an_loop (an_loop_info[ii].ind_init, an_loop_info[ii].cmp,
		      an_loop_info[ii].incr, body);
      body = pop_stmt_list (new_loop);
    }
  append_to_statement_list (body, &loop_with_init);

  release_vec_vec (an_info);

  return loop_with_init;
}
예제 #23
0
static tree
expand_an_in_modify_expr (location_t location, tree lhs,
			  enum tree_code modifycode, tree rhs,
			  tsubst_flags_t complain)
{
  tree array_expr_lhs = NULL_TREE, array_expr_rhs = NULL_TREE;
  tree array_expr = NULL_TREE;
  tree body = NULL_TREE;
  auto_vec<tree> cond_expr;
  vec<tree, va_gc> *lhs_array_operand = NULL, *rhs_array_operand = NULL;
  size_t lhs_rank = 0, rhs_rank = 0, ii = 0;
  vec<tree, va_gc> *rhs_list = NULL, *lhs_list = NULL;
  size_t rhs_list_size = 0, lhs_list_size = 0;
  tree new_modify_expr, new_var = NULL_TREE, builtin_loop, scalar_mods;
  bool found_builtin_fn = false;
  tree an_init, loop_with_init = alloc_stmt_list ();
  vec<vec<an_parts> > lhs_an_info = vNULL, rhs_an_info = vNULL;
  auto_vec<an_loop_parts> lhs_an_loop_info, rhs_an_loop_info;
  tree lhs_len, rhs_len;

  if (!find_rank (location, rhs, rhs, false, &rhs_rank))
    return error_mark_node;
  extract_array_notation_exprs (rhs, false, &rhs_list);
  rhs_list_size = vec_safe_length (rhs_list);
  an_init = push_stmt_list ();
  if (rhs_rank)
    {
      scalar_mods = replace_invariant_exprs (&rhs);
      if (scalar_mods)
	finish_expr_stmt (scalar_mods);
    }
  for (ii = 0; ii < rhs_list_size; ii++)
    {
      tree rhs_node = (*rhs_list)[ii];
      if (TREE_CODE (rhs_node) == CALL_EXPR)
	{
	  builtin_loop = expand_sec_reduce_builtin (rhs_node, &new_var);
	  if (builtin_loop == error_mark_node)
	    return error_mark_node;
	  else if (builtin_loop)
	    {
	      finish_expr_stmt (builtin_loop);
	      found_builtin_fn = true;
	      if (new_var)
		{
		  vec <tree, va_gc> *rhs_sub_list = NULL, *new_var_list = NULL;
		  vec_safe_push (rhs_sub_list, rhs_node);
		  vec_safe_push (new_var_list, new_var);
		  replace_array_notations (&rhs, false, rhs_sub_list,
					   new_var_list);
		}
	    }
	}
    }
  lhs_rank = 0;
  rhs_rank = 0;
  if (!find_rank (location, lhs, lhs, true, &lhs_rank)
      || !find_rank (location, rhs, rhs, true, &rhs_rank))
    {
      pop_stmt_list (an_init);
      return error_mark_node;
    }

  /* If both are scalar, then the only reason why we will get this far is if
     there is some array notations inside it and was using a builtin array
     notation functions.  If so, we have already broken those guys up and now 
     a simple build_x_modify_expr would do.  */
  if (lhs_rank == 0 && rhs_rank == 0)
    {
      if (found_builtin_fn)
	{
	  new_modify_expr = build_x_modify_expr (location, lhs,
						 modifycode, rhs, complain);
	  finish_expr_stmt (new_modify_expr);
	  pop_stmt_list (an_init);
	  return an_init;
	}
      else
	gcc_unreachable ();
    }

  /* If for some reason location is not set, then find if LHS or RHS has
     location info.  If so, then use that so we atleast have an idea.  */
  if (location == UNKNOWN_LOCATION)
    {
      if (EXPR_LOCATION (lhs) != UNKNOWN_LOCATION)
	location = EXPR_LOCATION (lhs);
      else if (EXPR_LOCATION (rhs) != UNKNOWN_LOCATION)
	location = EXPR_LOCATION (rhs);
    }
      
  /* We need this when we have a scatter issue.  */
  extract_array_notation_exprs (lhs, true, &lhs_list);
  rhs_list = NULL;
  extract_array_notation_exprs (rhs, true, &rhs_list);
  rhs_list_size = vec_safe_length (rhs_list);
  lhs_list_size = vec_safe_length (lhs_list);
    
  if (lhs_rank == 0 && rhs_rank != 0)
    {
      error_at (location, "%qE cannot be scalar when %qE is not", lhs, rhs);
      return error_mark_node;
    }
  if (lhs_rank != 0 && rhs_rank != 0 && lhs_rank != rhs_rank)
    {
      error_at (location, "rank mismatch between %qE and %qE", lhs, rhs);
      return error_mark_node;
    }
  
  /* Assign the array notation components to variable so that they can satisfy
     the execute-once rule.  */
  for (ii = 0; ii < lhs_list_size; ii++)
    {
      tree anode = (*lhs_list)[ii];
      make_triplet_val_inv (&ARRAY_NOTATION_START (anode));
      make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (anode));
      make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (anode));
    }
  for (ii = 0; ii < rhs_list_size; ii++)
    if ((*rhs_list)[ii] && TREE_CODE ((*rhs_list)[ii]) == ARRAY_NOTATION_REF)
      {
	tree aa = (*rhs_list)[ii];
	make_triplet_val_inv (&ARRAY_NOTATION_START (aa));
	make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (aa));
	make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (aa));
      }
  lhs_an_loop_info.safe_grow_cleared (lhs_rank);
  
  if (rhs_rank)
    rhs_an_loop_info.safe_grow_cleared (rhs_rank);

  cond_expr.safe_grow_cleared (MAX (lhs_rank, rhs_rank));
  cilkplus_extract_an_triplets (lhs_list, lhs_list_size, lhs_rank,
				&lhs_an_info);
  if (rhs_list)
    cilkplus_extract_an_triplets (rhs_list, rhs_list_size, rhs_rank,
				  &rhs_an_info);
  if (length_mismatch_in_expr_p (EXPR_LOCATION (lhs), lhs_an_info)
      || (rhs_list && length_mismatch_in_expr_p (EXPR_LOCATION (rhs),
						 rhs_an_info)))
    {
      pop_stmt_list (an_init);
      goto error;
    }
  rhs_len = ((rhs_list_size > 0 && rhs_rank > 0) ?
    rhs_an_info[0][0].length : NULL_TREE);
  lhs_len = ((lhs_list_size > 0 && lhs_rank > 0) ?
    lhs_an_info[0][0].length : NULL_TREE);
  if (lhs_list_size > 0 && rhs_list_size > 0 && lhs_rank > 0 && rhs_rank > 0
      && TREE_CODE (lhs_len) == INTEGER_CST && rhs_len
      && TREE_CODE (rhs_len) == INTEGER_CST 
      && !tree_int_cst_equal (rhs_len, lhs_len))
    { 
      error_at (location, "length mismatch between LHS and RHS"); 
      pop_stmt_list (an_init); 
      goto error;
    }
   for (ii = 0; ii < lhs_rank; ii++) 
     {
       tree typ = ptrdiff_type_node; 
       lhs_an_loop_info[ii].var = create_temporary_var (typ);
       add_decl_expr (lhs_an_loop_info[ii].var);
       lhs_an_loop_info[ii].ind_init = build_x_modify_expr 
	 (location, lhs_an_loop_info[ii].var, INIT_EXPR, build_zero_cst (typ), 
	  complain);
     }
   
   if (rhs_list_size > 0)
     {
       rhs_array_operand = fix_sec_implicit_args (location, rhs_list,
						  lhs_an_loop_info, lhs_rank,
						  lhs); 
       if (!rhs_array_operand)
	 goto error;
     }
  replace_array_notations (&rhs, true, rhs_list, rhs_array_operand);
  rhs_list_size = 0;
  rhs_list = NULL;
  extract_array_notation_exprs (rhs, true, &rhs_list);
  rhs_list_size = vec_safe_length (rhs_list);    

  for (ii = 0; ii < rhs_rank; ii++)
    {
      tree typ = ptrdiff_type_node;
      rhs_an_loop_info[ii].var = create_temporary_var (typ);
      add_decl_expr (rhs_an_loop_info[ii].var);
      rhs_an_loop_info[ii].ind_init = build_x_modify_expr
	(location, rhs_an_loop_info[ii].var, INIT_EXPR, build_zero_cst (typ), 
	 complain);
    }

  if (lhs_rank)
    {
      lhs_array_operand =
	create_array_refs (location, lhs_an_info, lhs_an_loop_info,
			    lhs_list_size, lhs_rank);
      replace_array_notations (&lhs, true, lhs_list, lhs_array_operand);
    }
  
  if (rhs_array_operand)
    vec_safe_truncate (rhs_array_operand, 0);
  if (rhs_rank)
    {
      rhs_array_operand = create_array_refs (location, rhs_an_info,
					      rhs_an_loop_info, rhs_list_size,
					      rhs_rank);
      /* Replace all the array refs created by the above function because this
	 variable is blown away by the fix_sec_implicit_args function below.  */
      replace_array_notations (&rhs, true, rhs_list, rhs_array_operand);
      vec_safe_truncate (rhs_array_operand , 0);
      rhs_array_operand = fix_sec_implicit_args (location, rhs_list,
						 rhs_an_loop_info, rhs_rank,
						 rhs);
      if (!rhs_array_operand)
	goto error;
      replace_array_notations (&rhs, true, rhs_list, rhs_array_operand);
    }

  array_expr_rhs = rhs;
  array_expr_lhs = lhs;
  
  array_expr = build_x_modify_expr (location, array_expr_lhs, modifycode,
				    array_expr_rhs, complain);
  create_cmp_incr (location, &lhs_an_loop_info, lhs_rank, lhs_an_info,
		   complain);
  if (rhs_rank) 
    create_cmp_incr (location, &rhs_an_loop_info, rhs_rank, rhs_an_info, 
		     complain);
  for (ii = 0; ii < MAX (rhs_rank, lhs_rank); ii++)
    if (ii < lhs_rank && ii < rhs_rank)
      cond_expr[ii] = build_x_binary_op
	(location, TRUTH_ANDIF_EXPR, lhs_an_loop_info[ii].cmp,
	 TREE_CODE (lhs_an_loop_info[ii].cmp), rhs_an_loop_info[ii].cmp,
	 TREE_CODE (rhs_an_loop_info[ii].cmp), NULL, complain);
    else if (ii < lhs_rank && ii >= rhs_rank)
      cond_expr[ii] = lhs_an_loop_info[ii].cmp;
    else
      /* No need to compare ii < rhs_rank && ii >= lhs_rank because in a valid 
	 Array notation expression, rank of RHS cannot be greater than LHS.  */
      gcc_unreachable ();
  
  an_init = pop_stmt_list (an_init);
  append_to_statement_list (an_init, &loop_with_init);
  body = array_expr;
  for (ii = 0; ii < MAX (lhs_rank, rhs_rank); ii++)
    {
      tree incr_list = alloc_stmt_list ();
      tree init_list = alloc_stmt_list ();
      tree new_loop = push_stmt_list ();

      if (lhs_rank)
	{
	  append_to_statement_list (lhs_an_loop_info[ii].ind_init, &init_list);
	  append_to_statement_list (lhs_an_loop_info[ii].incr, &incr_list);
	}
      if (rhs_rank)
	{
	  append_to_statement_list (rhs_an_loop_info[ii].ind_init, &init_list);
	  append_to_statement_list (rhs_an_loop_info[ii].incr, &incr_list);
	}
      create_an_loop (init_list, cond_expr[ii], incr_list, body);
      body = pop_stmt_list (new_loop);
    }
  append_to_statement_list (body, &loop_with_init);

  release_vec_vec (lhs_an_info);
  release_vec_vec (rhs_an_info);

  return loop_with_init;

error:
  release_vec_vec (lhs_an_info);
  release_vec_vec (rhs_an_info);

  return error_mark_node;
}
예제 #24
0
static tree
fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)
{
  tree new_var_type = NULL_TREE, func_parm, new_expr, new_yes_expr, new_no_expr;
  tree array_ind_value = NULL_TREE, new_no_ind, new_yes_ind, new_no_list;
  tree new_yes_list, new_cond_expr, new_var_init = NULL_TREE;
  tree new_exp_init = NULL_TREE;
  vec<tree, va_gc> *array_list = NULL, *array_operand = NULL;
  size_t list_size = 0, rank = 0, ii = 0;
  tree loop_init, array_op0;
  tree identity_value = NULL_TREE, call_fn = NULL_TREE, new_call_expr, body;
  location_t location = UNKNOWN_LOCATION;
  tree loop_with_init = alloc_stmt_list ();
  vec<vec<an_parts> > an_info = vNULL;
  vec<an_loop_parts> an_loop_info = vNULL;
  enum built_in_function an_type =
    is_cilkplus_reduce_builtin (CALL_EXPR_FN (an_builtin_fn));
  if (an_type == BUILT_IN_NONE)
    return NULL_TREE;

  /* Builtin call should contain at least one argument.  */
  if (call_expr_nargs (an_builtin_fn) == 0)
    {
      error_at (EXPR_LOCATION (an_builtin_fn), "Invalid builtin arguments");
      return error_mark_node;
    }

  if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE
      || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING)
    {
      call_fn = CALL_EXPR_ARG (an_builtin_fn, 2);
      if (TREE_CODE (call_fn) == ADDR_EXPR)
	call_fn = TREE_OPERAND (call_fn, 0);
      identity_value = CALL_EXPR_ARG (an_builtin_fn, 0);
      func_parm = CALL_EXPR_ARG (an_builtin_fn, 1);
    }
  else
    func_parm = CALL_EXPR_ARG (an_builtin_fn, 0);
  
  /* Fully fold any EXCESSIVE_PRECISION EXPR that can occur in the function
     parameter.  */
  func_parm = c_fully_fold (func_parm, false, NULL);
  if (func_parm == error_mark_node)
    return error_mark_node;
  
  location = EXPR_LOCATION (an_builtin_fn);
  
  if (!find_rank (location, an_builtin_fn, an_builtin_fn, true, &rank))
    return error_mark_node;
 
  if (rank == 0)
    {
      error_at (location, "Invalid builtin arguments");
      return error_mark_node;
    }
  else if (rank > 1 
	   && (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
	       || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND))
    {
      error_at (location, "__sec_reduce_min_ind or __sec_reduce_max_ind cannot"
		" have arrays with dimension greater than 1");
      return error_mark_node;
    }
  
  extract_array_notation_exprs (func_parm, true, &array_list);
  list_size = vec_safe_length (array_list);
  switch (an_type)
    {
    case BUILT_IN_CILKPLUS_SEC_REDUCE_ADD:
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MUL:
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX:
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN:
      new_var_type = TREE_TYPE ((*array_list)[0]);
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO:
    case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO:
    case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO:
    case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_NONZERO:
      new_var_type = integer_type_node;
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND:
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND:
      new_var_type = integer_type_node;
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE:
      if (call_fn && identity_value) 
	new_var_type = TREE_TYPE ((*array_list)[0]);
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING:
      new_var_type = NULL_TREE;
      break;
    default:
      gcc_unreachable (); 
    }

  an_loop_info.safe_grow_cleared (rank);
  cilkplus_extract_an_triplets (array_list, list_size, rank, &an_info);
  loop_init = alloc_stmt_list ();

  for (ii = 0; ii < rank; ii++)
    {
      an_loop_info[ii].var = create_tmp_var (integer_type_node);
      an_loop_info[ii].ind_init =
	build_modify_expr (location, an_loop_info[ii].var,
			   TREE_TYPE (an_loop_info[ii].var), NOP_EXPR,
			   location,
			   build_int_cst (TREE_TYPE (an_loop_info[ii].var), 0),
			   TREE_TYPE (an_loop_info[ii].var));	
    }
  array_operand = create_array_refs (location, an_info, an_loop_info,
				     list_size, rank);
  replace_array_notations (&func_parm, true, array_list, array_operand);

  create_cmp_incr (location, &an_loop_info, rank, an_info);
  if (an_type != BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING)
    {
      *new_var = build_decl (location, VAR_DECL, NULL_TREE, new_var_type);
      gcc_assert (*new_var && *new_var != error_mark_node);
    }
  else
    *new_var = NULL_TREE;
  
  if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
      || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND)
    array_ind_value = build_decl (location, VAR_DECL, NULL_TREE, 
				  TREE_TYPE (func_parm));
  array_op0 = (*array_operand)[0];
  if (TREE_CODE (array_op0) == INDIRECT_REF)
    array_op0 = TREE_OPERAND (array_op0, 0);
  switch (an_type)
    {
    case BUILT_IN_CILKPLUS_SEC_REDUCE_ADD:
      new_var_init = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	 location, build_zero_cst (new_var_type), new_var_type);
      new_expr = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), PLUS_EXPR,
	 location, func_parm, TREE_TYPE (func_parm));
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MUL:
      new_var_init = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	 location, build_one_cst (new_var_type), new_var_type);
      new_expr = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), MULT_EXPR,
	 location, func_parm, TREE_TYPE (func_parm));
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO:
      new_var_init = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	 location, build_one_cst (new_var_type), new_var_type);
      /* Initially you assume everything is zero, now if we find a case where 
	 it is NOT true, then we set the result to false. Otherwise 
	 we just keep the previous value.  */
      new_yes_expr = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	 location, build_zero_cst (TREE_TYPE (*new_var)),
	 TREE_TYPE (*new_var));
      new_no_expr = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	 location, *new_var, TREE_TYPE (*new_var));
      new_cond_expr = build2 (NE_EXPR, TREE_TYPE (func_parm), func_parm,
			      build_zero_cst (TREE_TYPE (func_parm)));
      new_expr = build_conditional_expr
	(location, new_cond_expr, false, new_yes_expr,
	 TREE_TYPE (new_yes_expr), new_no_expr, TREE_TYPE (new_no_expr));
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO:
      new_var_init = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	 location, build_one_cst (new_var_type), new_var_type);
      /* Initially you assume everything is non-zero, now if we find a case
	 where it is NOT true, then we set the result to false.  Otherwise
	 we just keep the previous value.  */
      new_yes_expr = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	 location, build_zero_cst (TREE_TYPE (*new_var)),
	 TREE_TYPE (*new_var));
      new_no_expr = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	 location, *new_var, TREE_TYPE (*new_var));
      new_cond_expr = build2 (EQ_EXPR, TREE_TYPE (func_parm), func_parm,
			      build_zero_cst (TREE_TYPE (func_parm)));
      new_expr = build_conditional_expr
	(location, new_cond_expr, false, new_yes_expr,
	 TREE_TYPE (new_yes_expr), new_no_expr, TREE_TYPE (new_no_expr));
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO:
      new_var_init = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	 location, build_zero_cst (new_var_type), new_var_type);
      /* Initially we assume there are NO zeros in the list. When we find 
	 a non-zero, we keep the previous value.  If we find a zero, we 
	 set the value to true.  */
      new_yes_expr = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	 location, build_one_cst (new_var_type), new_var_type);
      new_no_expr = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	 location, *new_var, TREE_TYPE (*new_var));
      new_cond_expr = build2 (EQ_EXPR, TREE_TYPE (func_parm), func_parm,
			      build_zero_cst (TREE_TYPE (func_parm)));
      new_expr = build_conditional_expr
	(location, new_cond_expr, false, new_yes_expr,
	 TREE_TYPE (new_yes_expr), new_no_expr, TREE_TYPE (new_no_expr));   
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_NONZERO:
      new_var_init = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	 location, build_zero_cst (new_var_type), new_var_type);
      /* Initially we assume there are NO non-zeros in the list. When we find 
	 a zero, we keep the previous value.  If we find a non-zero, we set 
	 the value to true.  */
      new_yes_expr = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	 location, build_one_cst (new_var_type), new_var_type);
      new_no_expr = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	 location, *new_var, TREE_TYPE (*new_var));
      new_cond_expr = build2 (NE_EXPR, TREE_TYPE (func_parm), func_parm,
			      build_zero_cst (TREE_TYPE (func_parm)));
      new_expr = build_conditional_expr
	(location, new_cond_expr, false, new_yes_expr,
	 TREE_TYPE (new_yes_expr), new_no_expr, TREE_TYPE (new_no_expr));   
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX:
      if (TYPE_MIN_VALUE (new_var_type))
	new_var_init = build_modify_expr
	  (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	   location, TYPE_MIN_VALUE (new_var_type), new_var_type);
      else
	new_var_init = build_modify_expr
	  (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	   location, func_parm, new_var_type);
      new_no_expr = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	 location, *new_var, TREE_TYPE (*new_var));
      new_yes_expr = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	 location, func_parm, TREE_TYPE (*new_var));
      new_expr = build_conditional_expr
	(location,
	 build2 (LT_EXPR, TREE_TYPE (*new_var), *new_var, func_parm), false,
	 new_yes_expr, TREE_TYPE (*new_var), new_no_expr, TREE_TYPE (*new_var));
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN:
      if (TYPE_MAX_VALUE (new_var_type))
	new_var_init = build_modify_expr
	  (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	   location, TYPE_MAX_VALUE (new_var_type), new_var_type);
      else
	new_var_init = build_modify_expr
	  (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	   location, func_parm, new_var_type);
      new_no_expr = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	 location, *new_var, TREE_TYPE (*new_var));
      new_yes_expr = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	 location, func_parm, TREE_TYPE (*new_var));
      new_expr = build_conditional_expr
	(location,
	 build2 (GT_EXPR, TREE_TYPE (*new_var), *new_var, func_parm), false,
	 new_yes_expr, TREE_TYPE (*new_var), new_no_expr, TREE_TYPE (*new_var));
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND:
      new_var_init = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	 location, build_zero_cst (new_var_type), new_var_type);
      new_exp_init = build_modify_expr
	(location, array_ind_value, TREE_TYPE (array_ind_value),
	 NOP_EXPR, location, func_parm, TREE_TYPE (func_parm));
      new_no_ind = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	 location, *new_var, TREE_TYPE (*new_var));
      new_no_expr = build_modify_expr
	(location, array_ind_value, TREE_TYPE (array_ind_value),
	 NOP_EXPR,
	 location, array_ind_value, TREE_TYPE (array_ind_value));
      if (list_size > 1)
	{
	  new_yes_ind = build_modify_expr
	    (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	     location, an_loop_info[0].var, TREE_TYPE (an_loop_info[0].var));
	  new_yes_expr = build_modify_expr
	    (location, array_ind_value, TREE_TYPE (array_ind_value),
	     NOP_EXPR,
	     location, func_parm, TREE_TYPE ((*array_operand)[0]));
	}
      else
	{
	  new_yes_ind = build_modify_expr
	    (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	     location, TREE_OPERAND (array_op0, 1),
	     TREE_TYPE (TREE_OPERAND (array_op0, 1)));
	  new_yes_expr = build_modify_expr
	    (location, array_ind_value, TREE_TYPE (array_ind_value),
	     NOP_EXPR,
	     location, func_parm, TREE_OPERAND (array_op0, 1));
	}
      new_yes_list = alloc_stmt_list ();
      append_to_statement_list (new_yes_ind, &new_yes_list);
      append_to_statement_list (new_yes_expr, &new_yes_list);

      new_no_list = alloc_stmt_list ();
      append_to_statement_list (new_no_ind, &new_no_list);
      append_to_statement_list (new_no_expr, &new_no_list);
 
      new_expr = build_conditional_expr
	(location,
	 build2 (LE_EXPR, TREE_TYPE (array_ind_value), array_ind_value,
		 func_parm),
	 false,
	 new_yes_list, TREE_TYPE (*new_var), new_no_list, TREE_TYPE (*new_var));
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND:
      new_var_init = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	 location, build_zero_cst (new_var_type), new_var_type);
      new_exp_init = build_modify_expr
	(location, array_ind_value, TREE_TYPE (array_ind_value),
	 NOP_EXPR, location, func_parm, TREE_TYPE (func_parm));
      new_no_ind = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	 location, *new_var, TREE_TYPE (*new_var));
      new_no_expr = build_modify_expr
	(location, array_ind_value, TREE_TYPE (array_ind_value),
	 NOP_EXPR,
	 location, array_ind_value, TREE_TYPE (array_ind_value));
      if (list_size > 1)
	{
	  new_yes_ind = build_modify_expr
	    (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	     location, an_loop_info[0].var, TREE_TYPE (an_loop_info[0].var));
	  new_yes_expr = build_modify_expr
	    (location, array_ind_value, TREE_TYPE (array_ind_value),
	     NOP_EXPR,
	     location, func_parm, TREE_TYPE (array_op0));
	}
      else
	{
	  new_yes_ind = build_modify_expr
	    (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	     location, TREE_OPERAND (array_op0, 1),
	     TREE_TYPE (TREE_OPERAND (array_op0, 1)));
	  new_yes_expr = build_modify_expr
	    (location, array_ind_value, TREE_TYPE (array_ind_value),
	     NOP_EXPR,
	     location, func_parm, TREE_OPERAND (array_op0, 1));
	}
      new_yes_list = alloc_stmt_list ();
      append_to_statement_list (new_yes_ind, &new_yes_list);
      append_to_statement_list (new_yes_expr, &new_yes_list);

      new_no_list = alloc_stmt_list ();
      append_to_statement_list (new_no_ind, &new_no_list);
      append_to_statement_list (new_no_expr, &new_no_list);
 
      new_expr = build_conditional_expr
	(location,
	 build2 (GE_EXPR, TREE_TYPE (array_ind_value), array_ind_value,
		 func_parm),
	 false,
	 new_yes_list, TREE_TYPE (*new_var), new_no_list, TREE_TYPE (*new_var));
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE:
      new_var_init = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	 location, identity_value, new_var_type);
      new_call_expr = build_call_expr (call_fn, 2, *new_var, func_parm);
      new_expr = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	 location, new_call_expr, TREE_TYPE (*new_var));
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING:
      new_expr = build_call_expr (call_fn, 2, identity_value, func_parm);
      break;
    default:
      gcc_unreachable ();
      break;
    }

  for (ii = 0; ii < rank; ii++)
    append_to_statement_list (an_loop_info[ii].ind_init, &loop_init);

  if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
      || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND)
    append_to_statement_list (new_exp_init, &loop_init);
  if (an_type != BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING)
    append_to_statement_list (new_var_init, &loop_init);

  append_to_statement_list_force (loop_init, &loop_with_init);
  body = new_expr;
  for (ii = 0; ii < rank; ii++)
    {
      tree new_loop = push_stmt_list ();
      c_finish_loop (location, an_loop_info[ii].cmp, an_loop_info[ii].incr,
		     body, NULL_TREE, NULL_TREE, true);
      body = pop_stmt_list (new_loop);
    }
  append_to_statement_list_force (body, &loop_with_init);

  an_info.release ();
  an_loop_info.release ();
  
  return loop_with_init;
}
예제 #25
0
static tree
expand_cilk_sync (void)
{
  tree frame = cfun->cilk_frame_decl;

  /* Cilk_sync is converted to the following code:

     sf.pedigree = sf.worker->pedigree;
     if (frame.flags & CILK_FRAME_UNSYNCHED)
     {
        __cilkrts_save_fp_state (&sf);
        if (!builtin_setjmp (sf.ctx) 
	    __cilkrts_sync (&sf); 
	else 
	   if (sf.flags & CILK_FRAME_EXCEPTING) 
	     __cilkrts_rethrow (&sf); 
      }
      sf.worker->pedigree.rank = sf.worker->pedigree.rank + 1;  */

  tree flags = cilk_dot (frame, CILK_TI_FRAME_FLAGS, false);
  
  tree unsynched = fold_build2 (BIT_AND_EXPR, TREE_TYPE (flags), flags,
				build_int_cst (TREE_TYPE (flags),
					       CILK_FRAME_UNSYNCHED));

  unsynched = fold_build2 (NE_EXPR, TREE_TYPE (unsynched), unsynched,
			   build_int_cst (TREE_TYPE (unsynched), 0));

  tree frame_addr = build1 (ADDR_EXPR, cilk_frame_ptr_type_decl, frame);

  /* Check if exception (0x10) bit is set in the sf->flags.  */
  tree except_flag = fold_build2 (BIT_AND_EXPR, TREE_TYPE (flags), flags,
				  build_int_cst (TREE_TYPE (flags),
						 CILK_FRAME_EXCEPTING));
  except_flag = fold_build2 (NE_EXPR, TREE_TYPE (except_flag), except_flag,
			     build_int_cst (TREE_TYPE (except_flag), 0));

  /* If the exception flag is set then call the __cilkrts_rethrow (&sf).  */
  tree except_cond = fold_build3 (COND_EXPR, void_type_node, except_flag,
				  build_call_expr (cilk_rethrow_fndecl, 1,
						   frame_addr),
				  build_empty_stmt (EXPR_LOCATION (unsynched)));
  
  tree sync_expr = build_call_expr (cilk_sync_fndecl, 1, frame_addr);
  tree setjmp_expr = cilk_call_setjmp (frame);
  setjmp_expr = fold_build2 (EQ_EXPR, TREE_TYPE (setjmp_expr), setjmp_expr,
			     build_int_cst (TREE_TYPE (setjmp_expr), 0));
  
  setjmp_expr = fold_build3 (COND_EXPR, void_type_node, setjmp_expr,
			     sync_expr, except_cond);
  tree sync_list = alloc_stmt_list ();
  append_to_statement_list (build_call_expr (cilk_save_fp_fndecl, 1,
					     frame_addr), &sync_list);
  append_to_statement_list (setjmp_expr, &sync_list);
  tree sync = fold_build3 (COND_EXPR, void_type_node, unsynched, sync_list,
			   build_empty_stmt (EXPR_LOCATION (unsynched)));
  tree parent_pedigree = cilk_dot (frame, CILK_TI_FRAME_PEDIGREE, false);
  tree worker = cilk_dot (frame, CILK_TI_FRAME_WORKER, false);
  tree worker_pedigree = cilk_arrow (worker, CILK_TI_WORKER_PEDIGREE, false);
  tree assign_pedigree = fold_build2 (MODIFY_EXPR, void_type_node,
				      parent_pedigree, worker_pedigree);
  tree w_ped_rank = cilk_dot (unshare_expr (worker_pedigree), 
			      CILK_TI_PEDIGREE_RANK, false);
  tree incr_ped_rank = fold_build2 (PLUS_EXPR, TREE_TYPE (w_ped_rank),
				    w_ped_rank,
				    build_one_cst (TREE_TYPE (w_ped_rank)));
  incr_ped_rank = fold_build2 (MODIFY_EXPR, void_type_node, w_ped_rank,
			       incr_ped_rank);
  tree ret_sync_exp = alloc_stmt_list ();
  append_to_statement_list (assign_pedigree, &ret_sync_exp);
  append_to_statement_list (sync, &ret_sync_exp);
  append_to_statement_list (incr_ped_rank, &ret_sync_exp);
  return ret_sync_exp;
}
예제 #26
0
static tree
cxx_omp_clause_apply_fn (tree fn, tree arg1, tree arg2)
{
  tree defparm, parm, t;
  int i = 0;
  int nargs;
  tree *argarray;

  if (fn == NULL)
    return NULL;

  nargs = list_length (DECL_ARGUMENTS (fn));
  argarray = (tree *) alloca (nargs * sizeof (tree));

  defparm = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fn)));
  if (arg2)
    defparm = TREE_CHAIN (defparm);

  if (TREE_CODE (TREE_TYPE (arg1)) == ARRAY_TYPE)
    {
      tree inner_type = TREE_TYPE (arg1);
      tree start1, end1, p1;
      tree start2 = NULL, p2 = NULL;
      tree ret = NULL, lab;

      start1 = arg1;
      start2 = arg2;
      do
	{
	  inner_type = TREE_TYPE (inner_type);
	  start1 = build4 (ARRAY_REF, inner_type, start1,
			   size_zero_node, NULL, NULL);
	  if (arg2)
	    start2 = build4 (ARRAY_REF, inner_type, start2,
			     size_zero_node, NULL, NULL);
	}
      while (TREE_CODE (inner_type) == ARRAY_TYPE);
      start1 = build_fold_addr_expr (start1);
      if (arg2)
	start2 = build_fold_addr_expr (start2);

      end1 = TYPE_SIZE_UNIT (TREE_TYPE (arg1));
      end1 = build2 (POINTER_PLUS_EXPR, TREE_TYPE (start1), start1, end1);

      p1 = create_tmp_var (TREE_TYPE (start1), NULL);
      t = build2 (MODIFY_EXPR, TREE_TYPE (p1), p1, start1);
      append_to_statement_list (t, &ret);

      if (arg2)
	{
	  p2 = create_tmp_var (TREE_TYPE (start2), NULL);
	  t = build2 (MODIFY_EXPR, TREE_TYPE (p2), p2, start2);
	  append_to_statement_list (t, &ret);
	}

      lab = create_artificial_label ();
      t = build1 (LABEL_EXPR, void_type_node, lab);
      append_to_statement_list (t, &ret);

      argarray[i++] = p1;
      if (arg2)
	argarray[i++] = p2;
      /* Handle default arguments.  */
      for (parm = defparm; parm && parm != void_list_node;
	   parm = TREE_CHAIN (parm), i++)
	argarray[i] = convert_default_arg (TREE_VALUE (parm),
					   TREE_PURPOSE (parm), fn, i);
      t = build_call_a (fn, i, argarray);
      t = fold_convert (void_type_node, t);
      t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
      append_to_statement_list (t, &ret);

      t = TYPE_SIZE_UNIT (inner_type);
      t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (p1), p1, t);
      t = build2 (MODIFY_EXPR, TREE_TYPE (p1), p1, t);
      append_to_statement_list (t, &ret);

      if (arg2)
	{
	  t = TYPE_SIZE_UNIT (inner_type);
	  t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (p2), p2, t);
	  t = build2 (MODIFY_EXPR, TREE_TYPE (p2), p2, t);
	  append_to_statement_list (t, &ret);
	}

      t = build2 (NE_EXPR, boolean_type_node, p1, end1);
      t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&lab), NULL);
      append_to_statement_list (t, &ret);

      return ret;
    }
  else
    {
      argarray[i++] = build_fold_addr_expr (arg1);
      if (arg2)
	argarray[i++] = build_fold_addr_expr (arg2);
      /* Handle default arguments.  */
      for (parm = defparm; parm && parm != void_list_node;
	   parm = TREE_CHAIN (parm), i++)
	argarray[i] = convert_default_arg (TREE_VALUE (parm),
					   TREE_PURPOSE (parm),
					   fn, i);
      t = build_call_a (fn, i, argarray);
      t = fold_convert (void_type_node, t);
      return fold_build_cleanup_point_expr (TREE_TYPE (t), t);
    }
}
예제 #27
0
static tree
gimplify_cp_loop (tree cond, tree body, tree incr, bool cond_is_first)
{
  tree top, entry, exit, cont_block, break_block, stmt_list, t;
  location_t stmt_locus;

  stmt_locus = input_location;
  stmt_list = NULL_TREE;
  entry = NULL_TREE;

  break_block = begin_bc_block (bc_break);
  cont_block = begin_bc_block (bc_continue);

  /* If condition is zero don't generate a loop construct.  */
  if (cond && integer_zerop (cond))
    {
      top = NULL_TREE;
      exit = NULL_TREE;
      if (cond_is_first)
	{
	  t = build_bc_goto (bc_break);
	  append_to_statement_list (t, &stmt_list);
	}
    }
  else
    {
      /* If we use a LOOP_EXPR here, we have to feed the whole thing
	 back through the main gimplifier to lower it.  Given that we
	 have to gimplify the loop body NOW so that we can resolve
	 break/continue stmts, seems easier to just expand to gotos.  */
      top = build1 (LABEL_EXPR, void_type_node, NULL_TREE);

      /* If we have an exit condition, then we build an IF with gotos either
	 out of the loop, or to the top of it.  If there's no exit condition,
	 then we just build a jump back to the top.  */
      exit = build_and_jump (&LABEL_EXPR_LABEL (top));
      if (cond && !integer_nonzerop (cond))
	{
	  t = build_bc_goto (bc_break);
	  exit = build3 (COND_EXPR, void_type_node, cond, exit, t);
	  exit = fold (exit);
	  gimplify_stmt (&exit);

	  if (cond_is_first)
	    {
	      if (incr)
		{
		  entry = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
		  t = build_and_jump (&LABEL_EXPR_LABEL (entry));
		}
	      else
		t = build_bc_goto (bc_continue);
	      append_to_statement_list (t, &stmt_list);
	    }
	}
    }

  gimplify_stmt (&body);
  gimplify_stmt (&incr);

  body = finish_bc_block (bc_continue, cont_block, body);

  append_to_statement_list (top, &stmt_list);
  append_to_statement_list (body, &stmt_list);
  append_to_statement_list (incr, &stmt_list);
  append_to_statement_list (entry, &stmt_list);
  append_to_statement_list (exit, &stmt_list);

  annotate_all_with_locus (&stmt_list, stmt_locus);

  return finish_bc_block (bc_break, break_block, stmt_list);
}
예제 #28
0
파일: cp-gimplify.c 프로젝트: didemoto/gcc
static void
genericize_cp_loop (tree *stmt_p, location_t start_locus, tree cond, tree body,
		    tree incr, bool cond_is_first, int *walk_subtrees,
		    void *data)
{
  tree blab, clab;
  tree entry = NULL, exit = NULL, t;
  tree stmt_list = NULL;

  blab = begin_bc_block (bc_break, start_locus);
  clab = begin_bc_block (bc_continue, start_locus);

  if (incr && EXPR_P (incr))
    SET_EXPR_LOCATION (incr, start_locus);

  cp_walk_tree (&cond, cp_genericize_r, data, NULL);
  cp_walk_tree (&body, cp_genericize_r, data, NULL);
  cp_walk_tree (&incr, cp_genericize_r, data, NULL);
  *walk_subtrees = 0;

  /* If condition is zero don't generate a loop construct.  */
  if (cond && integer_zerop (cond))
    {
      if (cond_is_first)
	{
	  t = build1_loc (start_locus, GOTO_EXPR, void_type_node,
			  get_bc_label (bc_break));
	  append_to_statement_list (t, &stmt_list);
	}
    }
  else
    {
      /* Expand to gotos, just like c_finish_loop.  TODO: Use LOOP_EXPR.  */
      tree top = build1 (LABEL_EXPR, void_type_node,
			 create_artificial_label (start_locus));

      /* If we have an exit condition, then we build an IF with gotos either
	 out of the loop, or to the top of it.  If there's no exit condition,
	 then we just build a jump back to the top.  */
      exit = build1 (GOTO_EXPR, void_type_node, LABEL_EXPR_LABEL (top));

      if (cond && !integer_nonzerop (cond))
	{
	  /* Canonicalize the loop condition to the end.  This means
	     generating a branch to the loop condition.  Reuse the
	     continue label, if possible.  */
	  if (cond_is_first)
	    {
	      if (incr)
		{
		  entry = build1 (LABEL_EXPR, void_type_node,
				  create_artificial_label (start_locus));
		  t = build1_loc (start_locus, GOTO_EXPR, void_type_node,
				  LABEL_EXPR_LABEL (entry));
		}
	      else
		t = build1_loc (start_locus, GOTO_EXPR, void_type_node,
				get_bc_label (bc_continue));
	      append_to_statement_list (t, &stmt_list);
	    }

	  t = build1 (GOTO_EXPR, void_type_node, get_bc_label (bc_break));
	  exit = fold_build3_loc (start_locus,
				  COND_EXPR, void_type_node, cond, exit, t);
	}

      append_to_statement_list (top, &stmt_list);
    }

  append_to_statement_list (body, &stmt_list);
  finish_bc_block (&stmt_list, bc_continue, clab);
  append_to_statement_list (incr, &stmt_list);
  append_to_statement_list (entry, &stmt_list);
  append_to_statement_list (exit, &stmt_list);
  finish_bc_block (&stmt_list, bc_break, blab);

  if (stmt_list == NULL_TREE)
    stmt_list = build1 (NOP_EXPR, void_type_node, integer_zero_node);

  *stmt_p = stmt_list;
}
예제 #29
0
파일: tree-mudflap.c 프로젝트: 0mp/freebsd
/* Emit any file-wide instrumentation.  */
void
mudflap_finish_file (void)
{
  tree ctor_statements = NULL_TREE;

  /* No need to continue when there were errors.  */
  if (errorcount != 0 || sorrycount != 0)
    return;

  /* Insert a call to __mf_init.  */
  {
    tree call2_stmt = build_function_call_expr (mf_init_fndecl, NULL_TREE);
    append_to_statement_list (call2_stmt, &ctor_statements);
  }
  
  /* If appropriate, call __mf_set_options to pass along read-ignore mode.  */
  if (flag_mudflap_ignore_reads)
    {
      tree arg = tree_cons (NULL_TREE, 
                            mf_build_string ("-ignore-reads"), NULL_TREE);
      tree call_stmt = build_function_call_expr (mf_set_options_fndecl, arg);
      append_to_statement_list (call_stmt, &ctor_statements);
    }

  /* Process all enqueued object decls.  */
  if (deferred_static_decls)
    {
      size_t i;
      tree obj;
      for (i = 0; VEC_iterate (tree, deferred_static_decls, i, obj); i++)
        {
          gcc_assert (DECL_P (obj));

          if (mf_marked_p (obj))
            continue;

          /* Omit registration for static unaddressed objects.  NB:
             Perform registration for non-static objects regardless of
             TREE_USED or TREE_ADDRESSABLE, because they may be used
             from other compilation units.  */
          if (! TREE_PUBLIC (obj) && ! TREE_ADDRESSABLE (obj))
            continue;

          if (! COMPLETE_TYPE_P (TREE_TYPE (obj)))
            {
              warning (0, "mudflap cannot track unknown size extern %qs",
                       IDENTIFIER_POINTER (DECL_NAME (obj)));
              continue;
            }
          
          mudflap_register_call (obj, 
                                 size_in_bytes (TREE_TYPE (obj)),
                                 mf_varname_tree (obj));
        }

      VEC_truncate (tree, deferred_static_decls, 0);
    }

  /* Append all the enqueued registration calls.  */
  if (enqueued_call_stmt_chain)
    {
      append_to_statement_list (enqueued_call_stmt_chain, &ctor_statements);
      enqueued_call_stmt_chain = NULL_TREE;
    }

  cgraph_build_static_cdtor ('I', ctor_statements, 
                             MAX_RESERVED_INIT_PRIORITY-1);
}
예제 #30
0
파일: tree-mudflap.c 프로젝트: 0mp/freebsd
/* Synthesize a CALL_EXPR and a TRY_FINALLY_EXPR, for this chain of
   _DECLs if appropriate.  Arrange to call the __mf_register function
   now, and the __mf_unregister function later for each.  */
static void
mx_register_decls (tree decl, tree *stmt_list)
{
  tree finally_stmts = NULL_TREE;
  tree_stmt_iterator initially_stmts = tsi_start (*stmt_list);

  while (decl != NULL_TREE)
    {
      if (mf_decl_eligible_p (decl) 
          /* Not already processed.  */
          && ! mf_marked_p (decl)
          /* Automatic variable.  */
          && ! DECL_EXTERNAL (decl)
          && ! TREE_STATIC (decl))
        {
          tree size = NULL_TREE, variable_name;
          tree unregister_fncall, unregister_fncall_params;
          tree register_fncall, register_fncall_params;

	  size = convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (decl)));

          /* (& VARIABLE, sizeof (VARIABLE), __MF_TYPE_STACK) */
          unregister_fncall_params =
            tree_cons (NULL_TREE,
                       convert (ptr_type_node,
                                mf_mark (build1 (ADDR_EXPR,
                                                 build_pointer_type (TREE_TYPE (decl)),
                                                 decl))),
                       tree_cons (NULL_TREE, 
                                  size,
                                  tree_cons (NULL_TREE,
					     /* __MF_TYPE_STACK */
                                             build_int_cst (NULL_TREE, 3),
                                             NULL_TREE)));
          /* __mf_unregister (...) */
          unregister_fncall = build_function_call_expr (mf_unregister_fndecl,
                                                        unregister_fncall_params);

          /* (& VARIABLE, sizeof (VARIABLE), __MF_TYPE_STACK, "name") */
          variable_name = mf_varname_tree (decl);
          register_fncall_params =
            tree_cons (NULL_TREE,
                   convert (ptr_type_node,
                            mf_mark (build1 (ADDR_EXPR,
                                             build_pointer_type (TREE_TYPE (decl)),
                                             decl))),
                       tree_cons (NULL_TREE,
                                  size,
                                  tree_cons (NULL_TREE,
					     /* __MF_TYPE_STACK */
                                             build_int_cst (NULL_TREE, 3),
                                             tree_cons (NULL_TREE,
                                                        variable_name,
                                                        NULL_TREE))));

          /* __mf_register (...) */
          register_fncall = build_function_call_expr (mf_register_fndecl,
                                                      register_fncall_params);

          /* Accumulate the two calls.  */
          /* ??? Set EXPR_LOCATION.  */
          gimplify_stmt (&register_fncall);
          gimplify_stmt (&unregister_fncall);

          /* Add the __mf_register call at the current appending point.  */
          if (tsi_end_p (initially_stmts))
	    warning (0, "mudflap cannot track %qs in stub function",
		     IDENTIFIER_POINTER (DECL_NAME (decl)));
	  else
	    {
	      tsi_link_before (&initially_stmts, register_fncall, TSI_SAME_STMT);

	      /* Accumulate the FINALLY piece.  */
	      append_to_statement_list (unregister_fncall, &finally_stmts);
	    }
          mf_mark (decl);
        }

      decl = TREE_CHAIN (decl);
    }

  /* Actually, (initially_stmts!=NULL) <=> (finally_stmts!=NULL) */
  if (finally_stmts != NULL_TREE)
    {
      tree t = build2 (TRY_FINALLY_EXPR, void_type_node,
                       *stmt_list, finally_stmts);
      *stmt_list = NULL;
      append_to_statement_list (t, stmt_list);
    }
}