Commit 92344ed0 by Jakub Jelinek Committed by Jakub Jelinek

re PR target/63848 (FAIL: c-c++-common/torture/builtin-arith-overflow-17.c -O0 execution test)

	PR target/63848
	PR target/63975
	* internal-fn.c (expand_arith_overflow_result_store,
	expand_addsub_overflow, expand_neg_overflow, expand_mul_overflow): Use
	do_compare_rtx_and_jump instead of emit_cmp_and_jump_insns everywhere,
	adjust arguments to those functions.  Use unsignedp = true for
	EQ, NE, GEU, LEU, LTU and GTU comparisons.

From-SVN: r217946
parent 09877e13
2014-11-21 Jakub Jelinek <jakub@redhat.com> 2014-11-21 Jakub Jelinek <jakub@redhat.com>
PR target/63848
PR target/63975
* internal-fn.c (expand_arith_overflow_result_store,
expand_addsub_overflow, expand_neg_overflow, expand_mul_overflow): Use
do_compare_rtx_and_jump instead of emit_cmp_and_jump_insns everywhere,
adjust arguments to those functions. Use unsignedp = true for
EQ, NE, GEU, LEU, LTU and GTU comparisons.
PR tree-optimization/64006 PR tree-optimization/64006
* tree-vrp.c (stmt_interesting_for_vrp): Return true * tree-vrp.c (stmt_interesting_for_vrp): Return true
for {ADD,SUB,MUL}_OVERFLOW internal calls. for {ADD,SUB,MUL}_OVERFLOW internal calls.
...@@ -386,8 +386,8 @@ expand_arith_overflow_result_store (tree lhs, rtx target, ...@@ -386,8 +386,8 @@ expand_arith_overflow_result_store (tree lhs, rtx target,
int uns = TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs))); int uns = TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs)));
lres = convert_modes (tgtmode, mode, res, uns); lres = convert_modes (tgtmode, mode, res, uns);
gcc_assert (GET_MODE_PRECISION (tgtmode) < GET_MODE_PRECISION (mode)); gcc_assert (GET_MODE_PRECISION (tgtmode) < GET_MODE_PRECISION (mode));
emit_cmp_and_jump_insns (res, convert_modes (mode, tgtmode, lres, uns), do_compare_rtx_and_jump (res, convert_modes (mode, tgtmode, lres, uns),
EQ, NULL_RTX, mode, false, done_label, EQ, true, mode, NULL_RTX, NULL_RTX, done_label,
PROB_VERY_LIKELY); PROB_VERY_LIKELY);
write_complex_part (target, const1_rtx, true); write_complex_part (target, const1_rtx, true);
emit_label (done_label); emit_label (done_label);
...@@ -533,8 +533,8 @@ expand_addsub_overflow (location_t loc, tree_code code, tree lhs, ...@@ -533,8 +533,8 @@ expand_addsub_overflow (location_t loc, tree_code code, tree lhs,
? (CONST_SCALAR_INT_P (op0) && REG_P (op1)) ? (CONST_SCALAR_INT_P (op0) && REG_P (op1))
: CONST_SCALAR_INT_P (op1))) : CONST_SCALAR_INT_P (op1)))
tem = op1; tem = op1;
emit_cmp_and_jump_insns (res, tem, code == PLUS_EXPR ? GEU : LEU, do_compare_rtx_and_jump (res, tem, code == PLUS_EXPR ? GEU : LEU,
NULL_RTX, mode, false, done_label, true, mode, NULL_RTX, NULL_RTX, done_label,
PROB_VERY_LIKELY); PROB_VERY_LIKELY);
goto do_error_label; goto do_error_label;
} }
...@@ -549,7 +549,7 @@ expand_addsub_overflow (location_t loc, tree_code code, tree lhs, ...@@ -549,7 +549,7 @@ expand_addsub_overflow (location_t loc, tree_code code, tree lhs,
rtx tem = expand_binop (mode, add_optab, rtx tem = expand_binop (mode, add_optab,
code == PLUS_EXPR ? res : op0, sgn, code == PLUS_EXPR ? res : op0, sgn,
NULL_RTX, false, OPTAB_LIB_WIDEN); NULL_RTX, false, OPTAB_LIB_WIDEN);
emit_cmp_and_jump_insns (tem, op1, GEU, NULL_RTX, mode, false, do_compare_rtx_and_jump (tem, op1, GEU, true, mode, NULL_RTX, NULL_RTX,
done_label, PROB_VERY_LIKELY); done_label, PROB_VERY_LIKELY);
goto do_error_label; goto do_error_label;
} }
...@@ -591,9 +591,9 @@ expand_addsub_overflow (location_t loc, tree_code code, tree lhs, ...@@ -591,9 +591,9 @@ expand_addsub_overflow (location_t loc, tree_code code, tree lhs,
emit_jump (do_error); emit_jump (do_error);
else if (pos_neg == 3) else if (pos_neg == 3)
/* If ARG0 is not known to be always positive, check at runtime. */ /* If ARG0 is not known to be always positive, check at runtime. */
emit_cmp_and_jump_insns (op0, const0_rtx, LT, NULL_RTX, mode, false, do_compare_rtx_and_jump (op0, const0_rtx, LT, false, mode, NULL_RTX,
do_error, PROB_VERY_UNLIKELY); NULL_RTX, do_error, PROB_VERY_UNLIKELY);
emit_cmp_and_jump_insns (op1, op0, LEU, NULL_RTX, mode, false, do_compare_rtx_and_jump (op1, op0, LEU, true, mode, NULL_RTX, NULL_RTX,
done_label, PROB_VERY_LIKELY); done_label, PROB_VERY_LIKELY);
goto do_error_label; goto do_error_label;
} }
...@@ -607,7 +607,7 @@ expand_addsub_overflow (location_t loc, tree_code code, tree lhs, ...@@ -607,7 +607,7 @@ expand_addsub_overflow (location_t loc, tree_code code, tree lhs,
OPTAB_LIB_WIDEN); OPTAB_LIB_WIDEN);
rtx tem = expand_binop (mode, add_optab, op1, sgn, NULL_RTX, false, rtx tem = expand_binop (mode, add_optab, op1, sgn, NULL_RTX, false,
OPTAB_LIB_WIDEN); OPTAB_LIB_WIDEN);
emit_cmp_and_jump_insns (op0, tem, LTU, NULL_RTX, mode, false, do_compare_rtx_and_jump (op0, tem, LTU, true, mode, NULL_RTX, NULL_RTX,
done_label, PROB_VERY_LIKELY); done_label, PROB_VERY_LIKELY);
goto do_error_label; goto do_error_label;
} }
...@@ -619,8 +619,8 @@ expand_addsub_overflow (location_t loc, tree_code code, tree lhs, ...@@ -619,8 +619,8 @@ expand_addsub_overflow (location_t loc, tree_code code, tree lhs,
unsigned. */ unsigned. */
res = expand_binop (mode, add_optab, op0, op1, NULL_RTX, false, res = expand_binop (mode, add_optab, op0, op1, NULL_RTX, false,
OPTAB_LIB_WIDEN); OPTAB_LIB_WIDEN);
emit_cmp_and_jump_insns (res, const0_rtx, LT, NULL_RTX, mode, false, do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode, NULL_RTX,
do_error, PROB_VERY_UNLIKELY); NULL_RTX, do_error, PROB_VERY_UNLIKELY);
rtx tem = op1; rtx tem = op1;
/* The operation is commutative, so we can pick operand to compare /* The operation is commutative, so we can pick operand to compare
against. For prec <= BITS_PER_WORD, I think preferring REG operand against. For prec <= BITS_PER_WORD, I think preferring REG operand
...@@ -633,7 +633,7 @@ expand_addsub_overflow (location_t loc, tree_code code, tree lhs, ...@@ -633,7 +633,7 @@ expand_addsub_overflow (location_t loc, tree_code code, tree lhs,
? (CONST_SCALAR_INT_P (op1) && REG_P (op0)) ? (CONST_SCALAR_INT_P (op1) && REG_P (op0))
: CONST_SCALAR_INT_P (op0)) : CONST_SCALAR_INT_P (op0))
tem = op0; tem = op0;
emit_cmp_and_jump_insns (res, tem, GEU, NULL_RTX, mode, false, do_compare_rtx_and_jump (res, tem, GEU, true, mode, NULL_RTX, NULL_RTX,
done_label, PROB_VERY_LIKELY); done_label, PROB_VERY_LIKELY);
goto do_error_label; goto do_error_label;
} }
...@@ -663,25 +663,26 @@ expand_addsub_overflow (location_t loc, tree_code code, tree lhs, ...@@ -663,25 +663,26 @@ expand_addsub_overflow (location_t loc, tree_code code, tree lhs,
tem = expand_binop (mode, ((pos_neg == 1) ^ (code == MINUS_EXPR)) tem = expand_binop (mode, ((pos_neg == 1) ^ (code == MINUS_EXPR))
? and_optab : ior_optab, ? and_optab : ior_optab,
op0, res, NULL_RTX, false, OPTAB_LIB_WIDEN); op0, res, NULL_RTX, false, OPTAB_LIB_WIDEN);
emit_cmp_and_jump_insns (tem, const0_rtx, GE, NULL_RTX, mode, false, do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
done_label, PROB_VERY_LIKELY); NULL_RTX, done_label, PROB_VERY_LIKELY);
} }
else else
{ {
rtx_code_label *do_ior_label = gen_label_rtx (); rtx_code_label *do_ior_label = gen_label_rtx ();
emit_cmp_and_jump_insns (op1, const0_rtx, do_compare_rtx_and_jump (op1, const0_rtx,
code == MINUS_EXPR ? GE : LT, NULL_RTX, code == MINUS_EXPR ? GE : LT, false, mode,
mode, false, do_ior_label, PROB_EVEN); NULL_RTX, NULL_RTX, do_ior_label,
PROB_EVEN);
tem = expand_binop (mode, and_optab, op0, res, NULL_RTX, false, tem = expand_binop (mode, and_optab, op0, res, NULL_RTX, false,
OPTAB_LIB_WIDEN); OPTAB_LIB_WIDEN);
emit_cmp_and_jump_insns (tem, const0_rtx, GE, NULL_RTX, mode, false, do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
done_label, PROB_VERY_LIKELY); NULL_RTX, done_label, PROB_VERY_LIKELY);
emit_jump (do_error); emit_jump (do_error);
emit_label (do_ior_label); emit_label (do_ior_label);
tem = expand_binop (mode, ior_optab, op0, res, NULL_RTX, false, tem = expand_binop (mode, ior_optab, op0, res, NULL_RTX, false,
OPTAB_LIB_WIDEN); OPTAB_LIB_WIDEN);
emit_cmp_and_jump_insns (tem, const0_rtx, GE, NULL_RTX, mode, false, do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
done_label, PROB_VERY_LIKELY); NULL_RTX, done_label, PROB_VERY_LIKELY);
} }
goto do_error_label; goto do_error_label;
} }
...@@ -694,14 +695,14 @@ expand_addsub_overflow (location_t loc, tree_code code, tree lhs, ...@@ -694,14 +695,14 @@ expand_addsub_overflow (location_t loc, tree_code code, tree lhs,
res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false, res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
OPTAB_LIB_WIDEN); OPTAB_LIB_WIDEN);
rtx_code_label *op0_geu_op1 = gen_label_rtx (); rtx_code_label *op0_geu_op1 = gen_label_rtx ();
emit_cmp_and_jump_insns (op0, op1, GEU, NULL_RTX, mode, false, do_compare_rtx_and_jump (op0, op1, GEU, true, mode, NULL_RTX, NULL_RTX,
op0_geu_op1, PROB_EVEN); op0_geu_op1, PROB_EVEN);
emit_cmp_and_jump_insns (res, const0_rtx, LT, NULL_RTX, mode, false, do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode, NULL_RTX,
done_label, PROB_VERY_LIKELY); NULL_RTX, done_label, PROB_VERY_LIKELY);
emit_jump (do_error); emit_jump (do_error);
emit_label (op0_geu_op1); emit_label (op0_geu_op1);
emit_cmp_and_jump_insns (res, const0_rtx, GE, NULL_RTX, mode, false, do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode, NULL_RTX,
done_label, PROB_VERY_LIKELY); NULL_RTX, done_label, PROB_VERY_LIKELY);
goto do_error_label; goto do_error_label;
} }
...@@ -754,7 +755,7 @@ expand_addsub_overflow (location_t loc, tree_code code, tree lhs, ...@@ -754,7 +755,7 @@ expand_addsub_overflow (location_t loc, tree_code code, tree lhs,
and conditional jump instead of 2 at runtime, 3 present in the and conditional jump instead of 2 at runtime, 3 present in the
emitted code. If one of the arguments is CONST_INT, all we emitted code. If one of the arguments is CONST_INT, all we
need is to make sure it is op1, then the first need is to make sure it is op1, then the first
emit_cmp_and_jump_insns will be just folded. Otherwise try do_compare_rtx_and_jump will be just folded. Otherwise try
to use range info if available. */ to use range info if available. */
if (code == PLUS_EXPR && CONST_INT_P (op0)) if (code == PLUS_EXPR && CONST_INT_P (op0))
{ {
...@@ -779,13 +780,13 @@ expand_addsub_overflow (location_t loc, tree_code code, tree lhs, ...@@ -779,13 +780,13 @@ expand_addsub_overflow (location_t loc, tree_code code, tree lhs,
/* If the op1 is negative, we have to use a different check. */ /* If the op1 is negative, we have to use a different check. */
if (pos_neg == 3) if (pos_neg == 3)
emit_cmp_and_jump_insns (op1, const0_rtx, LT, NULL_RTX, mode, do_compare_rtx_and_jump (op1, const0_rtx, LT, false, mode, NULL_RTX,
false, sub_check, PROB_EVEN); NULL_RTX, sub_check, PROB_EVEN);
/* Compare the result of the operation with one of the operands. */ /* Compare the result of the operation with one of the operands. */
if (pos_neg & 1) if (pos_neg & 1)
emit_cmp_and_jump_insns (res, op0, code == PLUS_EXPR ? GE : LE, do_compare_rtx_and_jump (res, op0, code == PLUS_EXPR ? GE : LE,
NULL_RTX, mode, false, done_label, false, mode, NULL_RTX, NULL_RTX, done_label,
PROB_VERY_LIKELY); PROB_VERY_LIKELY);
/* If we get here, we have to print the error. */ /* If we get here, we have to print the error. */
...@@ -798,8 +799,8 @@ expand_addsub_overflow (location_t loc, tree_code code, tree lhs, ...@@ -798,8 +799,8 @@ expand_addsub_overflow (location_t loc, tree_code code, tree lhs,
/* We have k = a + b for b < 0 here. k <= a must hold. */ /* We have k = a + b for b < 0 here. k <= a must hold. */
if (pos_neg & 2) if (pos_neg & 2)
emit_cmp_and_jump_insns (res, op0, code == PLUS_EXPR ? LE : GE, do_compare_rtx_and_jump (res, op0, code == PLUS_EXPR ? LE : GE,
NULL_RTX, mode, false, done_label, false, mode, NULL_RTX, NULL_RTX, done_label,
PROB_VERY_LIKELY); PROB_VERY_LIKELY);
} }
...@@ -895,7 +896,7 @@ expand_neg_overflow (location_t loc, tree lhs, tree arg1, bool is_ubsan) ...@@ -895,7 +896,7 @@ expand_neg_overflow (location_t loc, tree lhs, tree arg1, bool is_ubsan)
/* Compare the operand with the most negative value. */ /* Compare the operand with the most negative value. */
rtx minv = expand_normal (TYPE_MIN_VALUE (TREE_TYPE (arg1))); rtx minv = expand_normal (TYPE_MIN_VALUE (TREE_TYPE (arg1)));
emit_cmp_and_jump_insns (op1, minv, NE, NULL_RTX, mode, false, do_compare_rtx_and_jump (op1, minv, NE, true, mode, NULL_RTX, NULL_RTX,
done_label, PROB_VERY_LIKELY); done_label, PROB_VERY_LIKELY);
} }
...@@ -1031,16 +1032,16 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1, ...@@ -1031,16 +1032,16 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
ops.op2 = NULL_TREE; ops.op2 = NULL_TREE;
ops.location = loc; ops.location = loc;
res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL); res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
emit_cmp_and_jump_insns (op1, const0_rtx, EQ, NULL_RTX, mode, do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
false, done_label, PROB_VERY_LIKELY); NULL_RTX, done_label, PROB_VERY_LIKELY);
goto do_error_label; goto do_error_label;
case 3: case 3:
rtx_code_label *do_main_label; rtx_code_label *do_main_label;
do_main_label = gen_label_rtx (); do_main_label = gen_label_rtx ();
emit_cmp_and_jump_insns (op0, const0_rtx, GE, NULL_RTX, mode, do_compare_rtx_and_jump (op0, const0_rtx, GE, false, mode, NULL_RTX,
false, do_main_label, PROB_VERY_LIKELY); NULL_RTX, do_main_label, PROB_VERY_LIKELY);
emit_cmp_and_jump_insns (op1, const0_rtx, EQ, NULL_RTX, mode, do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
false, do_main_label, PROB_VERY_LIKELY); NULL_RTX, do_main_label, PROB_VERY_LIKELY);
write_complex_part (target, const1_rtx, true); write_complex_part (target, const1_rtx, true);
emit_label (do_main_label); emit_label (do_main_label);
goto do_main; goto do_main;
...@@ -1076,16 +1077,16 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1, ...@@ -1076,16 +1077,16 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
ops.op2 = NULL_TREE; ops.op2 = NULL_TREE;
ops.location = loc; ops.location = loc;
res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL); res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
emit_cmp_and_jump_insns (op0, const0_rtx, EQ, NULL_RTX, mode, do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
false, done_label, PROB_VERY_LIKELY); NULL_RTX, done_label, PROB_VERY_LIKELY);
emit_cmp_and_jump_insns (op0, constm1_rtx, NE, NULL_RTX, mode, do_compare_rtx_and_jump (op0, constm1_rtx, NE, true, mode, NULL_RTX,
false, do_error, PROB_VERY_UNLIKELY); NULL_RTX, do_error, PROB_VERY_UNLIKELY);
int prec; int prec;
prec = GET_MODE_PRECISION (mode); prec = GET_MODE_PRECISION (mode);
rtx sgn; rtx sgn;
sgn = immed_wide_int_const (wi::min_value (prec, SIGNED), mode); sgn = immed_wide_int_const (wi::min_value (prec, SIGNED), mode);
emit_cmp_and_jump_insns (op1, sgn, EQ, NULL_RTX, mode, do_compare_rtx_and_jump (op1, sgn, EQ, true, mode, NULL_RTX,
false, done_label, PROB_VERY_LIKELY); NULL_RTX, done_label, PROB_VERY_LIKELY);
goto do_error_label; goto do_error_label;
case 3: case 3:
/* Rest of handling of this case after res is computed. */ /* Rest of handling of this case after res is computed. */
...@@ -1130,8 +1131,9 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1, ...@@ -1130,8 +1131,9 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL); res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
tem = expand_binop (mode, and_optab, op0, op1, NULL_RTX, false, tem = expand_binop (mode, and_optab, op0, op1, NULL_RTX, false,
OPTAB_LIB_WIDEN); OPTAB_LIB_WIDEN);
emit_cmp_and_jump_insns (tem, const0_rtx, EQ, NULL_RTX, mode, do_compare_rtx_and_jump (tem, const0_rtx, EQ, true, mode,
false, done_label, PROB_VERY_LIKELY); NULL_RTX, NULL_RTX, done_label,
PROB_VERY_LIKELY);
goto do_error_label; goto do_error_label;
} }
/* The general case, do all the needed comparisons at runtime. */ /* The general case, do all the needed comparisons at runtime. */
...@@ -1147,8 +1149,9 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1, ...@@ -1147,8 +1149,9 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
after_negate_label = gen_label_rtx (); after_negate_label = gen_label_rtx ();
tem = expand_binop (mode, and_optab, op0, op1, NULL_RTX, false, tem = expand_binop (mode, and_optab, op0, op1, NULL_RTX, false,
OPTAB_LIB_WIDEN); OPTAB_LIB_WIDEN);
emit_cmp_and_jump_insns (tem, const0_rtx, GE, NULL_RTX, mode, false, do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
after_negate_label, PROB_VERY_LIKELY); NULL_RTX, after_negate_label,
PROB_VERY_LIKELY);
/* Both arguments negative here, negate them and continue with /* Both arguments negative here, negate them and continue with
normal unsigned overflow checking multiplication. */ normal unsigned overflow checking multiplication. */
emit_move_insn (op0, expand_unop (mode, neg_optab, op0, emit_move_insn (op0, expand_unop (mode, neg_optab, op0,
...@@ -1163,14 +1166,14 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1, ...@@ -1163,14 +1166,14 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
emit_label (after_negate_label); emit_label (after_negate_label);
tem2 = expand_binop (mode, xor_optab, op0, op1, NULL_RTX, false, tem2 = expand_binop (mode, xor_optab, op0, op1, NULL_RTX, false,
OPTAB_LIB_WIDEN); OPTAB_LIB_WIDEN);
emit_cmp_and_jump_insns (tem2, const0_rtx, GE, NULL_RTX, mode, false, do_compare_rtx_and_jump (tem2, const0_rtx, GE, false, mode, NULL_RTX,
do_main_label, PROB_VERY_LIKELY); NULL_RTX, do_main_label, PROB_VERY_LIKELY);
/* One argument is negative here, the other positive. This /* One argument is negative here, the other positive. This
overflows always, unless one of the arguments is 0. But overflows always, unless one of the arguments is 0. But
if e.g. s2 is 0, (U) s1 * 0 doesn't overflow, whatever s1 if e.g. s2 is 0, (U) s1 * 0 doesn't overflow, whatever s1
is, thus we can keep do_main code oring in overflow as is. */ is, thus we can keep do_main code oring in overflow as is. */
emit_cmp_and_jump_insns (tem, const0_rtx, EQ, NULL_RTX, mode, false, do_compare_rtx_and_jump (tem, const0_rtx, EQ, true, mode, NULL_RTX,
do_main_label, PROB_VERY_LIKELY); NULL_RTX, do_main_label, PROB_VERY_LIKELY);
write_complex_part (target, const1_rtx, true); write_complex_part (target, const1_rtx, true);
emit_label (do_main_label); emit_label (do_main_label);
goto do_main; goto do_main;
...@@ -1235,8 +1238,9 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1, ...@@ -1235,8 +1238,9 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
if (uns) if (uns)
/* For the unsigned multiplication, there was overflow if /* For the unsigned multiplication, there was overflow if
HIPART is non-zero. */ HIPART is non-zero. */
emit_cmp_and_jump_insns (hipart, const0_rtx, EQ, NULL_RTX, mode, do_compare_rtx_and_jump (hipart, const0_rtx, EQ, true, mode,
false, done_label, PROB_VERY_LIKELY); NULL_RTX, NULL_RTX, done_label,
PROB_VERY_LIKELY);
else else
{ {
rtx signbit = expand_shift (RSHIFT_EXPR, mode, res, prec - 1, rtx signbit = expand_shift (RSHIFT_EXPR, mode, res, prec - 1,
...@@ -1244,8 +1248,9 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1, ...@@ -1244,8 +1248,9 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
/* RES is low half of the double width result, HIPART /* RES is low half of the double width result, HIPART
the high half. There was overflow if the high half. There was overflow if
HIPART is different from RES < 0 ? -1 : 0. */ HIPART is different from RES < 0 ? -1 : 0. */
emit_cmp_and_jump_insns (signbit, hipart, EQ, NULL_RTX, mode, do_compare_rtx_and_jump (signbit, hipart, EQ, true, mode,
false, done_label, PROB_VERY_LIKELY); NULL_RTX, NULL_RTX, done_label,
PROB_VERY_LIKELY);
} }
} }
else if (hmode != BLKmode && 2 * GET_MODE_PRECISION (hmode) == prec) else if (hmode != BLKmode && 2 * GET_MODE_PRECISION (hmode) == prec)
...@@ -1336,12 +1341,13 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1, ...@@ -1336,12 +1341,13 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
} }
if (!op0_small_p) if (!op0_small_p)
emit_cmp_and_jump_insns (signbit0, hipart0, NE, NULL_RTX, hmode, do_compare_rtx_and_jump (signbit0, hipart0, NE, true, hmode,
false, large_op0, PROB_UNLIKELY); NULL_RTX, NULL_RTX, large_op0,
PROB_UNLIKELY);
if (!op1_small_p) if (!op1_small_p)
emit_cmp_and_jump_insns (signbit1, hipart1, NE, NULL_RTX, hmode, do_compare_rtx_and_jump (signbit1, hipart1, NE, true, hmode,
false, small_op0_large_op1, NULL_RTX, NULL_RTX, small_op0_large_op1,
PROB_UNLIKELY); PROB_UNLIKELY);
/* If both op0 and op1 are sign (!uns) or zero (uns) extended from /* If both op0 and op1 are sign (!uns) or zero (uns) extended from
...@@ -1386,8 +1392,9 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1, ...@@ -1386,8 +1392,9 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
emit_label (large_op0); emit_label (large_op0);
if (!op1_small_p) if (!op1_small_p)
emit_cmp_and_jump_insns (signbit1, hipart1, NE, NULL_RTX, hmode, do_compare_rtx_and_jump (signbit1, hipart1, NE, true, hmode,
false, both_ops_large, PROB_UNLIKELY); NULL_RTX, NULL_RTX, both_ops_large,
PROB_UNLIKELY);
/* If op1 is sign (!uns) or zero (uns) extended from hmode to mode, /* If op1 is sign (!uns) or zero (uns) extended from hmode to mode,
but op0 is not, prepare larger, hipart and lopart pseudos and but op0 is not, prepare larger, hipart and lopart pseudos and
...@@ -1422,8 +1429,8 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1, ...@@ -1422,8 +1429,8 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
if (larger_sign == 0) if (larger_sign == 0)
emit_jump (after_hipart_neg); emit_jump (after_hipart_neg);
else if (larger_sign != -1) else if (larger_sign != -1)
emit_cmp_and_jump_insns (hipart, const0_rtx, GE, NULL_RTX, do_compare_rtx_and_jump (hipart, const0_rtx, GE, false, hmode,
hmode, false, after_hipart_neg, NULL_RTX, NULL_RTX, after_hipart_neg,
PROB_EVEN); PROB_EVEN);
tem = convert_modes (mode, hmode, lopart, 1); tem = convert_modes (mode, hmode, lopart, 1);
...@@ -1438,8 +1445,8 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1, ...@@ -1438,8 +1445,8 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
if (smaller_sign == 0) if (smaller_sign == 0)
emit_jump (after_lopart_neg); emit_jump (after_lopart_neg);
else if (smaller_sign != -1) else if (smaller_sign != -1)
emit_cmp_and_jump_insns (lopart, const0_rtx, GE, NULL_RTX, do_compare_rtx_and_jump (lopart, const0_rtx, GE, false, hmode,
hmode, false, after_lopart_neg, NULL_RTX, NULL_RTX, after_lopart_neg,
PROB_EVEN); PROB_EVEN);
tem = expand_simple_binop (mode, MINUS, loxhi, larger, NULL_RTX, tem = expand_simple_binop (mode, MINUS, loxhi, larger, NULL_RTX,
...@@ -1467,8 +1474,8 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1, ...@@ -1467,8 +1474,8 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
gen_lowpart (hmode, loxhi), gen_lowpart (hmode, loxhi),
hprec - 1, NULL_RTX, 0); hprec - 1, NULL_RTX, 0);
emit_cmp_and_jump_insns (signbitloxhi, hipartloxhi, NE, NULL_RTX, do_compare_rtx_and_jump (signbitloxhi, hipartloxhi, NE, true, hmode,
hmode, false, do_overflow, NULL_RTX, NULL_RTX, do_overflow,
PROB_VERY_UNLIKELY); PROB_VERY_UNLIKELY);
/* res = (loxhi << (bitsize / 2)) | (hmode) lo0xlo1; */ /* res = (loxhi << (bitsize / 2)) | (hmode) lo0xlo1; */
...@@ -1503,8 +1510,8 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1, ...@@ -1503,8 +1510,8 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
{ {
tem = expand_simple_binop (hmode, PLUS, hipart0, const1_rtx, tem = expand_simple_binop (hmode, PLUS, hipart0, const1_rtx,
NULL_RTX, 1, OPTAB_DIRECT); NULL_RTX, 1, OPTAB_DIRECT);
emit_cmp_and_jump_insns (tem, const1_rtx, GTU, NULL_RTX, do_compare_rtx_and_jump (tem, const1_rtx, GTU, true, hmode,
hmode, true, do_error, NULL_RTX, NULL_RTX, do_error,
PROB_VERY_UNLIKELY); PROB_VERY_UNLIKELY);
} }
...@@ -1512,8 +1519,8 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1, ...@@ -1512,8 +1519,8 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
{ {
tem = expand_simple_binop (hmode, PLUS, hipart1, const1_rtx, tem = expand_simple_binop (hmode, PLUS, hipart1, const1_rtx,
NULL_RTX, 1, OPTAB_DIRECT); NULL_RTX, 1, OPTAB_DIRECT);
emit_cmp_and_jump_insns (tem, const1_rtx, GTU, NULL_RTX, do_compare_rtx_and_jump (tem, const1_rtx, GTU, true, hmode,
hmode, true, do_error, NULL_RTX, NULL_RTX, do_error,
PROB_VERY_UNLIKELY); PROB_VERY_UNLIKELY);
} }
...@@ -1523,17 +1530,20 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1, ...@@ -1523,17 +1530,20 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
if (op0_sign != 1 && op1_sign != 1 && op0_sign != op1_sign) if (op0_sign != 1 && op1_sign != 1 && op0_sign != op1_sign)
emit_jump (hipart_different); emit_jump (hipart_different);
else if (op0_sign == 1 || op1_sign == 1) else if (op0_sign == 1 || op1_sign == 1)
emit_cmp_and_jump_insns (hipart0, hipart1, NE, NULL_RTX, hmode, do_compare_rtx_and_jump (hipart0, hipart1, NE, true, hmode,
true, hipart_different, PROB_EVEN); NULL_RTX, NULL_RTX, hipart_different,
PROB_EVEN);
emit_cmp_and_jump_insns (res, const0_rtx, LT, NULL_RTX, mode, do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode,
false, do_error, PROB_VERY_UNLIKELY); NULL_RTX, NULL_RTX, do_error,
PROB_VERY_UNLIKELY);
emit_jump (done_label); emit_jump (done_label);
emit_label (hipart_different); emit_label (hipart_different);
emit_cmp_and_jump_insns (res, const0_rtx, GE, NULL_RTX, mode, do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode,
false, do_error, PROB_VERY_UNLIKELY); NULL_RTX, NULL_RTX, do_error,
PROB_VERY_UNLIKELY);
emit_jump (done_label); emit_jump (done_label);
} }
...@@ -1577,8 +1587,8 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1, ...@@ -1577,8 +1587,8 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
if (uns0_p && uns1_p && !unsr_p) if (uns0_p && uns1_p && !unsr_p)
{ {
rtx_code_label *all_done_label = gen_label_rtx (); rtx_code_label *all_done_label = gen_label_rtx ();
emit_cmp_and_jump_insns (res, const0_rtx, GE, NULL_RTX, mode, do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode, NULL_RTX,
false, all_done_label, PROB_VERY_LIKELY); NULL_RTX, all_done_label, PROB_VERY_LIKELY);
write_complex_part (target, const1_rtx, true); write_complex_part (target, const1_rtx, true);
emit_label (all_done_label); emit_label (all_done_label);
} }
...@@ -1588,15 +1598,15 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1, ...@@ -1588,15 +1598,15 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
{ {
rtx_code_label *all_done_label = gen_label_rtx (); rtx_code_label *all_done_label = gen_label_rtx ();
rtx_code_label *set_noovf = gen_label_rtx (); rtx_code_label *set_noovf = gen_label_rtx ();
emit_cmp_and_jump_insns (op1, const0_rtx, GE, NULL_RTX, mode, do_compare_rtx_and_jump (op1, const0_rtx, GE, false, mode, NULL_RTX,
false, all_done_label, PROB_VERY_LIKELY); NULL_RTX, all_done_label, PROB_VERY_LIKELY);
write_complex_part (target, const1_rtx, true); write_complex_part (target, const1_rtx, true);
emit_cmp_and_jump_insns (op0, const0_rtx, EQ, NULL_RTX, mode, do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
false, set_noovf, PROB_VERY_LIKELY); NULL_RTX, set_noovf, PROB_VERY_LIKELY);
emit_cmp_and_jump_insns (op0, constm1_rtx, NE, NULL_RTX, mode, do_compare_rtx_and_jump (op0, constm1_rtx, NE, true, mode, NULL_RTX,
false, all_done_label, PROB_VERY_UNLIKELY); NULL_RTX, all_done_label, PROB_VERY_UNLIKELY);
emit_cmp_and_jump_insns (op1, res, NE, NULL_RTX, mode, do_compare_rtx_and_jump (op1, res, NE, true, mode, NULL_RTX, NULL_RTX,
false, all_done_label, PROB_VERY_UNLIKELY); all_done_label, PROB_VERY_UNLIKELY);
emit_label (set_noovf); emit_label (set_noovf);
write_complex_part (target, const0_rtx, true); write_complex_part (target, const0_rtx, true);
emit_label (all_done_label); emit_label (all_done_label);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment