Ejemplo n.º 1
0
int
oacc_get_ifn_dim_arg (const gimple *stmt)
{
  gcc_checking_assert (gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_SIZE
		       || gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_POS);
  tree arg = gimple_call_arg (stmt, 0);
  HOST_WIDE_INT axis = TREE_INT_CST_LOW (arg);

  gcc_checking_assert (axis >= 0 && axis < GOMP_DIM_MAX);
  return (int) axis;
}
Ejemplo n.º 2
0
static void
adjust_simduid_builtins (hash_table<simduid_to_vf> *htab)
{
  basic_block bb;

  FOR_EACH_BB_FN (bb, cfun)
    {
      gimple_stmt_iterator i;

      for (i = gsi_start_bb (bb); !gsi_end_p (i); gsi_next (&i))
	{
	  unsigned int vf = 1;
	  enum internal_fn ifn;
	  gimple stmt = gsi_stmt (i);
	  tree t;
	  if (!is_gimple_call (stmt)
	      || !gimple_call_internal_p (stmt))
	    continue;
	  ifn = gimple_call_internal_fn (stmt);
	  switch (ifn)
	    {
	    case IFN_GOMP_SIMD_LANE:
	    case IFN_GOMP_SIMD_VF:
	    case IFN_GOMP_SIMD_LAST_LANE:
	      break;
	    default:
	      continue;
	    }
	  tree arg = gimple_call_arg (stmt, 0);
	  gcc_assert (arg != NULL_TREE);
	  gcc_assert (TREE_CODE (arg) == SSA_NAME);
	  simduid_to_vf *p = NULL, data;
	  data.simduid = DECL_UID (SSA_NAME_VAR (arg));
	  if (htab)
	    {
	      p = htab->find (&data);
	      if (p)
		vf = p->vf;
	    }
	  switch (ifn)
	    {
	    case IFN_GOMP_SIMD_VF:
	      t = build_int_cst (unsigned_type_node, vf);
	      break;
	    case IFN_GOMP_SIMD_LANE:
	      t = build_int_cst (unsigned_type_node, 0);
	      break;
	    case IFN_GOMP_SIMD_LAST_LANE:
	      t = gimple_call_arg (stmt, 1);
	      break;
	    default:
	      gcc_unreachable ();
	    }
	  update_call_from_tree (&i, t);
	}
    }
Ejemplo n.º 3
0
void
expand_internal_call (gimple stmt)
{
  internal_fn_expanders[(int) gimple_call_internal_fn (stmt)] (stmt);
}
Ejemplo n.º 4
0
static void
output_gimple_stmt (struct output_block *ob, gimple stmt)
{
  unsigned i;
  enum gimple_code code;
  enum LTO_tags tag;
  struct bitpack_d bp;
  histogram_value hist;

  /* Emit identifying tag.  */
  code = gimple_code (stmt);
  tag = lto_gimple_code_to_tag (code);
  streamer_write_record_start (ob, tag);

  /* Emit the tuple header.  */
  bp = bitpack_create (ob->main_stream);
  bp_pack_var_len_unsigned (&bp, gimple_num_ops (stmt));
  bp_pack_value (&bp, gimple_no_warning_p (stmt), 1);
  if (is_gimple_assign (stmt))
    bp_pack_value (&bp, gimple_assign_nontemporal_move_p (stmt), 1);
  bp_pack_value (&bp, gimple_has_volatile_ops (stmt), 1);
  hist = gimple_histogram_value (cfun, stmt);
  bp_pack_value (&bp, hist != NULL, 1);
  bp_pack_var_len_unsigned (&bp, stmt->gsbase.subcode);

  /* Emit location information for the statement.  */
  stream_output_location (ob, &bp, LOCATION_LOCUS (gimple_location (stmt)));
  streamer_write_bitpack (&bp);

  /* Emit the lexical block holding STMT.  */
  stream_write_tree (ob, gimple_block (stmt), true);

  /* Emit the operands.  */
  switch (gimple_code (stmt))
    {
    case GIMPLE_RESX:
      streamer_write_hwi (ob, gimple_resx_region (stmt));
      break;

    case GIMPLE_EH_MUST_NOT_THROW:
      stream_write_tree (ob, gimple_eh_must_not_throw_fndecl (stmt), true);
      break;

    case GIMPLE_EH_DISPATCH:
      streamer_write_hwi (ob, gimple_eh_dispatch_region (stmt));
      break;

    case GIMPLE_ASM:
      streamer_write_uhwi (ob, gimple_asm_ninputs (stmt));
      streamer_write_uhwi (ob, gimple_asm_noutputs (stmt));
      streamer_write_uhwi (ob, gimple_asm_nclobbers (stmt));
      streamer_write_uhwi (ob, gimple_asm_nlabels (stmt));
      streamer_write_string (ob, ob->main_stream, gimple_asm_string (stmt),
			     true);
      /* Fallthru  */

    case GIMPLE_ASSIGN:
    case GIMPLE_CALL:
    case GIMPLE_RETURN:
    case GIMPLE_SWITCH:
    case GIMPLE_LABEL:
    case GIMPLE_COND:
    case GIMPLE_GOTO:
    case GIMPLE_DEBUG:
      for (i = 0; i < gimple_num_ops (stmt); i++)
	{
	  tree op = gimple_op (stmt, i);
	  tree *basep = NULL;
	  /* Wrap all uses of non-automatic variables inside MEM_REFs
	     so that we do not have to deal with type mismatches on
	     merged symbols during IL read in.  The first operand
	     of GIMPLE_DEBUG must be a decl, not MEM_REF, though.  */
	  if (op && (i || !is_gimple_debug (stmt)))
	    {
	      basep = &op;
	      while (handled_component_p (*basep))
		basep = &TREE_OPERAND (*basep, 0);
	      if (TREE_CODE (*basep) == VAR_DECL
		  && !auto_var_in_fn_p (*basep, current_function_decl)
		  && !DECL_REGISTER (*basep))
		{
		  bool volatilep = TREE_THIS_VOLATILE (*basep);
		  *basep = build2 (MEM_REF, TREE_TYPE (*basep),
				   build_fold_addr_expr (*basep),
				   build_int_cst (build_pointer_type
						  (TREE_TYPE (*basep)), 0));
		  TREE_THIS_VOLATILE (*basep) = volatilep;
		}
	      else
		basep = NULL;
	    }
	  stream_write_tree (ob, op, true);
	  /* Restore the original base if we wrapped it inside a MEM_REF.  */
	  if (basep)
	    *basep = TREE_OPERAND (TREE_OPERAND (*basep, 0), 0);
	}
      if (is_gimple_call (stmt))
	{
	  if (gimple_call_internal_p (stmt))
	    streamer_write_enum (ob->main_stream, internal_fn,
				 IFN_LAST, gimple_call_internal_fn (stmt));
	  else
	    stream_write_tree (ob, gimple_call_fntype (stmt), true);
	}
      break;

    case GIMPLE_NOP:
    case GIMPLE_PREDICT:
      break;

    case GIMPLE_TRANSACTION:
      gcc_assert (gimple_transaction_body (stmt) == NULL);
      stream_write_tree (ob, gimple_transaction_label (stmt), true);
      break;

    default:
      gcc_unreachable ();
    }
  if (hist)
    stream_out_histogram_value (ob, hist);
}
Ejemplo n.º 5
0
void
expr_hash_elt::print (FILE *stream)
{
  fprintf (stream, "STMT ");

  if (m_lhs)
    {
      print_generic_expr (stream, m_lhs, 0);
      fprintf (stream, " = ");
    }

  switch (m_expr.kind)
    {
      case EXPR_SINGLE:
        print_generic_expr (stream, m_expr.ops.single.rhs, 0);
        break;

      case EXPR_UNARY:
	fprintf (stream, "%s ", get_tree_code_name (m_expr.ops.unary.op));
        print_generic_expr (stream, m_expr.ops.unary.opnd, 0);
        break;

      case EXPR_BINARY:
        print_generic_expr (stream, m_expr.ops.binary.opnd0, 0);
	fprintf (stream, " %s ", get_tree_code_name (m_expr.ops.binary.op));
        print_generic_expr (stream, m_expr.ops.binary.opnd1, 0);
        break;

      case EXPR_TERNARY:
	fprintf (stream, " %s <", get_tree_code_name (m_expr.ops.ternary.op));
        print_generic_expr (stream, m_expr.ops.ternary.opnd0, 0);
	fputs (", ", stream);
        print_generic_expr (stream, m_expr.ops.ternary.opnd1, 0);
	fputs (", ", stream);
        print_generic_expr (stream, m_expr.ops.ternary.opnd2, 0);
	fputs (">", stream);
        break;

      case EXPR_CALL:
        {
          size_t i;
          size_t nargs = m_expr.ops.call.nargs;
          gcall *fn_from;

          fn_from = m_expr.ops.call.fn_from;
          if (gimple_call_internal_p (fn_from))
            fputs (internal_fn_name (gimple_call_internal_fn (fn_from)),
                   stream);
          else
            print_generic_expr (stream, gimple_call_fn (fn_from), 0);
          fprintf (stream, " (");
          for (i = 0; i < nargs; i++)
            {
              print_generic_expr (stream, m_expr.ops.call.args[i], 0);
              if (i + 1 < nargs)
                fprintf (stream, ", ");
            }
          fprintf (stream, ")");
        }
        break;

      case EXPR_PHI:
        {
          size_t i;
          size_t nargs = m_expr.ops.phi.nargs;

          fprintf (stream, "PHI <");
          for (i = 0; i < nargs; i++)
            {
              print_generic_expr (stream, m_expr.ops.phi.args[i], 0);
              if (i + 1 < nargs)
                fprintf (stream, ", ");
            }
          fprintf (stream, ">");
        }
        break;
    }

  if (m_vop)
    {
      fprintf (stream, " with ");
      print_generic_expr (stream, m_vop, 0);
    }

  fprintf (stream, "\n");
}
Ejemplo n.º 6
0
static void
add_hashable_expr (const struct hashable_expr *expr, hash &hstate)
{
  switch (expr->kind)
    {
    case EXPR_SINGLE:
      inchash::add_expr (expr->ops.single.rhs, hstate);
      break;

    case EXPR_UNARY:
      hstate.add_object (expr->ops.unary.op);

      /* Make sure to include signedness in the hash computation.
         Don't hash the type, that can lead to having nodes which
         compare equal according to operand_equal_p, but which
         have different hash codes.  */
      if (CONVERT_EXPR_CODE_P (expr->ops.unary.op)
          || expr->ops.unary.op == NON_LVALUE_EXPR)
        hstate.add_int (TYPE_UNSIGNED (expr->type));

      inchash::add_expr (expr->ops.unary.opnd, hstate);
      break;

    case EXPR_BINARY:
      hstate.add_object (expr->ops.binary.op);
      if (commutative_tree_code (expr->ops.binary.op))
	inchash::add_expr_commutative (expr->ops.binary.opnd0,
					  expr->ops.binary.opnd1, hstate);
      else
        {
          inchash::add_expr (expr->ops.binary.opnd0, hstate);
          inchash::add_expr (expr->ops.binary.opnd1, hstate);
        }
      break;

    case EXPR_TERNARY:
      hstate.add_object (expr->ops.ternary.op);
      if (commutative_ternary_tree_code (expr->ops.ternary.op))
	inchash::add_expr_commutative (expr->ops.ternary.opnd0,
					  expr->ops.ternary.opnd1, hstate);
      else
        {
          inchash::add_expr (expr->ops.ternary.opnd0, hstate);
          inchash::add_expr (expr->ops.ternary.opnd1, hstate);
        }
      inchash::add_expr (expr->ops.ternary.opnd2, hstate);
      break;

    case EXPR_CALL:
      {
        size_t i;
        enum tree_code code = CALL_EXPR;
        gcall *fn_from;

        hstate.add_object (code);
        fn_from = expr->ops.call.fn_from;
        if (gimple_call_internal_p (fn_from))
          hstate.merge_hash ((hashval_t) gimple_call_internal_fn (fn_from));
        else
          inchash::add_expr (gimple_call_fn (fn_from), hstate);
        for (i = 0; i < expr->ops.call.nargs; i++)
          inchash::add_expr (expr->ops.call.args[i], hstate);
      }
      break;

    case EXPR_PHI:
      {
        size_t i;

        for (i = 0; i < expr->ops.phi.nargs; i++)
          inchash::add_expr (expr->ops.phi.args[i], hstate);
      }
      break;

    default:
      gcc_unreachable ();
    }
}
Ejemplo n.º 7
0
static void
adjust_simduid_builtins (hash_table<simduid_to_vf> *htab)
{
  basic_block bb;

  FOR_EACH_BB_FN (bb, cfun)
    {
      gimple_stmt_iterator i;

      for (i = gsi_start_bb (bb); !gsi_end_p (i); )
	{
	  unsigned int vf = 1;
	  enum internal_fn ifn;
	  gimple *stmt = gsi_stmt (i);
	  tree t;
	  if (!is_gimple_call (stmt)
	      || !gimple_call_internal_p (stmt))
	    {
	      gsi_next (&i);
	      continue;
	    }
	  ifn = gimple_call_internal_fn (stmt);
	  switch (ifn)
	    {
	    case IFN_GOMP_SIMD_LANE:
	    case IFN_GOMP_SIMD_VF:
	    case IFN_GOMP_SIMD_LAST_LANE:
	      break;
	    case IFN_GOMP_SIMD_ORDERED_START:
	    case IFN_GOMP_SIMD_ORDERED_END:
	      if (integer_onep (gimple_call_arg (stmt, 0)))
		{
		  enum built_in_function bcode
		    = (ifn == IFN_GOMP_SIMD_ORDERED_START
		       ? BUILT_IN_GOMP_ORDERED_START
		       : BUILT_IN_GOMP_ORDERED_END);
		  gimple *g
		    = gimple_build_call (builtin_decl_explicit (bcode), 0);
		  tree vdef = gimple_vdef (stmt);
		  gimple_set_vdef (g, vdef);
		  SSA_NAME_DEF_STMT (vdef) = g;
		  gimple_set_vuse (g, gimple_vuse (stmt));
		  gsi_replace (&i, g, true);
		  continue;
		}
	      gsi_remove (&i, true);
	      unlink_stmt_vdef (stmt);
	      continue;
	    default:
	      gsi_next (&i);
	      continue;
	    }
	  tree arg = gimple_call_arg (stmt, 0);
	  gcc_assert (arg != NULL_TREE);
	  gcc_assert (TREE_CODE (arg) == SSA_NAME);
	  simduid_to_vf *p = NULL, data;
	  data.simduid = DECL_UID (SSA_NAME_VAR (arg));
	  /* Need to nullify loop safelen field since it's value is not
	     valid after transformation.  */
	  if (bb->loop_father && bb->loop_father->safelen > 0)
	    bb->loop_father->safelen = 0;
	  if (htab)
	    {
	      p = htab->find (&data);
	      if (p)
		vf = p->vf;
	    }
	  switch (ifn)
	    {
	    case IFN_GOMP_SIMD_VF:
	      t = build_int_cst (unsigned_type_node, vf);
	      break;
	    case IFN_GOMP_SIMD_LANE:
	      t = build_int_cst (unsigned_type_node, 0);
	      break;
	    case IFN_GOMP_SIMD_LAST_LANE:
	      t = gimple_call_arg (stmt, 1);
	      break;
	    default:
	      gcc_unreachable ();
	    }
	  update_call_from_tree (&i, t);
	  gsi_next (&i);
	}
    }
Ejemplo n.º 8
0
bool
gimple_simplify (gimple *stmt,
		 code_helper *rcode, tree *ops,
		 gimple_seq *seq,
		 tree (*valueize)(tree), tree (*top_valueize)(tree))
{
  switch (gimple_code (stmt))
    {
    case GIMPLE_ASSIGN:
      {
	enum tree_code code = gimple_assign_rhs_code (stmt);
	tree type = TREE_TYPE (gimple_assign_lhs (stmt));
	switch (gimple_assign_rhs_class (stmt))
	  {
	  case GIMPLE_SINGLE_RHS:
	    if (code == REALPART_EXPR
		|| code == IMAGPART_EXPR
		|| code == VIEW_CONVERT_EXPR)
	      {
		tree op0 = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0);
		bool valueized = false;
		op0 = do_valueize (op0, top_valueize, valueized);
		*rcode = code;
		ops[0] = op0;
		return (gimple_resimplify1 (seq, rcode, type, ops, valueize)
			|| valueized);
	      }
	    else if (code == BIT_FIELD_REF)
	      {
		tree rhs1 = gimple_assign_rhs1 (stmt);
		tree op0 = TREE_OPERAND (rhs1, 0);
		bool valueized = false;
		op0 = do_valueize (op0, top_valueize, valueized);
		*rcode = code;
		ops[0] = op0;
		ops[1] = TREE_OPERAND (rhs1, 1);
		ops[2] = TREE_OPERAND (rhs1, 2);
		return (gimple_resimplify3 (seq, rcode, type, ops, valueize)
			|| valueized);
	      }
	    else if (code == SSA_NAME
		     && top_valueize)
	      {
		tree op0 = gimple_assign_rhs1 (stmt);
		tree valueized = top_valueize (op0);
		if (!valueized || op0 == valueized)
		  return false;
		ops[0] = valueized;
		*rcode = TREE_CODE (op0);
		return true;
	      }
	    break;
	  case GIMPLE_UNARY_RHS:
	    {
	      tree rhs1 = gimple_assign_rhs1 (stmt);
	      bool valueized = false;
	      rhs1 = do_valueize (rhs1, top_valueize, valueized);
	      *rcode = code;
	      ops[0] = rhs1;
	      return (gimple_resimplify1 (seq, rcode, type, ops, valueize)
		      || valueized);
	    }
	  case GIMPLE_BINARY_RHS:
	    {
	      tree rhs1 = gimple_assign_rhs1 (stmt);
	      tree rhs2 = gimple_assign_rhs2 (stmt);
	      bool valueized = false;
	      rhs1 = do_valueize (rhs1, top_valueize, valueized);
	      rhs2 = do_valueize (rhs2, top_valueize, valueized);
	      *rcode = code;
	      ops[0] = rhs1;
	      ops[1] = rhs2;
	      return (gimple_resimplify2 (seq, rcode, type, ops, valueize)
		      || valueized);
	    }
	  case GIMPLE_TERNARY_RHS:
	    {
	      bool valueized = false;
	      tree rhs1 = gimple_assign_rhs1 (stmt);
	      /* If this is a [VEC_]COND_EXPR first try to simplify an
		 embedded GENERIC condition.  */
	      if (code == COND_EXPR
		  || code == VEC_COND_EXPR)
		{
		  if (COMPARISON_CLASS_P (rhs1))
		    {
		      tree lhs = TREE_OPERAND (rhs1, 0);
		      tree rhs = TREE_OPERAND (rhs1, 1);
		      lhs = do_valueize (lhs, top_valueize, valueized);
		      rhs = do_valueize (rhs, top_valueize, valueized);
		      code_helper rcode2 = TREE_CODE (rhs1);
		      tree ops2[3] = {};
		      ops2[0] = lhs;
		      ops2[1] = rhs;
		      if ((gimple_resimplify2 (seq, &rcode2, TREE_TYPE (rhs1),
					       ops2, valueize)
			   || valueized)
			  && rcode2.is_tree_code ())
			{
			  valueized = true;
			  if (TREE_CODE_CLASS ((enum tree_code)rcode2)
			      == tcc_comparison)
			    rhs1 = build2 (rcode2, TREE_TYPE (rhs1),
					   ops2[0], ops2[1]);
			  else if (rcode2 == SSA_NAME
				   || rcode2 == INTEGER_CST
				   || rcode2 == VECTOR_CST)
			    rhs1 = ops2[0];
			  else
			    valueized = false;
			}
		    }
		}
	      tree rhs2 = gimple_assign_rhs2 (stmt);
	      tree rhs3 = gimple_assign_rhs3 (stmt);
	      rhs1 = do_valueize (rhs1, top_valueize, valueized);
	      rhs2 = do_valueize (rhs2, top_valueize, valueized);
	      rhs3 = do_valueize (rhs3, top_valueize, valueized);
	      *rcode = code;
	      ops[0] = rhs1;
	      ops[1] = rhs2;
	      ops[2] = rhs3;
	      return (gimple_resimplify3 (seq, rcode, type, ops, valueize)
		      || valueized);
	    }
	  default:
	    gcc_unreachable ();
	  }
	break;
      }

    case GIMPLE_CALL:
      /* ???  This way we can't simplify calls with side-effects.  */
      if (gimple_call_lhs (stmt) != NULL_TREE
	  && gimple_call_num_args (stmt) >= 1
	  && gimple_call_num_args (stmt) <= 3)
	{
	  bool valueized = false;
	  if (gimple_call_internal_p (stmt))
	    *rcode = as_combined_fn (gimple_call_internal_fn (stmt));
	  else
	    {
	      tree fn = gimple_call_fn (stmt);
	      if (!fn)
		return false;

	      fn = do_valueize (fn, top_valueize, valueized);
	      if (TREE_CODE (fn) != ADDR_EXPR
		  || TREE_CODE (TREE_OPERAND (fn, 0)) != FUNCTION_DECL)
		return false;

	      tree decl = TREE_OPERAND (fn, 0);
	      if (DECL_BUILT_IN_CLASS (decl) != BUILT_IN_NORMAL
		  || !gimple_builtin_call_types_compatible_p (stmt, decl))
		return false;

	      *rcode = as_combined_fn (DECL_FUNCTION_CODE (decl));
	    }

	  tree type = TREE_TYPE (gimple_call_lhs (stmt));
	  for (unsigned i = 0; i < gimple_call_num_args (stmt); ++i)
	    {
	      tree arg = gimple_call_arg (stmt, i);
	      ops[i] = do_valueize (arg, top_valueize, valueized);
	    }
	  switch (gimple_call_num_args (stmt))
	    {
	    case 1:
	      return (gimple_resimplify1 (seq, rcode, type, ops, valueize)
		      || valueized);
	    case 2:
	      return (gimple_resimplify2 (seq, rcode, type, ops, valueize)
		      || valueized);
	    case 3:
	      return (gimple_resimplify3 (seq, rcode, type, ops, valueize)
		      || valueized);
	    default:
	     gcc_unreachable ();
	    }
	}
      break;

    case GIMPLE_COND:
      {
	tree lhs = gimple_cond_lhs (stmt);
	tree rhs = gimple_cond_rhs (stmt);
	bool valueized = false;
	lhs = do_valueize (lhs, top_valueize, valueized);
	rhs = do_valueize (rhs, top_valueize, valueized);
	*rcode = gimple_cond_code (stmt);
	ops[0] = lhs;
	ops[1] = rhs;
        return (gimple_resimplify2 (seq, rcode,
				    boolean_type_node, ops, valueize)
		|| valueized);
      }

    default:
      break;
    }

  return false;
}