本文整理汇总了C++中SSA_NAME_DEF_STMT函数的典型用法代码示例。如果您正苦于以下问题:C++ SSA_NAME_DEF_STMT函数的具体用法?C++ SSA_NAME_DEF_STMT怎么用?C++ SSA_NAME_DEF_STMT使用的例子?那么, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了SSA_NAME_DEF_STMT函数的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: get_name_for_bit_test
static tree
get_name_for_bit_test (tree candidate)
{
/* Skip single-use names in favor of using the name from a
non-widening conversion definition. */
if (TREE_CODE (candidate) == SSA_NAME
&& has_single_use (candidate))
{
gimple def_stmt = SSA_NAME_DEF_STMT (candidate);
if (is_gimple_assign (def_stmt)
&& CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt)))
{
if (TYPE_PRECISION (TREE_TYPE (candidate))
<= TYPE_PRECISION (TREE_TYPE (gimple_assign_rhs1 (def_stmt))))
return gimple_assign_rhs1 (def_stmt);
}
}
return candidate;
}
示例2: recognize_bits_test
static bool
recognize_bits_test (gimple cond, tree *name, tree *bits, bool inv)
{
gimple stmt;
/* Get at the definition of the result of the bit test. */
if (gimple_cond_code (cond) != (inv ? EQ_EXPR : NE_EXPR)
|| TREE_CODE (gimple_cond_lhs (cond)) != SSA_NAME
|| !integer_zerop (gimple_cond_rhs (cond)))
return false;
stmt = SSA_NAME_DEF_STMT (gimple_cond_lhs (cond));
if (!is_gimple_assign (stmt)
|| gimple_assign_rhs_code (stmt) != BIT_AND_EXPR)
return false;
*name = get_name_for_bit_test (gimple_assign_rhs1 (stmt));
*bits = gimple_assign_rhs2 (stmt);
return true;
}
示例3: sese_build_liveouts_use
static void
sese_build_liveouts_use (sese region, bitmap liveouts, basic_block bb,
tree use)
{
unsigned ver;
basic_block def_bb;
if (TREE_CODE (use) != SSA_NAME)
return;
ver = SSA_NAME_VERSION (use);
def_bb = gimple_bb (SSA_NAME_DEF_STMT (use));
if (!def_bb
|| !bb_in_sese_p (def_bb, region)
|| bb_in_sese_p (bb, region))
return;
bitmap_set_bit (liveouts, ver);
}
示例4: build_one_array
static void
build_one_array (gimple swtch, int num, tree arr_index_type, gimple phi,
tree tidx)
{
tree array_type, ctor, decl, value_type, name, fetch;
gimple load;
gimple_stmt_iterator gsi;
gcc_assert (info.default_values[num]);
value_type = TREE_TYPE (info.default_values[num]);
array_type = build_array_type (value_type, arr_index_type);
ctor = build_constructor (array_type, info.constructors[num]);
TREE_CONSTANT (ctor) = true;
decl = build_decl (VAR_DECL, NULL_TREE, array_type);
TREE_STATIC (decl) = 1;
DECL_INITIAL (decl) = ctor;
DECL_NAME (decl) = create_tmp_var_name ("CSWTCH");
DECL_ARTIFICIAL (decl) = 1;
TREE_CONSTANT (decl) = 1;
add_referenced_var (decl);
varpool_mark_needed_node (varpool_node (decl));
varpool_finalize_decl (decl);
mark_sym_for_renaming (decl);
name = make_ssa_name (SSA_NAME_VAR (PHI_RESULT (phi)), NULL);
info.target_inbound_names[num] = name;
fetch = build4 (ARRAY_REF, value_type, decl, tidx, NULL_TREE,
NULL_TREE);
load = gimple_build_assign (name, fetch);
SSA_NAME_DEF_STMT (name) = load;
gsi = gsi_for_stmt (swtch);
gsi_insert_before (&gsi, load, GSI_SAME_STMT);
mark_symbols_for_renaming (load);
info.arr_ref_last = load;
}
开发者ID:prateekdhawalia,项目名称:gcc-designated-initializer-support-cpp,代码行数:41,代码来源:tree-switch-conversion.c
示例5: tree_may_unswitch_on
static tree
tree_may_unswitch_on (basic_block bb, struct loop *loop)
{
tree stmt, def, cond, use;
basic_block def_bb;
ssa_op_iter iter;
/* BB must end in a simple conditional jump. */
stmt = last_stmt (bb);
if (!stmt || TREE_CODE (stmt) != COND_EXPR)
return NULL_TREE;
/* Condition must be invariant. */
FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE)
{
def = SSA_NAME_DEF_STMT (use);
def_bb = bb_for_stmt (def);
if (def_bb
&& flow_bb_inside_loop_p (loop, def_bb))
return NULL_TREE;
}
示例6: input_phi
static gimple
input_phi (struct lto_input_block *ib, basic_block bb, struct data_in *data_in,
struct function *fn)
{
unsigned HOST_WIDE_INT ix;
tree phi_result;
int i, len;
gimple result;
ix = streamer_read_uhwi (ib);
phi_result = VEC_index (tree, SSANAMES (fn), ix);
len = EDGE_COUNT (bb->preds);
result = create_phi_node (phi_result, bb);
SSA_NAME_DEF_STMT (phi_result) = result;
/* We have to go through a lookup process here because the preds in the
reconstructed graph are generally in a different order than they
were in the original program. */
for (i = 0; i < len; i++)
{
tree def = stream_read_tree (ib, data_in);
int src_index = streamer_read_uhwi (ib);
location_t arg_loc = lto_input_location (ib, data_in);
basic_block sbb = BASIC_BLOCK_FOR_FUNCTION (fn, src_index);
edge e = NULL;
int j;
for (j = 0; j < len; j++)
if (EDGE_PRED (bb, j)->src == sbb)
{
e = EDGE_PRED (bb, j);
break;
}
add_phi_arg (result, def, e, arg_loc);
}
return result;
}
示例7: reserve_phi_args_for_new_edge
void
reserve_phi_args_for_new_edge (basic_block bb)
{
size_t len = EDGE_COUNT (bb->preds);
size_t cap = ideal_phi_node_len (len + 4);
gimple_stmt_iterator gsi;
for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
{
gimple_statement_phi *stmt =
as_a <gimple_statement_phi> (gsi_stmt (gsi));
if (len > gimple_phi_capacity (stmt))
{
gimple_statement_phi *new_phi = resize_phi_node (stmt, cap);
/* The result of the PHI is defined by this PHI node. */
SSA_NAME_DEF_STMT (gimple_phi_result (new_phi)) = new_phi;
gsi_set_stmt (&gsi, new_phi);
release_phi_node (stmt);
stmt = new_phi;
}
/* We represent a "missing PHI argument" by placing NULL_TREE in
the corresponding slot. If PHI arguments were added
immediately after an edge is created, this zeroing would not
be necessary, but unfortunately this is not the case. For
example, the loop optimizer duplicates several basic blocks,
redirects edges, and then fixes up PHI arguments later in
batch. */
SET_PHI_ARG_DEF (stmt, len - 1, NULL_TREE);
gimple_phi_arg_set_location (stmt, len - 1, UNKNOWN_LOCATION);
stmt->nargs++;
}
}
示例8: add_dependency
static bool
add_dependency (tree def, struct lim_aux_data *data, struct loop *loop,
bool add_cost)
{
tree def_stmt = SSA_NAME_DEF_STMT (def);
basic_block def_bb = bb_for_stmt (def_stmt);
struct loop *max_loop;
struct depend *dep;
if (!def_bb)
return true;
max_loop = outermost_invariant_loop (def, loop);
if (!max_loop)
return false;
if (flow_loop_nested_p (data->max_loop, max_loop))
data->max_loop = max_loop;
if (!LIM_DATA (def_stmt))
return true;
if (add_cost
/* Only add the cost if the statement defining DEF is inside LOOP,
i.e. if it is likely that by moving the invariants dependent
on it, we will be able to avoid creating a new register for
it (since it will be only used in these dependent invariants). */
&& def_bb->loop_father == loop)
data->cost += LIM_DATA (def_stmt)->cost;
dep = XNEW (struct depend);
dep->stmt = def_stmt;
dep->next = data->depends;
data->depends = dep;
return true;
}
示例9: forward_propagate_into_cond
static void
forward_propagate_into_cond (tree cond_expr)
{
gcc_assert (TREE_CODE (cond_expr) == COND_EXPR);
while (1)
{
tree test_var = NULL_TREE;
tree cond = COND_EXPR_COND (cond_expr);
tree new_cond = forward_propagate_into_cond_1 (cond, &test_var);
/* Return if unsuccessful. */
if (new_cond == NULL_TREE)
break;
/* Dump details. */
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, " Replaced '");
print_generic_expr (dump_file, cond, dump_flags);
fprintf (dump_file, "' with '");
print_generic_expr (dump_file, new_cond, dump_flags);
fprintf (dump_file, "'\n");
}
COND_EXPR_COND (cond_expr) = new_cond;
update_stmt (cond_expr);
if (has_zero_uses (test_var))
{
tree def = SSA_NAME_DEF_STMT (test_var);
block_stmt_iterator bsi = bsi_for_stmt (def);
bsi_remove (&bsi);
}
}
}
示例10: chkp_get_check_result
/* Return 1 if check CI against BOUNDS always pass,
-1 if check CI against BOUNDS always fails and
0 if we cannot compute check result. */
static int
chkp_get_check_result (struct check_info *ci, tree bounds)
{
gimple *bnd_def;
address_t bound_val;
int sign, res = 0;
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "Trying to compute result of the check\n");
fprintf (dump_file, " check: ");
print_gimple_stmt (dump_file, ci->stmt, 0, 0);
fprintf (dump_file, " address: ");
chkp_print_addr (ci->addr);
fprintf (dump_file, "\n bounds: ");
print_generic_expr (dump_file, bounds, 0);
fprintf (dump_file, "\n");
}
if (TREE_CODE (bounds) != SSA_NAME)
{
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, " result: bounds tree code is not ssa_name\n");
return 0;
}
bnd_def = SSA_NAME_DEF_STMT (bounds);
/* Currently we handle cases when bounds are result of bndmk
or loaded static bounds var. */
if (gimple_code (bnd_def) == GIMPLE_CALL
&& gimple_call_fndecl (bnd_def) == chkp_bndmk_fndecl)
{
bound_val.pol.create (0);
chkp_collect_value (gimple_call_arg (bnd_def, 0), bound_val);
if (ci->type == CHECK_UPPER_BOUND)
{
address_t size_val;
size_val.pol.create (0);
chkp_collect_value (gimple_call_arg (bnd_def, 1), size_val);
chkp_add_addr_addr (bound_val, size_val);
size_val.pol.release ();
chkp_add_addr_item (bound_val, integer_minus_one_node, NULL);
}
}
else if (gimple_code (bnd_def) == GIMPLE_ASSIGN
&& gimple_assign_rhs1 (bnd_def) == chkp_get_zero_bounds_var ())
{
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, " result: always pass with zero bounds\n");
return 1;
}
else if (gimple_code (bnd_def) == GIMPLE_ASSIGN
&& gimple_assign_rhs1 (bnd_def) == chkp_get_none_bounds_var ())
{
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, " result: always fails with none bounds\n");
return -1;
}
else if (gimple_code (bnd_def) == GIMPLE_ASSIGN
&& TREE_CODE (gimple_assign_rhs1 (bnd_def)) == VAR_DECL)
{
tree bnd_var = gimple_assign_rhs1 (bnd_def);
tree var;
tree size;
if (!DECL_INITIAL (bnd_var)
|| DECL_INITIAL (bnd_var) == error_mark_node)
{
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, " result: cannot compute bounds\n");
return 0;
}
gcc_assert (TREE_CODE (DECL_INITIAL (bnd_var)) == ADDR_EXPR);
var = TREE_OPERAND (DECL_INITIAL (bnd_var), 0);
bound_val.pol.create (0);
chkp_collect_value (DECL_INITIAL (bnd_var), bound_val);
if (ci->type == CHECK_UPPER_BOUND)
{
if (TREE_CODE (var) == VAR_DECL)
{
if (DECL_SIZE (var)
&& !chkp_variable_size_type (TREE_TYPE (var)))
size = DECL_SIZE_UNIT (var);
else
{
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, " result: cannot compute bounds\n");
return 0;
}
}
else
{
gcc_assert (TREE_CODE (var) == STRING_CST);
size = build_int_cst (size_type_node,
TREE_STRING_LENGTH (var));
//.........这里部分代码省略.........
示例11: chkp_collect_value
/* Compute value of PTR and put it into address RES. */
static void
chkp_collect_value (tree ptr, address_t &res)
{
gimple *def_stmt;
enum gimple_code code;
enum tree_code rhs_code;
address_t addr;
tree rhs1;
if (TREE_CODE (ptr) == INTEGER_CST)
{
chkp_add_addr_item (res, ptr, NULL);
return;
}
else if (TREE_CODE (ptr) == ADDR_EXPR)
{
chkp_collect_addr_value (ptr, res);
return;
}
else if (TREE_CODE (ptr) != SSA_NAME)
{
chkp_add_addr_item (res, integer_one_node, ptr);
return;
}
/* Now we handle the case when polynomial is computed
for SSA NAME. */
def_stmt = SSA_NAME_DEF_STMT (ptr);
code = gimple_code (def_stmt);
/* Currently we do not walk through statements other
than assignment. */
if (code != GIMPLE_ASSIGN)
{
chkp_add_addr_item (res, integer_one_node, ptr);
return;
}
rhs_code = gimple_assign_rhs_code (def_stmt);
rhs1 = gimple_assign_rhs1 (def_stmt);
switch (rhs_code)
{
case SSA_NAME:
case INTEGER_CST:
case ADDR_EXPR:
chkp_collect_value (rhs1, res);
break;
case PLUS_EXPR:
case POINTER_PLUS_EXPR:
chkp_collect_value (rhs1, res);
addr.pol.create (0);
chkp_collect_value (gimple_assign_rhs2 (def_stmt), addr);
chkp_add_addr_addr (res, addr);
addr.pol.release ();
break;
case MINUS_EXPR:
chkp_collect_value (rhs1, res);
addr.pol.create (0);
chkp_collect_value (gimple_assign_rhs2 (def_stmt), addr);
chkp_sub_addr_addr (res, addr);
addr.pol.release ();
break;
case MULT_EXPR:
if (TREE_CODE (rhs1) == SSA_NAME
&& TREE_CODE (gimple_assign_rhs2 (def_stmt)) == INTEGER_CST)
{
chkp_collect_value (rhs1, res);
chkp_mult_addr (res, gimple_assign_rhs2 (def_stmt));
}
else if (TREE_CODE (gimple_assign_rhs2 (def_stmt)) == SSA_NAME
&& TREE_CODE (rhs1) == INTEGER_CST)
{
chkp_collect_value (gimple_assign_rhs2 (def_stmt), res);
chkp_mult_addr (res, rhs1);
}
else
chkp_add_addr_item (res, integer_one_node, ptr);
break;
default:
chkp_add_addr_item (res, integer_one_node, ptr);
break;
}
}
示例12: rewrite_bittest
static tree
rewrite_bittest (block_stmt_iterator *bsi)
{
tree stmt, lhs, rhs, var, name, use_stmt, stmt1, stmt2, t;
use_operand_p use;
stmt = bsi_stmt (*bsi);
lhs = GENERIC_TREE_OPERAND (stmt, 0);
rhs = GENERIC_TREE_OPERAND (stmt, 1);
/* Verify that the single use of lhs is a comparison against zero. */
if (TREE_CODE (lhs) != SSA_NAME
|| !single_imm_use (lhs, &use, &use_stmt)
|| TREE_CODE (use_stmt) != COND_EXPR)
return stmt;
t = COND_EXPR_COND (use_stmt);
if (TREE_OPERAND (t, 0) != lhs
|| (TREE_CODE (t) != NE_EXPR
&& TREE_CODE (t) != EQ_EXPR)
|| !integer_zerop (TREE_OPERAND (t, 1)))
return stmt;
/* Get at the operands of the shift. The rhs is TMP1 & 1. */
stmt1 = SSA_NAME_DEF_STMT (TREE_OPERAND (rhs, 0));
if (TREE_CODE (stmt1) != GIMPLE_MODIFY_STMT)
return stmt;
/* There is a conversion in between possibly inserted by fold. */
t = GIMPLE_STMT_OPERAND (stmt1, 1);
if (TREE_CODE (t) == NOP_EXPR
|| TREE_CODE (t) == CONVERT_EXPR)
{
t = TREE_OPERAND (t, 0);
if (TREE_CODE (t) != SSA_NAME
|| !has_single_use (t))
return stmt;
stmt1 = SSA_NAME_DEF_STMT (t);
if (TREE_CODE (stmt1) != GIMPLE_MODIFY_STMT)
return stmt;
t = GIMPLE_STMT_OPERAND (stmt1, 1);
}
/* Verify that B is loop invariant but A is not. Verify that with
all the stmt walking we are still in the same loop. */
if (TREE_CODE (t) == RSHIFT_EXPR
&& loop_containing_stmt (stmt1) == loop_containing_stmt (stmt)
&& outermost_invariant_loop_expr (TREE_OPERAND (t, 1),
loop_containing_stmt (stmt1)) != NULL
&& outermost_invariant_loop_expr (TREE_OPERAND (t, 0),
loop_containing_stmt (stmt1)) == NULL)
{
tree a = TREE_OPERAND (t, 0);
tree b = TREE_OPERAND (t, 1);
/* 1 << B */
var = create_tmp_var (TREE_TYPE (a), "shifttmp");
add_referenced_var (var);
t = fold_build2 (LSHIFT_EXPR, TREE_TYPE (a),
build_int_cst (TREE_TYPE (a), 1), b);
stmt1 = build_gimple_modify_stmt (var, t);
name = make_ssa_name (var, stmt1);
GIMPLE_STMT_OPERAND (stmt1, 0) = name;
/* A & (1 << B) */
t = fold_build2 (BIT_AND_EXPR, TREE_TYPE (a), a, name);
stmt2 = build_gimple_modify_stmt (var, t);
name = make_ssa_name (var, stmt2);
GIMPLE_STMT_OPERAND (stmt2, 0) = name;
/* Replace the SSA_NAME we compare against zero. Adjust
the type of zero accordingly. */
SET_USE (use, name);
TREE_OPERAND (COND_EXPR_COND (use_stmt), 1)
= build_int_cst_type (TREE_TYPE (name), 0);
bsi_insert_before (bsi, stmt1, BSI_SAME_STMT);
bsi_replace (bsi, stmt2, true);
return stmt1;
}
return stmt;
}
示例13: recognize_single_bit_test
static bool
recognize_single_bit_test (gimple cond, tree *name, tree *bit)
{
gimple stmt;
/* Get at the definition of the result of the bit test. */
if (gimple_cond_code (cond) != NE_EXPR
|| TREE_CODE (gimple_cond_lhs (cond)) != SSA_NAME
|| !integer_zerop (gimple_cond_rhs (cond)))
return false;
stmt = SSA_NAME_DEF_STMT (gimple_cond_lhs (cond));
if (!is_gimple_assign (stmt))
return false;
/* Look at which bit is tested. One form to recognize is
D.1985_5 = state_3(D) >> control1_4(D);
D.1986_6 = (int) D.1985_5;
D.1987_7 = op0 & 1;
if (D.1987_7 != 0) */
if (gimple_assign_rhs_code (stmt) == BIT_AND_EXPR
&& integer_onep (gimple_assign_rhs2 (stmt))
&& TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME)
{
tree orig_name = gimple_assign_rhs1 (stmt);
/* Look through copies and conversions to eventually
find the stmt that computes the shift. */
stmt = SSA_NAME_DEF_STMT (orig_name);
while (is_gimple_assign (stmt)
&& ((CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (stmt))
&& (TYPE_PRECISION (TREE_TYPE (gimple_assign_lhs (stmt)))
<= TYPE_PRECISION (TREE_TYPE (gimple_assign_rhs1 (stmt)))))
|| gimple_assign_ssa_name_copy_p (stmt)))
stmt = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt));
/* If we found such, decompose it. */
if (is_gimple_assign (stmt)
&& gimple_assign_rhs_code (stmt) == RSHIFT_EXPR)
{
/* op0 & (1 << op1) */
*bit = gimple_assign_rhs2 (stmt);
*name = gimple_assign_rhs1 (stmt);
}
else
{
/* t & 1 */
*bit = integer_zero_node;
*name = get_name_for_bit_test (orig_name);
}
return true;
}
/* Another form is
D.1987_7 = op0 & (1 << CST)
if (D.1987_7 != 0) */
if (gimple_assign_rhs_code (stmt) == BIT_AND_EXPR
&& TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME
&& integer_pow2p (gimple_assign_rhs2 (stmt)))
{
*name = gimple_assign_rhs1 (stmt);
*bit = build_int_cst (integer_type_node,
tree_log2 (gimple_assign_rhs2 (stmt)));
return true;
}
/* Another form is
D.1986_6 = 1 << control1_4(D)
D.1987_7 = op0 & D.1986_6
if (D.1987_7 != 0) */
if (gimple_assign_rhs_code (stmt) == BIT_AND_EXPR
&& TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME
&& TREE_CODE (gimple_assign_rhs2 (stmt)) == SSA_NAME)
{
gimple tmp;
/* Both arguments of the BIT_AND_EXPR can be the single-bit
specifying expression. */
tmp = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt));
if (is_gimple_assign (tmp)
&& gimple_assign_rhs_code (tmp) == LSHIFT_EXPR
&& integer_onep (gimple_assign_rhs1 (tmp)))
{
*name = gimple_assign_rhs2 (stmt);
*bit = gimple_assign_rhs2 (tmp);
return true;
}
tmp = SSA_NAME_DEF_STMT (gimple_assign_rhs2 (stmt));
if (is_gimple_assign (tmp)
&& gimple_assign_rhs_code (tmp) == LSHIFT_EXPR
&& integer_onep (gimple_assign_rhs1 (tmp)))
{
*name = gimple_assign_rhs1 (stmt);
*bit = gimple_assign_rhs2 (tmp);
return true;
}
}
//.........这里部分代码省略.........
示例14: forward_propagate_addr_into_variable_array_index
static bool
forward_propagate_addr_into_variable_array_index (tree offset,
tree def_rhs,
gimple_stmt_iterator *use_stmt_gsi)
{
tree index, tunit;
gimple offset_def, use_stmt = gsi_stmt (*use_stmt_gsi);
tree tmp;
tunit = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (def_rhs)));
if (!host_integerp (tunit, 1))
return false;
/* Get the offset's defining statement. */
offset_def = SSA_NAME_DEF_STMT (offset);
/* Try to find an expression for a proper index. This is either a
multiplication expression by the element size or just the ssa name we came
along in case the element size is one. In that case, however, we do not
allow multiplications because they can be computing index to a higher
level dimension (PR 37861). */
if (integer_onep (tunit))
{
if (is_gimple_assign (offset_def)
&& gimple_assign_rhs_code (offset_def) == MULT_EXPR)
return false;
index = offset;
}
else
{
/* The statement which defines OFFSET before type conversion
must be a simple GIMPLE_ASSIGN. */
if (!is_gimple_assign (offset_def))
return false;
/* The RHS of the statement which defines OFFSET must be a
multiplication of an object by the size of the array elements.
This implicitly verifies that the size of the array elements
is constant. */
if (gimple_assign_rhs_code (offset_def) == MULT_EXPR
&& TREE_CODE (gimple_assign_rhs2 (offset_def)) == INTEGER_CST
&& tree_int_cst_equal (gimple_assign_rhs2 (offset_def), tunit))
{
/* The first operand to the MULT_EXPR is the desired index. */
index = gimple_assign_rhs1 (offset_def);
}
/* If we have idx * tunit + CST * tunit re-associate that. */
else if ((gimple_assign_rhs_code (offset_def) == PLUS_EXPR
|| gimple_assign_rhs_code (offset_def) == MINUS_EXPR)
&& TREE_CODE (gimple_assign_rhs1 (offset_def)) == SSA_NAME
&& TREE_CODE (gimple_assign_rhs2 (offset_def)) == INTEGER_CST
&& (tmp = div_if_zero_remainder (EXACT_DIV_EXPR,
gimple_assign_rhs2 (offset_def),
tunit)) != NULL_TREE)
{
gimple offset_def2 = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (offset_def));
if (is_gimple_assign (offset_def2)
&& gimple_assign_rhs_code (offset_def2) == MULT_EXPR
&& TREE_CODE (gimple_assign_rhs2 (offset_def2)) == INTEGER_CST
&& tree_int_cst_equal (gimple_assign_rhs2 (offset_def2), tunit))
{
index = fold_build2 (gimple_assign_rhs_code (offset_def),
TREE_TYPE (offset),
gimple_assign_rhs1 (offset_def2), tmp);
}
else
return false;
}
else
return false;
}
/* Replace the pointer addition with array indexing. */
index = force_gimple_operand_gsi (use_stmt_gsi, index, true, NULL_TREE,
true, GSI_SAME_STMT);
gimple_assign_set_rhs_from_tree (use_stmt_gsi, unshare_expr (def_rhs));
use_stmt = gsi_stmt (*use_stmt_gsi);
TREE_OPERAND (TREE_OPERAND (gimple_assign_rhs1 (use_stmt), 0), 1)
= index;
/* That should have created gimple, so there is no need to
record information to undo the propagation. */
fold_stmt_inplace (use_stmt);
tidy_after_forward_propagate_addr (use_stmt);
return true;
}
示例15: vect_recog_widen_sum_pattern
static gimple
vect_recog_widen_sum_pattern (gimple last_stmt, tree *type_in, tree *type_out)
{
gimple stmt;
tree oprnd0, oprnd1;
stmt_vec_info stmt_vinfo = vinfo_for_stmt (last_stmt);
tree type, half_type;
gimple pattern_stmt;
loop_vec_info loop_info = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
struct loop *loop = LOOP_VINFO_LOOP (loop_info);
tree var;
if (!is_gimple_assign (last_stmt))
return NULL;
type = gimple_expr_type (last_stmt);
/* Look for the following pattern
DX = (TYPE) X;
sum_1 = DX + sum_0;
In which DX is at least double the size of X, and sum_1 has been
recognized as a reduction variable.
*/
/* Starting from LAST_STMT, follow the defs of its uses in search
of the above pattern. */
if (gimple_assign_rhs_code (last_stmt) != PLUS_EXPR)
return NULL;
if (STMT_VINFO_DEF_TYPE (stmt_vinfo) != vect_reduction_def)
return NULL;
oprnd0 = gimple_assign_rhs1 (last_stmt);
oprnd1 = gimple_assign_rhs2 (last_stmt);
if (!types_compatible_p (TREE_TYPE (oprnd0), type)
|| !types_compatible_p (TREE_TYPE (oprnd1), type))
return NULL;
/* So far so good. Since last_stmt was detected as a (summation) reduction,
we know that oprnd1 is the reduction variable (defined by a loop-header
phi), and oprnd0 is an ssa-name defined by a stmt in the loop body.
Left to check that oprnd0 is defined by a cast from type 'type' to type
'TYPE'. */
if (!widened_name_p (oprnd0, last_stmt, &half_type, &stmt))
return NULL;
oprnd0 = gimple_assign_rhs1 (stmt);
*type_in = half_type;
*type_out = type;
/* Pattern detected. Create a stmt to be used to replace the pattern: */
var = vect_recog_temp_ssa_var (type, NULL);
pattern_stmt = gimple_build_assign_with_ops (WIDEN_SUM_EXPR, var,
oprnd0, oprnd1);
SSA_NAME_DEF_STMT (var) = pattern_stmt;
if (vect_print_dump_info (REPORT_DETAILS))
{
fprintf (vect_dump, "vect_recog_widen_sum_pattern: detected: ");
print_gimple_stmt (vect_dump, pattern_stmt, 0, TDF_SLIM);
}
/* We don't allow changing the order of the computation in the inner-loop
when doing outer-loop vectorization. */
gcc_assert (!nested_in_vect_loop_p (loop, last_stmt));
return pattern_stmt;
}