On 12/7/18 8:57 AM, Andreas Krebbel wrote: > Hi, > > debugging a problem with an older GCC (4.6). I've seen RTXs using > ZERO_EXTRACT LHS operands on MEMs as in: > > (insn 7 6 0 (set (zero_extract:DI (mem/s/c:QI (plus:DI (reg/f:DI 39 > virtual-stack-vars) > (const_int -5 [0xfffffffffffffffb])) [0+0 S1 A8]) > (const_int 24 [0x18]) > (const_int 0 [0])) > (subreg:DI (reg:SI 45) 0)) t.c:19 -1 > (nil)) Yes. They're essentially a bitfield manipulation.
[ ... ] > > However, I still think that's a legal RTX which needs to be handled by > DSE correctly. I couldn't find anything preventing that problem from > occuring also with current GCCs. On the other hand I couldn't trigger > it with anything in testsuite.I'd look for a target which can do a bitfield > manipulation of a memory object. So likely old targets nobody cares about :-) m68k, h8, etc. > > Perhaps something like that would be needed for current GCC: > > diff --git a/gcc/dse.c b/gcc/dse.c > index 21d166d..d27fb54 100644 > --- a/gcc/dse.c > +++ b/gcc/dse.c > @@ -1346,6 +1346,47 @@ record_store (rtx body, bb_info_t bb_info) > > mem = SET_DEST (body); > > + /* Deal with (zero_extract:XX (mem:QI ...)). */ > + if (GET_CODE (mem) == ZERO_EXTRACT && MEM_P (XEXP (mem, 0))) > + { > + rtx size_op = XEXP (mem, 1); > + rtx offset_op = XEXP (mem, 2); > + enum machine_mode mode = GET_MODE (mem); > + scalar_int_mode int_mode; > + > + /* Turn a (zero_extract:XX (mem:QI ...)) into a (mem:BLK with > + the proper size and the adjusted address. */ > + if (CONST_INT_P (size_op) > + && CONST_INT_P (offset_op) > + && is_a <scalar_int_mode> (mode, &int_mode) > + && INTVAL (size_op) + INTVAL (offset_op) <= GET_MODE_PRECISION > (int_mode)) > + { > + int size = INTVAL (size_op); > + int offset = INTVAL (offset_op); > + > + mem = copy_rtx (XEXP (mem, 0)); > + if (BITS_BIG_ENDIAN) > + mem = adjust_address (mem, BLKmode, offset / BITS_PER_UNIT); > + else > + mem = adjust_address (mem, BLKmode, > + (GET_MODE_BITSIZE (int_mode) - size - offset) > + / BITS_PER_UNIT); > + > + set_mem_size (mem, (size - 1) / BITS_PER_UNIT + 1); > + } > + else > + { > + if (find_reg_note (insn_info->insn, REG_UNUSED, mem) == NULL) > + { > + /* If the set or clobber is unused, then it does not effect our > + ability to get rid of the entire insn. */ > + insn_info->cannot_delete = true; > + clear_rhs_from_active_local_stores (); > + } > + return 0; > + } > + } Looks sane at a high level. The trick is exercising it... jeff