aboutsummaryrefslogtreecommitdiff
path: root/gcc/expr.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/expr.cc')
-rw-r--r--gcc/expr.cc239
1 files changed, 136 insertions, 103 deletions
diff --git a/gcc/expr.cc b/gcc/expr.cc
index 3815c56..ac4fdfa 100644
--- a/gcc/expr.cc
+++ b/gcc/expr.cc
@@ -471,8 +471,7 @@ convert_mode_scalar (rtx to, rtx from, int unsignedp)
emit_move_insn (to, tof);
}
}
- insns = get_insns ();
- end_sequence ();
+ insns = end_sequence ();
if (tof)
{
emit_insn (insns);
@@ -542,8 +541,7 @@ convert_mode_scalar (rtx to, rtx from, int unsignedp)
emit_move_insn (to, tof);
}
while (0);
- insns = get_insns ();
- end_sequence ();
+ insns = end_sequence ();
if (tof)
{
emit_insn (insns);
@@ -562,8 +560,7 @@ convert_mode_scalar (rtx to, rtx from, int unsignedp)
start_sequence ();
value = emit_library_call_value (libcall, NULL_RTX, LCT_CONST, to_mode,
from, from_mode);
- insns = get_insns ();
- end_sequence ();
+ insns = end_sequence ();
emit_libcall_block (insns, to, value,
tab == trunc_optab ? gen_rtx_FLOAT_TRUNCATE (to_mode,
from)
@@ -736,8 +733,7 @@ convert_mode_scalar (rtx to, rtx from, int unsignedp)
emit_move_insn (subword, fill_value);
}
- insns = get_insns ();
- end_sequence ();
+ insns = end_sequence ();
emit_insn (insns);
return;
@@ -4547,8 +4543,7 @@ emit_move_multi_word (machine_mode mode, rtx x, rtx y)
last_insn = emit_move_insn (xpart, ypart);
}
- seq = get_insns ();
- end_sequence ();
+ seq = end_sequence ();
/* Show the output dies here. This is necessary for SUBREGs
of pseudos since we cannot track their lifetimes correctly;
@@ -4765,13 +4760,9 @@ emit_move_insn (rtx x, rtx y)
rtx_insn *
gen_move_insn (rtx x, rtx y)
{
- rtx_insn *seq;
-
start_sequence ();
emit_move_insn_1 (x, y);
- seq = get_insns ();
- end_sequence ();
- return seq;
+ return end_sequence ();
}
/* If Y is representable exactly in a narrower mode, and the target can
@@ -7640,8 +7631,8 @@ store_constructor (tree exp, rtx target, int cleared, poly_int64 size,
tree domain;
tree elttype = TREE_TYPE (type);
bool const_bounds_p;
- HOST_WIDE_INT minelt = 0;
- HOST_WIDE_INT maxelt = 0;
+ unsigned HOST_WIDE_INT minelt = 0;
+ unsigned HOST_WIDE_INT maxelt = 0;
/* The storage order is specified for every aggregate type. */
reverse = TYPE_REVERSE_STORAGE_ORDER (type);
@@ -7649,14 +7640,14 @@ store_constructor (tree exp, rtx target, int cleared, poly_int64 size,
domain = TYPE_DOMAIN (type);
const_bounds_p = (TYPE_MIN_VALUE (domain)
&& TYPE_MAX_VALUE (domain)
- && tree_fits_shwi_p (TYPE_MIN_VALUE (domain))
- && tree_fits_shwi_p (TYPE_MAX_VALUE (domain)));
+ && tree_fits_uhwi_p (TYPE_MIN_VALUE (domain))
+ && tree_fits_uhwi_p (TYPE_MAX_VALUE (domain)));
/* If we have constant bounds for the range of the type, get them. */
if (const_bounds_p)
{
- minelt = tree_to_shwi (TYPE_MIN_VALUE (domain));
- maxelt = tree_to_shwi (TYPE_MAX_VALUE (domain));
+ minelt = tree_to_uhwi (TYPE_MIN_VALUE (domain));
+ maxelt = tree_to_uhwi (TYPE_MAX_VALUE (domain));
}
/* If the constructor has fewer elements than the array, clear
@@ -7669,7 +7660,7 @@ store_constructor (tree exp, rtx target, int cleared, poly_int64 size,
else
{
unsigned HOST_WIDE_INT idx;
- HOST_WIDE_INT count = 0, zero_count = 0;
+ unsigned HOST_WIDE_INT count = 0, zero_count = 0;
need_to_clear = ! const_bounds_p;
/* This loop is a more accurate version of the loop in
@@ -7677,7 +7668,7 @@ store_constructor (tree exp, rtx target, int cleared, poly_int64 size,
is also needed to check for missing elements. */
FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (exp), idx, index, value)
{
- HOST_WIDE_INT this_node_count;
+ unsigned HOST_WIDE_INT this_node_count;
if (need_to_clear)
break;
@@ -7751,16 +7742,16 @@ store_constructor (tree exp, rtx target, int cleared, poly_int64 size,
{
tree lo_index = TREE_OPERAND (index, 0);
tree hi_index = TREE_OPERAND (index, 1);
- rtx index_r, pos_rtx;
- HOST_WIDE_INT lo, hi, count;
- tree position;
+ rtx index_r;
+ unsigned HOST_WIDE_INT lo, hi, count;
+ tree offset;
/* If the range is constant and "small", unroll the loop. */
if (const_bounds_p
- && tree_fits_shwi_p (lo_index)
- && tree_fits_shwi_p (hi_index)
- && (lo = tree_to_shwi (lo_index),
- hi = tree_to_shwi (hi_index),
+ && tree_fits_uhwi_p (lo_index)
+ && tree_fits_uhwi_p (hi_index)
+ && (lo = tree_to_uhwi (lo_index),
+ hi = tree_to_uhwi (hi_index),
count = hi - lo + 1,
(!MEM_P (target)
|| count <= 2
@@ -7771,7 +7762,7 @@ store_constructor (tree exp, rtx target, int cleared, poly_int64 size,
lo -= minelt; hi -= minelt;
for (; lo <= hi; lo++)
{
- bitpos = lo * tree_to_shwi (TYPE_SIZE (elttype));
+ bitpos = lo * tree_to_uhwi (TYPE_SIZE (elttype));
if (MEM_P (target)
&& !MEM_KEEP_ALIAS_SET_P (target)
@@ -7807,21 +7798,18 @@ store_constructor (tree exp, rtx target, int cleared, poly_int64 size,
emit_label (loop_start);
/* Assign value to element index. */
- position =
- fold_convert (ssizetype,
- fold_build2 (MINUS_EXPR,
- TREE_TYPE (index),
- index,
- TYPE_MIN_VALUE (domain)));
-
- position =
- size_binop (MULT_EXPR, position,
- fold_convert (ssizetype,
- TYPE_SIZE_UNIT (elttype)));
-
- pos_rtx = expand_normal (position);
- xtarget = offset_address (target, pos_rtx,
- highest_pow2_factor (position));
+ offset = fold_build2 (MINUS_EXPR,
+ TREE_TYPE (index),
+ index,
+ TYPE_MIN_VALUE (domain));
+
+ offset = size_binop (MULT_EXPR,
+ fold_convert (sizetype, offset),
+ TYPE_SIZE_UNIT (elttype));
+
+ xtarget = offset_address (target,
+ expand_normal (offset),
+ highest_pow2_factor (offset));
xtarget = adjust_address (xtarget, mode, 0);
if (TREE_CODE (value) == CONSTRUCTOR)
store_constructor (value, xtarget, cleared,
@@ -7849,35 +7837,32 @@ store_constructor (tree exp, rtx target, int cleared, poly_int64 size,
emit_label (loop_end);
}
}
- else if ((index != 0 && ! tree_fits_shwi_p (index))
- || ! tree_fits_uhwi_p (TYPE_SIZE (elttype)))
+ else if ((index && !tree_fits_uhwi_p (index))
+ || !tree_fits_uhwi_p (TYPE_SIZE (elttype)))
{
- tree position;
-
- if (index == 0)
- index = ssize_int (1);
-
- if (minelt)
- index = fold_convert (ssizetype,
- fold_build2 (MINUS_EXPR,
- TREE_TYPE (index),
- index,
- TYPE_MIN_VALUE (domain)));
-
- position =
- size_binop (MULT_EXPR, index,
- fold_convert (ssizetype,
- TYPE_SIZE_UNIT (elttype)));
+ tree offset;
+
+ if (index)
+ offset = fold_build2 (MINUS_EXPR,
+ TREE_TYPE (index),
+ index,
+ TYPE_MIN_VALUE (domain));
+ else
+ offset = size_int (i);
+
+ offset = size_binop (MULT_EXPR,
+ fold_convert (sizetype, offset),
+ TYPE_SIZE_UNIT (elttype));
xtarget = offset_address (target,
- expand_normal (position),
- highest_pow2_factor (position));
+ expand_normal (offset),
+ highest_pow2_factor (offset));
xtarget = adjust_address (xtarget, mode, 0);
store_expr (value, xtarget, 0, false, reverse);
}
else
{
- if (index != 0)
- bitpos = ((tree_to_shwi (index) - minelt)
+ if (index)
+ bitpos = ((tree_to_uhwi (index) - minelt)
* tree_to_uhwi (TYPE_SIZE (elttype)));
else
bitpos = (i * tree_to_uhwi (TYPE_SIZE (elttype)));
@@ -9639,8 +9624,7 @@ expand_cond_expr_using_cmove (tree treeop0 ATTRIBUTE_UNUSED,
and return. */
if (insn)
{
- rtx_insn *seq = get_insns ();
- end_sequence ();
+ rtx_insn *seq = end_sequence ();
emit_insn (seq);
return convert_modes (orig_mode, mode, temp, 0);
}
@@ -9697,8 +9681,8 @@ expand_expr_divmod (tree_code code, machine_mode mode, tree treeop0,
|| code == CEIL_MOD_EXPR || code == ROUND_MOD_EXPR);
if (SCALAR_INT_MODE_P (mode)
&& optimize >= 2
- && get_range_pos_neg (treeop0) == 1
- && get_range_pos_neg (treeop1) == 1)
+ && get_range_pos_neg (treeop0, currently_expanding_gimple_stmt) == 1
+ && get_range_pos_neg (treeop1, currently_expanding_gimple_stmt) == 1)
{
/* If both arguments are known to be positive when interpreted
as signed, we can expand it as both signed and unsigned
@@ -9707,12 +9691,10 @@ expand_expr_divmod (tree_code code, machine_mode mode, tree treeop0,
do_pending_stack_adjust ();
start_sequence ();
rtx uns_ret = expand_divmod (mod_p, code, mode, op0, op1, target, 1);
- rtx_insn *uns_insns = get_insns ();
- end_sequence ();
+ rtx_insn *uns_insns = end_sequence ();
start_sequence ();
rtx sgn_ret = expand_divmod (mod_p, code, mode, op0, op1, target, 0);
- rtx_insn *sgn_insns = get_insns ();
- end_sequence ();
+ rtx_insn *sgn_insns = end_sequence ();
unsigned uns_cost = seq_cost (uns_insns, speed_p);
unsigned sgn_cost = seq_cost (sgn_insns, speed_p);
bool was_tie = false;
@@ -9897,14 +9879,68 @@ expand_expr_real_2 (const_sepops ops, rtx target, machine_mode tmode,
op0 = gen_rtx_fmt_e (TYPE_UNSIGNED (TREE_TYPE (treeop0))
? ZERO_EXTEND : SIGN_EXTEND, mode, op0);
+ else if (SCALAR_INT_MODE_P (GET_MODE (op0))
+ && optimize >= 2
+ && SCALAR_INT_MODE_P (mode)
+ && (GET_MODE_SIZE (as_a <scalar_int_mode> (mode))
+ > GET_MODE_SIZE (as_a <scalar_int_mode> (GET_MODE (op0))))
+ && get_range_pos_neg (treeop0,
+ currently_expanding_gimple_stmt) == 1)
+ {
+ /* If argument is known to be positive when interpreted
+ as signed, we can expand it as both sign and zero
+ extension. Choose the cheaper sequence in that case. */
+ bool speed_p = optimize_insn_for_speed_p ();
+ rtx uns_ret = NULL_RTX, sgn_ret = NULL_RTX;
+ do_pending_stack_adjust ();
+ start_sequence ();
+ if (target == NULL_RTX)
+ uns_ret = convert_to_mode (mode, op0, 1);
+ else
+ convert_move (target, op0, 1);
+ rtx_insn *uns_insns = end_sequence ();
+ start_sequence ();
+ if (target == NULL_RTX)
+ sgn_ret = convert_to_mode (mode, op0, 0);
+ else
+ convert_move (target, op0, 0);
+ rtx_insn *sgn_insns = end_sequence ();
+ unsigned uns_cost = seq_cost (uns_insns, speed_p);
+ unsigned sgn_cost = seq_cost (sgn_insns, speed_p);
+ bool was_tie = false;
+
+ /* If costs are the same then use as tie breaker the other other
+ factor. */
+ if (uns_cost == sgn_cost)
+ {
+ uns_cost = seq_cost (uns_insns, !speed_p);
+ sgn_cost = seq_cost (sgn_insns, !speed_p);
+ was_tie = true;
+ }
+
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, ";; positive extension:%s unsigned cost: %u; "
+ "signed cost: %u\n",
+ was_tie ? " (needed tie breaker)" : "",
+ uns_cost, sgn_cost);
+ if (uns_cost < sgn_cost
+ || (uns_cost == sgn_cost && TYPE_UNSIGNED (TREE_TYPE (treeop0))))
+ {
+ emit_insn (uns_insns);
+ sgn_ret = uns_ret;
+ }
+ else
+ emit_insn (sgn_insns);
+ if (target == NULL_RTX)
+ op0 = sgn_ret;
+ else
+ op0 = target;
+ }
else if (target == 0)
- op0 = convert_to_mode (mode, op0,
- TYPE_UNSIGNED (TREE_TYPE
- (treeop0)));
+ op0 = convert_to_mode (mode, op0, TYPE_UNSIGNED (TREE_TYPE (treeop0)));
else
{
- convert_move (target, op0,
- TYPE_UNSIGNED (TREE_TYPE (treeop0)));
+ convert_move (target, op0, TYPE_UNSIGNED (TREE_TYPE (treeop0)));
op0 = target;
}
@@ -10310,8 +10346,7 @@ expand_expr_real_2 (const_sepops ops, rtx target, machine_mode tmode,
op0, op1, NULL_RTX, unsignedp);
divmul_ret = expand_mult (mode, divmul_ret, op1, target,
unsignedp);
- rtx_insn *divmul_insns = get_insns ();
- end_sequence ();
+ rtx_insn *divmul_insns = end_sequence ();
start_sequence ();
rtx modsub_ret
= expand_expr_divmod (TRUNC_MOD_EXPR, mode, treeop0, treeop1,
@@ -10320,8 +10355,7 @@ expand_expr_real_2 (const_sepops ops, rtx target, machine_mode tmode,
optab_default);
modsub_ret = expand_binop (mode, this_optab, op0, modsub_ret,
target, unsignedp, OPTAB_LIB_WIDEN);
- rtx_insn *modsub_insns = get_insns ();
- end_sequence ();
+ rtx_insn *modsub_insns = end_sequence ();
unsigned divmul_cost = seq_cost (divmul_insns, speed_p);
unsigned modsub_cost = seq_cost (modsub_insns, speed_p);
/* If costs are the same then use as tie breaker the other other
@@ -10563,8 +10597,7 @@ expand_expr_real_2 (const_sepops ops, rtx target, machine_mode tmode,
and return. */
if (insn)
{
- rtx_insn *seq = get_insns ();
- end_sequence ();
+ rtx_insn *seq = end_sequence ();
emit_insn (seq);
return target;
}
@@ -10736,8 +10769,7 @@ expand_expr_real_2 (const_sepops ops, rtx target, machine_mode tmode,
if (temp != dest_low)
emit_move_insn (dest_low, temp);
- seq = get_insns ();
- end_sequence ();
+ seq = end_sequence ();
temp = target ;
if (have_insn_for (ASHIFT, int_mode))
@@ -10749,8 +10781,7 @@ expand_expr_real_2 (const_sepops ops, rtx target, machine_mode tmode,
target,
unsignedp);
- seq_old = get_insns ();
- end_sequence ();
+ seq_old = end_sequence ();
if (seq_cost (seq, speed_p)
>= seq_cost (seq_old, speed_p))
{
@@ -11389,11 +11420,16 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
/* ??? internal call expansion doesn't follow the usual API
of returning the destination RTX and being passed a desired
target. */
+ if (modifier == EXPAND_WRITE)
+ return DECL_RTL (SSA_NAME_VAR (exp));
rtx dest = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
tree tmplhs = make_tree (TREE_TYPE (exp), dest);
- gimple_call_set_lhs (g, tmplhs);
+ tree var_or_id = SSA_NAME_VAR (exp);
+ if (!var_or_id)
+ var_or_id = SSA_NAME_IDENTIFIER (exp);
+ SET_SSA_NAME_VAR_OR_IDENTIFIER (exp, tmplhs);
expand_internal_call (as_a <gcall *> (g));
- gimple_call_set_lhs (g, exp);
+ SET_SSA_NAME_VAR_OR_IDENTIFIER (exp, var_or_id);
return dest;
}
@@ -13240,7 +13276,7 @@ maybe_optimize_pow2p_mod_cmp (enum tree_code code, tree *arg0, tree *arg1)
|| integer_zerop (*arg1)
/* If c is known to be non-negative, modulo will be expanded as unsigned
modulo. */
- || get_range_pos_neg (treeop0) == 1)
+ || get_range_pos_neg (treeop0, currently_expanding_gimple_stmt) == 1)
return code;
/* x % c == d where d < 0 && d <= -c should be always false. */
@@ -13274,8 +13310,7 @@ maybe_optimize_pow2p_mod_cmp (enum tree_code code, tree *arg0, tree *arg1)
start_sequence ();
rtx mor = expand_expr_real_2 (&ops, NULL_RTX, TYPE_MODE (ops.type),
EXPAND_NORMAL);
- rtx_insn *moinsns = get_insns ();
- end_sequence ();
+ rtx_insn *moinsns = end_sequence ();
unsigned mocost = seq_cost (moinsns, speed_p);
mocost += rtx_cost (mor, mode, EQ, 0, speed_p);
@@ -13290,8 +13325,7 @@ maybe_optimize_pow2p_mod_cmp (enum tree_code code, tree *arg0, tree *arg1)
start_sequence ();
rtx mur = expand_expr_real_2 (&ops, NULL_RTX, TYPE_MODE (ops.type),
EXPAND_NORMAL);
- rtx_insn *muinsns = get_insns ();
- end_sequence ();
+ rtx_insn *muinsns = end_sequence ();
unsigned mucost = seq_cost (muinsns, speed_p);
mucost += rtx_cost (mur, mode, EQ, 0, speed_p);
@@ -13374,7 +13408,8 @@ maybe_optimize_mod_cmp (enum tree_code code, tree *arg0, tree *arg1)
/* If both operands are known to have the sign bit clear, handle
even the signed modulo case as unsigned. treeop1 is always
positive >= 2, checked above. */
- if (!TYPE_UNSIGNED (type) && get_range_pos_neg (treeop0) != 1)
+ if (!TYPE_UNSIGNED (type)
+ && get_range_pos_neg (treeop0, currently_expanding_gimple_stmt) != 1)
sgn = SIGNED;
if (!TYPE_UNSIGNED (type))
@@ -13477,8 +13512,7 @@ maybe_optimize_mod_cmp (enum tree_code code, tree *arg0, tree *arg1)
start_sequence ();
rtx mor = expand_expr_real_2 (&ops, NULL_RTX, TYPE_MODE (ops.type),
EXPAND_NORMAL);
- rtx_insn *moinsns = get_insns ();
- end_sequence ();
+ rtx_insn *moinsns = end_sequence ();
unsigned mocost = seq_cost (moinsns, speed_p);
mocost += rtx_cost (mor, mode, EQ, 0, speed_p);
@@ -13498,8 +13532,7 @@ maybe_optimize_mod_cmp (enum tree_code code, tree *arg0, tree *arg1)
start_sequence ();
rtx mur = expand_normal (t);
- rtx_insn *muinsns = get_insns ();
- end_sequence ();
+ rtx_insn *muinsns = end_sequence ();
unsigned mucost = seq_cost (muinsns, speed_p);
mucost += rtx_cost (mur, mode, LE, 0, speed_p);