diff options
author | Aldy Hernandez <aldyh@redhat.com> | 2011-07-27 13:22:09 +0000 |
---|---|---|
committer | Aldy Hernandez <aldyh@gcc.gnu.org> | 2011-07-27 13:22:09 +0000 |
commit | 1169e45d2716d769be78cf38bcea449414e6ce75 (patch) | |
tree | efd1ef13f8faacffa0a54f18314494501d46696b /gcc/expmed.c | |
parent | 4f13e17fff3c787928f674a9ba26fd5517fc387d (diff) | |
download | gcc-1169e45d2716d769be78cf38bcea449414e6ce75.zip gcc-1169e45d2716d769be78cf38bcea449414e6ce75.tar.gz gcc-1169e45d2716d769be78cf38bcea449414e6ce75.tar.bz2 |
params.h (ALLOW_STORE_DATA_RACES): New.
* params.h (ALLOW_STORE_DATA_RACES): New.
* params.def (PARAM_ALLOW_STORE_DATA_RACES): New.
* Makefile.in (expr.o): Depend on PARAMS_H.
* machmode.h (get_best_mode): Add argument.
* fold-const.c (optimize_bit_field_compare): Add argument to
get_best_mode.
(fold_truthop): Same.
* ifcvt.c (noce_emit_move_insn): Add argument to store_bit_field.
* expr.c (emit_group_store): Same.
(copy_blkmode_from_reg): Same.
(write_complex_part): Same.
(optimize_bitfield_assignment_op): Add argument.
Add argument to get_best_mode.
(get_bit_range): New.
(expand_assignment): Calculate maxbits and pass it down
accordingly.
(store_field): New argument.
(expand_expr_real_2): New argument to store_field.
Include params.h.
* expr.h (store_bit_field): New argument.
* stor-layout.c (get_best_mode): Restrict mode expansion by taking
into account maxbits.
* calls.c (store_unaligned_arguments_into_pseudos): New argument
to store_bit_field.
* expmed.c (store_bit_field_1): New argument. Use it.
(store_bit_field): Same.
(store_fixed_bit_field): Same.
(store_split_bit_field): Same.
(extract_bit_field_1): Pass new argument to get_best_mode.
(extract_bit_field): Same.
* stmt.c (store_bit_field): Pass new argument to store_bit_field.
* doc/invoke.texi: Document parameter allow-store-data-races.
From-SVN: r176824
Diffstat (limited to 'gcc/expmed.c')
-rw-r--r-- | gcc/expmed.c | 103 |
1 files changed, 88 insertions, 15 deletions
diff --git a/gcc/expmed.c b/gcc/expmed.c index 272994f..92167f1 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -47,9 +47,15 @@ struct target_expmed *this_target_expmed = &default_target_expmed; static void store_fixed_bit_field (rtx, unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT, - unsigned HOST_WIDE_INT, rtx); + unsigned HOST_WIDE_INT, + unsigned HOST_WIDE_INT, + unsigned HOST_WIDE_INT, + rtx); static void store_split_bit_field (rtx, unsigned HOST_WIDE_INT, - unsigned HOST_WIDE_INT, rtx); + unsigned HOST_WIDE_INT, + unsigned HOST_WIDE_INT, + unsigned HOST_WIDE_INT, + rtx); static rtx extract_fixed_bit_field (enum machine_mode, rtx, unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT, @@ -333,7 +339,10 @@ mode_for_extraction (enum extraction_pattern pattern, int opno) static bool store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, - unsigned HOST_WIDE_INT bitnum, enum machine_mode fieldmode, + unsigned HOST_WIDE_INT bitnum, + unsigned HOST_WIDE_INT bitregion_start, + unsigned HOST_WIDE_INT bitregion_end, + enum machine_mode fieldmode, rtx value, bool fallback_p) { unsigned int unit @@ -455,6 +464,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, /* We may be accessing data outside the field, which means we can alias adjacent data. */ + /* ?? not always for C++0x memory model ?? */ if (MEM_P (op0)) { op0 = shallow_copy_rtx (op0); @@ -547,7 +557,9 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, if (!store_bit_field_1 (op0, MIN (BITS_PER_WORD, bitsize - i * BITS_PER_WORD), - bitnum + bit_offset, word_mode, + bitnum + bit_offset, + bitregion_start, bitregion_end, + word_mode, value_word, fallback_p)) { delete_insns_since (last); @@ -710,6 +722,10 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, if (HAVE_insv && MEM_P (op0)) { enum machine_mode bestmode; + unsigned HOST_WIDE_INT maxbits = MAX_FIXED_MODE_SIZE; + + if (bitregion_end) + maxbits = bitregion_end - bitregion_start + 1; /* Get the mode to use for inserting into this field. If OP0 is BLKmode, get the smallest mode consistent with the alignment. If @@ -717,9 +733,12 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, mode. Otherwise, use the smallest mode containing the field. */ if (GET_MODE (op0) == BLKmode + || GET_MODE_BITSIZE (GET_MODE (op0)) > maxbits || (op_mode != MAX_MACHINE_MODE && GET_MODE_SIZE (GET_MODE (op0)) > GET_MODE_SIZE (op_mode))) - bestmode = get_best_mode (bitsize, bitnum, MEM_ALIGN (op0), + bestmode = get_best_mode (bitsize, bitnum, + bitregion_start, bitregion_end, + MEM_ALIGN (op0), (op_mode == MAX_MACHINE_MODE ? VOIDmode : op_mode), MEM_VOLATILE_P (op0)); @@ -748,6 +767,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, the unit. */ tempreg = copy_to_reg (xop0); if (store_bit_field_1 (tempreg, bitsize, xbitpos, + bitregion_start, bitregion_end, fieldmode, orig_value, false)) { emit_move_insn (xop0, tempreg); @@ -760,21 +780,59 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, if (!fallback_p) return false; - store_fixed_bit_field (op0, offset, bitsize, bitpos, value); + store_fixed_bit_field (op0, offset, bitsize, bitpos, + bitregion_start, bitregion_end, value); return true; } /* Generate code to store value from rtx VALUE into a bit-field within structure STR_RTX containing BITSIZE bits starting at bit BITNUM. + + BITREGION_START is bitpos of the first bitfield in this region. + BITREGION_END is the bitpos of the ending bitfield in this region. + These two fields are 0, if the C++ memory model does not apply, + or we are not interested in keeping track of bitfield regions. + FIELDMODE is the machine-mode of the FIELD_DECL node for this field. */ void store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, - unsigned HOST_WIDE_INT bitnum, enum machine_mode fieldmode, + unsigned HOST_WIDE_INT bitnum, + unsigned HOST_WIDE_INT bitregion_start, + unsigned HOST_WIDE_INT bitregion_end, + enum machine_mode fieldmode, rtx value) { - if (!store_bit_field_1 (str_rtx, bitsize, bitnum, fieldmode, value, true)) + /* Under the C++0x memory model, we must not touch bits outside the + bit region. Adjust the address to start at the beginning of the + bit region. */ + if (MEM_P (str_rtx) + && bitregion_start > 0) + { + enum machine_mode bestmode; + enum machine_mode op_mode; + unsigned HOST_WIDE_INT offset; + + op_mode = mode_for_extraction (EP_insv, 3); + if (op_mode == MAX_MACHINE_MODE) + op_mode = VOIDmode; + + offset = bitregion_start / BITS_PER_UNIT; + bitnum -= bitregion_start; + bitregion_end -= bitregion_start; + bitregion_start = 0; + bestmode = get_best_mode (bitsize, bitnum, + bitregion_start, bitregion_end, + MEM_ALIGN (str_rtx), + op_mode, + MEM_VOLATILE_P (str_rtx)); + str_rtx = adjust_address (str_rtx, bestmode, offset); + } + + if (!store_bit_field_1 (str_rtx, bitsize, bitnum, + bitregion_start, bitregion_end, + fieldmode, value, true)) gcc_unreachable (); } @@ -790,7 +848,10 @@ store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, static void store_fixed_bit_field (rtx op0, unsigned HOST_WIDE_INT offset, unsigned HOST_WIDE_INT bitsize, - unsigned HOST_WIDE_INT bitpos, rtx value) + unsigned HOST_WIDE_INT bitpos, + unsigned HOST_WIDE_INT bitregion_start, + unsigned HOST_WIDE_INT bitregion_end, + rtx value) { enum machine_mode mode; unsigned int total_bits = BITS_PER_WORD; @@ -811,12 +872,19 @@ store_fixed_bit_field (rtx op0, unsigned HOST_WIDE_INT offset, /* Special treatment for a bit field split across two registers. */ if (bitsize + bitpos > BITS_PER_WORD) { - store_split_bit_field (op0, bitsize, bitpos, value); + store_split_bit_field (op0, bitsize, bitpos, + bitregion_start, bitregion_end, + value); return; } } else { + unsigned HOST_WIDE_INT maxbits = MAX_FIXED_MODE_SIZE; + + if (bitregion_end) + maxbits = bitregion_end - bitregion_start + 1; + /* Get the proper mode to use for this field. We want a mode that includes the entire field. If such a mode would be larger than a word, we won't be doing the extraction the normal way. @@ -829,10 +897,12 @@ store_fixed_bit_field (rtx op0, unsigned HOST_WIDE_INT offset, if (MEM_VOLATILE_P (op0) && GET_MODE_BITSIZE (GET_MODE (op0)) > 0 + && GET_MODE_BITSIZE (GET_MODE (op0)) <= maxbits && flag_strict_volatile_bitfields > 0) mode = GET_MODE (op0); else mode = get_best_mode (bitsize, bitpos + offset * BITS_PER_UNIT, + bitregion_start, bitregion_end, MEM_ALIGN (op0), mode, MEM_VOLATILE_P (op0)); if (mode == VOIDmode) @@ -840,7 +910,7 @@ store_fixed_bit_field (rtx op0, unsigned HOST_WIDE_INT offset, /* The only way this should occur is if the field spans word boundaries. */ store_split_bit_field (op0, bitsize, bitpos + offset * BITS_PER_UNIT, - value); + bitregion_start, bitregion_end, value); return; } @@ -960,7 +1030,10 @@ store_fixed_bit_field (rtx op0, unsigned HOST_WIDE_INT offset, static void store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize, - unsigned HOST_WIDE_INT bitpos, rtx value) + unsigned HOST_WIDE_INT bitpos, + unsigned HOST_WIDE_INT bitregion_start, + unsigned HOST_WIDE_INT bitregion_end, + rtx value) { unsigned int unit; unsigned int bitsdone = 0; @@ -1075,7 +1148,7 @@ store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize, it is just an out-of-bounds access. Ignore it. */ if (word != const0_rtx) store_fixed_bit_field (word, offset * unit / BITS_PER_UNIT, thissize, - thispos, part); + thispos, bitregion_start, bitregion_end, part); bitsdone += thissize; } } @@ -1515,7 +1588,7 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, if (GET_MODE (op0) == BLKmode || (ext_mode != MAX_MACHINE_MODE && GET_MODE_SIZE (GET_MODE (op0)) > GET_MODE_SIZE (ext_mode))) - bestmode = get_best_mode (bitsize, bitnum, MEM_ALIGN (op0), + bestmode = get_best_mode (bitsize, bitnum, 0, 0, MEM_ALIGN (op0), (ext_mode == MAX_MACHINE_MODE ? VOIDmode : ext_mode), MEM_VOLATILE_P (op0)); @@ -1641,7 +1714,7 @@ extract_fixed_bit_field (enum machine_mode tmode, rtx op0, mode = tmode; } else - mode = get_best_mode (bitsize, bitpos + offset * BITS_PER_UNIT, + mode = get_best_mode (bitsize, bitpos + offset * BITS_PER_UNIT, 0, 0, MEM_ALIGN (op0), word_mode, MEM_VOLATILE_P (op0)); if (mode == VOIDmode) |