This is the mail archive of the gcc-patches@gcc.gnu.org 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: [PATCH 6/6] [RS6000] inline plt call sequences


Hi Alan,

On Tue, Nov 13, 2018 at 11:23:43PM +1030, Alan Modra wrote:
> Finally, the point of the previous patches in this series, support for
> inline PLT calls, keyed off -fno-plt.  This emits code using new
> relocations that tie all insns in the sequence together, so that the
> linker can edit the sequence back to a direct call should the call
> target turn out to be local.  An example of ELFv2 code to call puts is
> as follows:
> 
>      .reloc .,R_PPC64_PLTSEQ,puts
>         std 2,24(1)
>      .reloc .,R_PPC64_PLT16_HA,puts
>         addis 12,2,0
>      .reloc .,R_PPC64_PLT16_LO_DS,puts
>         ld 12,0(12)
>      .reloc .,R_PPC64_PLTSEQ,puts
>         mtctr 12
>      .reloc .,R_PPC64_PLTCALL,puts
>         bctrl
>         ld 2,24(1)
> 
> "addis 12,2,puts@plt@ha" and "ld 12,puts@plt@l(12)" are also supported
> by the assembler.  gcc instead uses the explicit R_PPC64_PLT16_HA and
> R_PPC64_PLT16_LO_DS relocs because when the call is to __tls_get_addr
> an extra reloc is emitted at every place where one is shown above, to
> specify the __tls_get_addr arg.  The linker expects the extra reloc to
> come first.  .reloc enforces that ordering.
> 
> The patch also changes code emitted for longcalls if the assembler
> supports the new marker relocs, so that these too can be edited.  One
> side effect of longcalls using PLT16 relocs is that they can now be
> resolved lazily by ld.so.
> 
> I don't support lazy inline PLT calls for ELFv1, because ELFv1 would
> need barriers to reliably load both the function address and toc
> pointer from the PLT.  ELFv1 -fno-plt uses the longcall sequence
> instead, which isn't edited by GNU ld.

That all sounds great :-)  Has this been tested with older binutils, too?


> 	* config.in (HAVE_AS_PLTSEQ): Add.
> 	* config/rs6000/predicates.md (indirect_call_operand): New.
> 	* config/rs6000/rs6000-protos.h (rs6000_pltseq_template),
> 	(rs6000_sibcall_sysv): Declare.
> 	* config/rs6000/rs6000.c (init_cumulative_args): Set cookie
> 	CALL_LONG for -fno-plt.
> 	(print_operand <T, z, 0>): Handle UNSPEC_PLTSEQ.
> 	(rs6000_indirect_call_template_1): Emit .reloc directives for
> 	UNSPEC_PLTSEQ calls.
> 	(rs6000_pltseq_template): New function.
> 	(rs6000_longcall_ref): Add arg parameter.  Use PLT16 insns if
> 	relocs supported by assembler.  Move SYMBOL_REF test to callers.
> 	(rs6000_call_aix): Adjust rs6000_longcall_ref call.  Package
> 	insns in UNSPEC_PLTSEQ, preserving original func_desc.
> 	(rs6000_call_sysv): Likewise.
> 	(rs6000_sibcall_sysv): New function.
> 	* config/rs6000/rs6000.h (HAVE_AS_PLTSEQ): Provide default.
> 	* config/rs6000/rs6000.md (UNSPEC_PLTSEQ, UNSPEC_PLT16_HA,
> 	UNSPEC_PLT16_LO): New.
> 	(pltseq_tocsave, pltseq_plt16_ha, pltseq_plt16_lo, pltseq_mtctr): New.
> 	(call_indirect_nonlocal_sysv): Don't differentiate zero from non-zero
> 	cookie in constraints.  Test explicitly for flags in length attr.
> 	Handle unspec operand 1.
> 	(call_value_indirect_nonlocal_sysv): Likewise.
> 	(call_indirect_aix, call_value_indirect_aix): Handle unspec operand 1.
> 	(call_indirect_elfv2, call_value_indirect_elfv2): Likewise.
> 	(sibcall, sibcall_value): Use rs6000_sibcall_sysv.
> 	(sibcall_indirect_nonlocal_sysv): New pattern.
> 	(sibcall_value_indirect_nonlocal_sysv): Likewise.
> 	(sibcall_nonlocal_sysv, sibcall_value_nonlocal_sysv): Remove indirect
> 	call alternatives.
> 	* configure.ac: Check for gas plt sequence marker support.
> 	* configure: Regenerate.


> @@ -10727,10 +10727,20 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
>      cum->nargs_prototype = n_named_args;
>  
>    /* Check for a longcall attribute.  */
> -  if ((!fntype && rs6000_default_long_calls)
> -      || (fntype
> -	  && lookup_attribute ("longcall", TYPE_ATTRIBUTES (fntype))
> -	  && !lookup_attribute ("shortcall", TYPE_ATTRIBUTES (fntype))))
> +  if (((!fntype && rs6000_default_long_calls)
> +       || (fntype
> +	   && lookup_attribute ("longcall", TYPE_ATTRIBUTES (fntype))
> +	   && !lookup_attribute ("shortcall", TYPE_ATTRIBUTES (fntype))))
> +      || (DEFAULT_ABI != ABI_DARWIN
> +	  && !(fndecl
> +	       && !DECL_EXTERNAL (fndecl)
> +	       && !DECL_WEAK (fndecl)
> +	       && (*targetm.binds_local_p) (fndecl))
> +	  && (flag_plt
> +	      ? (fntype
> +		 && lookup_attribute ("noplt", TYPE_ATTRIBUTES (fntype)))
> +	      : !(fntype
> +		  && lookup_attribute ("plt", TYPE_ATTRIBUTES (fntype))))))
>      cum->call_cookie |= CALL_LONG;

Could you split this into a few cases?  Maybe with some extra locals.  It
is hard to understand the code as it is.

I mean like

  if (...)
    cum->call_cookie |= CALL_LONG;
  if (...)
    cum->call_cookie |= CALL_LONG;
  if (...)
    cum->call_cookie |= CALL_LONG;


> +(define_insn "*sibcall_indirect_nonlocal_sysv<mode>"

> +   (set (attr "length")
> +	(cond [(and (and (match_test "!rs6000_speculate_indirect_jumps")
> +			 (match_test "which_alternative != 1"))
> +		    (match_test "(INTVAL (operands[2]) & (CALL_V4_SET_FP_ARGS | CALL_V4_CLEAR_FP_ARGS))"))
> +		  (const_string "12")
> +	       (ior (and (match_test "!rs6000_speculate_indirect_jumps")
> +			 (match_test "which_alternative != 1"))
> +		   (match_test "(INTVAL (operands[2]) & (CALL_V4_SET_FP_ARGS | CALL_V4_CLEAR_FP_ARGS))"))
> +		  (const_string "8")]
> +	      (const_string "4")))])

Please use set_attr_alternative for these.


Looks fine modulo those nits.  Okay for trunk.  Thanks!


Segher


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