View | Details | Return to bug 82981 | Differences between
and this patch

Collapse All | Expand All

(-)gcc/internal-fn.c.jj (-2 / +88 lines)
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
(-)gcc/expmed.h.jj (-1 / +1 lines)
Lines 727-733 extern rtx extract_bit_field (rtx, unsig Link Here
727
			      unsigned HOST_WIDE_INT, int, rtx,
727
			      unsigned HOST_WIDE_INT, int, rtx,
728
			      machine_mode, machine_mode, bool, rtx *);
728
			      machine_mode, machine_mode, bool, rtx *);
729
extern rtx extract_low_bits (machine_mode, machine_mode, rtx);
729
extern rtx extract_low_bits (machine_mode, machine_mode, rtx);
730
extern rtx expand_mult (machine_mode, rtx, rtx, rtx, int);
730
extern rtx expand_mult (machine_mode, rtx, rtx, rtx, int, bool = false);
731
extern rtx expand_mult_highpart_adjust (scalar_int_mode, rtx, rtx, rtx,
731
extern rtx expand_mult_highpart_adjust (scalar_int_mode, rtx, rtx, rtx,
732
					rtx, int);
732
					rtx, int);
733
733
(-)gcc/expmed.c.jj (-4 / +6 lines)
Lines 3284-3290 expand_mult_const (machine_mode mode, rt Link Here
3284
3284
3285
rtx
3285
rtx
3286
expand_mult (machine_mode mode, rtx op0, rtx op1, rtx target,
3286
expand_mult (machine_mode mode, rtx op0, rtx op1, rtx target,
3287
	     int unsignedp)
3287
	     int unsignedp, bool no_libcall)
3288
{
3288
{
3289
  enum mult_variant variant;
3289
  enum mult_variant variant;
3290
  struct algorithm algorithm;
3290
  struct algorithm algorithm;
Lines 3420-3433 expand_mult (machine_mode mode, rtx op0, Link Here
3420
    {
3420
    {
3421
      op0 = force_reg (GET_MODE (op0), op0);
3421
      op0 = force_reg (GET_MODE (op0), op0);
3422
      return expand_binop (mode, add_optab, op0, op0,
3422
      return expand_binop (mode, add_optab, op0, op0,
3423
			   target, unsignedp, OPTAB_LIB_WIDEN);
3423
			   target, unsignedp,
3424
			   no_libcall ? OPTAB_WIDEN : OPTAB_LIB_WIDEN);
3424
    }
3425
    }
3425
3426
3426
  /* This used to use umul_optab if unsigned, but for non-widening multiply
3427
  /* This used to use umul_optab if unsigned, but for non-widening multiply
3427
     there is no difference between signed and unsigned.  */
3428
     there is no difference between signed and unsigned.  */
3428
  op0 = expand_binop (mode, do_trapv ? smulv_optab : smul_optab,
3429
  op0 = expand_binop (mode, do_trapv ? smulv_optab : smul_optab,
3429
		      op0, op1, target, unsignedp, OPTAB_LIB_WIDEN);
3430
		      op0, op1, target, unsignedp,
3430
  gcc_assert (op0);
3431
		      no_libcall ? OPTAB_WIDEN : OPTAB_LIB_WIDEN);
3432
  gcc_assert (op0 || no_libcall);
3431
  return op0;
3433
  return op0;
3432
}
3434
}
3433
3435

Return to bug 82981