diff options
author | Nathan Froyd <froydnj@codesourcery.com> | 2010-11-16 14:19:43 +0000 |
---|---|---|
committer | Nathan Froyd <froydnj@gcc.gnu.org> | 2010-11-16 14:19:43 +0000 |
commit | d824aea207d38cb67dcafd992c9ce3fd46afb7d9 (patch) | |
tree | 009d184c66e63f2861848fdff7492820d9952dc6 /gcc/expr.c | |
parent | 69d540bdc7418ff3fc91f5de114c40a1b99cb454 (diff) | |
download | gcc-d824aea207d38cb67dcafd992c9ce3fd46afb7d9.zip gcc-d824aea207d38cb67dcafd992c9ce3fd46afb7d9.tar.gz gcc-d824aea207d38cb67dcafd992c9ce3fd46afb7d9.tar.bz2 |
expr.c (alignment_for_piecewise_move): New function.
* expr.c (alignment_for_piecewise_move): New function.
(widest_int_mode_for_size): New function.
(move_by_pieces, move_by_pieces_ninsns): Call them.
(can_store_by_pieces, store_by_pieces_1): Likewise.
From-SVN: r166802
Diffstat (limited to 'gcc/expr.c')
-rw-r--r-- | gcc/expr.c | 160 |
1 files changed, 64 insertions, 96 deletions
@@ -792,6 +792,50 @@ convert_modes (enum machine_mode mode, enum machine_mode oldmode, rtx x, int uns return temp; } +/* Return the largest alignment we can use for doing a move (or store) + of MAX_PIECES. ALIGN is the largest alignment we could use. */ + +static unsigned int +alignment_for_piecewise_move (unsigned int max_pieces, unsigned int align) +{ + enum machine_mode tmode; + + tmode = mode_for_size (max_pieces * BITS_PER_UNIT, MODE_INT, 1); + if (align >= GET_MODE_ALIGNMENT (tmode)) + align = GET_MODE_ALIGNMENT (tmode); + else + { + enum machine_mode tmode, xmode; + + for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT), xmode = tmode; + tmode != VOIDmode; + xmode = tmode, tmode = GET_MODE_WIDER_MODE (tmode)) + if (GET_MODE_SIZE (tmode) > max_pieces + || SLOW_UNALIGNED_ACCESS (tmode, align)) + break; + + align = MAX (align, GET_MODE_ALIGNMENT (xmode)); + } + + return align; +} + +/* Return the widest integer mode no wider than SIZE. If no such mode + can be found, return VOIDmode. */ + +static enum machine_mode +widest_int_mode_for_size (unsigned int size) +{ + enum machine_mode tmode, mode = VOIDmode; + + for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT); + tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode)) + if (GET_MODE_SIZE (tmode) < size) + mode = tmode; + + return mode; +} + /* STORE_MAX_PIECES is the number of bytes at a time that we can store efficiently. Due to internal GCC limitations, this is MOVE_MAX_PIECES limited by the number of bytes GCC can represent @@ -831,7 +875,6 @@ move_by_pieces (rtx to, rtx from, unsigned HOST_WIDE_INT len, = targetm.addr_space.address_mode (MEM_ADDR_SPACE (from)); rtx to_addr, from_addr = XEXP (from, 0); unsigned int max_size = MOVE_MAX_PIECES + 1; - enum machine_mode mode = VOIDmode, tmode; enum insn_code icode; align = MIN (to ? MEM_ALIGN (to) : align, MEM_ALIGN (from)); @@ -879,11 +922,11 @@ move_by_pieces (rtx to, rtx from, unsigned HOST_WIDE_INT len, if (!(data.autinc_from && data.autinc_to) && move_by_pieces_ninsns (len, align, max_size) > 2) { - /* Find the mode of the largest move... */ - for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT); - tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode)) - if (GET_MODE_SIZE (tmode) < max_size) - mode = tmode; + /* Find the mode of the largest move... + MODE might not be used depending on the definitions of the + USE_* macros below. */ + enum machine_mode mode ATTRIBUTE_UNUSED + = widest_int_mode_for_size (max_size); if (USE_LOAD_PRE_DECREMENT (mode) && data.reverse && ! data.autinc_from) { @@ -917,32 +960,14 @@ move_by_pieces (rtx to, rtx from, unsigned HOST_WIDE_INT len, data.to_addr = copy_to_mode_reg (to_addr_mode, to_addr); } - tmode = mode_for_size (MOVE_MAX_PIECES * BITS_PER_UNIT, MODE_INT, 1); - if (align >= GET_MODE_ALIGNMENT (tmode)) - align = GET_MODE_ALIGNMENT (tmode); - else - { - enum machine_mode xmode; - - for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT), xmode = tmode; - tmode != VOIDmode; - xmode = tmode, tmode = GET_MODE_WIDER_MODE (tmode)) - if (GET_MODE_SIZE (tmode) > MOVE_MAX_PIECES - || SLOW_UNALIGNED_ACCESS (tmode, align)) - break; - - align = MAX (align, GET_MODE_ALIGNMENT (xmode)); - } + align = alignment_for_piecewise_move (MOVE_MAX_PIECES, align); /* First move what we can in the largest integer mode, then go to successively smaller modes. */ while (max_size > 1) { - for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT); - tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode)) - if (GET_MODE_SIZE (tmode) < max_size) - mode = tmode; + enum machine_mode mode = widest_int_mode_for_size (max_size); if (mode == VOIDmode) break; @@ -996,34 +1021,15 @@ move_by_pieces_ninsns (unsigned HOST_WIDE_INT l, unsigned int align, unsigned int max_size) { unsigned HOST_WIDE_INT n_insns = 0; - enum machine_mode tmode; - tmode = mode_for_size (MOVE_MAX_PIECES * BITS_PER_UNIT, MODE_INT, 1); - if (align >= GET_MODE_ALIGNMENT (tmode)) - align = GET_MODE_ALIGNMENT (tmode); - else - { - enum machine_mode tmode, xmode; - - for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT), xmode = tmode; - tmode != VOIDmode; - xmode = tmode, tmode = GET_MODE_WIDER_MODE (tmode)) - if (GET_MODE_SIZE (tmode) > MOVE_MAX_PIECES - || SLOW_UNALIGNED_ACCESS (tmode, align)) - break; - - align = MAX (align, GET_MODE_ALIGNMENT (xmode)); - } + align = alignment_for_piecewise_move (MOVE_MAX_PIECES, align); while (max_size > 1) { - enum machine_mode mode = VOIDmode; + enum machine_mode mode; enum insn_code icode; - for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT); - tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode)) - if (GET_MODE_SIZE (tmode) < max_size) - mode = tmode; + mode = widest_int_mode_for_size (max_size); if (mode == VOIDmode) break; @@ -2258,7 +2264,7 @@ can_store_by_pieces (unsigned HOST_WIDE_INT len, unsigned HOST_WIDE_INT l; unsigned int max_size; HOST_WIDE_INT offset = 0; - enum machine_mode mode, tmode; + enum machine_mode mode; enum insn_code icode; int reverse; /* cst is set but not used if LEGITIMATE_CONSTANT doesn't use it. */ @@ -2272,22 +2278,7 @@ can_store_by_pieces (unsigned HOST_WIDE_INT len, : STORE_BY_PIECES_P (len, align))) return 0; - tmode = mode_for_size (STORE_MAX_PIECES * BITS_PER_UNIT, MODE_INT, 1); - if (align >= GET_MODE_ALIGNMENT (tmode)) - align = GET_MODE_ALIGNMENT (tmode); - else - { - enum machine_mode xmode; - - for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT), xmode = tmode; - tmode != VOIDmode; - xmode = tmode, tmode = GET_MODE_WIDER_MODE (tmode)) - if (GET_MODE_SIZE (tmode) > STORE_MAX_PIECES - || SLOW_UNALIGNED_ACCESS (tmode, align)) - break; - - align = MAX (align, GET_MODE_ALIGNMENT (xmode)); - } + align = alignment_for_piecewise_move (STORE_MAX_PIECES, align); /* We would first store what we can in the largest integer mode, then go to successively smaller modes. */ @@ -2297,14 +2288,10 @@ can_store_by_pieces (unsigned HOST_WIDE_INT len, reverse++) { l = len; - mode = VOIDmode; max_size = STORE_MAX_PIECES + 1; while (max_size > 1) { - for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT); - tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode)) - if (GET_MODE_SIZE (tmode) < max_size) - mode = tmode; + mode = widest_int_mode_for_size (max_size); if (mode == VOIDmode) break; @@ -2445,7 +2432,6 @@ store_by_pieces_1 (struct store_by_pieces_d *data ATTRIBUTE_UNUSED, = targetm.addr_space.address_mode (MEM_ADDR_SPACE (data->to)); rtx to_addr = XEXP (data->to, 0); unsigned int max_size = STORE_MAX_PIECES + 1; - enum machine_mode mode = VOIDmode, tmode; enum insn_code icode; data->offset = 0; @@ -2466,11 +2452,11 @@ store_by_pieces_1 (struct store_by_pieces_d *data ATTRIBUTE_UNUSED, if (!data->autinc_to && move_by_pieces_ninsns (data->len, align, max_size) > 2) { - /* Determine the main mode we'll be using. */ - for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT); - tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode)) - if (GET_MODE_SIZE (tmode) < max_size) - mode = tmode; + /* Determine the main mode we'll be using. + MODE might not be used depending on the definitions of the + USE_* macros below. */ + enum machine_mode mode ATTRIBUTE_UNUSED + = widest_int_mode_for_size (max_size); if (USE_STORE_PRE_DECREMENT (mode) && data->reverse && ! data->autinc_to) { @@ -2492,32 +2478,14 @@ store_by_pieces_1 (struct store_by_pieces_d *data ATTRIBUTE_UNUSED, data->to_addr = copy_to_mode_reg (to_addr_mode, to_addr); } - tmode = mode_for_size (STORE_MAX_PIECES * BITS_PER_UNIT, MODE_INT, 1); - if (align >= GET_MODE_ALIGNMENT (tmode)) - align = GET_MODE_ALIGNMENT (tmode); - else - { - enum machine_mode xmode; - - for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT), xmode = tmode; - tmode != VOIDmode; - xmode = tmode, tmode = GET_MODE_WIDER_MODE (tmode)) - if (GET_MODE_SIZE (tmode) > STORE_MAX_PIECES - || SLOW_UNALIGNED_ACCESS (tmode, align)) - break; - - align = MAX (align, GET_MODE_ALIGNMENT (xmode)); - } + align = alignment_for_piecewise_move (STORE_MAX_PIECES, align); /* First store what we can in the largest integer mode, then go to successively smaller modes. */ while (max_size > 1) { - for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT); - tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode)) - if (GET_MODE_SIZE (tmode) < max_size) - mode = tmode; + enum machine_mode mode = widest_int_mode_for_size (max_size); if (mode == VOIDmode) break; |