From f1cc958978c4b3a76ccf96571972f95963c9f0ea Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Wed, 25 Apr 2012 16:27:08 +0200 Subject: re PR tree-optimization/52979 (likely wrong code bug w/packed bitfields) PR middle-end/52979 * stor-layout.c (get_best_mode): Don't return mode with bitsize larger than maxbits. Don't compute maxbits modulo align. Also check that unit bytes long store at bitpos / unit * unit doesn't affect bits beyond bitregion_end. * expmed.c (store_bit_field_1): Avoid trying insv if OP_MODE MEM would not fit into bitregion_start ... bitregion_end + 1 bit region. (store_split_bit_field): Decrease unit close to end of bitregion_end if access is restricted in order to avoid mutual recursion. * gcc.c-torture/compile/pr52979-1.c: New test. * gcc.c-torture/execute/pr52979-1.c: New test. * gcc.c-torture/execute/pr52979-2.c: New test. From-SVN: r186819 --- gcc/expmed.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) (limited to 'gcc/expmed.c') diff --git a/gcc/expmed.c b/gcc/expmed.c index aa24fbf..a0a0960 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -640,7 +640,13 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, && !(MEM_P (op0) && MEM_VOLATILE_P (op0) && flag_strict_volatile_bitfields > 0) && ! ((REG_P (op0) || GET_CODE (op0) == SUBREG) - && (bitsize + bitpos > GET_MODE_BITSIZE (op_mode)))) + && (bitsize + bitpos > GET_MODE_BITSIZE (op_mode))) + /* Do not use insv if the bit region is restricted and + op_mode integer at offset doesn't fit into the + restricted region. */ + && !(MEM_P (op0) && bitregion_end + && bitnum - bitpos + GET_MODE_BITSIZE (op_mode) + > bitregion_end + 1)) { struct expand_operand ops[4]; int xbitpos = bitpos; @@ -760,7 +766,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, || 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, + bestmode = get_best_mode (bitsize, bitnum, bitregion_start, bitregion_end, MEM_ALIGN (op0), (op_mode == MAX_MACHINE_MODE @@ -1096,6 +1102,16 @@ store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize, offset = (bitpos + bitsdone) / unit; thispos = (bitpos + bitsdone) % unit; + /* When region of bytes we can touch is restricted, decrease + UNIT close to the end of the region as needed. */ + if (bitregion_end + && unit > BITS_PER_UNIT + && bitpos + bitsdone - thispos + unit > bitregion_end + 1) + { + unit = unit / 2; + continue; + } + /* THISSIZE must not overrun a word boundary. Otherwise, store_fixed_bit_field will call us again, and we will mutually recurse forever. */ -- cgit v1.1