On Mon, Jan 02, 2017 at 03:47:43PM +0100, Georg-Johann Lay wrote:
> This fixes PR78883 which is a problem in reload revealed by a
> change to combine.c.  The fix is as proposed by Segher: implement
> CANNOT_CHANGE_MODE_CLASS.
> 
> Ok for trunk?
> 
> Johann
> 
> 
> gcc/
>       PR target/78883
>       * config/avr/avr.h (CANNOT_CHANGE_MODE_CLASS): New define.
>       * config/avr/avr-protos.h (avr_cannot_change_mode_class): New proto.
>       * config/avr/avr.c (avr_cannot_change_mode_class): New function.
> 
> gcc/testsuite/
>       PR target/78883
>       * gcc.c-torture/compile/pr78883.c: New test.

> Index: config/avr/avr-protos.h
> ===================================================================
> --- config/avr/avr-protos.h   (revision 244001)
> +++ config/avr/avr-protos.h   (working copy)
> @@ -111,7 +111,7 @@ extern int _reg_unused_after (rtx_insn *
>  extern int avr_jump_mode (rtx x, rtx_insn *insn);
>  extern int test_hard_reg_class (enum reg_class rclass, rtx x);
>  extern int jump_over_one_insn_p (rtx_insn *insn, rtx dest);
> -
> +extern int avr_cannot_change_mode_class (machine_mode, machine_mode, enum 
> reg_class);
>  extern int avr_hard_regno_mode_ok (int regno, machine_mode mode);
>  extern void avr_final_prescan_insn (rtx_insn *insn, rtx *operand,
>                                   int num_operands);
> Index: config/avr/avr.c
> ===================================================================
> --- config/avr/avr.c  (revision 244001)
> +++ config/avr/avr.c  (working copy)
> @@ -11833,6 +11833,21 @@ jump_over_one_insn_p (rtx_insn *insn, rt
>  }
> 
> 
> +/* Worker function for `CANNOT_CHANGE_MODE_CLASS'.  */
> +
> +int
> +avr_cannot_change_mode_class (machine_mode from, machine_mode to,
> +                              enum reg_class /* rclass */)
> +{
> +  /* We cannot access a hard register in a wider mode, for example we
> +     must not access (reg:QI 31) as (reg:HI 31).  HARD_REGNO_MODE_OK
> +     would avoid such hard regs, but reload would generate it anyway
> +     from paradoxical subregs of mem, cf. PR78883.  */
> +   
> +  return GET_MODE_SIZE (to) > GET_MODE_SIZE (from);

I understand how this fixes the ICE, but is it really necessary to
suppress conversions to a wider mode for lower numbered registers?

> +}
> +
> +
>  /* Worker function for `HARD_REGNO_MODE_OK'.  */
>  /* Returns 1 if a value of mode MODE can be stored starting with hard
>     register number REGNO.  On the enhanced core, anything larger than
> Index: config/avr/avr.h
> ===================================================================
> --- config/avr/avr.h  (revision 244001)
> +++ config/avr/avr.h  (working copy)
> @@ -216,6 +216,9 @@ These two properties are reflected by bu
> 
>  #define MODES_TIEABLE_P(MODE1, MODE2) 1
> 
> +#define CANNOT_CHANGE_MODE_CLASS(MFROM, MTO, RCLASS) \
> +  avr_cannot_change_mode_class (MFROM, MTO, RCLASS)
> +
>  enum reg_class {
>    NO_REGS,
>    R0_REG,                    /* r0 */
> Index: testsuite/gcc.c-torture/compile/pr78883.c
> ===================================================================
> --- testsuite/gcc.c-torture/compile/pr78883.c (nonexistent)
> +++ testsuite/gcc.c-torture/compile/pr78883.c (working copy)
> @@ -0,0 +1,12 @@
> +/* { dg-do compile } */
> +
> +int foo (int *p)
> +{
> +  int i;
> +  for (i = 0; i < 5; i++)
> +    {
> +      if (p[i] & 1)
> +        return i;
> +    }
> +  return -1;
> +}

Ciao

Dominik ^_^  ^_^

-- 

Dominik Vogt
IBM Germany

Reply via email to