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]
Other format: [Raw text]

Re: Automatic MMX/x87 FPU mode switching


Quoting Richard Henderson <rth@redhat.com>:

> > (call_insn:HI 14 39 15 0 (set (reg:V8QI 29 mm0)
> >         (call (mem:QI (symbol_ref:SI ("aaa") [flags 0x41] <function_decl
> > 0x40305360 aaa>) [0 S1 A8])
> >             (const_int 0 [0x0]))) 526 {*call_value_0}
> (insn_list:REG_DEP_TRUE 12
> > (insn_list:REG_DEP_TRUE 1
> > 3 (nil)))
> >     (expr_list:REG_DEAD (reg:ALLREGS 8 st)
> >         (expr_list:REG_DEAD (reg:V8QI 30 mm1)
> >             (nil)))
> >     (expr_list:REG_DEP_TRUE (use (reg:V8QI 29 mm0))
> >         (expr_list:REG_DEP_TRUE (use (reg:V8QI 30 mm1))
> >             (expr_list:REG_DEP_TRUE (use (reg:ALLREGS 8 st))
> >                 (nil)))))
> > 
> > ...
> > 
> > (insn 40 21 36 0 (set (reg:ALLREGS 29 mm0)
> >         (unspec_volatile:ALLREGS [
> >                 (reg:ALLREGS 8 st)
> >             ] 5)) 872 {emms} (nil)
> >     (expr_list:REG_DEAD (reg:ALLREGS 8 st)
> >         (nil)))
> 
> Do we have confirmation that (reg:allregs st) is really live here
> between the call and the emms?

Unfortunatelly, %st registers _are_ dead after call_insn. It looks that this is
a show-stopper at the moment, as there is no way to tell register allocator
which "other" registers are live (in fact "disabled") after function call.

I have hacked into this problem this way:

There is following code in flow.c, propagate_one_insn () function that handles
(expr_list:REG_DEP_TRUE ([use,clobber] (reg: ...)) expressions:


	  /* Calls use their arguments, and may clobber memory which
	     address involves some register.  */
	  for (note = CALL_INSN_FUNCTION_USAGE (insn);
	       note;
	       note = XEXP (note, 1))
	    /* We find USE or CLOBBER entities in a FUNCTION_USAGE list: both
	       of which mark_used_regs knows how to handle.  */
	    mark_used_regs (pbi, XEXP (XEXP (note, 0), 0), cond, insn);


	  /* There may be extra registers to be clobbered.  */
	  for (note = CALL_INSN_FUNCTION_USAGE (insn);
	       note;
	       note = XEXP (note, 1))
	    if (GET_CODE (XEXP (note, 0)) == CLOBBER)
	      mark_set_1 (pbi, CLOBBER, XEXP (XEXP (note, 0), 0),
			  cond, insn, pbi->flags);

I have added a "set" expression to set registers instead of using/clobbering it,
i.e: (expr_list:REG_DEP_TRUE (set (reg:ALLREGS 8 st)) to call_insn, and it
managed to mark registers live at the end of call_insn. However, other code does
not expect these registers to die and another "internal consistency error" is
triggered:

	  /* No registers should die.  */
	  if (REGNO_REG_SET_P (bb->global_live_at_start, i))
	    {
	      if (dump_file)
		{
		  fprintf (dump_file,
			   "Register %d died unexpectedly.\n", i);
		  dump_bb (bb, dump_file, 0);
		}
	      fatal_error ("internal consistency failure");
	    }

OTOH, if fatal_error is disabled by commenting it out, the call_insn sets %st
registers live and they remain live between call_insn and the emms. Correct RTL
code is produced up to regstack pass (where compiler ICEs for known reasons
regarding uninitialized live stack registers at function entry).

> We'd also want to test functions with mmx args and fpu return, and
> vice versa.  But if shown to be ok, this is certainly a nice solution.

  With above hacks, correct register life info is produced. However, it is a
hacky solution and some other code should be updated to handle

(expr_list:REG_DEP_TRUE (set (reg:ALLREGS 8 st))

statements.

Uros.


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