From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 3470 invoked by alias); 13 Nov 2012 22:25:47 -0000 Received: (qmail 3350 invoked by uid 48); 13 Nov 2012 22:25:31 -0000 From: "olegendo at gcc dot gnu.org" To: gcc-bugs@gcc.gnu.org Subject: [Bug target/54429] [SH] SImode values get ferried through FPUL and FP regs for -O0 Date: Tue, 13 Nov 2012 22:25:00 -0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: changed X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: target X-Bugzilla-Keywords: X-Bugzilla-Severity: enhancement X-Bugzilla-Who: olegendo at gcc dot gnu.org X-Bugzilla-Status: UNCONFIRMED X-Bugzilla-Priority: P3 X-Bugzilla-Assigned-To: olegendo at gcc dot gnu.org X-Bugzilla-Target-Milestone: --- X-Bugzilla-Changed-Fields: Message-ID: In-Reply-To: References: X-Bugzilla-URL: http://gcc.gnu.org/bugzilla/ Auto-Submitted: auto-generated Content-Type: text/plain; charset="UTF-8" MIME-Version: 1.0 Mailing-List: contact gcc-bugs-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-bugs-owner@gcc.gnu.org X-SW-Source: 2012-11/txt/msg01202.txt.bz2 http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54429 --- Comment #4 from Oleg Endo 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.