http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54429



--- Comment #4 from Oleg Endo <olegendo at gcc dot gnu.org> 2012-11-13 22:25:30 
UTC ---

(In reply to comment #3)

> I've tested this:

> 

> Index: gcc/config/sh/sh.c

> ===================================================================

> --- gcc/config/sh/sh.c    (revision 193423)

> +++ gcc/config/sh/sh.c    (working copy)

> @@ -12113,6 +12113,11 @@

>    if (FP_REGISTER_P (regno) && mode == SFmode)

>      return true;

> 

> +  if (FP_REGISTER_P (regno)

> +      && !(GET_MODE_CLASS (mode) == MODE_FLOAT

> +       || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT))

> +    return false;

> +

>    if (mode == V2SFmode)

>      {

>        if (((FP_REGISTER_P (regno) && (regno - FIRST_FP_REG) % 2 == 0)

> 

> 

> on rev 193423.  There are a few failures on targets with HW FPU:

> 



It seems these problems happen on big endian targets only.



> FAIL: gcc.c-torture/execute/20080502-1.c compilation



Reload failure.  Problematic insn:



(insn 12 44 13 2 (set (reg:SI 147 t)

        (eq:SI (and:SI (reg:SI 1 r1 [166])

                (subreg:SI (reg:DF 68 fr4 [ x ]) 0))

            (const_int 0 [0]))) sh_tmp.cpp:110 1 {tstsi_t}

     (expr_list:REG_DEAD (reg:SI 1 r1 [166])

        (expr_list:REG_DEAD (reg:DF 68 fr4 [ x ])

            (nil))))



> FAIL: gcc.c-torture/execute/ieee/copysign1.c compilation



Reload failure.  Problematic insn:



(insn 10 41 11 2 (set (reg:SI 147 t)

        (eq:SI (and:SI (reg:SI 1 r1 [165])

                (subreg:SI (reg:DF 70 fr6 [ y ]) 0))

            (const_int 0 [0]))) sh_tmp.cpp:67 1 {tstsi_t}

     (expr_list:REG_DEAD (reg:SI 1 r1 [165])

        (expr_list:REG_DEAD (reg:DF 70 fr6 [ y ])

            (nil))))



> FAIL: gcc.dg/builtins-32.c (internal compiler error)



Reload failure.  Problematic insn:



(insn 8 7 21 2 (set (reg:SI 0 r0 [164])

        (and:SI (reg:SI 0 r0 [164])

            (subreg:SI (reg:DF 68 fr4 [ x ]) 0))) sh_tmp.cpp:30 111

{*andsi_compact}

     (expr_list:REG_DEAD (reg:DF 68 fr4 [ x ])

        (nil)))



> FAIL: gcc.dg/builtins-50.c (internal compiler error)



Reload failure.  Problematic insn:



(insn 10 43 11 2 (set (reg:SI 147 t)

        (eq:SI (and:SI (reg:SI 1 r1 [165])

                (subreg:SI (reg:DF 70 fr6 [ y ]) 0))

            (const_int 0 [0]))) sh_tmp.cpp:24 1 {tstsi_t}

     (expr_list:REG_DEAD (reg:SI 1 r1 [165])

        (expr_list:REG_DEAD (reg:DF 70 fr6 [ y ])

            (nil))))





> FAIL: gcc.dg/pr48335-7.c (internal compiler error)



Reload failure.  Problematic insn:



(insn 9 3 10 2 (set (reg:SI 0 r0 [167])

        (ashift:SI (subreg:SI (reg:DF 68 fr4 [ x ]) 0)

            (const_int 8 [0x8]))) sh_tmp.cpp:28 149 {ashlsi3_k}

     (expr_list:REG_DEAD (reg:DF 68 fr4 [ x ])

        (nil)))





The problem is that 'arith_reg_operand' matches subregs of FP modes and so, for

example, combine folds insn sequences such as



(insn 8 7 9 2 (set (reg:SI 166)

        (subreg:SI (reg:DI 165) 0)) sh_tmp.cpp:33 -1

     (nil))



(insn 9 8 10 2 (set (reg:SI 167)

        (ashift:SI (reg:SI 166)

            (const_int 8 [0x8]))) sh_tmp.cpp:33 -1

     (nil))





Adding this:



Index: gcc/config/sh/predicates.md

===================================================================

--- gcc/config/sh/predicates.md    (revision 193423)

+++ gcc/config/sh/predicates.md    (working copy)

@@ -156,7 +156,12 @@

       if (REG_P (op))

     regno = REGNO (op);

       else if (GET_CODE (op) == SUBREG && REG_P (SUBREG_REG (op)))

-    regno = REGNO (SUBREG_REG (op));

+    {

+      regno = REGNO (SUBREG_REG (op));

+      if (!(GET_MODE_CLASS (GET_MODE (SUBREG_REG (op))) == MODE_INT

+            || GET_MODE_CLASS (GET_MODE (SUBREG_REG (op))) ==

MODE_VECTOR_INT))

+        return false;

+    } 

       else

     return 1;





makes the unwanted subreg propagation go away, but ends up in another reload

trouble:



sh_tmp.cpp:92:1: error: unable to find a register to spill in class

'TARGET_REGS'

 }

 ^

sh_tmp.cpp:92:1: error: this is the insn:

(insn 7 4 8 2 (set (reg:SI 1 r1 [165])

        (subreg:SI (reg:DF 70 fr6 [ y ]) 0)) sh_tmp.cpp:91 244 {movsi_ie}

     (expr_list:REG_DEAD (reg:DF 70 fr6 [ y ])

        (nil)))



On little endian this problem does not happen and the same insn right before

the reload pass looks like:



(insn 7 4 8 2 (set (reg:SI 165)

        (subreg:SI (reg/v:DF 163 [ y ]) 4)) sh_tmp.cpp:91 244 {movsi_ie}

     (expr_list:REG_DEAD (reg/v:DF 163 [ y ])

        (nil)))



Notice that on big endian the insn contains hard regs.

I've tried tapping sh_secondary_reload and there are some weird things

happening such as:



in = 1  rlcass = 8  mode = SI  x = (reg:DF 70 fr6 [ y ])



 --> rclass = 5



This is caused by the way sh_cannot_change_mode_class handles stuff on big

endian.  Adding this to 'sh_cannot_change_mode_class':



  if (from == DFmode && to == SImode)

    return true;



fixes at least one of the test cases, but I'm totally unaware of the

consequences.

Reply via email to