This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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);
! 	      }
  	}
      }
  



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]