213 lines
8.1 KiB
Diff
213 lines
8.1 KiB
Diff
|
|
From 8539e5560e7bf11473cc7c386043b7019264236a Mon Sep 17 00:00:00 2001
|
||
|
|
From: Xi Ruoyao <xry111@xry111.site>
|
||
|
|
Date: Sat, 30 Sep 2023 18:46:28 +0800
|
||
|
|
Subject: [PATCH 016/188] 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.
|
||
|
|
---
|
||
|
|
gcc/config/loongarch/loongarch-protos.h | 1 +
|
||
|
|
gcc/config/loongarch/loongarch.cc | 34 +++++++++++++++----
|
||
|
|
gcc/config/loongarch/loongarch.md | 4 +--
|
||
|
|
gcc/config/loongarch/predicates.md | 8 ++---
|
||
|
|
.../loongarch/explicit-relocs-auto-lto.c | 26 ++++++++++++++
|
||
|
|
5 files changed, 59 insertions(+), 14 deletions(-)
|
||
|
|
create mode 100644 gcc/testsuite/gcc.target/loongarch/explicit-relocs-auto-lto.c
|
||
|
|
|
||
|
|
diff --git a/gcc/config/loongarch/loongarch-protos.h b/gcc/config/loongarch/loongarch-protos.h
|
||
|
|
index 163162598..51d38177b 100644
|
||
|
|
--- a/gcc/config/loongarch/loongarch-protos.h
|
||
|
|
+++ b/gcc/config/loongarch/loongarch-protos.h
|
||
|
|
@@ -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 */
|
||
|
|
diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc
|
||
|
|
index 3258c8655..1d20577e7 100644
|
||
|
|
--- a/gcc/config/loongarch/loongarch.cc
|
||
|
|
+++ b/gcc/config/loongarch/loongarch.cc
|
||
|
|
@@ -1922,6 +1922,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
|
||
|
|
@@ -1937,7 +1960,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;
|
||
|
|
@@ -3034,7 +3057,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.
|
||
|
|
@@ -3048,12 +3071,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;
|
||
|
|
@@ -4793,7 +4813,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)
|
||
|
|
diff --git a/gcc/config/loongarch/loongarch.md b/gcc/config/loongarch/loongarch.md
|
||
|
|
index 29ac950bf..81c97393b 100644
|
||
|
|
--- a/gcc/config/loongarch/loongarch.md
|
||
|
|
+++ b/gcc/config/loongarch/loongarch.md
|
||
|
|
@@ -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")]
|
||
|
|
)
|
||
|
|
diff --git a/gcc/config/loongarch/predicates.md b/gcc/config/loongarch/predicates.md
|
||
|
|
index ad6cee5c4..6b50b3a4d 100644
|
||
|
|
--- a/gcc/config/loongarch/predicates.md
|
||
|
|
+++ b/gcc/config/loongarch/predicates.md
|
||
|
|
@@ -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:
|
||
|
|
diff --git a/gcc/testsuite/gcc.target/loongarch/explicit-relocs-auto-lto.c b/gcc/testsuite/gcc.target/loongarch/explicit-relocs-auto-lto.c
|
||
|
|
new file mode 100644
|
||
|
|
index 000000000..f53b54689
|
||
|
|
--- /dev/null
|
||
|
|
+++ b/gcc/testsuite/gcc.target/loongarch/explicit-relocs-auto-lto.c
|
||
|
|
@@ -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\\\)" } } */
|
||
|
|
--
|
||
|
|
2.43.0
|
||
|
|
|