LoongArch: Use explicit relocs for GOT access when -mexplicit-relocs=auto and LTO during a final link with linker plugin

If we are performing LTO for a final link and linker plugin is enabled,
then we are sure any GOT access may resolve to a symbol out of the link
unit (otherwise the linker plugin will tell us the symbol should be
resolved locally and we'll use PC-relative access instead).

Produce machine instructions with explicit relocs instead of la.global
for better scheduling.

gcc/ChangeLog:

	* config/loongarch/loongarch-protos.h
	(loongarch_explicit_relocs_p): Declare new function.
	* config/loongarch/loongarch.cc (loongarch_explicit_relocs_p):
	Implement.
	(loongarch_symbol_insns): Call loongarch_explicit_relocs_p for
	SYMBOL_GOT_DISP, instead of using TARGET_EXPLICIT_RELOCS.
	(loongarch_split_symbol): Call loongarch_explicit_relocs_p for
	deciding if return early, instead of using
	TARGET_EXPLICIT_RELOCS.
	(loongarch_output_move): CAll loongarch_explicit_relocs_p
	instead of using TARGET_EXPLICIT_RELOCS.
	* config/loongarch/loongarch.md (*low<mode>): Remove
	TARGET_EXPLICIT_RELOCS from insn condition.
	(@ld_from_got<mode>): Likewise.
	* config/loongarch/predicates.md (move_operand): Call
	loongarch_explicit_relocs_p instead of using
	TARGET_EXPLICIT_RELOCS.

gcc/testsuite/ChangeLog:

	* gcc.target/loongarch/explicit-relocs-auto-lto.c: New test.
This commit is contained in:
Xi Ruoyao 2023-09-30 18:46:28 +08:00
parent 93a46d18f5
commit 8811630df8
No known key found for this signature in database
GPG key ID: ACAAD20E19E710E3
5 changed files with 59 additions and 14 deletions

View file

@ -220,4 +220,5 @@ extern rtx loongarch_gen_const_int_vector_shuffle (machine_mode, int);
extern tree loongarch_build_builtin_va_list (void);
extern rtx loongarch_build_signbit_mask (machine_mode, bool, bool);
extern bool loongarch_explicit_relocs_p (enum loongarch_symbol_type);
#endif /* ! GCC_LOONGARCH_PROTOS_H */

View file

@ -1925,6 +1925,29 @@ loongarch_symbolic_constant_p (rtx x, enum loongarch_symbol_type *symbol_type)
gcc_unreachable ();
}
/* If -mexplicit-relocs=auto, we use machine operations with reloc hints
for cases where the linker is unable to relax so we can schedule the
machine operations, otherwise use an assembler pseudo-op so the
assembler will generate R_LARCH_RELAX. */
bool
loongarch_explicit_relocs_p (enum loongarch_symbol_type type)
{
if (la_opt_explicit_relocs != EXPLICIT_RELOCS_AUTO)
return la_opt_explicit_relocs == EXPLICIT_RELOCS_ALWAYS;
/* If we are performing LTO for a final link, and we have the linker
plugin so we know the resolution of the symbols, then all GOT
references are binding to external symbols or preemptable symbols.
So the linker cannot relax them. */
return (in_lto_p
&& !flag_incremental_link
&& HAVE_LTO_PLUGIN == 2
&& (!global_options_set.x_flag_use_linker_plugin
|| global_options.x_flag_use_linker_plugin)
&& type == SYMBOL_GOT_DISP);
}
/* Returns the number of instructions necessary to reference a symbol. */
static int
@ -1940,7 +1963,7 @@ loongarch_symbol_insns (enum loongarch_symbol_type type, machine_mode mode)
case SYMBOL_GOT_DISP:
/* The constant will have to be loaded from the GOT before it
is used in an address. */
if (!TARGET_EXPLICIT_RELOCS && mode != MAX_MACHINE_MODE)
if (!loongarch_explicit_relocs_p (type) && mode != MAX_MACHINE_MODE)
return 0;
return 3;
@ -3038,7 +3061,7 @@ loongarch_symbol_extreme_p (enum loongarch_symbol_type type)
If so, and if LOW_OUT is nonnull, emit the high part and store the
low part in *LOW_OUT. Leave *LOW_OUT unchanged otherwise.
Return false if build with '-mno-explicit-relocs'.
Return false if build with '-mexplicit-relocs=none'.
TEMP is as for loongarch_force_temporary and is used to load the high
part into a register.
@ -3052,12 +3075,9 @@ loongarch_split_symbol (rtx temp, rtx addr, machine_mode mode, rtx *low_out)
{
enum loongarch_symbol_type symbol_type;
/* If build with '-mno-explicit-relocs', don't split symbol. */
if (!TARGET_EXPLICIT_RELOCS)
return false;
if ((GET_CODE (addr) == HIGH && mode == MAX_MACHINE_MODE)
|| !loongarch_symbolic_constant_p (addr, &symbol_type)
|| !loongarch_explicit_relocs_p (symbol_type)
|| loongarch_symbol_insns (symbol_type, mode) == 0
|| !loongarch_split_symbol_type (symbol_type))
return false;
@ -4797,7 +4817,7 @@ loongarch_output_move (rtx dest, rtx src)
}
}
if (!TARGET_EXPLICIT_RELOCS
if (!loongarch_explicit_relocs_p (loongarch_classify_symbol (src))
&& dest_code == REG && symbolic_operand (src, VOIDmode))
{
if (loongarch_classify_symbol (src) == SYMBOL_PCREL)

View file

@ -2247,7 +2247,7 @@
[(set (match_operand:P 0 "register_operand" "=r")
(lo_sum:P (match_operand:P 1 "register_operand" " r")
(match_operand:P 2 "symbolic_operand" "")))]
"TARGET_EXPLICIT_RELOCS"
""
"addi.<d>\t%0,%1,%L2"
[(set_attr "type" "arith")
(set_attr "mode" "<MODE>")])
@ -2275,7 +2275,7 @@
(match_operand:P 1 "register_operand" "r")
(match_operand:P 2 "symbolic_operand")))]
UNSPEC_LOAD_FROM_GOT))]
"TARGET_EXPLICIT_RELOCS"
""
"ld.<d>\t%0,%1,%L2"
[(set_attr "type" "move")]
)

View file

@ -541,16 +541,14 @@
case SYMBOL_REF:
case LABEL_REF:
return (loongarch_symbolic_constant_p (op, &symbol_type)
&& (!TARGET_EXPLICIT_RELOCS
&& (!loongarch_explicit_relocs_p (symbol_type)
|| !loongarch_split_symbol_type (symbol_type)));
case HIGH:
/* '-mno-explicit-relocs' don't generate high/low pairs. */
if (!TARGET_EXPLICIT_RELOCS)
return false;
op = XEXP (op, 0);
return (loongarch_symbolic_constant_p (op, &symbol_type)
&& loongarch_explicit_relocs_p (symbol_type)
&& loongarch_split_symbol_type (symbol_type));
default:

View file

@ -0,0 +1,26 @@
/* { dg-do link } */
/* { dg-require-effective-target lto } */
/* { dg-require-linker-plugin "" } */
/* { dg-options "-fpic -shared -O2 --save-temps -mexplicit-relocs=auto -flto -fuse-linker-plugin -flto-partition=one" } */
int pcrel __attribute__ ((visibility ("hidden")));
int got __attribute__ ((visibility ("default")));
int
*addr_pcrel (void)
{
return &pcrel;
}
int
*addr_got (void)
{
return &got;
}
/* With linker plugin we should use la.local (it can be relaxed to pcaddi),
but not la.global (we are pretty sure the linker cannot relax la.global
got). */
/* { dg-final { scan-lto-assembler "la.local.*pcrel" } } */
/* { dg-final { scan-lto-assembler "pcalau12i.*%got_pc_hi20\\\(got\\\)" } } */
/* { dg-final { scan-lto-assembler "ld.*%got_pc_lo12\\\(got\\\)" } } */