Mercurial > hg > CbC > CbC_gcc
diff gcc/expmed.c @ 63:b7f97abdc517 gcc-4.6-20100522
update gcc from gcc-4.5.0 to gcc-4.6
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 24 May 2010 12:47:05 +0900 |
parents | 77e2b8dfacca |
children | f6334be47118 |
line wrap: on
line diff
--- a/gcc/expmed.c Fri Feb 12 23:41:23 2010 +0900 +++ b/gcc/expmed.c Mon May 24 12:47:05 2010 +0900 @@ -1,7 +1,7 @@ /* Medium-level subroutines: convert bit-field store and extract and shifts, multiplies and divides to rtl instructions. Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GCC. @@ -33,7 +33,6 @@ #include "insn-config.h" #include "expr.h" #include "optabs.h" -#include "real.h" #include "recog.h" #include "langhooks.h" #include "df.h" @@ -698,7 +697,7 @@ and we will need the original value of op0 if insv fails. */ xop0 = gen_rtx_SUBREG (op_mode, SUBREG_REG (xop0), SUBREG_BYTE (xop0)); if (REG_P (xop0) && GET_MODE (xop0) != op_mode) - xop0 = gen_rtx_SUBREG (op_mode, xop0, 0); + xop0 = gen_lowpart_SUBREG (op_mode, xop0); /* If the destination is a paradoxical subreg such that we need a truncate to the inner mode, perform the insertion on a temporary and @@ -1542,7 +1541,7 @@ /* If op0 is a register, we need it in EXT_MODE to make it acceptable to the format of ext(z)v. */ if (REG_P (xop0) && GET_MODE (xop0) != ext_mode) - xop0 = gen_rtx_SUBREG (ext_mode, xop0, 0); + xop0 = gen_lowpart_SUBREG (ext_mode, xop0); if (MEM_P (xop0)) /* Get ref to first byte containing part of the field. */ xop0 = adjust_address (xop0, byte_mode, xoffset); @@ -1839,39 +1838,15 @@ static rtx mask_rtx (enum machine_mode mode, int bitpos, int bitsize, int complement) { - HOST_WIDE_INT masklow, maskhigh; - - if (bitsize == 0) - masklow = 0; - else if (bitpos < HOST_BITS_PER_WIDE_INT) - masklow = (HOST_WIDE_INT) -1 << bitpos; - else - masklow = 0; - - if (bitpos + bitsize < HOST_BITS_PER_WIDE_INT) - masklow &= ((unsigned HOST_WIDE_INT) -1 - >> (HOST_BITS_PER_WIDE_INT - bitpos - bitsize)); - - if (bitpos <= HOST_BITS_PER_WIDE_INT) - maskhigh = -1; - else - maskhigh = (HOST_WIDE_INT) -1 << (bitpos - HOST_BITS_PER_WIDE_INT); - - if (bitsize == 0) - maskhigh = 0; - else if (bitpos + bitsize > HOST_BITS_PER_WIDE_INT) - maskhigh &= ((unsigned HOST_WIDE_INT) -1 - >> (2 * HOST_BITS_PER_WIDE_INT - bitpos - bitsize)); - else - maskhigh = 0; + double_int mask; + + mask = double_int_mask (bitsize); + mask = double_int_lshift (mask, bitpos, HOST_BITS_PER_DOUBLE_INT, false); if (complement) - { - maskhigh = ~maskhigh; - masklow = ~masklow; - } - - return immed_double_const (masklow, maskhigh, mode); + mask = double_int_not (mask); + + return immed_double_int_const (mask, mode); } /* Return a constant integer (CONST_INT or CONST_DOUBLE) rtx with the value @@ -1880,24 +1855,12 @@ static rtx lshift_value (enum machine_mode mode, rtx value, int bitpos, int bitsize) { - unsigned HOST_WIDE_INT v = INTVAL (value); - HOST_WIDE_INT low, high; - - if (bitsize < HOST_BITS_PER_WIDE_INT) - v &= ~((HOST_WIDE_INT) -1 << bitsize); - - if (bitpos < HOST_BITS_PER_WIDE_INT) - { - low = v << bitpos; - high = (bitpos > 0 ? (v >> (HOST_BITS_PER_WIDE_INT - bitpos)) : 0); - } - else - { - low = 0; - high = v << (bitpos - HOST_BITS_PER_WIDE_INT); - } - - return immed_double_const (low, high, mode); + double_int val; + + val = double_int_zext (uhwi_to_double_int (INTVAL (value)), bitsize); + val = double_int_lshift (val, bitpos, HOST_BITS_PER_DOUBLE_INT, false); + + return immed_double_int_const (val, mode); } /* Extract a bit field that is split across two words @@ -3253,6 +3216,55 @@ gcc_assert (op0); return op0; } + +/* Perform a widening multiplication and return an rtx for the result. + MODE is mode of value; OP0 and OP1 are what to multiply (rtx's); + TARGET is a suggestion for where to store the result (an rtx). + THIS_OPTAB is the optab we should use, it must be either umul_widen_optab + or smul_widen_optab. + + We check specially for a constant integer as OP1, comparing the + cost of a widening multiply against the cost of a sequence of shifts + and adds. */ + +rtx +expand_widening_mult (enum machine_mode mode, rtx op0, rtx op1, rtx target, + int unsignedp, optab this_optab) +{ + bool speed = optimize_insn_for_speed_p (); + + if (CONST_INT_P (op1) + && (INTVAL (op1) >= 0 + || GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)) + { + HOST_WIDE_INT coeff = INTVAL (op1); + int max_cost; + enum mult_variant variant; + struct algorithm algorithm; + + /* Special case powers of two. */ + if (EXACT_POWER_OF_2_OR_ZERO_P (coeff)) + { + op0 = convert_to_mode (mode, op0, this_optab == umul_widen_optab); + return expand_shift (LSHIFT_EXPR, mode, op0, + build_int_cst (NULL_TREE, floor_log2 (coeff)), + target, unsignedp); + } + + /* Exclude cost of op0 from max_cost to match the cost + calculation of the synth_mult. */ + max_cost = mul_widen_cost[speed][mode]; + if (choose_mult_variant (mode, coeff, &algorithm, &variant, + max_cost)) + { + op0 = convert_to_mode (mode, op0, this_optab == umul_widen_optab); + return expand_mult_const (mode, op0, coeff, target, + &algorithm, variant); + } + } + return expand_binop (mode, this_optab, op0, op1, target, + unsignedp, OPTAB_LIB_WIDEN); +} /* Return the smallest n such that 2**n >= X. */ @@ -5792,7 +5804,7 @@ { label = gen_label_rtx (); do_compare_rtx_and_jump (target, const0_rtx, EQ, unsignedp, - mode, NULL_RTX, NULL_RTX, label); + mode, NULL_RTX, NULL_RTX, label, -1); emit_move_insn (target, trueval); emit_label (label); return target; @@ -5830,7 +5842,7 @@ emit_move_insn (target, trueval); label = gen_label_rtx (); do_compare_rtx_and_jump (op0, op1, code, unsignedp, mode, NULL_RTX, - NULL_RTX, label); + NULL_RTX, label, -1); emit_move_insn (target, falseval); emit_label (label); @@ -5848,5 +5860,5 @@ { int unsignedp = (op == LTU || op == LEU || op == GTU || op == GEU); do_compare_rtx_and_jump (arg1, arg2, op, unsignedp, mode, - NULL_RTX, NULL_RTX, label); + NULL_RTX, NULL_RTX, label, -1); }