dojump.c (do_jump_by_parts_greater_rtx): Invert probability when swapping the arms of the branch.
* dojump.c (do_jump_by_parts_greater_rtx): Invert probability when swapping the arms of the branch. * internal-fn.c (expand_addsub_overflow): Use a straight-line code sequence for the generic signed-signed-signed case. From-SVN: r241656
This commit is contained in:
parent
eae2ada503
commit
4713516712
3 changed files with 60 additions and 40 deletions
|
@ -1,3 +1,10 @@
|
|||
2016-10-28 Eric Botcazou <ebotcazou@adacore.com>
|
||||
|
||||
* dojump.c (do_jump_by_parts_greater_rtx): Invert probability when
|
||||
swapping the arms of the branch.
|
||||
* internal-fn.c (expand_addsub_overflow): Use a straight-line code
|
||||
sequence for the generic signed-signed-signed case.
|
||||
|
||||
2016-10-28 Jeff Law <law@redhat.com>
|
||||
|
||||
* config/bfin/bfin.c (bfin_legitimate_address_p): Add missing
|
||||
|
|
|
@ -703,6 +703,7 @@ do_jump_by_parts_greater_rtx (machine_mode mode, int unsignedp, rtx op0,
|
|||
if_false_label = drop_through_label;
|
||||
drop_through_if_true = false;
|
||||
drop_through_if_false = true;
|
||||
prob = inv (prob);
|
||||
}
|
||||
|
||||
/* Compare a word at a time, high order first. */
|
||||
|
|
|
@ -847,56 +847,68 @@ expand_addsub_overflow (location_t loc, tree_code code, tree lhs,
|
|||
delete_insns_since (last);
|
||||
}
|
||||
|
||||
rtx_code_label *sub_check = gen_label_rtx ();
|
||||
int pos_neg = 3;
|
||||
|
||||
/* Compute the operation. On RTL level, the addition is always
|
||||
unsigned. */
|
||||
res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
|
||||
op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
|
||||
|
||||
/* If we can prove one of the arguments (for MINUS_EXPR only
|
||||
/* If we can prove that one of the arguments (for MINUS_EXPR only
|
||||
the second operand, as subtraction is not commutative) is always
|
||||
non-negative or always negative, we can do just one comparison
|
||||
and conditional jump instead of 2 at runtime, 3 present in the
|
||||
emitted code. If one of the arguments is CONST_INT, all we
|
||||
need is to make sure it is op1, then the first
|
||||
do_compare_rtx_and_jump will be just folded. Otherwise try
|
||||
to use range info if available. */
|
||||
if (code == PLUS_EXPR && CONST_INT_P (op0))
|
||||
std::swap (op0, op1);
|
||||
else if (CONST_INT_P (op1))
|
||||
;
|
||||
else if (code == PLUS_EXPR && TREE_CODE (arg0) == SSA_NAME)
|
||||
and conditional jump. */
|
||||
int pos_neg = get_range_pos_neg (arg1);
|
||||
if (code == PLUS_EXPR)
|
||||
{
|
||||
pos_neg = get_range_pos_neg (arg0);
|
||||
if (pos_neg != 3)
|
||||
std::swap (op0, op1);
|
||||
}
|
||||
if (pos_neg == 3 && !CONST_INT_P (op1) && TREE_CODE (arg1) == SSA_NAME)
|
||||
pos_neg = get_range_pos_neg (arg1);
|
||||
|
||||
/* If the op1 is negative, we have to use a different check. */
|
||||
if (pos_neg == 3)
|
||||
do_compare_rtx_and_jump (op1, const0_rtx, LT, false, mode, NULL_RTX,
|
||||
NULL, sub_check, PROB_EVEN);
|
||||
|
||||
/* Compare the result of the operation with one of the operands. */
|
||||
if (pos_neg & 1)
|
||||
do_compare_rtx_and_jump (res, op0, code == PLUS_EXPR ? GE : LE,
|
||||
false, mode, NULL_RTX, NULL, done_label,
|
||||
PROB_VERY_LIKELY);
|
||||
|
||||
/* If we get here, we have to print the error. */
|
||||
if (pos_neg == 3)
|
||||
{
|
||||
emit_jump (do_error);
|
||||
emit_label (sub_check);
|
||||
int pos_neg0 = get_range_pos_neg (arg0);
|
||||
if (pos_neg0 != 3 && pos_neg == 3)
|
||||
{
|
||||
std::swap (op0, op1);
|
||||
pos_neg = pos_neg0;
|
||||
}
|
||||
}
|
||||
|
||||
/* We have k = a + b for b < 0 here. k <= a must hold. */
|
||||
if (pos_neg & 2)
|
||||
do_compare_rtx_and_jump (res, op0, code == PLUS_EXPR ? LE : GE,
|
||||
/* Addition overflows if and only if the two operands have the same sign,
|
||||
and the result has the opposite sign. Subtraction overflows if and
|
||||
only if the two operands have opposite sign, and the subtrahend has
|
||||
the same sign as the result. Here 0 is counted as positive. */
|
||||
if (pos_neg == 3)
|
||||
{
|
||||
/* Compute op0 ^ op1 (operands have opposite sign). */
|
||||
rtx op_xor = expand_binop (mode, xor_optab, op0, op1, NULL_RTX, false,
|
||||
OPTAB_LIB_WIDEN);
|
||||
|
||||
/* Compute res ^ op1 (result and 2nd operand have opposite sign). */
|
||||
rtx res_xor = expand_binop (mode, xor_optab, res, op1, NULL_RTX, false,
|
||||
OPTAB_LIB_WIDEN);
|
||||
|
||||
rtx tem;
|
||||
if (code == PLUS_EXPR)
|
||||
{
|
||||
/* Compute (res ^ op1) & ~(op0 ^ op1). */
|
||||
tem = expand_unop (mode, one_cmpl_optab, op_xor, NULL_RTX, false);
|
||||
tem = expand_binop (mode, and_optab, res_xor, tem, NULL_RTX, false,
|
||||
OPTAB_LIB_WIDEN);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Compute (op0 ^ op1) & ~(res ^ op1). */
|
||||
tem = expand_unop (mode, one_cmpl_optab, res_xor, NULL_RTX, false);
|
||||
tem = expand_binop (mode, and_optab, op_xor, tem, NULL_RTX, false,
|
||||
OPTAB_LIB_WIDEN);
|
||||
}
|
||||
|
||||
/* No overflow if the result has bit sign cleared. */
|
||||
do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
|
||||
NULL, done_label, PROB_VERY_LIKELY);
|
||||
}
|
||||
|
||||
/* Compare the result of the operation with the first operand.
|
||||
No overflow for addition if second operand is positive and result
|
||||
is larger or second operand is negative and result is smaller.
|
||||
Likewise for subtraction with sign of second operand flipped. */
|
||||
else
|
||||
do_compare_rtx_and_jump (res, op0,
|
||||
(pos_neg == 1) ^ (code == MINUS_EXPR) ? GE : LE,
|
||||
false, mode, NULL_RTX, NULL, done_label,
|
||||
PROB_VERY_LIKELY);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue