Commit 1169e45d by Aldy Hernandez Committed by Aldy Hernandez

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
parent 4f13e17f
2011-07-27 Aldy Hernandez <aldyh@redhat.com>
* 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.
2011-07-27 Jakub Jelinek <jakub@redhat.com> 2011-07-27 Jakub Jelinek <jakub@redhat.com>
* dwarf2out.c (gen_producer_string): Ignore also -fverbose-asm * dwarf2out.c (gen_producer_string): Ignore also -fverbose-asm
......
...@@ -2909,7 +2909,7 @@ expr.o : expr.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ ...@@ -2909,7 +2909,7 @@ expr.o : expr.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
reload.h langhooks.h intl.h $(TM_P_H) $(TARGET_H) \ reload.h langhooks.h intl.h $(TM_P_H) $(TARGET_H) \
tree-iterator.h gt-expr.h $(MACHMODE_H) $(TIMEVAR_H) $(TREE_FLOW_H) \ tree-iterator.h gt-expr.h $(MACHMODE_H) $(TIMEVAR_H) $(TREE_FLOW_H) \
$(TREE_PASS_H) $(DF_H) $(DIAGNOSTIC_H) vecprim.h $(SSAEXPAND_H) \ $(TREE_PASS_H) $(DF_H) $(DIAGNOSTIC_H) vecprim.h $(SSAEXPAND_H) \
$(COMMON_TARGET_H) $(PARAMS_H) $(COMMON_TARGET_H)
dojump.o : dojump.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \ dojump.o : dojump.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \
$(FLAGS_H) $(FUNCTION_H) $(EXPR_H) $(OPTABS_H) $(INSN_ATTR_H) insn-config.h \ $(FLAGS_H) $(FUNCTION_H) $(EXPR_H) $(OPTABS_H) $(INSN_ATTR_H) insn-config.h \
langhooks.h $(GGC_H) gt-dojump.h vecprim.h $(BASIC_BLOCK_H) output.h langhooks.h $(GGC_H) gt-dojump.h vecprim.h $(BASIC_BLOCK_H) output.h
......
...@@ -924,8 +924,8 @@ store_unaligned_arguments_into_pseudos (struct arg_data *args, int num_actuals) ...@@ -924,8 +924,8 @@ store_unaligned_arguments_into_pseudos (struct arg_data *args, int num_actuals)
emit_move_insn (reg, const0_rtx); emit_move_insn (reg, const0_rtx);
bytes -= bitsize / BITS_PER_UNIT; bytes -= bitsize / BITS_PER_UNIT;
store_bit_field (reg, bitsize, endian_correction, word_mode, store_bit_field (reg, bitsize, endian_correction, 0, 0,
word); word_mode, word);
} }
} }
} }
......
...@@ -9058,6 +9058,11 @@ The maximum number of conditional stores paires that can be sunk. Set to 0 ...@@ -9058,6 +9058,11 @@ The maximum number of conditional stores paires that can be sunk. Set to 0
if either vectorization (@option{-ftree-vectorize}) or if-conversion if either vectorization (@option{-ftree-vectorize}) or if-conversion
(@option{-ftree-loop-if-convert}) is disabled. The default is 2. (@option{-ftree-loop-if-convert}) is disabled. The default is 2.
@item allow-store-data-races
Allow optimizers to introduce new data races on stores.
Set to 1 to allow, otherwise to 0. This option is enabled by default
unless implicitly set by the @option{-fmemory-model=} option.
@item case-values-threshold @item case-values-threshold
The smallest number of different values for which it is best to use a The smallest number of different values for which it is best to use a
jump-table instead of a tree of conditional branches. If the value is jump-table instead of a tree of conditional branches. If the value is
......
...@@ -47,9 +47,15 @@ struct target_expmed *this_target_expmed = &default_target_expmed; ...@@ -47,9 +47,15 @@ struct target_expmed *this_target_expmed = &default_target_expmed;
static void store_fixed_bit_field (rtx, unsigned HOST_WIDE_INT, static void store_fixed_bit_field (rtx, unsigned HOST_WIDE_INT,
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, 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, static rtx extract_fixed_bit_field (enum machine_mode, rtx,
unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT,
...@@ -333,7 +339,10 @@ mode_for_extraction (enum extraction_pattern pattern, int opno) ...@@ -333,7 +339,10 @@ mode_for_extraction (enum extraction_pattern pattern, int opno)
static bool static bool
store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, 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) rtx value, bool fallback_p)
{ {
unsigned int unit unsigned int unit
...@@ -455,6 +464,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, ...@@ -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 may be accessing data outside the field, which means
we can alias adjacent data. */ we can alias adjacent data. */
/* ?? not always for C++0x memory model ?? */
if (MEM_P (op0)) if (MEM_P (op0))
{ {
op0 = shallow_copy_rtx (op0); op0 = shallow_copy_rtx (op0);
...@@ -547,7 +557,9 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, ...@@ -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, if (!store_bit_field_1 (op0, MIN (BITS_PER_WORD,
bitsize - i * 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)) value_word, fallback_p))
{ {
delete_insns_since (last); delete_insns_since (last);
...@@ -710,6 +722,10 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, ...@@ -710,6 +722,10 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
if (HAVE_insv && MEM_P (op0)) if (HAVE_insv && MEM_P (op0))
{ {
enum machine_mode bestmode; 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 /* Get the mode to use for inserting into this field. If OP0 is
BLKmode, get the smallest mode consistent with the alignment. If 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, ...@@ -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. */ mode. Otherwise, use the smallest mode containing the field. */
if (GET_MODE (op0) == BLKmode if (GET_MODE (op0) == BLKmode
|| GET_MODE_BITSIZE (GET_MODE (op0)) > maxbits
|| (op_mode != MAX_MACHINE_MODE || (op_mode != MAX_MACHINE_MODE
&& GET_MODE_SIZE (GET_MODE (op0)) > GET_MODE_SIZE (op_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 (op_mode == MAX_MACHINE_MODE
? VOIDmode : op_mode), ? VOIDmode : op_mode),
MEM_VOLATILE_P (op0)); MEM_VOLATILE_P (op0));
...@@ -748,6 +767,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, ...@@ -748,6 +767,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
the unit. */ the unit. */
tempreg = copy_to_reg (xop0); tempreg = copy_to_reg (xop0);
if (store_bit_field_1 (tempreg, bitsize, xbitpos, if (store_bit_field_1 (tempreg, bitsize, xbitpos,
bitregion_start, bitregion_end,
fieldmode, orig_value, false)) fieldmode, orig_value, false))
{ {
emit_move_insn (xop0, tempreg); emit_move_insn (xop0, tempreg);
...@@ -760,21 +780,59 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, ...@@ -760,21 +780,59 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
if (!fallback_p) if (!fallback_p)
return false; 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; return true;
} }
/* Generate code to store value from rtx VALUE /* Generate code to store value from rtx VALUE
into a bit-field within structure STR_RTX into a bit-field within structure STR_RTX
containing BITSIZE bits starting at bit BITNUM. 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. */ FIELDMODE is the machine-mode of the FIELD_DECL node for this field. */
void void
store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, 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) 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 (); gcc_unreachable ();
} }
...@@ -790,7 +848,10 @@ store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, ...@@ -790,7 +848,10 @@ store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
static void static void
store_fixed_bit_field (rtx op0, unsigned HOST_WIDE_INT offset, store_fixed_bit_field (rtx op0, unsigned HOST_WIDE_INT offset,
unsigned HOST_WIDE_INT bitsize, 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; enum machine_mode mode;
unsigned int total_bits = BITS_PER_WORD; unsigned int total_bits = BITS_PER_WORD;
...@@ -811,12 +872,19 @@ store_fixed_bit_field (rtx op0, unsigned HOST_WIDE_INT offset, ...@@ -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. */ /* Special treatment for a bit field split across two registers. */
if (bitsize + bitpos > BITS_PER_WORD) 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; return;
} }
} }
else 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 /* 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 includes the entire field. If such a mode would be larger than
a word, we won't be doing the extraction the normal way. 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, ...@@ -829,10 +897,12 @@ store_fixed_bit_field (rtx op0, unsigned HOST_WIDE_INT offset,
if (MEM_VOLATILE_P (op0) if (MEM_VOLATILE_P (op0)
&& GET_MODE_BITSIZE (GET_MODE (op0)) > 0 && GET_MODE_BITSIZE (GET_MODE (op0)) > 0
&& GET_MODE_BITSIZE (GET_MODE (op0)) <= maxbits
&& flag_strict_volatile_bitfields > 0) && flag_strict_volatile_bitfields > 0)
mode = GET_MODE (op0); mode = GET_MODE (op0);
else else
mode = get_best_mode (bitsize, bitpos + offset * BITS_PER_UNIT, mode = get_best_mode (bitsize, bitpos + offset * BITS_PER_UNIT,
bitregion_start, bitregion_end,
MEM_ALIGN (op0), mode, MEM_VOLATILE_P (op0)); MEM_ALIGN (op0), mode, MEM_VOLATILE_P (op0));
if (mode == VOIDmode) if (mode == VOIDmode)
...@@ -840,7 +910,7 @@ store_fixed_bit_field (rtx op0, unsigned HOST_WIDE_INT offset, ...@@ -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 /* The only way this should occur is if the field spans word
boundaries. */ boundaries. */
store_split_bit_field (op0, bitsize, bitpos + offset * BITS_PER_UNIT, store_split_bit_field (op0, bitsize, bitpos + offset * BITS_PER_UNIT,
value); bitregion_start, bitregion_end, value);
return; return;
} }
...@@ -960,7 +1030,10 @@ store_fixed_bit_field (rtx op0, unsigned HOST_WIDE_INT offset, ...@@ -960,7 +1030,10 @@ store_fixed_bit_field (rtx op0, unsigned HOST_WIDE_INT offset,
static void static void
store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize, 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 unit;
unsigned int bitsdone = 0; unsigned int bitsdone = 0;
...@@ -1075,7 +1148,7 @@ store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize, ...@@ -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. */ it is just an out-of-bounds access. Ignore it. */
if (word != const0_rtx) if (word != const0_rtx)
store_fixed_bit_field (word, offset * unit / BITS_PER_UNIT, thissize, store_fixed_bit_field (word, offset * unit / BITS_PER_UNIT, thissize,
thispos, part); thispos, bitregion_start, bitregion_end, part);
bitsdone += thissize; bitsdone += thissize;
} }
} }
...@@ -1515,7 +1588,7 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, ...@@ -1515,7 +1588,7 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
if (GET_MODE (op0) == BLKmode if (GET_MODE (op0) == BLKmode
|| (ext_mode != MAX_MACHINE_MODE || (ext_mode != MAX_MACHINE_MODE
&& GET_MODE_SIZE (GET_MODE (op0)) > GET_MODE_SIZE (ext_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 (ext_mode == MAX_MACHINE_MODE
? VOIDmode : ext_mode), ? VOIDmode : ext_mode),
MEM_VOLATILE_P (op0)); MEM_VOLATILE_P (op0));
...@@ -1641,7 +1714,7 @@ extract_fixed_bit_field (enum machine_mode tmode, rtx op0, ...@@ -1641,7 +1714,7 @@ extract_fixed_bit_field (enum machine_mode tmode, rtx op0,
mode = tmode; mode = tmode;
} }
else 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)); MEM_ALIGN (op0), word_mode, MEM_VOLATILE_P (op0));
if (mode == VOIDmode) if (mode == VOIDmode)
......
...@@ -665,7 +665,10 @@ extern enum machine_mode ...@@ -665,7 +665,10 @@ extern enum machine_mode
mode_for_extraction (enum extraction_pattern, int); mode_for_extraction (enum extraction_pattern, int);
extern void store_bit_field (rtx, unsigned HOST_WIDE_INT, extern void store_bit_field (rtx, unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT, enum machine_mode, rtx); unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT,
enum machine_mode, rtx);
extern rtx extract_bit_field (rtx, unsigned HOST_WIDE_INT, extern rtx extract_bit_field (rtx, unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT, int, bool, rtx, unsigned HOST_WIDE_INT, int, bool, rtx,
enum machine_mode, enum machine_mode); enum machine_mode, enum machine_mode);
......
...@@ -3394,7 +3394,7 @@ optimize_bit_field_compare (location_t loc, enum tree_code code, ...@@ -3394,7 +3394,7 @@ optimize_bit_field_compare (location_t loc, enum tree_code code,
&& flag_strict_volatile_bitfields > 0) && flag_strict_volatile_bitfields > 0)
nmode = lmode; nmode = lmode;
else else
nmode = get_best_mode (lbitsize, lbitpos, nmode = get_best_mode (lbitsize, lbitpos, 0, 0,
const_p ? TYPE_ALIGN (TREE_TYPE (linner)) const_p ? TYPE_ALIGN (TREE_TYPE (linner))
: MIN (TYPE_ALIGN (TREE_TYPE (linner)), : MIN (TYPE_ALIGN (TREE_TYPE (linner)),
TYPE_ALIGN (TREE_TYPE (rinner))), TYPE_ALIGN (TREE_TYPE (rinner))),
...@@ -5221,7 +5221,7 @@ fold_truthop (location_t loc, enum tree_code code, tree truth_type, ...@@ -5221,7 +5221,7 @@ fold_truthop (location_t loc, enum tree_code code, tree truth_type,
to be relative to a field of that size. */ to be relative to a field of that size. */
first_bit = MIN (ll_bitpos, rl_bitpos); first_bit = MIN (ll_bitpos, rl_bitpos);
end_bit = MAX (ll_bitpos + ll_bitsize, rl_bitpos + rl_bitsize); end_bit = MAX (ll_bitpos + ll_bitsize, rl_bitpos + rl_bitsize);
lnmode = get_best_mode (end_bit - first_bit, first_bit, lnmode = get_best_mode (end_bit - first_bit, first_bit, 0, 0,
TYPE_ALIGN (TREE_TYPE (ll_inner)), word_mode, TYPE_ALIGN (TREE_TYPE (ll_inner)), word_mode,
volatilep); volatilep);
if (lnmode == VOIDmode) if (lnmode == VOIDmode)
...@@ -5286,7 +5286,7 @@ fold_truthop (location_t loc, enum tree_code code, tree truth_type, ...@@ -5286,7 +5286,7 @@ fold_truthop (location_t loc, enum tree_code code, tree truth_type,
first_bit = MIN (lr_bitpos, rr_bitpos); first_bit = MIN (lr_bitpos, rr_bitpos);
end_bit = MAX (lr_bitpos + lr_bitsize, rr_bitpos + rr_bitsize); end_bit = MAX (lr_bitpos + lr_bitsize, rr_bitpos + rr_bitsize);
rnmode = get_best_mode (end_bit - first_bit, first_bit, rnmode = get_best_mode (end_bit - first_bit, first_bit, 0, 0,
TYPE_ALIGN (TREE_TYPE (lr_inner)), word_mode, TYPE_ALIGN (TREE_TYPE (lr_inner)), word_mode,
volatilep); volatilep);
if (rnmode == VOIDmode) if (rnmode == VOIDmode)
......
...@@ -885,7 +885,7 @@ noce_emit_move_insn (rtx x, rtx y) ...@@ -885,7 +885,7 @@ noce_emit_move_insn (rtx x, rtx y)
} }
gcc_assert (start < (MEM_P (op) ? BITS_PER_UNIT : BITS_PER_WORD)); gcc_assert (start < (MEM_P (op) ? BITS_PER_UNIT : BITS_PER_WORD));
store_bit_field (op, size, start, GET_MODE (x), y); store_bit_field (op, size, start, 0, 0, GET_MODE (x), y);
return; return;
} }
...@@ -939,7 +939,8 @@ noce_emit_move_insn (rtx x, rtx y) ...@@ -939,7 +939,8 @@ noce_emit_move_insn (rtx x, rtx y)
inner = XEXP (outer, 0); inner = XEXP (outer, 0);
outmode = GET_MODE (outer); outmode = GET_MODE (outer);
bitpos = SUBREG_BYTE (outer) * BITS_PER_UNIT; bitpos = SUBREG_BYTE (outer) * BITS_PER_UNIT;
store_bit_field (inner, GET_MODE_BITSIZE (outmode), bitpos, outmode, y); store_bit_field (inner, GET_MODE_BITSIZE (outmode), bitpos,
0, 0, outmode, y);
} }
/* Return sequence of instructions generated by if conversion. This /* Return sequence of instructions generated by if conversion. This
......
...@@ -248,7 +248,10 @@ extern enum machine_mode mode_for_vector (enum machine_mode, unsigned); ...@@ -248,7 +248,10 @@ extern enum machine_mode mode_for_vector (enum machine_mode, unsigned);
/* Find the best mode to use to access a bit field. */ /* Find the best mode to use to access a bit field. */
extern enum machine_mode get_best_mode (int, int, unsigned int, extern enum machine_mode get_best_mode (int, int,
unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT,
unsigned int,
enum machine_mode, int); enum machine_mode, int);
/* Determine alignment, 1<=result<=BIGGEST_ALIGNMENT. */ /* Determine alignment, 1<=result<=BIGGEST_ALIGNMENT. */
......
...@@ -908,6 +908,12 @@ DEFPARAM (PARAM_CASE_VALUES_THRESHOLD, ...@@ -908,6 +908,12 @@ DEFPARAM (PARAM_CASE_VALUES_THRESHOLD,
"if 0, use the default for the machine", "if 0, use the default for the machine",
0, 0, 0) 0, 0, 0)
/* Data race flags for C++0x memory model compliance. */
DEFPARAM (PARAM_ALLOW_STORE_DATA_RACES,
"allow-store-data-races",
"Allow new data races on stores to be introduced",
1, 0, 1)
/* /*
Local variables: Local variables:
......
...@@ -211,4 +211,6 @@ extern void init_param_values (int *params); ...@@ -211,4 +211,6 @@ extern void init_param_values (int *params);
PARAM_VALUE (PARAM_MIN_NONDEBUG_INSN_UID) PARAM_VALUE (PARAM_MIN_NONDEBUG_INSN_UID)
#define MAX_STORES_TO_SINK \ #define MAX_STORES_TO_SINK \
PARAM_VALUE (PARAM_MAX_STORES_TO_SINK) PARAM_VALUE (PARAM_MAX_STORES_TO_SINK)
#define ALLOW_STORE_DATA_RACES \
PARAM_VALUE (PARAM_ALLOW_STORE_DATA_RACES)
#endif /* ! GCC_PARAMS_H */ #endif /* ! GCC_PARAMS_H */
...@@ -1759,7 +1759,8 @@ expand_return (tree retval) ...@@ -1759,7 +1759,8 @@ expand_return (tree retval)
/* Use bitpos for the source extraction (left justified) and /* Use bitpos for the source extraction (left justified) and
xbitpos for the destination store (right justified). */ xbitpos for the destination store (right justified). */
store_bit_field (dst, bitsize, xbitpos % BITS_PER_WORD, word_mode, store_bit_field (dst, bitsize, xbitpos % BITS_PER_WORD,
0, 0, word_mode,
extract_bit_field (src, bitsize, extract_bit_field (src, bitsize,
bitpos % BITS_PER_WORD, 1, false, bitpos % BITS_PER_WORD, 1, false,
NULL_RTX, word_mode, word_mode)); NULL_RTX, word_mode, word_mode));
......
...@@ -2361,6 +2361,13 @@ fixup_unsigned_type (tree type) ...@@ -2361,6 +2361,13 @@ fixup_unsigned_type (tree type)
/* Find the best machine mode to use when referencing a bit field of length /* Find the best machine mode to use when referencing a bit field of length
BITSIZE bits starting at BITPOS. BITSIZE bits starting at BITPOS.
BITREGION_START is the bit position of the first bit in this
sequence of bit fields. BITREGION_END is the last bit in this
sequence. If these two fields are non-zero, we should restrict the
memory access to a maximum sized chunk of
BITREGION_END - BITREGION_START + 1. Otherwise, we are allowed to touch
any adjacent non bit-fields.
The underlying object is known to be aligned to a boundary of ALIGN bits. The underlying object is known to be aligned to a boundary of ALIGN bits.
If LARGEST_MODE is not VOIDmode, it means that we should not use a mode If LARGEST_MODE is not VOIDmode, it means that we should not use a mode
larger than LARGEST_MODE (usually SImode). larger than LARGEST_MODE (usually SImode).
...@@ -2378,11 +2385,21 @@ fixup_unsigned_type (tree type) ...@@ -2378,11 +2385,21 @@ fixup_unsigned_type (tree type)
decide which of the above modes should be used. */ decide which of the above modes should be used. */
enum machine_mode enum machine_mode
get_best_mode (int bitsize, int bitpos, unsigned int align, get_best_mode (int bitsize, int bitpos,
unsigned HOST_WIDE_INT bitregion_start,
unsigned HOST_WIDE_INT bitregion_end,
unsigned int align,
enum machine_mode largest_mode, int volatilep) enum machine_mode largest_mode, int volatilep)
{ {
enum machine_mode mode; enum machine_mode mode;
unsigned int unit = 0; unsigned int unit = 0;
unsigned HOST_WIDE_INT maxbits;
/* If unset, no restriction. */
if (!bitregion_end)
maxbits = MAX_FIXED_MODE_SIZE;
else
maxbits = (bitregion_end - bitregion_start) % align + 1;
/* Find the narrowest integer mode that contains the bit field. */ /* Find the narrowest integer mode that contains the bit field. */
for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode; for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;
...@@ -2419,6 +2436,7 @@ get_best_mode (int bitsize, int bitpos, unsigned int align, ...@@ -2419,6 +2436,7 @@ get_best_mode (int bitsize, int bitpos, unsigned int align,
&& bitpos / unit == (bitpos + bitsize - 1) / unit && bitpos / unit == (bitpos + bitsize - 1) / unit
&& unit <= BITS_PER_WORD && unit <= BITS_PER_WORD
&& unit <= MIN (align, BIGGEST_ALIGNMENT) && unit <= MIN (align, BIGGEST_ALIGNMENT)
&& unit <= maxbits
&& (largest_mode == VOIDmode && (largest_mode == VOIDmode
|| unit <= GET_MODE_BITSIZE (largest_mode))) || unit <= GET_MODE_BITSIZE (largest_mode)))
wide_mode = tmode; wide_mode = tmode;
......
/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
/* { dg-options "-O2 --param allow-store-data-races=0" } */
/* Test that we don't store past VAR.K. */
struct S
{
volatile int i;
volatile int j: 32;
volatile int k: 15;
volatile char c[2];
} var;
void setit()
{
var.k = 13;
}
/* { dg-final { scan-assembler-not "movl.*, var" } } */
/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
/* { dg-options "-O2 --param allow-store-data-races=0" } */
/* Make sure we don't narrow down to a QI or HI to store into VAR.J,
but instead use an SI. */
struct S
{
volatile int i: 4;
volatile int j: 4;
volatile int k: 8;
volatile int l: 8;
volatile int m: 8;
} var;
void setit()
{
var.j = 5;
}
/* { dg-final { scan-assembler "movl.*, var" } } */
/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
/* { dg-options "-O2 --param allow-store-data-races=0" } */
struct bits
{
char a;
int b:7;
int c:9;
unsigned char d;
} x;
/* Store into <c> should not clobber <d>. */
void update_c(struct bits *p, int val)
{
p -> c = val;
}
/* { dg-final { scan-assembler-not "movl" } } */
/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
/* { dg-options "-O2 --param allow-store-data-races=0" } */
#include <stdlib.h>
struct bits
{
char a;
int b:7;
int c:9;
unsigned char d;
} x;
struct bits *p;
static void allocit()
{
p = (struct bits *) malloc (sizeof (struct bits));
}
/* Store into <c> should not clobber <d>. */
/* We should not use a 32-bit move to store into p->, but a smaller move. */
void foo()
{
allocit();
p -> c = 55;
}
/* { dg-final { scan-assembler-not "movl\t\\(" } } */
/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
/* { dg-options "-O2 --param allow-store-data-races=0" } */
/* Test that we don't store past VAR.A. */
struct S
{
volatile unsigned int a : 4;
unsigned char b;
unsigned int c : 6;
} var;
void set_a()
{
var.a = 12;
}
/* { dg-final { scan-assembler-not "movl.*, var" } } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment