This is the mail archive of the 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: PR gcc/7618: Support MI thunks in the MIPS backend

Richard Sandiford <> writes:

> To be honest, I've been very reluctant to do this.  Two main reasons:
> - As your patch demonstrates, there's not really any special
>   MIPS-specific tricks that we can pull.  It's really just a case
>   of using standard patterns.
>   I was hoping that (at least after tree-ssa) it would be possible
>   to provide a target-independent implementation.

A target independent pattern would probably be better.  However, I
think it would require a new standard RTL pattern.  That's because
there is no standard RTL way to jump to another function.  A sibcall
is not the same, since it only operates in the context of a function

> - It's always difficult writing out MIPS asm directly.  There are so
>   many variations to worry about.  (At least 6 ABI variations that
>   I think of as supported, plus PIC/no-PIC and mips16/non-mips16.)
>   The necessary logic is already present elsewhere in the compiler,
>   but it's all geared towards rtl.  If we're trying to write out
>   the asm directly, we end up having to duplicate a lot of it.

Sure.  I punted on all that by just relying on the assembler macros
which we know are there for MIPS targets.  Like it or not, the
assembler already has to know how to handle all the different

> Plus a minor reason: when using explicit relocs for -mabicalls,
> I suspect the current (generic) implementation will give slightly
> better code for the cases that it can handle.

As I see it, on the one hand the generic implementation will permit
lazy binding.  On the other hand, it will require an extra pop for the
return address each time the thunk is used.  Hard to say where the
advantage lies.

Clearly, when using explicit relocs, it should be possible to do lazy
binding even when using thunks.  However, gas doesn't appear to
generate them.  I'm not entirely sure why.  I think it's because
tc_gen_reloc() relaxes CALL16 to GOT_DISP, but I haven't investigated
why this happens.

In fact, gas is supposed to do lazy binding even when not using
explicit relocs.  However, that doesn't work either, perhaps for the
same reason.  I haven't investigated why this happens either, but I'm
pretty sure it's a bug.  The lca macro is supposed to do lazy binding,
and I'm sure it worked once, but it doesn't seem to work now.

> WRT patch itself:
> - I couldn't see any code to set up the gp for TARGET_ABICALLS.
>   Note that you'll need to use a call-clobbered register rather
>   than $gp for TARGET_NEWABI.

Hmmm, good point.

> - The mips16 call sequence looks wrong.  "la" and "dla" can only be used
>   for (PC-relative) references to constant pool labels.  You can't use
>   them for loading arbitrary addresses.

Yes, I know.  It worked in my tests, but they were admittedly
simplistic.  The fix is simple: put the address to jump to in a little
constant pool.

> - Did you consider using an rtl implementation, like alpha or rs6000?

I did, but then I decided to just let the assembler deal with all the
complicated issues.  An RTL implementation needs to use the sibcall
instruction, but the MIPS sibcall instruction is only available in
limited circumstances.

This is what i worked out for the RTL implementation.  This isn't
correct, though.  This is the point at which I gave up.

I looked at PR 7618 because it is targeted for 3.4.0.  If you do not
want to implement the MI thunk code for the MIPS backend, even though
it has been implemented for most or all other popular backends, then
we should retarget the PR to a different release.


  rtx this;
  rtx tmp;
  rtx funexp;
  rtx picreg;
  rtx insn;

  /* Mark the end of the (empty) prologue.  */

  if (mips_return_in_memory (TREE_TYPE (TREE_TYPE (function))))
    this = gen_rtx_REG (Pmode, GP_ARG_FIRST + 1);
    this = gen_rtx_REG (Pmode, GP_ARG_FIRST);

  tmp = gen_rtx_REG (Pmode, 2);

  if (delta != 0)
      rtx delta_rtx;

      if (SMALL_OPERAND (delta))
	delta_rtx = GEN_INT (delta);
	  mips_move_integer (tmp, delta);
	  delta_rtx = tmp;

      emit_insn (TARGET_64BIT
		 ? gen_adddi3 (this, this, delta_rtx)
		 : gen_addsi3 (this, this, delta_rtx));

  if (vcall_offset != 0)
      emit_move_insn (tmp, gen_rtx_MEM (Pmode, this));
      if (SMALL_OPERAND (vcall_offset))
	emit_move_insn (tmp,
			gen_rtx_MEM (Pmode,
				     gen_rtx_PLUS (Pmode, tmp,
						   GEN_INT (vcall_offset))));
	  rtx tmp2;

	  tmp2 = gen_rtx_REG (Pmode, 3);
	  mips_move_integer (tmp2, vcall_offset);
	  emit_insn (TARGET_64BIT
		     ? gen_adddi3 (tmp, tmp, tmp2)
		     : gen_addsi3 (tmp, tmp, tmp2));
	  emit_move_insn (tmp, gen_rtx_MEM (Pmode, tmp));
      emit_insn (TARGET_64BIT
		 ? gen_adddi3 (this, this, tmp)
		 : gen_addsi3 (this, this, tmp));

  if (! TREE_USED (function))
      assemble_external (function);
      TREE_USED (function) = 1;
  funexp = XEXP (DECL_RTL (function), 0);
  no_new_pseudos = 1;
  picreg = gen_rtx_REG (Pmode, PIC_FUNCTION_ADDR_REGNUM);
  mips_legitimize_const_move (Pmode, picreg, funexp);
  insn = emit_call_insn (gen_sibcall_internal (picreg, GEN_INT (0)));
  SIBLING_CALL_P (insn) = 1;
  emit_barrier ();

  /* Run just enough of rest_of_compilation to get the insns emitted.
     There's not really enough bulk here to make other passes such as
     instruction scheduling worth while.  Note that use_thunk calls
     assemble_start_function and assemble_end_function.  */
  insn = get_insns ();
  insn_locators_initialize ();
  shorten_branches (insn);
  final_start_function (insn, file, 1);
  final (insn, file, 1, 0);
  final_end_function ();
  output_constant_pool (XSTR (XEXP (DECL_RTL (thunk_fndecl), 0), 0),
  function_section (thunk_fndecl);

  reload_completed = 0;
  epilogue_completed = 0;
  no_new_pseudos = 0;

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