Lines 46-51
along with GCC; see the file COPYING3.
Link Here
|
46 |
#include "recog.h" |
46 |
#include "recog.h" |
47 |
#include "builtins.h" |
47 |
#include "builtins.h" |
48 |
#include "optabs-tree.h" |
48 |
#include "optabs-tree.h" |
|
|
49 |
#include "gimple-ssa.h" |
50 |
#include "tree-phinodes.h" |
51 |
#include "ssa-iterators.h" |
49 |
|
52 |
|
50 |
/* The names of each internal function, indexed by function number. */ |
53 |
/* The names of each internal function, indexed by function number. */ |
51 |
const char *const internal_fn_name_array[] = { |
54 |
const char *const internal_fn_name_array[] = { |
Lines 1172-1177
expand_neg_overflow (location_t loc, tre
Link Here
|
1172 |
} |
1175 |
} |
1173 |
} |
1176 |
} |
1174 |
|
1177 |
|
|
|
1178 |
/* Return true if UNS WIDEN_MULT_EXPR with result mode WMODE and operand |
1179 |
mode MODE can be expanded without using a libcall. */ |
1180 |
|
1181 |
static bool |
1182 |
can_widen_mult_without_libcall (scalar_int_mode wmode, scalar_int_mode mode, |
1183 |
rtx op0, rtx op1, bool uns) |
1184 |
{ |
1185 |
if (find_widening_optab_handler (umul_widen_optab, wmode, mode) |
1186 |
!= CODE_FOR_nothing) |
1187 |
return true; |
1188 |
|
1189 |
if (find_widening_optab_handler (smul_widen_optab, wmode, mode) |
1190 |
!= CODE_FOR_nothing) |
1191 |
return true; |
1192 |
|
1193 |
rtx_insn *last = get_last_insn (); |
1194 |
if (CONSTANT_P (op0)) |
1195 |
op0 = convert_modes (wmode, mode, op0, uns); |
1196 |
else |
1197 |
op0 = gen_raw_REG (wmode, LAST_VIRTUAL_REGISTER + 1); |
1198 |
if (CONSTANT_P (op1)) |
1199 |
op1 = convert_modes (wmode, mode, op1, uns); |
1200 |
else |
1201 |
op1 = gen_raw_REG (wmode, LAST_VIRTUAL_REGISTER + 2); |
1202 |
rtx ret = expand_mult (wmode, op0, op1, NULL_RTX, uns, true); |
1203 |
delete_insns_since (last); |
1204 |
return ret != NULL_RTX; |
1205 |
} |
1206 |
|
1175 |
/* Add mul overflow checking to the statement STMT. */ |
1207 |
/* Add mul overflow checking to the statement STMT. */ |
1176 |
|
1208 |
|
1177 |
static void |
1209 |
static void |
Lines 1465-1473
expand_mul_overflow (location_t loc, tre
Link Here
|
1465 |
ops.op1 = make_tree (type, op1); |
1497 |
ops.op1 = make_tree (type, op1); |
1466 |
ops.op2 = NULL_TREE; |
1498 |
ops.op2 = NULL_TREE; |
1467 |
ops.location = loc; |
1499 |
ops.location = loc; |
|
|
1500 |
|
1501 |
/* Optimize unsigned overflow check where we don't use the |
1502 |
multiplication result, just whether overflow happened. |
1503 |
If we can do MULT_HIGHPART_EXPR, that followed by |
1504 |
comparison of the result against zero is cheapest. |
1505 |
We'll still compute res, but it should be DCEd later. */ |
1506 |
use_operand_p use; |
1507 |
gimple *use_stmt; |
1508 |
if (!is_ubsan |
1509 |
&& lhs |
1510 |
&& uns |
1511 |
&& !(uns0_p && uns1_p && !unsr_p) |
1512 |
&& can_mult_highpart_p (mode, uns) == 1 |
1513 |
&& single_imm_use (lhs, &use, &use_stmt) |
1514 |
&& is_gimple_assign (use_stmt) |
1515 |
&& gimple_assign_rhs_code (use_stmt) == IMAGPART_EXPR) |
1516 |
goto highpart; |
1517 |
|
1468 |
if (GET_MODE_2XWIDER_MODE (mode).exists (&wmode) |
1518 |
if (GET_MODE_2XWIDER_MODE (mode).exists (&wmode) |
1469 |
&& targetm.scalar_mode_supported_p (wmode)) |
1519 |
&& targetm.scalar_mode_supported_p (wmode) |
|
|
1520 |
&& can_widen_mult_without_libcall (wmode, mode, op0, op1, uns)) |
1470 |
{ |
1521 |
{ |
|
|
1522 |
twoxwider: |
1471 |
ops.code = WIDEN_MULT_EXPR; |
1523 |
ops.code = WIDEN_MULT_EXPR; |
1472 |
ops.type |
1524 |
ops.type |
1473 |
= build_nonstandard_integer_type (GET_MODE_PRECISION (wmode), uns); |
1525 |
= build_nonstandard_integer_type (GET_MODE_PRECISION (wmode), uns); |
Lines 1495-1500
expand_mul_overflow (location_t loc, tre
Link Here
|
1495 |
profile_probability::very_likely ()); |
1547 |
profile_probability::very_likely ()); |
1496 |
} |
1548 |
} |
1497 |
} |
1549 |
} |
|
|
1550 |
else if (can_mult_highpart_p (mode, uns) == 1) |
1551 |
{ |
1552 |
highpart: |
1553 |
ops.code = MULT_HIGHPART_EXPR; |
1554 |
ops.type = type; |
1555 |
|
1556 |
rtx hipart = expand_expr_real_2 (&ops, NULL_RTX, mode, |
1557 |
EXPAND_NORMAL); |
1558 |
ops.code = MULT_EXPR; |
1559 |
res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL); |
1560 |
if (uns) |
1561 |
/* For the unsigned multiplication, there was overflow if |
1562 |
HIPART is non-zero. */ |
1563 |
do_compare_rtx_and_jump (hipart, const0_rtx, EQ, true, mode, |
1564 |
NULL_RTX, NULL, done_label, |
1565 |
profile_probability::very_likely ()); |
1566 |
else |
1567 |
{ |
1568 |
rtx signbit = expand_shift (RSHIFT_EXPR, mode, res, prec - 1, |
1569 |
NULL_RTX, 0); |
1570 |
/* RES is low half of the double width result, HIPART |
1571 |
the high half. There was overflow if |
1572 |
HIPART is different from RES < 0 ? -1 : 0. */ |
1573 |
do_compare_rtx_and_jump (signbit, hipart, EQ, true, mode, |
1574 |
NULL_RTX, NULL, done_label, |
1575 |
profile_probability::very_likely ()); |
1576 |
} |
1577 |
|
1578 |
} |
1498 |
else if (int_mode_for_size (prec / 2, 1).exists (&hmode) |
1579 |
else if (int_mode_for_size (prec / 2, 1).exists (&hmode) |
1499 |
&& 2 * GET_MODE_PRECISION (hmode) == prec) |
1580 |
&& 2 * GET_MODE_PRECISION (hmode) == prec) |
1500 |
{ |
1581 |
{ |
Lines 1800-1805
expand_mul_overflow (location_t loc, tre
Link Here
|
1800 |
tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL); |
1881 |
tem = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL); |
1801 |
emit_move_insn (res, tem); |
1882 |
emit_move_insn (res, tem); |
1802 |
} |
1883 |
} |
|
|
1884 |
else if (GET_MODE_2XWIDER_MODE (mode).exists (&wmode) |
1885 |
&& targetm.scalar_mode_supported_p (wmode)) |
1886 |
/* Even emitting a libcall is better than not detecting overflow |
1887 |
at all. */ |
1888 |
goto twoxwider; |
1803 |
else |
1889 |
else |
1804 |
{ |
1890 |
{ |
1805 |
gcc_assert (!is_ubsan); |
1891 |
gcc_assert (!is_ubsan); |
Lines 2588-2594
expand_DIVMOD (internal_fn, gcall *call_
Link Here
|
2588 |
expand_expr (build2 (COMPLEX_EXPR, TREE_TYPE (lhs), |
2674 |
expand_expr (build2 (COMPLEX_EXPR, TREE_TYPE (lhs), |
2589 |
make_tree (TREE_TYPE (arg0), quotient), |
2675 |
make_tree (TREE_TYPE (arg0), quotient), |
2590 |
make_tree (TREE_TYPE (arg1), remainder)), |
2676 |
make_tree (TREE_TYPE (arg1), remainder)), |
2591 |
target, VOIDmode, EXPAND_NORMAL); |
2677 |
target, VOIDmode, EXPAND_NORMAL); |
2592 |
} |
2678 |
} |
2593 |
|
2679 |
|
2594 |
/* Expand a call to FN using the operands in STMT. FN has a single |
2680 |
/* Expand a call to FN using the operands in STMT. FN has a single |