This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: Automatic MMX/x87 FPU mode switching
- From: Uros Bizjak <uros dot bizjak at kss-loka dot si>
- To: Richard Henderson <rth at redhat dot com>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Wed, 06 Jul 2005 08:42:24 +0200
- Subject: Re: Automatic MMX/x87 FPU mode switching
- References: <1119350611.42b7ef5373f49@ssl.kss-loka.si> <20050627052044.GD27305@redhat.com> <1119947886.42c10c6e7f6f2@ssl.kss-loka.si> <20050628164510.GA17378@redhat.com> <1120209233.42c50951ae0eb@ssl.kss-loka.si> <20050701193553.GA2300@redhat.com>
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.