This is the mail archive of the binutils@sourceware.org mailing list for the binutils 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: [patch - gas] MIPS: fix problem with mips16 delay branchoptimization.


On Mon, 2005-09-05 at 22:46 +0100, Richard Sandiford wrote:
> David Ung <davidu@mips.com> writes:
> > This patch fixes a problem for Mips16 delay branch optimization when
> > swapping instructions, but the instructions belongs to different
> > fragments.  This shows up in the GCC C regressions for mips16.
> 
> > *************** append_insn (struct mips_cl_insn *ip, ex
> > *** 2698,2706 ****
> >   	      struct mips_cl_insn delay = history[0];
> >   	      if (mips_opts.mips16)
> >   		{
> > ! 		  know (delay.frag == ip->frag);
> >   		  move_insn (ip, delay.frag, delay.where);
> > ! 		  move_insn (&delay, ip->frag, ip->where + insn_length (ip));
> >   		}
> >   	      else if (relaxed_branch)
> >   		{
> > --- 2698,2719 ----
> >   	      struct mips_cl_insn delay = history[0];
> >   	      if (mips_opts.mips16)
> >   		{
> > ! 		  if (delay.frag == ip->frag)
> > ! 		    {
> >   		      move_insn (ip, delay.frag, delay.where);
> > ! 		      move_insn (&delay, ip->frag, delay.where 
> > ! 				 + insn_length (ip));
> > ! 		    }
> > ! 		  else if (insn_length (ip) == insn_length (&delay))
> > ! 		    {
> > ! 		      move_insn (&delay, ip->frag, ip->where);
> > ! 		      move_insn (ip, history[0].frag, history[0].where);
> > ! 		    }
> > ! 		  else
> > ! 		    {
> > ! 		      add_fixed_insn (NOP_INSN);
> > ! 		      delay = *NOP_INSN;
> > ! 		    }
> >   		}
> >   	      else if (relaxed_branch)
> >   		{
> 
> Can you explain the patch in more detail?  Do you have a reduced testcase?
> 
> In theory, the code adding the instruction is supposed to guarantee
> that the frag has enough room to accomodate the branch:
> 
>       /* Make sure there is enough room to swap this instruction with
>          a following jump instruction.  */
>       frag_grow (6);
>       add_fixed_insn (ip);
> 
> Presumably this code isn't triggering, or something else has decided
> to close the frag between the previous instruction and the branch,
> even though there was enough room.  If the latter, then how does
> this happen?

If I remember correctly.  The frag_grow statement will triggering a new
frag being created, hence the jump instruction gets added to new frag
while the delay instruction would still be in the last frag.

You need to create enough instructions for the above case to happen and
I could reproduce it by compiling the c_compat_x_tst.c file from the GCC
scalar-return-3 regression suite.  Turning on just these tests.

c_compat_x_tst.c:

T(ci, _Complex int, CINT (2, 3))
T(cl, _Complex long, CINT (3, 4))

from the c_compat_x_tst.s file, you'll get thses functions: 
checkci, testitci, checkcl, testitcl and scalar_return_3_x.
And it's the last "jr" from "testitcl" that shows the problem.

function testitcl:
...
.L36:
        move    $sp,$17
        lw      $7,88($sp)
        lw      $17,84($sp)
        lw      $16,80($sp)
        addiu   $sp,$sp,96
        jr      $7
        .align  2
.L37:
        .word   g01cl
.L38:
        .word   g02cl
...

after assembling with gas, objdump of fuction testitcl:

     ....
     ca4:       65b9            move    sp,s1
     ca6:       9716            lw      a3,88(sp)
     ca8:       9115            lw      s1,84(sp)
     caa:       9014            lw      s0,80(sp)
     cac:       ef00            jr      a3
     cae:       ef00            jr      a3
     cb0:       0000            addiu   s0,sp,0
                        cb0: R_MIPS_32  g01cl
        ...
                        cb4: R_MIPS_32  g02cl


David.


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