This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
[PATCH] global register problem
- From: Richard Zidlicky <rz at linux-m68k dot org>
- To: gcc mailing list <gcc at gcc dot gnu dot org>
- Date: Thu, 1 Aug 2002 18:01:23 +0200
- Subject: [PATCH] global register problem
Hi,
I have a problem with this testcase:
void bar(void);
extern int x1;
register int g1 asm("%d7");
void foo(void)
{
g1=x1;
bar();
}
gcc 3.1.1 will ICE as
# m68k-linux-gcc -O2 -da -S -fverbose-asm x4.i
x4.i: In function `foo':
x4.i:12: Internal compiler error in verify_wide_reg, at flow.c:557
x4.i.15.life:
;; Function foo
30 registers.
Register 29 used 2 times across 2 insns in block 0; set 1 time; pointer.
1 basic blocks, 2 edges.
Basic block 0: first insn 17, last 13, loop_depth 0, count 0, freq 10000.
Predecessors: ENTRY [100.0%] (fallthru)
Successors: EXIT [100.0%] (fallthru)
Registers live at start: 14 [%a6] 15 [%sp]
Registers live at end: 7 [%d7] 14 [%a6] 15 [%sp]
(note 2 0 3 NOTE_INSN_DELETED)
(note 3 2 17 NOTE_INSN_FUNCTION_BEG)
;; Start of basic block 0, registers live: 14 [%a6] 15 [%sp]
(note 17 3 9 [bb 0] NOTE_INSN_BASIC_BLOCK)
(insn 9 17 12 (set (reg/v:SI 7 %d7)
(mem/f:SI (symbol_ref:SI ("x1")) [2 x1+0 S4 A16])) 29 {*m68k.md:976} (n
il)
(nil))
(insn 12 9 13 (set (reg/f:SI 29)
(symbol_ref:SI ("bar"))) 29 {*m68k.md:976} (nil)
(expr_list:REG_EQUAL (symbol_ref:SI ("bar"))
(nil)))
(call_insn 13 12 14 (call (mem:QI (reg/f:SI 29) [0 S1 A8])
(const_int 0 [0x0])) 370 {*m68k.md:7234} (insn_list 9 (insn_list 12 (ni
l)))
(expr_list:REG_DEAD (reg:SI 7 %d7)
(expr_list:REG_DEAD (reg/f:SI 29)
(nil)))
(nil))
;; End of basic block 0, registers live:
7 [%d7] 14 [%a6] 15 [%sp]
(note 14 13 0 NOTE_INSN_FUNCTION_END)
Because %d7 is in regs_invalidated_by_call %d7 it is mark_set_1(..)
for the call instruction. This removes it from pbi->reg_live
and the subsequent attempt to make it live again by calling
mark_used_reg(..) in flow.c:1773 results in adding an REG_DEAD note
for %d7 to the call instruction instead of making it live again.
Later the store to g1 gets eliminated somewhere.
This is the backtrace at the point where the REG_DEAD note for %d7
is added:
#0 mark_used_reg (pbi=0x82d4d30, reg=<incomplete type>,
cond=<incomplete type>, insn=<incomplete type>)
at ../../gcc-3.1-new/gcc/flow.c:3569
#1 0x80f58a6 in propagate_one_insn (pbi=0x82d4d30, insn=<incomplete type>)
at ../../gcc-3.1-new/gcc/flow.c:1773
#2 0x80f5c47 in propagate_block (bb=<error type>, live=<error type>,
local_set=<error type>, cond_local_set=<error type>, flags=103)
at ../../gcc-3.1-new/gcc/flow.c:2026
#3 0x80f4033 in update_life_info (blocks=<error type>, extent=<error type>,
prop_flags=127) at ../../gcc-3.1-new/gcc/flow.c:726
#4 0x80f3ac7 in life_analysis (f=<incomplete type>, file=0x82d23d8, flags=127)
at ../../gcc-3.1-new/gcc/flow.c:477
#5 0x818dbed in rest_of_compilation (decl=<incomplete type>)
at ../../gcc-3.1-new/gcc/toplev.c:3028
This patch seems to cure all regression in my program that heavilly
relies on global register variables, any opinions?
Richard
*** flow.c.rz Mon Jul 29 12:01:06 2002
--- flow.c Thu Aug 1 17:24:06 2002
***************
*** 1770,1777 ****
so they are made live. */
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
if (global_regs[i])
! mark_used_reg (pbi, gen_rtx_REG (reg_raw_mode[i], i),
! cond, insn);
}
}
--- 1770,1780 ----
so they are made live. */
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
if (global_regs[i])
! {
! SET_REGNO_REG_SET (pbi->reg_live, i);
! mark_used_reg (pbi, gen_rtx_REG (reg_raw_mode[i], i),
! cond, insn);
! }
}
}