Mercurial > hg > CbC > CbC_gcc
comparison 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 |
comparison
equal
deleted
inserted
replaced
56:3c8a44c06a95 | 63:b7f97abdc517 |
---|---|
1 /* Medium-level subroutines: convert bit-field store and extract | 1 /* Medium-level subroutines: convert bit-field store and extract |
2 and shifts, multiplies and divides to rtl instructions. | 2 and shifts, multiplies and divides to rtl instructions. |
3 Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, | 3 Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, |
4 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 | 4 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 |
5 Free Software Foundation, Inc. | 5 Free Software Foundation, Inc. |
6 | 6 |
7 This file is part of GCC. | 7 This file is part of GCC. |
8 | 8 |
9 GCC is free software; you can redistribute it and/or modify it under | 9 GCC is free software; you can redistribute it and/or modify it under |
31 #include "tm_p.h" | 31 #include "tm_p.h" |
32 #include "flags.h" | 32 #include "flags.h" |
33 #include "insn-config.h" | 33 #include "insn-config.h" |
34 #include "expr.h" | 34 #include "expr.h" |
35 #include "optabs.h" | 35 #include "optabs.h" |
36 #include "real.h" | |
37 #include "recog.h" | 36 #include "recog.h" |
38 #include "langhooks.h" | 37 #include "langhooks.h" |
39 #include "df.h" | 38 #include "df.h" |
40 #include "target.h" | 39 #include "target.h" |
41 | 40 |
696 if (GET_CODE (xop0) == SUBREG) | 695 if (GET_CODE (xop0) == SUBREG) |
697 /* We can't just change the mode, because this might clobber op0, | 696 /* We can't just change the mode, because this might clobber op0, |
698 and we will need the original value of op0 if insv fails. */ | 697 and we will need the original value of op0 if insv fails. */ |
699 xop0 = gen_rtx_SUBREG (op_mode, SUBREG_REG (xop0), SUBREG_BYTE (xop0)); | 698 xop0 = gen_rtx_SUBREG (op_mode, SUBREG_REG (xop0), SUBREG_BYTE (xop0)); |
700 if (REG_P (xop0) && GET_MODE (xop0) != op_mode) | 699 if (REG_P (xop0) && GET_MODE (xop0) != op_mode) |
701 xop0 = gen_rtx_SUBREG (op_mode, xop0, 0); | 700 xop0 = gen_lowpart_SUBREG (op_mode, xop0); |
702 | 701 |
703 /* If the destination is a paradoxical subreg such that we need a | 702 /* If the destination is a paradoxical subreg such that we need a |
704 truncate to the inner mode, perform the insertion on a temporary and | 703 truncate to the inner mode, perform the insertion on a temporary and |
705 truncate the result to the original destination. Note that we can't | 704 truncate the result to the original destination. Note that we can't |
706 just truncate the paradoxical subreg as (truncate:N (subreg:W (reg:N | 705 just truncate the paradoxical subreg as (truncate:N (subreg:W (reg:N |
1540 rtx pat; | 1539 rtx pat; |
1541 | 1540 |
1542 /* If op0 is a register, we need it in EXT_MODE to make it | 1541 /* If op0 is a register, we need it in EXT_MODE to make it |
1543 acceptable to the format of ext(z)v. */ | 1542 acceptable to the format of ext(z)v. */ |
1544 if (REG_P (xop0) && GET_MODE (xop0) != ext_mode) | 1543 if (REG_P (xop0) && GET_MODE (xop0) != ext_mode) |
1545 xop0 = gen_rtx_SUBREG (ext_mode, xop0, 0); | 1544 xop0 = gen_lowpart_SUBREG (ext_mode, xop0); |
1546 if (MEM_P (xop0)) | 1545 if (MEM_P (xop0)) |
1547 /* Get ref to first byte containing part of the field. */ | 1546 /* Get ref to first byte containing part of the field. */ |
1548 xop0 = adjust_address (xop0, byte_mode, xoffset); | 1547 xop0 = adjust_address (xop0, byte_mode, xoffset); |
1549 | 1548 |
1550 /* On big-endian machines, we count bits from the most significant. | 1549 /* On big-endian machines, we count bits from the most significant. |
1837 BITSIZE+BITPOS is too small for MODE. */ | 1836 BITSIZE+BITPOS is too small for MODE. */ |
1838 | 1837 |
1839 static rtx | 1838 static rtx |
1840 mask_rtx (enum machine_mode mode, int bitpos, int bitsize, int complement) | 1839 mask_rtx (enum machine_mode mode, int bitpos, int bitsize, int complement) |
1841 { | 1840 { |
1842 HOST_WIDE_INT masklow, maskhigh; | 1841 double_int mask; |
1843 | 1842 |
1844 if (bitsize == 0) | 1843 mask = double_int_mask (bitsize); |
1845 masklow = 0; | 1844 mask = double_int_lshift (mask, bitpos, HOST_BITS_PER_DOUBLE_INT, false); |
1846 else if (bitpos < HOST_BITS_PER_WIDE_INT) | |
1847 masklow = (HOST_WIDE_INT) -1 << bitpos; | |
1848 else | |
1849 masklow = 0; | |
1850 | |
1851 if (bitpos + bitsize < HOST_BITS_PER_WIDE_INT) | |
1852 masklow &= ((unsigned HOST_WIDE_INT) -1 | |
1853 >> (HOST_BITS_PER_WIDE_INT - bitpos - bitsize)); | |
1854 | |
1855 if (bitpos <= HOST_BITS_PER_WIDE_INT) | |
1856 maskhigh = -1; | |
1857 else | |
1858 maskhigh = (HOST_WIDE_INT) -1 << (bitpos - HOST_BITS_PER_WIDE_INT); | |
1859 | |
1860 if (bitsize == 0) | |
1861 maskhigh = 0; | |
1862 else if (bitpos + bitsize > HOST_BITS_PER_WIDE_INT) | |
1863 maskhigh &= ((unsigned HOST_WIDE_INT) -1 | |
1864 >> (2 * HOST_BITS_PER_WIDE_INT - bitpos - bitsize)); | |
1865 else | |
1866 maskhigh = 0; | |
1867 | 1845 |
1868 if (complement) | 1846 if (complement) |
1869 { | 1847 mask = double_int_not (mask); |
1870 maskhigh = ~maskhigh; | 1848 |
1871 masklow = ~masklow; | 1849 return immed_double_int_const (mask, mode); |
1872 } | |
1873 | |
1874 return immed_double_const (masklow, maskhigh, mode); | |
1875 } | 1850 } |
1876 | 1851 |
1877 /* Return a constant integer (CONST_INT or CONST_DOUBLE) rtx with the value | 1852 /* Return a constant integer (CONST_INT or CONST_DOUBLE) rtx with the value |
1878 VALUE truncated to BITSIZE bits and then shifted left BITPOS bits. */ | 1853 VALUE truncated to BITSIZE bits and then shifted left BITPOS bits. */ |
1879 | 1854 |
1880 static rtx | 1855 static rtx |
1881 lshift_value (enum machine_mode mode, rtx value, int bitpos, int bitsize) | 1856 lshift_value (enum machine_mode mode, rtx value, int bitpos, int bitsize) |
1882 { | 1857 { |
1883 unsigned HOST_WIDE_INT v = INTVAL (value); | 1858 double_int val; |
1884 HOST_WIDE_INT low, high; | 1859 |
1885 | 1860 val = double_int_zext (uhwi_to_double_int (INTVAL (value)), bitsize); |
1886 if (bitsize < HOST_BITS_PER_WIDE_INT) | 1861 val = double_int_lshift (val, bitpos, HOST_BITS_PER_DOUBLE_INT, false); |
1887 v &= ~((HOST_WIDE_INT) -1 << bitsize); | 1862 |
1888 | 1863 return immed_double_int_const (val, mode); |
1889 if (bitpos < HOST_BITS_PER_WIDE_INT) | |
1890 { | |
1891 low = v << bitpos; | |
1892 high = (bitpos > 0 ? (v >> (HOST_BITS_PER_WIDE_INT - bitpos)) : 0); | |
1893 } | |
1894 else | |
1895 { | |
1896 low = 0; | |
1897 high = v << (bitpos - HOST_BITS_PER_WIDE_INT); | |
1898 } | |
1899 | |
1900 return immed_double_const (low, high, mode); | |
1901 } | 1864 } |
1902 | 1865 |
1903 /* Extract a bit field that is split across two words | 1866 /* Extract a bit field that is split across two words |
1904 and return an RTX for the result. | 1867 and return an RTX for the result. |
1905 | 1868 |
3250 && flag_trapv && (GET_MODE_CLASS(mode) == MODE_INT) | 3213 && flag_trapv && (GET_MODE_CLASS(mode) == MODE_INT) |
3251 ? smulv_optab : smul_optab, | 3214 ? smulv_optab : smul_optab, |
3252 op0, op1, target, unsignedp, OPTAB_LIB_WIDEN); | 3215 op0, op1, target, unsignedp, OPTAB_LIB_WIDEN); |
3253 gcc_assert (op0); | 3216 gcc_assert (op0); |
3254 return op0; | 3217 return op0; |
3218 } | |
3219 | |
3220 /* Perform a widening multiplication and return an rtx for the result. | |
3221 MODE is mode of value; OP0 and OP1 are what to multiply (rtx's); | |
3222 TARGET is a suggestion for where to store the result (an rtx). | |
3223 THIS_OPTAB is the optab we should use, it must be either umul_widen_optab | |
3224 or smul_widen_optab. | |
3225 | |
3226 We check specially for a constant integer as OP1, comparing the | |
3227 cost of a widening multiply against the cost of a sequence of shifts | |
3228 and adds. */ | |
3229 | |
3230 rtx | |
3231 expand_widening_mult (enum machine_mode mode, rtx op0, rtx op1, rtx target, | |
3232 int unsignedp, optab this_optab) | |
3233 { | |
3234 bool speed = optimize_insn_for_speed_p (); | |
3235 | |
3236 if (CONST_INT_P (op1) | |
3237 && (INTVAL (op1) >= 0 | |
3238 || GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)) | |
3239 { | |
3240 HOST_WIDE_INT coeff = INTVAL (op1); | |
3241 int max_cost; | |
3242 enum mult_variant variant; | |
3243 struct algorithm algorithm; | |
3244 | |
3245 /* Special case powers of two. */ | |
3246 if (EXACT_POWER_OF_2_OR_ZERO_P (coeff)) | |
3247 { | |
3248 op0 = convert_to_mode (mode, op0, this_optab == umul_widen_optab); | |
3249 return expand_shift (LSHIFT_EXPR, mode, op0, | |
3250 build_int_cst (NULL_TREE, floor_log2 (coeff)), | |
3251 target, unsignedp); | |
3252 } | |
3253 | |
3254 /* Exclude cost of op0 from max_cost to match the cost | |
3255 calculation of the synth_mult. */ | |
3256 max_cost = mul_widen_cost[speed][mode]; | |
3257 if (choose_mult_variant (mode, coeff, &algorithm, &variant, | |
3258 max_cost)) | |
3259 { | |
3260 op0 = convert_to_mode (mode, op0, this_optab == umul_widen_optab); | |
3261 return expand_mult_const (mode, op0, coeff, target, | |
3262 &algorithm, variant); | |
3263 } | |
3264 } | |
3265 return expand_binop (mode, this_optab, op0, op1, target, | |
3266 unsignedp, OPTAB_LIB_WIDEN); | |
3255 } | 3267 } |
3256 | 3268 |
3257 /* Return the smallest n such that 2**n >= X. */ | 3269 /* Return the smallest n such that 2**n >= X. */ |
3258 | 3270 |
3259 int | 3271 int |
5790 && op0 == target | 5802 && op0 == target |
5791 && op1 == const0_rtx) | 5803 && op1 == const0_rtx) |
5792 { | 5804 { |
5793 label = gen_label_rtx (); | 5805 label = gen_label_rtx (); |
5794 do_compare_rtx_and_jump (target, const0_rtx, EQ, unsignedp, | 5806 do_compare_rtx_and_jump (target, const0_rtx, EQ, unsignedp, |
5795 mode, NULL_RTX, NULL_RTX, label); | 5807 mode, NULL_RTX, NULL_RTX, label, -1); |
5796 emit_move_insn (target, trueval); | 5808 emit_move_insn (target, trueval); |
5797 emit_label (label); | 5809 emit_label (label); |
5798 return target; | 5810 return target; |
5799 } | 5811 } |
5800 | 5812 |
5828 } | 5840 } |
5829 | 5841 |
5830 emit_move_insn (target, trueval); | 5842 emit_move_insn (target, trueval); |
5831 label = gen_label_rtx (); | 5843 label = gen_label_rtx (); |
5832 do_compare_rtx_and_jump (op0, op1, code, unsignedp, mode, NULL_RTX, | 5844 do_compare_rtx_and_jump (op0, op1, code, unsignedp, mode, NULL_RTX, |
5833 NULL_RTX, label); | 5845 NULL_RTX, label, -1); |
5834 | 5846 |
5835 emit_move_insn (target, falseval); | 5847 emit_move_insn (target, falseval); |
5836 emit_label (label); | 5848 emit_label (label); |
5837 | 5849 |
5838 return target; | 5850 return target; |
5846 do_cmp_and_jump (rtx arg1, rtx arg2, enum rtx_code op, enum machine_mode mode, | 5858 do_cmp_and_jump (rtx arg1, rtx arg2, enum rtx_code op, enum machine_mode mode, |
5847 rtx label) | 5859 rtx label) |
5848 { | 5860 { |
5849 int unsignedp = (op == LTU || op == LEU || op == GTU || op == GEU); | 5861 int unsignedp = (op == LTU || op == LEU || op == GTU || op == GEU); |
5850 do_compare_rtx_and_jump (arg1, arg2, op, unsignedp, mode, | 5862 do_compare_rtx_and_jump (arg1, arg2, op, unsignedp, mode, |
5851 NULL_RTX, NULL_RTX, label); | 5863 NULL_RTX, NULL_RTX, label, -1); |
5852 } | 5864 } |