Пример #1
0
/* this function does the transformation involved in replacing an
 * expression */
static void replace_expression(expr_t* expr,mloop_t* mloop) {
  symboltable_t *new_temp;
  expr_t *new_expr;
  char *new_id = (char *)malloc(10);
  statement_t *body=T_MLOOP_BODY(mloop);

  /* drop out if replacement expr already exists */
  if (find_replacement(mloop, expr)) return;

  /* create a new temporary variable */
  sprintf(new_id,"__temp%d",idnum);
  new_temp = alloc_loc_st (S_VARIABLE,new_id);
  S_DTYPE(new_temp) = T_TYPEINFO(expr);
  S_VAR_INIT(new_temp) = NULL;
  S_INIT(new_temp) = build_init(expr,NULL);
  S_PROHIBITIONS(new_temp) |= TILED_OUTER_MLOOP_FLAG;
  new_expr = build_0ary_op(VARIABLE,new_temp);
  idnum++;

  /* replace the variable */
  T_ADD_MLOOP_VAR (mloop, new_temp, T_MLOOP_ORDER(mloop, T_MLOOP_RANK(mloop)-1));
  replace_expr(expr, copy_expr(new_expr));
  /*add_replacement(mloop,copy_expr(expr),copy_expr(new_expr));*/

  /* if necessary, reassign the variable */
  if (is_written(new_expr,body)) {
    statement_t* post;
    expr_t* reassign;
    reassign=build_binary_op(BIASSIGNMENT,copy_expr(new_expr),copy_expr(expr));
    post=build_expr_statement(reassign,T_LINENO(body),T_FILENAME(body));
    T_PROHIBITIONS(post) |= TILED_OUTER_MLOOP_FLAG;
    T_ADD_MLOOP_POST(mloop,post,T_MLOOP_ORDER(mloop, T_MLOOP_RANK(mloop)-1));
  }
} /* replace_expression(expr,mloop) */
Пример #2
0
tree
c_finish_omp_atomic (location_t loc, enum tree_code code,
		     enum tree_code opcode, tree lhs, tree rhs,
		     tree v, tree lhs1, tree rhs1, bool swapped, bool seq_cst)
{
  tree x, type, addr, pre = NULL_TREE;

  if (lhs == error_mark_node || rhs == error_mark_node
      || v == error_mark_node || lhs1 == error_mark_node
      || rhs1 == error_mark_node)
    return error_mark_node;

  /* ??? According to one reading of the OpenMP spec, complex type are
     supported, but there are no atomic stores for any architecture.
     But at least icc 9.0 doesn't support complex types here either.
     And lets not even talk about vector types...  */
  type = TREE_TYPE (lhs);
  if (!INTEGRAL_TYPE_P (type)
      && !POINTER_TYPE_P (type)
      && !SCALAR_FLOAT_TYPE_P (type))
    {
      error_at (loc, "invalid expression type for %<#pragma omp atomic%>");
      return error_mark_node;
    }

  if (opcode == RDIV_EXPR)
    opcode = TRUNC_DIV_EXPR;

  /* ??? Validate that rhs does not overlap lhs.  */

  /* Take and save the address of the lhs.  From then on we'll reference it
     via indirection.  */
  addr = build_unary_op (loc, ADDR_EXPR, lhs, 0);
  if (addr == error_mark_node)
    return error_mark_node;
  addr = save_expr (addr);
  if (TREE_CODE (addr) != SAVE_EXPR
      && (TREE_CODE (addr) != ADDR_EXPR
	  || !VAR_P (TREE_OPERAND (addr, 0))))
    {
      /* Make sure LHS is simple enough so that goa_lhs_expr_p can recognize
	 it even after unsharing function body.  */
      tree var = create_tmp_var_raw (TREE_TYPE (addr));
      DECL_CONTEXT (var) = current_function_decl;
      addr = build4 (TARGET_EXPR, TREE_TYPE (addr), var, addr, NULL, NULL);
    }
  lhs = build_indirect_ref (loc, addr, RO_NULL);

  if (code == OMP_ATOMIC_READ)
    {
      x = build1 (OMP_ATOMIC_READ, type, addr);
      SET_EXPR_LOCATION (x, loc);
      OMP_ATOMIC_SEQ_CST (x) = seq_cst;
      return build_modify_expr (loc, v, NULL_TREE, NOP_EXPR,
				loc, x, NULL_TREE);
    }

  /* There are lots of warnings, errors, and conversions that need to happen
     in the course of interpreting a statement.  Use the normal mechanisms
     to do this, and then take it apart again.  */
  if (swapped)
    {
      rhs = build_binary_op (loc, opcode, rhs, lhs, 1);
      opcode = NOP_EXPR;
    }
  bool save = in_late_binary_op;
  in_late_binary_op = true;
  x = build_modify_expr (loc, lhs, NULL_TREE, opcode, loc, rhs, NULL_TREE);
  in_late_binary_op = save;
  if (x == error_mark_node)
    return error_mark_node;
  if (TREE_CODE (x) == COMPOUND_EXPR)
    {
      pre = TREE_OPERAND (x, 0);
      gcc_assert (TREE_CODE (pre) == SAVE_EXPR);
      x = TREE_OPERAND (x, 1);
    }
  gcc_assert (TREE_CODE (x) == MODIFY_EXPR);
  rhs = TREE_OPERAND (x, 1);

  /* Punt the actual generation of atomic operations to common code.  */
  if (code == OMP_ATOMIC)
    type = void_type_node;
  x = build2 (code, type, addr, rhs);
  SET_EXPR_LOCATION (x, loc);
  OMP_ATOMIC_SEQ_CST (x) = seq_cst;

  /* Generally it is hard to prove lhs1 and lhs are the same memory
     location, just diagnose different variables.  */
  if (rhs1
      && VAR_P (rhs1)
      && VAR_P (lhs)
      && rhs1 != lhs)
    {
      if (code == OMP_ATOMIC)
	error_at (loc, "%<#pragma omp atomic update%> uses two different variables for memory");
      else
	error_at (loc, "%<#pragma omp atomic capture%> uses two different variables for memory");
      return error_mark_node;
    }

  if (code != OMP_ATOMIC)
    {
      /* Generally it is hard to prove lhs1 and lhs are the same memory
	 location, just diagnose different variables.  */
      if (lhs1 && VAR_P (lhs1) && VAR_P (lhs))
	{
	  if (lhs1 != lhs)
	    {
	      error_at (loc, "%<#pragma omp atomic capture%> uses two different variables for memory");
	      return error_mark_node;
	    }
	}
      x = build_modify_expr (loc, v, NULL_TREE, NOP_EXPR,
			     loc, x, NULL_TREE);
      if (rhs1 && rhs1 != lhs)
	{
	  tree rhs1addr = build_unary_op (loc, ADDR_EXPR, rhs1, 0);
	  if (rhs1addr == error_mark_node)
	    return error_mark_node;
	  x = omit_one_operand_loc (loc, type, x, rhs1addr);
	}
      if (lhs1 && lhs1 != lhs)
	{
	  tree lhs1addr = build_unary_op (loc, ADDR_EXPR, lhs1, 0);
	  if (lhs1addr == error_mark_node)
	    return error_mark_node;
	  if (code == OMP_ATOMIC_CAPTURE_OLD)
	    x = omit_one_operand_loc (loc, type, x, lhs1addr);
	  else
	    {
	      x = save_expr (x);
	      x = omit_two_operands_loc (loc, type, x, x, lhs1addr);
	    }
	}
    }
  else if (rhs1 && rhs1 != lhs)
    {
      tree rhs1addr = build_unary_op (loc, ADDR_EXPR, rhs1, 0);
      if (rhs1addr == error_mark_node)
	return error_mark_node;
      x = omit_one_operand_loc (loc, type, x, rhs1addr);
    }

  if (pre)
    x = omit_one_operand_loc (loc, type, x, pre);
  return x;
}
Пример #3
0
static void gen_alloca_stmts(gimple_seq* stmts_, tree* sp_)
{
    /* doc: tree-complex.c, c-common.c, omp-low.c */

    /* create the stmt sequence so that:
       *sp = alloca(sizeof(type));
       type: the type to be stacked
       stmts: the allocation sequence
       sp: the allocated area ptr
     */

    gimple call;
    gimple_seq stmts;
    tree binop;
    tree mul;
    tree val;
    tree count;
    tree sizeuf;
    tree sp;
    tree ref;
    gimple assign;
    gimple_stmt_iterator gsi;

    /* build an empty sequence */
    stmts = gimple_seq_alloc();
    gsi = gsi_last(stmts);

#if 0 /* fixme */
    sp = create_tmp_var(ptr_type_node, NULL);
#else
    /* from varpool.c */
    sp = add_new_static_var(ptr_type_node);
#endif

    /* sp = __builtin_alloca(count * sizeof(uintptr_t)); */
    count = build_int_cst(integer_type_node, 2);
    sizeuf = build_int_cst(integer_type_node, sizeof(uintptr_t));
    mul = build2(MULT_EXPR, integer_type_node, count, sizeuf);
    /* call = gimple_build_call(built_in_decls[BUILT_IN_ALLOCA], 1, mul); */
    call = gimple_build_call(kaapi_pushdata_aligned_decl, 1, mul);
    gimple_call_set_lhs(call, sp);
    gsi_insert_after(&gsi, call, GSI_CONTINUE_LINKING);

    /* *(sp + 0) = 42; */
    ref = build1(INDIRECT_REF, TREE_TYPE(sp), sp);
    val = build_int_cst(ptr_type_node, 0xdeadc0d3);
    assign = gimple_build_assign(ref, val);
    gsi_insert_after(&gsi, assign, GSI_CONTINUE_LINKING);

    /* *(sp + 8) = 24 */
    binop = build_binary_op
            (0, PLUS_EXPR, convert(integer_type_node, sp), sizeuf, 0);
    ref = build1(INDIRECT_REF, TREE_TYPE(binop), binop);
    val = build_int_cst(ptr_type_node, 0xdeadc003);
    assign = gimple_build_assign(ref, val);
    gsi_insert_after(&gsi, assign, GSI_CONTINUE_LINKING);

    /* affect results */
    *sp_ = sp;
    *stmts_ = stmts;
}