This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug target/60071] [4.9 Regression] [SH] internal compiler error: in final_scan_insn, at final.c:2963
- From: "olegendo at gcc dot gnu.org" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Tue, 25 Feb 2014 23:07:19 +0000
- Subject: [Bug target/60071] [4.9 Regression] [SH] internal compiler error: in final_scan_insn, at final.c:2963
- Auto-submitted: auto-generated
- References: <bug-60071-4 at http dot gcc dot gnu dot org/bugzilla/>
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60071
Oleg Endo <olegendo at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Status|UNCONFIRMED |NEW
Last reconfirmed| |2014-02-25
Ever confirmed|0 |1
--- Comment #6 from Oleg Endo <olegendo at gcc dot gnu.org> ---
I've just tried this with -O2. This is what happens...
After combine, there is the problematic insn:
(insn 41 40 34 3 (parallel [
(set (reg:SI 161 [ <retval> ])
(minus:SI (const_int -2147483648 [0xffffffff80000000])
(reg:SI 147 t)))
(clobber (reg:SI 147 t))
]) sh_tmp.cpp:10 404 {*mov_t_msb_neg}
(nil))
After split1 it is split correctly into constant load + negc and before the IRA
pass it looks like this:
(insn 45 40 46 4 (set (reg:SI 169)
(const_int -2147483648 [0xffffffff80000000])) sh_tmp.cpp:10 257
{movsi_ie}
(nil))
(insn 46 45 43 4 (parallel [
(set (reg:SI 161 [ <retval> ])
(minus:SI (neg:SI (reg:SI 169))
(reg:SI 147 t)))
(clobber (reg:SI 147 t))
]) sh_tmp.cpp:10 205 {*negc}
(nil))
However, the IRA pass moves the constant back and replaces the insn:
(insn 46 40 43 4 (parallel [
(set (reg:SI 161 [ <retval> ])
(minus:SI (const_int -2147483648 [0xffffffff80000000])
(reg:SI 147 t)))
(clobber (reg:SI 147 t))
]) sh_tmp.cpp:10 404 {*mov_t_msb_neg}
which happens while can_create_pseudo_p () returns 'true', thus the insn
matches. This is a bit counter productive. The constant load was split out on
purpose so that it can be hoisted/combined easier (I was thinking of adding an
SH specific RTL pass to optimize constant loads and sharing. On SH there are a
couple of cases where constants are emitted during combine and split1 which
won't be CSE'd).
The following seems to fix the problem (although not fully tested):
Index: gcc/config/sh/sh.md
===================================================================
--- gcc/config/sh/sh.md (revision 208155)
+++ gcc/config/sh/sh.md (working copy)
@@ -11434,6 +11434,10 @@
;; T = 1: 0x80000000 -> reg
;; T = 0: 0x7FFFFFFF -> reg
;; This works because 0 - 0x80000000 = 0x80000000.
+;;
+;; This insn must not match again after it has been split into the constant
+;; load and negc. This is accomplished by the special negc insn that
+;; has a use on the operand.
(define_insn_and_split "*mov_t_msb_neg"
[(set (match_operand:SI 0 "arith_reg_dest")
(minus:SI (const_int -2147483648) ;; 0x80000000
@@ -11444,12 +11448,23 @@
"&& can_create_pseudo_p ()"
[(set (match_dup 2) (const_int -2147483648))
(parallel [(set (match_dup 0) (minus:SI (neg:SI (match_dup 2))
- (reg:SI T_REG)))
- (clobber (reg:SI T_REG))])]
+ (reg:SI T_REG)))
+ (clobber (reg:SI T_REG))
+ (use (match_dup 2))])]
{
operands[2] = gen_reg_rtx (SImode);
})
+(define_insn "*mov_t_msb_neg_negc"
+ [(set (match_operand:SI 0 "arith_reg_dest" "=r")
+ (minus:SI (neg:SI (match_operand:SI 1 "arith_reg_operand" "r"))
+ (match_operand:SI 2 "t_reg_operand")))
+ (clobber (reg:SI T_REG))
+ (use (match_dup 1))]
+ "TARGET_SH1"
+ "negc %1,%0"
+ [(set_attr "type" "arith")])
+
;; These are essentially the same as above, but with the inverted T bit.
;; Combine recognizes the split patterns, but does not take them sometimes
;; if the T_REG clobber is specified. Instead it tries to split out the