Bug 39522 - [4.4 Regression] fix for PR37514 gives FAIL: gcc.c-torture/execute/stdarg-3.c compilation, -O3 -fomit-frame-pointer -funroll-loops (internal compiler error)
Summary: [4.4 Regression] fix for PR37514 gives FAIL: gcc.c-torture/execute/stdarg-3.c...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: rtl-optimization (show other bugs)
Version: 4.4.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: ice-on-valid-code, patch
Depends on:
Blocks:
 
Reported: 2009-03-22 22:32 UTC by Hans-Peter Nilsson
Modified: 2009-03-27 05:46 UTC (History)
2 users (show)

See Also:
Host: x86_64-unknown-linux-gnu, i686-unknown-linux-gnu
Target: crisv32-*-*
Build:
Known to work:
Known to fail:
Last reconfirmed: 2009-03-26 01:34:16


Attachments
preprocessed stdarg-3.c to avoid stdarg.h dependency. (774 bytes, text/plain)
2009-03-22 22:34 UTC, Hans-Peter Nilsson
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Hans-Peter Nilsson 2009-03-22 22:32:27 UTC
Using r144996 configured for crisv32-axis-linux-gnu (but the error is there for crisv32-axis-elf, which is somewhat more repeatable and simulator-friendly), I get these errors:

Running /tmp/x144980/gcc/gcc/testsuite/gcc.c-torture/execute/execute.exp ...
...
FAIL: gcc.c-torture/execute/stdarg-3.c compilation,  -O3 -fomit-frame-pointer -funroll-loops  (internal compiler error)
FAIL: gcc.c-torture/execute/stdarg-3.c compilation,  -O3 -fomit-frame-pointer -funroll-all-loops -finline-functions  (internal compiler error)

The error message in gcc.log for the both is:
x/gcc.c-torture/execute/stdarg-3.c: In function 'main':
x/gcc.c-torture/execute/stdarg-3.c:166: internal compiler error: in reload_as_needed, at reload1.c:4380

"call debug_rtx (insn)" at the gcc_assert at the line in question yields
(insn 427 1353 1140 17 /tmp/x144980/gcc/gcc/testsuite/gcc.c-torture/execute/stdarg-3.c:144 (set (mem/s/c:SI (reg:SI 6 r6) [10 S4 A8])
        (reg:SI 8 r8)) 38 {*movsi_internal} (expr_list:REG_INC (reg:SI 8 r8)
        (expr_list:REG_INC (reg:SI 6 r6)
            (nil))))

and in_hard_regno is 8 and in_regno is 207.  Note the "spurious" left-over REG_INC note.

It seems revision 142328 (the fix for PR37514, in which the code and the triggering gcc_assert was added) exposed or cause this bug.  A crisv32-axis-elf cc1 from tags/gcc_4_3_3_release does not give any such error, neither does trunk r142327.  Trunk r142328 does give the error.

FWIW, crisv32-*-* has the interesting trait that it's AUTO_INC_DEC, has a moderate amount of registers available (in contrast to e.g. ia64) and can't offset addresses (only (mem reg) and (mem (post_inc reg)) are valid).
Comment 1 Hans-Peter Nilsson 2009-03-22 22:34:36 UTC
Created attachment 17515 [details]
preprocessed stdarg-3.c to avoid stdarg.h dependency.
Comment 2 Hans-Peter Nilsson 2009-03-22 23:04:43 UTC
Same bug is present as a g++.dg/torture/pr31863.C  -O2 (and higher) regression.
Comment 3 Vladimir Makarov 2009-03-25 21:05:55 UTC
Thanks for reporting this.

The compiler is broken on gcc_assert in the following code

+		  else if ((code == PRE_INC || code == PRE_DEC
+			    || code == POST_INC || code == POST_DEC))
+		    {
+		      int in_hard_regno;
+		      int in_regno = REGNO (XEXP (in_reg, 0));
+
+		      if (reg_last_reload_reg[in_regno] != NULL_RTX)
+			{
+			  in_hard_regno = REGNO (reg_last_reload_reg[in_regno]);
+			  gcc_assert (TEST_HARD_REG_BIT (reg_reloaded_valid,
+							 in_hard_regno));
+			  for (x = old_prev ? NEXT_INSN (old_prev) : insn;
+			       x != old_next;
+			       x = NEXT_INSN (x))
+			    if (x == reg_reloaded_insn[in_hard_regno])
+			      break;
+			  /* If for some reasons, we didn't set up
+			     reg_last_reload_reg in this insn,
+			     invalidate inheritance from previous
+			     insns for the incremented/decremented
+			     register.  Such registers will be not in
+			     reg_has_output_reload.  */
+			  if (x == old_next)
+			    forget_old_reloads_1 (XEXP (in_reg, 0),
+						  NULL_RTX, NULL);
+			}
+		    }

Here in_regno is 191 and in_hard_regno is 8.  This code is executed
after emit_insn_reloads which invalidates hard register 8 when
processing reload #5 of the current insn.  I've overlooked this
possibility in my patch for PR37514

http://gcc.gnu.org/ml/gcc-patches/2008-11/msg01424.html

reg_reloaded_valid should be checked for reg_reloaded_insn validity
but not as gcc_assert.  I'll send a new patch solving the problem soon.


(insn 411 1161 1160 17 /tmp/x144980/gcc/gcc/testsuite/gcc.c-torture/execute/stdarg-3.c:144 (set (mem/s/c:SI (post_inc:SI (reg/f:SI 192)) [10 S4 A8])
        (mem/s/c:SI (post_inc:SI (reg/f:SI 191)) [10 a3+4 S4 A16])) 38 {*movsi_internal} (expr_list:REG_INC (reg/f:SI 191)
        (expr_list:REG_INC (reg/f:SI 192)
            (nil))))

Reloads for insn # 411
Reload 0: reload_in (SI) = (plus:SI (reg/f:SI 14 sp)
                                                    (const_int 104 [0x68]))
	GENERAL_REGS, RELOAD_FOR_OPERAND_ADDRESS (opnum = 0), can't combine
	reload_in_reg: (plus:SI (reg/f:SI 14 sp)
                                                    (const_int 104 [0x68]))
	reload_reg_rtx: (reg:SI 9 r9)
Reload 1: reload_in (SI) = (post_inc:SI (mem/c:SI (plus:SI (reg/f:SI 14 sp)
                                                            (const_int 104 [0x68])) [11 %sfp+-280 S4 A8]))
	reload_out (SI) = (post_inc:SI (mem/c:SI (plus:SI (reg/f:SI 14 sp)
                                                            (const_int 104 [0x68])) [11 %sfp+-280 S4 A8]))
	GENERAL_REGS, RELOAD_FOR_OPERAND_ADDRESS (opnum = 0), inc by 4, can't combine
	reload_in_reg: (post_inc:SI (reg/f:SI 192))
	reload_reg_rtx: (reg:SI 6 r6)
Reload 2: reload_in (SI) = (plus:SI (reg/f:SI 14 sp)
                                                    (const_int 100 [0x64]))
	GENERAL_REGS, RELOAD_FOR_INPUT_ADDRESS (opnum = 1), can't combine
	reload_in_reg: (plus:SI (reg/f:SI 14 sp)
                                                    (const_int 100 [0x64]))
	reload_reg_rtx: (reg:SI 9 r9)
Reload 3: reload_in (SI) = (post_inc:SI (mem/c:SI (plus:SI (reg/f:SI 14 sp)
                                                            (const_int 100 [0x64])) [11 %sfp+-284 S4 A8]))
	reload_out (SI) = (post_inc:SI (mem/c:SI (plus:SI (reg/f:SI 14 sp)
                                                            (const_int 100 [0x64])) [11 %sfp+-284 S4 A8]))
	GENERAL_REGS, RELOAD_FOR_INPUT_ADDRESS (opnum = 1), inc by 4, can't combine
	reload_in_reg: (post_inc:SI (reg/f:SI 191))
	reload_reg_rtx: (reg:SI 8 r8)
Reload 4: reload_out (SI) = (mem/s/c:SI (post_inc:SI (reg/f:SI 192)) [10 S4 A8])
	NO_REGS, RELOAD_FOR_OUTPUT (opnum = 0), optional
	reload_out_reg: (mem/s/c:SI (post_inc:SI (reg/f:SI 192)) [10 S4 A8])
Reload 5: reload_in (SI) = (mem/s/c:SI (post_inc:SI (reg/f:SI 191)) [10 a3+4 S4 A16])
	GENERAL_REGS, RELOAD_FOR_INPUT (opnum = 1)
	reload_in_reg: (mem/s/c:SI (post_inc:SI (reg/f:SI 191)) [10 a3+4 S4 A16])
	reload_reg_rtx: (reg:SI 8 r8)

Comment 4 Hans-Peter Nilsson 2009-03-26 01:34:16 UTC
Patch at <http://gcc.gnu.org/ml/gcc-patches/2009-03/msg01229.html>.
Thanks!  I'll test crisv32-axis-linux-gnu and report.
Comment 5 Vladimir Makarov 2009-03-26 19:21:31 UTC
Subject: Bug 39522

Author: vmakarov
Date: Thu Mar 26 19:21:18 2009
New Revision: 145093

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=145093
Log:
2009-03-26  Vladimir Makarov  <vmakarov@redhat.com>

	PR rtl-optimization/39522
	* reload1.c (reload_as_needed): Invalidate reg_last_reload_reg too
	when reg_reloaded_valid is set.


Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/reload1.c

Comment 6 Hans-Peter Nilsson 2009-03-27 05:46:10 UTC
Closing.  The patch, now committed, does the job with no regressions for crisv32-axis-linux-gnu.