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

Reply via email to