This is the mail archive of the gcc-patches@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]

Fix sh spill failures for libcalls


All our libcall blocks are supposed to end with an insn that copies the
hard return register into a pseudo.
This pseudo can turn into a MEM later on due to being a user variable
whose address is taken.  Worse, the address of the MEM might need to be
computed just before the insn, moving the call and the insn that kills
the call value register apart.  By the time we reach local-alloc, we have
something like

(call_insn/u 29 28 132 (parallel[ 
            (set (reg:SI 0 r0)
                (call (mem:SI (reg:SI 61) 0)
                    (const_int 0 [0x0])))
            (use (reg:SI 48 fpscr))
            (clobber (reg:SI 17 pr))
        ] ) 101 {call_valuei}

(insn 132 29 133 (set (reg:SI 89)
        (const_int 128 [0x80])) 81 {movsi_i}

(insn 31 133 34 (set (mem/f:SI (plus:SI (reg:SI 14 r14)
                (reg:SI 89)) 5)
        (reg:SI 0 r0)) 81 {movsi_i}

and we can't reload insn 31 because we'd need register 0 for the address.
The patch below attempts to fix this problem at the earliest time possible
by simply not allowing user variables as target in a libcall block.


Bernd

	* optabs.c (emit_libcall_block): If target is a user variable,
	copy to a temporary first.

Index: optabs.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/optabs.c,v
retrieving revision 1.77
diff -u -p -r1.77 optabs.c
--- optabs.c	2000/09/11 01:50:46	1.77
+++ optabs.c	2000/09/15 12:19:28
@@ -2756,8 +2756,14 @@ emit_libcall_block (insns, target, resul
      rtx result;
      rtx equiv;
 {
+  rtx final_dest = target;
   rtx prev, next, first, last, insn;
 
+  /* If this is a reg with REG_USERVAR_P set, then it could possibly turn
+     into a MEM later.  Protect the libcall block from this change.  */
+  if (! REG_P (target) || REG_USERVAR_P (target))
+    target = gen_reg_rtx (GET_MODE (target));
+
   /* look for any CALL_INSNs in this sequence, and attach a REG_EH_REGION
      reg note to indicate that this call cannot throw or execute a nonlocal
      goto. (Unless there is already a REG_EH_REGION note, in which case
@@ -2832,6 +2838,9 @@ emit_libcall_block (insns, target, resul
 	 "last".  */
       remove_note (last, find_reg_note (last, REG_EQUAL, NULL_RTX));
     }
+
+  if (final_dest != target)
+    emit_move_insn (final_dest, target);
 
   if (prev == 0)
     first = get_insns ();


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