示例#1
0
static tree
expand_return_expr (tree expr)
{
  tree new_mod_list, new_var, new_mod, retval_expr;
  size_t rank  = 0;
  location_t loc = EXPR_LOCATION (expr);
  if (TREE_CODE (expr) != RETURN_EXPR)
    return expr;
      
  if (!find_rank (loc, expr, expr, false, &rank))
    return error_mark_node;

  /* If the return expression contains array notations, then flag it as
     error.  */
  if (rank >= 1)
    {
      error_at (loc, "array notation expression cannot be used as a return "
		"value");
      return error_mark_node;
    }
  
  new_mod_list = push_stmt_list ();
  retval_expr = TREE_OPERAND (expr, 0);
  new_var = create_temporary_var (TREE_TYPE (retval_expr));
  add_decl_expr (new_var);
  new_mod = expand_an_in_modify_expr (loc, new_var, NOP_EXPR,
				      TREE_OPERAND (retval_expr, 1),
				      tf_warning_or_error);
  TREE_OPERAND (retval_expr, 1) = new_var;
  TREE_OPERAND (expr, 0) = retval_expr;
  add_stmt (new_mod);
  add_stmt (expr);
  new_mod_list = pop_stmt_list (new_mod_list);
  return new_mod_list;
}
示例#2
0
tree
replace_invariant_exprs (tree *node)
{
  size_t ix = 0;
  tree node_list = NULL_TREE;
  tree t = NULL_TREE, new_var = NULL_TREE, new_node; 
  struct inv_list data;

  data.list_values = NULL;
  data.replacement = NULL;
  data.additional_tcodes = NULL;
  walk_tree (node, find_inv_trees, (void *)&data, NULL);

  if (vec_safe_length (data.list_values))
    {
      node_list = push_stmt_list ();
      for (ix = 0; vec_safe_iterate (data.list_values, ix, &t); ix++)
	{
	  new_var = build_decl (EXPR_LOCATION (t), VAR_DECL, NULL_TREE,
				TREE_TYPE (t));
	  gcc_assert (new_var != NULL_TREE && new_var != error_mark_node);
	  new_node = build2 (MODIFY_EXPR, TREE_TYPE (t), new_var, t);
	  add_stmt (new_node);
	  vec_safe_push (data.replacement, new_var);
	}
      walk_tree (node, replace_inv_trees, (void *)&data, NULL);
      node_list = pop_stmt_list (node_list);
    }
  return node_list;
}
示例#3
0
tree
begin_eh_spec_block (void)
{
  tree r = build_stmt (EH_SPEC_BLOCK, NULL_TREE, NULL_TREE);
  add_stmt (r);
  EH_SPEC_STMTS (r) = push_stmt_list ();
  return r;
}
示例#4
0
tree
begin_eh_spec_block (void)
{
  tree r;
  location_t spec_location = DECL_SOURCE_LOCATION (current_function_decl);

  /* A noexcept specification (or throw() with -fnothrow-opt) is a
     MUST_NOT_THROW_EXPR.  */
  if (TYPE_NOEXCEPT_P (TREE_TYPE (current_function_decl)))
    {
      r = build_stmt (spec_location, MUST_NOT_THROW_EXPR,
		      NULL_TREE, NULL_TREE);
      TREE_SIDE_EFFECTS (r) = 1;
    }
  else
    r = build_stmt (spec_location, EH_SPEC_BLOCK, NULL_TREE, NULL_TREE);
  add_stmt (r);
  TREE_OPERAND (r, 0) = push_stmt_list ();
  return r;
}
示例#5
0
static tree
replace_invariant_exprs (tree *node)
{
  size_t ix = 0;
  tree node_list = NULL_TREE;
  tree t = NULL_TREE, new_var = NULL_TREE;
  struct inv_list data;

  data.list_values = NULL;
  data.replacement = NULL;
  data.additional_tcodes = NULL;
  cp_walk_tree (node, find_inv_trees, (void *) &data, NULL);

  if (vec_safe_length (data.list_values))
    {
      node_list = push_stmt_list ();
      for (ix = 0; vec_safe_iterate (data.list_values, ix, &t); ix++)
	{ 
	  /* Sometimes, when comma_expr has a function call in it, it will
	     typecast it to void.  Find_inv_trees finds those nodes and so
	     if it void type, then don't bother creating a new var to hold 
	     the return value.   */
	  if (VOID_TYPE_P (TREE_TYPE (t)))
	    {
	      finish_expr_stmt (t);
	      new_var = void_node;
	    }
	  else 
	    new_var = get_temp_regvar (TREE_TYPE (t), t); 
	  vec_safe_push (data.replacement, new_var);
	}
      cp_walk_tree (node, replace_inv_trees, (void *) &data, NULL);
      node_list = pop_stmt_list (node_list);
    }
  return node_list;
}
示例#6
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;
}
示例#7
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;
}
示例#8
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;
}
示例#9
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;
}
示例#10
0
static tree
fix_conditional_array_notations_1 (tree stmt)
{
  vec<tree, va_gc> *array_list = NULL, *array_operand = NULL;
  size_t list_size = 0;
  tree cond = NULL_TREE, builtin_loop = NULL_TREE, new_var = NULL_TREE;
  size_t rank = 0, ii = 0;
  tree loop_init;
  location_t location = EXPR_LOCATION (stmt);
  tree body = NULL_TREE, loop_with_init = alloc_stmt_list ();
  vec<vec<an_parts> > an_info = vNULL;
  vec<an_loop_parts> an_loop_info = vNULL;
 
  if (TREE_CODE (stmt) == COND_EXPR)
    cond = COND_EXPR_COND (stmt);
  else if (TREE_CODE (stmt) == SWITCH_EXPR)
    cond = SWITCH_COND (stmt);
  else if (truth_value_p (TREE_CODE (stmt)))
    cond = TREE_OPERAND (stmt, 0);
  else
    /* Otherwise dont even touch the statement.  */
    return stmt;

  if (!find_rank (location, cond, cond, false, &rank))
    return error_mark_node;
  
  extract_array_notation_exprs (stmt, false, &array_list);
  loop_init = push_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)
	{
	  builtin_loop = fix_builtin_array_notation_fn (array_node, &new_var);
	  if (builtin_loop == error_mark_node)
	    {
	      add_stmt (error_mark_node);
	      pop_stmt_list (loop_init);
	      return loop_init;
	    }
	  else if (builtin_loop)
	    {
	      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);
	      add_stmt (builtin_loop);
	      replace_array_notations (&stmt, false, sub_list, new_var_list); 
	    }
	}
    }
  if (!find_rank (location, stmt, stmt, true, &rank))
    {
      pop_stmt_list (loop_init);
      return error_mark_node;
    }
  if (rank == 0)
    {
      add_stmt (stmt);
      pop_stmt_list (loop_init); 
      return loop_init;
    }  
  extract_array_notation_exprs (stmt, true, &array_list);

  if (vec_safe_length (array_list) == 0)
    return stmt;

  list_size = vec_safe_length (array_list);
  an_loop_info.safe_grow_cleared (rank);
  
  for (ii = 0; ii < list_size; ii++)
    if ((*array_list)[ii]
	&& TREE_CODE ((*array_list)[ii]) == ARRAY_NOTATION_REF)
      {
	tree array_node = (*array_list)[ii];
	make_triplet_val_inv (location, &ARRAY_NOTATION_START (array_node));
	make_triplet_val_inv (location, &ARRAY_NOTATION_LENGTH (array_node));
	make_triplet_val_inv (location, &ARRAY_NOTATION_STRIDE (array_node));
      }
  cilkplus_extract_an_triplets (array_list, list_size, rank, &an_info);
  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 (&stmt, true, array_list, array_operand);
  create_cmp_incr (location, &an_loop_info, rank, an_info);
  
  loop_init = pop_stmt_list (loop_init);
  body = stmt;
  append_to_statement_list_force (loop_init, &loop_with_init);

  for (ii = 0; ii < rank; ii++)
    {
      tree new_loop = push_stmt_list ();
      add_stmt (an_loop_info[ii].ind_init);
      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_loop_info.release ();
  an_info.release ();

  return loop_with_init;
}
示例#11
0
tree
build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
			   enum tree_code modifycode, location_t rhs_loc,
			   tree rhs, tree rhs_origtype)
{
  bool found_builtin_fn = false;
  tree array_expr_lhs = NULL_TREE, array_expr_rhs = NULL_TREE;
  tree array_expr = NULL_TREE;
  tree an_init = NULL_TREE;
  vec<tree> cond_expr = vNULL;
  tree body, loop_with_init = alloc_stmt_list();
  tree scalar_mods = NULL_TREE;
  vec<tree, va_gc> *rhs_array_operand = NULL, *lhs_array_operand = NULL;
  size_t lhs_rank = 0, rhs_rank = 0;
  size_t ii = 0;
  vec<tree, va_gc> *lhs_list = NULL, *rhs_list = NULL;
  tree new_modify_expr, new_var = NULL_TREE, builtin_loop = NULL_TREE;
  size_t rhs_list_size = 0, lhs_list_size = 0; 
  vec<vec<an_parts> > lhs_an_info = vNULL, rhs_an_info = vNULL;
  vec<an_loop_parts> lhs_an_loop_info = vNULL, rhs_an_loop_info = vNULL;
  
  /* If either of this is true, an error message must have been send out
     already.  Not necessary to send out multiple error messages.  */
  if (lhs == error_mark_node || rhs == error_mark_node)
    return error_mark_node;
  
  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)
	add_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 = fix_builtin_array_notation_fn (rhs_node, &new_var);
	  if (builtin_loop == error_mark_node)
	    {
	      pop_stmt_list (an_init); 
	      return error_mark_node;
	    }
	  else if (builtin_loop)
	    {
	      add_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))
    {
      pop_stmt_list (an_init);
      return error_mark_node;
    }
  
  if (!find_rank (location, rhs, rhs, true, &rhs_rank))
    {
      pop_stmt_list (an_init);
      return error_mark_node;
    }

  if (lhs_rank == 0 && rhs_rank == 0)
    {
      if (found_builtin_fn)
	{
	  new_modify_expr = build_modify_expr (location, lhs, lhs_origtype,
					       modifycode, rhs_loc, rhs,
					       rhs_origtype);
	  add_stmt (new_modify_expr);
	  pop_stmt_list (an_init);	  
	  return an_init;
	}
      else
	{
	  pop_stmt_list (an_init);
	  return NULL_TREE;
	}
    }
  rhs_list_size = 0;
  rhs_list = NULL;
  extract_array_notation_exprs (rhs, true, &rhs_list);
  extract_array_notation_exprs (lhs, true, &lhs_list);
  rhs_list_size = vec_safe_length (rhs_list);
  lhs_list_size = vec_safe_length (lhs_list);
  
  if (lhs_rank == 0 && rhs_rank != 0)
    {
      tree rhs_base = rhs;
      if (TREE_CODE (rhs_base) == ARRAY_NOTATION_REF)
	{
	  for (ii = 0; ii < (size_t) rhs_rank; ii++)
	    rhs_base = ARRAY_NOTATION_ARRAY (rhs);
      
	  error_at (location, "%qE cannot be scalar when %qE is not", lhs,
		    rhs_base);
	  return error_mark_node;
	}
      else
	{
	  error_at (location, "%qE cannot be scalar when %qE is not", lhs,
		    rhs_base);
	  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);
      pop_stmt_list (an_init);
      return error_mark_node;
    }
  
  /* Here we assign the array notation components to variable so that we can
     satisfy the exec once rule.  */
  for (ii = 0; ii < lhs_list_size; ii++)
    { 
      tree array_node = (*lhs_list)[ii];
      make_triplet_val_inv (location, &ARRAY_NOTATION_START (array_node));
      make_triplet_val_inv (location, &ARRAY_NOTATION_LENGTH (array_node));
      make_triplet_val_inv (location, &ARRAY_NOTATION_STRIDE (array_node));
    }
  for (ii = 0; ii < rhs_list_size; ii++)
    if ((*rhs_list)[ii] && TREE_CODE ((*rhs_list)[ii]) == ARRAY_NOTATION_REF)
      {  
	tree array_node = (*rhs_list)[ii];
	make_triplet_val_inv (location, &ARRAY_NOTATION_START (array_node));
	make_triplet_val_inv (location, &ARRAY_NOTATION_LENGTH (array_node));
	make_triplet_val_inv (location, &ARRAY_NOTATION_STRIDE (array_node));
      }
  
  cond_expr.safe_grow_cleared (MAX (lhs_rank, rhs_rank));

  lhs_an_loop_info.safe_grow_cleared (lhs_rank);
  if (rhs_rank)
    rhs_an_loop_info.safe_grow_cleared (rhs_rank);

  cilkplus_extract_an_triplets (lhs_list, lhs_list_size, lhs_rank,
				&lhs_an_info);
  if (rhs_rank)
    {
      rhs_an_loop_info.safe_grow_cleared (rhs_rank);
      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_rank
	  && length_mismatch_in_expr_p (EXPR_LOCATION (rhs), rhs_an_info)))
    {
      pop_stmt_list (an_init);
      return error_mark_node;
    }
  if (lhs_list_size > 0 && rhs_list_size > 0 && lhs_rank > 0 && rhs_rank > 0
      && TREE_CODE (lhs_an_info[0][0].length) == INTEGER_CST
      && rhs_an_info[0][0].length
      && TREE_CODE (rhs_an_info[0][0].length) == INTEGER_CST)
    {
      HOST_WIDE_INT l_length = int_cst_value (lhs_an_info[0][0].length);
      HOST_WIDE_INT r_length = int_cst_value (rhs_an_info[0][0].length);
      /* Length can be negative or positive.  As long as the magnitude is OK,
	 then the array notation is valid.  */
      if (absu_hwi (l_length) != absu_hwi (r_length))
	{
	  error_at (location, "length mismatch between LHS and RHS");
	  pop_stmt_list (an_init);
	  return error_mark_node;
	}
    }
  for (ii = 0; ii < lhs_rank; ii++)
    if (lhs_an_info[0][ii].is_vector)
      {
	lhs_an_loop_info[ii].var = create_tmp_var (integer_type_node);
	lhs_an_loop_info[ii].ind_init = build_modify_expr
	  (location, lhs_an_loop_info[ii].var,
	   TREE_TYPE (lhs_an_loop_info[ii].var), NOP_EXPR,
	   location, build_zero_cst (TREE_TYPE (lhs_an_loop_info[ii].var)),
	   TREE_TYPE (lhs_an_loop_info[ii].var));
      }
  for (ii = 0; ii < rhs_rank; ii++)
    {
      /* When we have a polynomial, we assume that the indices are of type 
	 integer.  */
      rhs_an_loop_info[ii].var = create_tmp_var (integer_type_node);
      rhs_an_loop_info[ii].ind_init = build_modify_expr
	(location, rhs_an_loop_info[ii].var,
	 TREE_TYPE (rhs_an_loop_info[ii].var), NOP_EXPR,
	 location, build_int_cst (TREE_TYPE (rhs_an_loop_info[ii].var), 0),
	 TREE_TYPE (rhs_an_loop_info[ii].var));
    }
  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);
      array_expr_lhs = lhs;
    }
  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_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)
	return error_mark_node;
      replace_array_notations (&rhs, true, rhs_list, rhs_array_operand);
    }
  else 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)
	return error_mark_node;
      replace_array_notations (&rhs, true, rhs_list, rhs_array_operand);
    }
  array_expr_lhs = lhs;
  array_expr_rhs = rhs;
  array_expr = build_modify_expr (location, array_expr_lhs, lhs_origtype, 
				  modifycode, rhs_loc, array_expr_rhs, 
				  rhs_origtype);
  create_cmp_incr (location, &lhs_an_loop_info, lhs_rank, lhs_an_info);
  if (rhs_rank)
    create_cmp_incr (location, &rhs_an_loop_info, rhs_rank, rhs_an_info);
  
  for (ii = 0; ii < MAX (lhs_rank, rhs_rank); ii++)
    if (ii < lhs_rank && ii < rhs_rank)
      cond_expr[ii] = build2 (TRUTH_ANDIF_EXPR, boolean_type_node,
			      lhs_an_loop_info[ii].cmp,
			      rhs_an_loop_info[ii].cmp);
    else if (ii < lhs_rank && ii >= rhs_rank)
      cond_expr[ii] = lhs_an_loop_info[ii].cmp;
    else
      gcc_unreachable ();

  an_init = pop_stmt_list (an_init);
  append_to_statement_list_force (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 new_loop = push_stmt_list ();
      if (lhs_rank)
	add_stmt (lhs_an_loop_info[ii].ind_init);
      if (rhs_rank)
	add_stmt (rhs_an_loop_info[ii].ind_init);
      if (lhs_rank)
	append_to_statement_list_force (lhs_an_loop_info[ii].incr, &incr_list);
      if (rhs_rank && rhs_an_loop_info[ii].incr)
	append_to_statement_list_force (rhs_an_loop_info[ii].incr, &incr_list);
      c_finish_loop (location, cond_expr[ii], incr_list, body, NULL_TREE,
		     NULL_TREE, true);
      body = pop_stmt_list (new_loop);
    }
  append_to_statement_list_force (body, &loop_with_init);

  lhs_an_info.release ();
  lhs_an_loop_info.release ();
  if (rhs_rank)
    {
      rhs_an_info.release ();
      rhs_an_loop_info.release ();
    }
  cond_expr.release ();
  return loop_with_init;
}
示例#12
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;
}
示例#13
0
static tree
fix_array_notation_call_expr (tree arg)
{
  vec<tree, va_gc> *array_list = NULL, *array_operand = NULL;
  tree new_var = NULL_TREE;
  size_t list_size = 0, rank = 0, ii = 0;
  tree loop_init;
  tree body, loop_with_init = alloc_stmt_list ();
  location_t location = UNKNOWN_LOCATION;
  vec<vec<an_parts> > an_info = vNULL;
  vec<an_loop_parts> an_loop_info = vNULL;

  if (TREE_CODE (arg) == CALL_EXPR
      && is_cilkplus_reduce_builtin (CALL_EXPR_FN (arg)))
    {
      loop_init = fix_builtin_array_notation_fn (arg, &new_var);
      /* We are ignoring the new var because either the user does not want to
	 capture it OR he is using sec_reduce_mutating function.  */
      return loop_init;
    }  
  if (!find_rank (location, arg, arg, false, &rank))
    return error_mark_node;
  
  if (rank == 0)
    return arg;
  
  extract_array_notation_exprs (arg, true, &array_list);
  if (vec_safe_length (array_list) == 0)
    return arg;
  
  list_size = vec_safe_length (array_list);
  location = EXPR_LOCATION (arg);
  an_loop_info.safe_grow_cleared (rank);
  
  loop_init = push_stmt_list ();
  for (ii = 0; ii < list_size; ii++)
    if ((*array_list)[ii]
	&& TREE_CODE ((*array_list)[ii]) == ARRAY_NOTATION_REF)
	{
	  tree array_node = (*array_list)[ii];
	  make_triplet_val_inv (location, &ARRAY_NOTATION_START (array_node));
	  make_triplet_val_inv (location, &ARRAY_NOTATION_LENGTH (array_node));
	  make_triplet_val_inv (location, &ARRAY_NOTATION_STRIDE (array_node));
	}
  cilkplus_extract_an_triplets (array_list, list_size, rank, &an_info);
  if (length_mismatch_in_expr_p (location, an_info))
    {
      pop_stmt_list (loop_init);
      return error_mark_node;
    }
  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 (&arg, true, array_list, array_operand);
  create_cmp_incr (location, &an_loop_info, rank, an_info);
  loop_init = pop_stmt_list (loop_init);
  append_to_statement_list_force (loop_init, &loop_with_init);
  body = arg;
  for (ii = 0; ii < rank; ii++)
    {
      tree new_loop = push_stmt_list ();
      add_stmt (an_loop_info[ii].ind_init);
      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_loop_info.release ();
  an_info.release ();
  return loop_with_init;
}
示例#14
0
struct c_expr 
fix_array_notation_expr (location_t location, enum tree_code code,
			 struct c_expr arg)
{

  vec<tree, va_gc> *array_list = NULL, *array_operand = NULL;
  size_t list_size = 0, rank = 0, ii = 0;
  tree loop_init;
  tree body, loop_with_init = alloc_stmt_list ();
  vec<vec<an_parts> > an_info = vNULL;
  vec<an_loop_parts> an_loop_info = vNULL;
  
  if (!find_rank (location, arg.value, arg.value, false, &rank))
    {
      /* If this function returns a NULL, we convert the tree value in the
	 structure to error_mark_node and the parser should take care of the
	 rest.  */
      arg.value = error_mark_node;
      return arg;
    }
  
  if (rank == 0)
    return arg;
  
  extract_array_notation_exprs (arg.value, true, &array_list);

  if (vec_safe_length (array_list) == 0)
    return arg;

  list_size = vec_safe_length (array_list);

  an_loop_info.safe_grow_cleared (rank);
  cilkplus_extract_an_triplets (array_list, list_size, rank, &an_info);
  
  loop_init = push_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 (&arg.value, true, array_list, array_operand);
  create_cmp_incr (location, &an_loop_info, rank, an_info);

  arg = default_function_array_read_conversion (location, arg);
  if (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR)
    arg.value = build_unary_op (location, code, arg.value, 0);
  else if (code == PREINCREMENT_EXPR || code == PREDECREMENT_EXPR)
    arg = parser_build_unary_op (location, code, arg);

  loop_init = pop_stmt_list (loop_init);
  append_to_statement_list_force (loop_init, &loop_with_init);
  body = arg.value;

  for (ii = 0; ii < rank; ii++)
    {
      tree new_loop = push_stmt_list ();
      add_stmt (an_loop_info[ii].ind_init);
      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);
  arg.value = loop_with_init;
  an_info.release ();
  an_loop_info.release ();
  return arg;
}
示例#15
0
/* FN is a constructor or destructor, and there are FUNCTION_DECLs
   cloned from it nearby.  Instead of cloning this body, leave it
   alone and create tiny one-call bodies for the cloned
   FUNCTION_DECLs.  These clones are sibcall candidates, and their
   resulting code will be very thunk-esque.  */
static void
thunk_body (tree clone, tree fn, tree clone_to_call)
{
  tree bind, block, call, fn_parm, fn_parm_typelist;
  int parmno, vtt_parmno;
  tree clone_parm, parmlist;

  for (vtt_parmno = -1, parmno = 0, fn_parm = DECL_ARGUMENTS (fn);
       fn_parm;
       ++parmno, fn_parm = TREE_CHAIN (fn_parm))
    {
      if (DECL_ARTIFICIAL (fn_parm) && DECL_NAME (fn_parm) == vtt_parm_identifier)
	{
	  vtt_parmno = parmno;	/* Compensate for removed in_charge parameter.  */
	  break;
	}
    }
  /* Currently, we are not supposed to have a vtt argument. */
  gcc_assert(vtt_parmno == -1);

  /* Walk parameter lists together, creating parameter list for call to original function.  */
  for (parmno = 0,
	 parmlist = NULL,
	 fn_parm = DECL_ARGUMENTS (fn),
	 fn_parm_typelist = TYPE_ARG_TYPES (TREE_TYPE (fn)),
	 clone_parm = DECL_ARGUMENTS (clone);
       fn_parm;
       ++parmno,
	 fn_parm = TREE_CHAIN (fn_parm))
    {
      if (parmno == vtt_parmno && ! DECL_HAS_VTT_PARM_P (clone))
	{
	  tree typed_null_pointer_node = copy_node (null_pointer_node);
	  gcc_assert (fn_parm_typelist);
	  /* Clobber actual parameter with formal parameter type.  */
	  TREE_TYPE (typed_null_pointer_node) = TREE_VALUE (fn_parm_typelist);
	  parmlist = tree_cons (NULL, typed_null_pointer_node, parmlist);
	}
      else if (parmno == 1 && DECL_HAS_IN_CHARGE_PARM_P (fn))
	{
	  /* Just skip it. */
	}
      /* Map other parameters to their equivalents in the cloned
	 function.  */
      else
	{
	  gcc_assert (clone_parm);
	  DECL_ABSTRACT_ORIGIN (clone_parm) = NULL;
	  parmlist = tree_cons (NULL, clone_parm, parmlist);
	  clone_parm = TREE_CHAIN (clone_parm);
	}
      if (fn_parm_typelist)
	fn_parm_typelist = TREE_CHAIN (fn_parm_typelist);
    }

    /* We built this list backwards; fix now.  */
    parmlist = nreverse (parmlist);

    TREE_USED (clone_to_call) = 1;
    call = build_cxx_call (clone_to_call, parmlist);

    for (parmlist = TREE_OPERAND (call, 1); parmlist; parmlist = TREE_CHAIN (parmlist))
      {
	fn_parm = TREE_VALUE (parmlist);
	/* Remove the EMPTY_CLASS_EXPR because it upsets estimate_num_insns().  */
	if (TREE_CODE (fn_parm) == COMPOUND_EXPR)
	  {
	    gcc_assert (TREE_CODE (TREE_OPERAND (fn_parm, 1)) == EMPTY_CLASS_EXPR);
	    TREE_VALUE (parmlist) = TREE_OPERAND (fn_parm, 0);
	  }
      }
    block = make_node (BLOCK);
    if (targetm.cxx.cdtor_returns_this ())
      {
	tree clone_result = DECL_RESULT (clone);
	tree modify = build2 (MODIFY_EXPR, TREE_TYPE (clone_result), clone_result, call);
	add_stmt (modify);
	BLOCK_VARS (block) = clone_result;
      }
    else
      {
	add_stmt (call);
      }
    bind = c_build_bind_expr (block, cur_stmt_list);
    DECL_SAVED_TREE (clone) = push_stmt_list ();
    add_stmt (bind);
}