> 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.

Honza

Reply via email to