On Mon, May 11, 2015 at 8:00 PM, Jan Hubicka <hubi...@ucw.cz> wrote: >> On Sun, 10 May 2015, Jan Hubicka wrote: >> >> > > On i386, peepholes that transform memory load and register-indirect jump >> > > into >> > > memory-indirect jump are overly restrictive in that they don't allow >> > > combining >> > > when the jump target is loaded into %eax, and the called function >> > > returns a >> > > value (also in %eax, so it's not dead after the call). Fix this by >> > > checking >> > > for same source and output register operands separately. >> > > >> > > OK? >> > > * config/i386/i386.md (sibcall_value_memory): Extend peepholes to >> > > allow memory address in %eax. >> > > (sibcall_value_pop_memory): Likewise. >> > >> > Why do we need the check for liveness after all? There is SIBLING_CALL_P >> > (peep2_next_insn (1)) so we know that the function terminates by the call >> > and there are no other uses of the value. >> >> Indeed. Uros, the peep2_reg_dead_p check was added by your patch as svn >> revision 211776, git commit e51f8b8fed. Would you agree that the check is >> not >> necessary for sibcalls as Honza explains? Would you approve a patch that >> removes it in the sibcall peepholes I modify in the patch under discussion? >> >> > Don't we however need to check that operands[0] is not used by the >> > call_insn as >> > parameter of the call? I.e. something like >> > >> > void >> > test(void (*callback ())) >> > { >> > callback(callback); >> > } >> >> You need a pointer-to-pointer-to-function to trigger the peephole. Something >> like this: >> >> void foo() >> { >> void (**bar)(void*); >> asm("":"=r"(bar)); >> (*bar)(*bar); >> } >> >> > I think instead of peep2_reg_dead_p we want to check that the parameter is >> > not in >> > CALL_INSN_FUNCTION_USAGE of the sibcall.. >> >> Playing with the above testcase I can't induce failure. It seems today GCC >> won't allocate the same register as callee address and one of the arguments. >> Do you want me to implement such a check anyway? > > Hmm, only way I can trigger same register is: > void foo() > { > void (**bar)(void*); > asm("":"=r"(bar)); > register void (*var)(void *) asm("%eax"); > var=*bar; > asm("":"+r"(var)); > var(var); > } > > removing the second asm makes CSE to forward propagae the memory operand > to call that makes the call different from the register variable. > > Still I would check for that, but this is more Uros' area.
This is from [1], and reading this reference, it looks to me that the check was introduced due to: - Adds check that eliminated register is really dead after the call (maybe an overkill, but some hard-to-debug problems surfaced due to missing liveness checks in the past) Going down that memory lane, it looks like a safety check for something that *might* happen. Looking at the comment, I'd say we can remove the check, but we should look for possible fallout. [1] https://gcc.gnu.org/ml/gcc-patches/2014-06/msg01451.html Uros.