* [PATCH v2 0/3] LoongArch: Modify the method of obtaining symbolic addresses.
@ 2022-07-21 6:41 Lulu Cheng
2022-07-21 6:41 ` [PATCH v2 1/3] LoongArch: Subdivision symbol type, add SYMBOL_PCREL support Lulu Cheng
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Lulu Cheng @ 2022-07-21 6:41 UTC (permalink / raw)
To: gcc-patches; +Cc: xry111, i, xuchenghua, Lulu Cheng
1. The original LA macro instruction is split into two instructions to
obtain the address of the symbol if enable '-mexplicit-relocs'.
2. Currently, '-mcmodel=' only supports 'normal' mode, because other mode
behaviors are not yet determined. This function is gradually improved
by the subsequent handling.
3. The method that calls global functions from 'la.global + jirl' to 'bl'
when build with '-fplt'.
4. Some R_LARCH_64 in section .eh_frame will to generate R_LARCH_NONE, we
change ASM_PREFERRED_EH_DATA_FORMAT from 'WD_EH_PE_absptr' to
'WD_EH_PE_pcrel | DW_EH_PE_sdata4' then relocation to R_LARCH_32_PCREL
from R_LARCH_64 in setction .eh_frame and not generate dynamic relocation
for R_LARCH_32_PCREL.
This new symbol loading method not support by upstream binutils yet,
this GCC port requires the following patches applied to binutils to build.
[1]https://sourceware.org/pipermail/binutils/2022-July/121933.html
[2]https://sourceware.org/pipermail/binutils/2022-July/121937.html
[3]https://sourceware.org/pipermail/binutils/2022-July/121934.html
[4]https://sourceware.org/pipermail/binutils/2022-July/121935.html
[5]https://sourceware.org/pipermail/binutils/2022-July/121936.html
[6]https://sourceware.org/pipermail/binutils/2022-July/121938.html
[7]https://sourceware.org/pipermail/binutils/2022-July/121939.html
Lulu Cheng (3):
LoongArch: Subdivision symbol type, add SYMBOL_PCREL support.
LoongArch: Support split symbol.
LoongArch: Modify the definition of the ASM_PREFERRED_EH_DATA_FORMAT
macro.
.../config/loongarch/loongarch-common.cc | 1 +
gcc/config/loongarch/constraints.md | 24 +-
gcc/config/loongarch/genopts/loongarch.opt.in | 4 +
gcc/config/loongarch/loongarch-protos.h | 10 +-
gcc/config/loongarch/loongarch.cc | 652 +++++++++++++-----
gcc/config/loongarch/loongarch.h | 4 +-
gcc/config/loongarch/loongarch.md | 401 +++--------
gcc/config/loongarch/loongarch.opt | 4 +
gcc/config/loongarch/predicates.md | 56 +-
.../gcc.target/loongarch/func-call-1.c | 32 +
.../gcc.target/loongarch/func-call-2.c | 32 +
.../gcc.target/loongarch/func-call-3.c | 32 +
.../gcc.target/loongarch/func-call-4.c | 32 +
.../gcc.target/loongarch/func-call-5.c | 33 +
.../gcc.target/loongarch/func-call-6.c | 33 +
.../gcc.target/loongarch/func-call-7.c | 34 +
.../gcc.target/loongarch/func-call-8.c | 33 +
.../loongarch/relocs-symbol-noaddend.c | 23 +
18 files changed, 905 insertions(+), 535 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/loongarch/func-call-1.c
create mode 100644 gcc/testsuite/gcc.target/loongarch/func-call-2.c
create mode 100644 gcc/testsuite/gcc.target/loongarch/func-call-3.c
create mode 100644 gcc/testsuite/gcc.target/loongarch/func-call-4.c
create mode 100644 gcc/testsuite/gcc.target/loongarch/func-call-5.c
create mode 100644 gcc/testsuite/gcc.target/loongarch/func-call-6.c
create mode 100644 gcc/testsuite/gcc.target/loongarch/func-call-7.c
create mode 100644 gcc/testsuite/gcc.target/loongarch/func-call-8.c
create mode 100644 gcc/testsuite/gcc.target/loongarch/relocs-symbol-noaddend.c
--
2.31.1
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v2 1/3] LoongArch: Subdivision symbol type, add SYMBOL_PCREL support.
2022-07-21 6:41 [PATCH v2 0/3] LoongArch: Modify the method of obtaining symbolic addresses Lulu Cheng
@ 2022-07-21 6:41 ` Lulu Cheng
2022-07-21 6:41 ` [PATCH v2 2/3] LoongArch: Support split symbol Lulu Cheng
2022-07-21 6:41 ` [PATCH v2 3/3] LoongArch: Modify the definition of the ASM_PREFERRED_EH_DATA_FORMAT macro Lulu Cheng
2 siblings, 0 replies; 4+ messages in thread
From: Lulu Cheng @ 2022-07-21 6:41 UTC (permalink / raw)
To: gcc-patches; +Cc: xry111, i, xuchenghua, Lulu Cheng
1. Remove cModel type support other than normal.
2. The method that calls global functions from 'la.global + jirl' to 'bl'
when build with '-fplt'.
gcc/ChangeLog:
* config/loongarch/constraints.md (a): Delete the constraint.
(b): A constant call not local address.
(h): Delete the constraint.
(t): Delete the constraint.
* config/loongarch/loongarch-protos.h (enum loongarch_symbol_type):
Add new symbol type 'SYMBOL_PCREL', 'SYMBOL_TLS_IE' and 'SYMBOL_TLS_LE'.
(loongarch_split_symbol): Delete useless function declarations.
(loongarch_split_symbol_type): Delete useless function declarations.
* config/loongarch/loongarch.cc (enum loongarch_address_type):
Delete unnecessary comment information.
(loongarch_symbol_binds_local_p): Modified the judgment order of label
and symbol.
(loongarch_classify_symbol): Return symbol type. If symbol is a label,
or symbol is a local symbol return SYMBOL_PCREL. If is a tls symbol,
return SYMBOL_TLS. If is a not local symbol return SYMBOL_GOT_DISP.
(loongarch_symbolic_constant_p): Add handling of 'SYMBOL_TLS_IE'
'SYMBOL_TLS_LE' and 'SYMBOL_PCREL'.
(loongarch_symbol_insns): Add handling of 'SYMBOL_TLS_IE' 'SYMBOL_TLS_LE'
and 'SYMBOL_PCREL'.
(loongarch_address_insns): Sort code.
(loongarch_12bit_offset_address_p): Sort code.
(loongarch_14bit_shifted_offset_address_p): Sort code.
(loongarch_call_tls_get_addr): Sort code.
(loongarch_legitimize_tls_address): Sort code.
(loongarch_output_move): Remove schema support for cmodel other than normal.
(loongarch_memmodel_needs_release_fence): Sort code.
(loongarch_print_operand): Sort code.
* config/loongarch/loongarch.h (LARCH_U12BIT_OFFSET_P):
Rename to LARCH_12BIT_OFFSET_P.
(LARCH_12BIT_OFFSET_P): New macro.
* config/loongarch/loongarch.md: Reimplement the function call. Remove schema
support for cmodel other than normal.
* config/loongarch/predicates.md (is_const_call_weak_symbol): Delete this predicate.
(is_const_call_plt_symbol): Delete this predicate.
(is_const_call_global_noplt_symbol): Delete this predicate.
(is_const_call_no_local_symbol): New predicate, determines whether it is a local
symbol or label.
gcc/testsuite/ChangeLog:
* gcc.target/loongarch/func-call-1.c: New test.
* gcc.target/loongarch/func-call-2.c: New test.
* gcc.target/loongarch/func-call-3.c: New test.
* gcc.target/loongarch/func-call-4.c: New test.
---
gcc/config/loongarch/constraints.md | 24 +-
gcc/config/loongarch/loongarch-protos.h | 9 +-
gcc/config/loongarch/loongarch.cc | 256 +++++++---------
gcc/config/loongarch/loongarch.h | 2 +-
gcc/config/loongarch/loongarch.md | 279 +++---------------
gcc/config/loongarch/predicates.md | 40 ++-
.../gcc.target/loongarch/func-call-1.c | 32 ++
.../gcc.target/loongarch/func-call-2.c | 32 ++
.../gcc.target/loongarch/func-call-3.c | 32 ++
.../gcc.target/loongarch/func-call-4.c | 32 ++
10 files changed, 305 insertions(+), 433 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/loongarch/func-call-1.c
create mode 100644 gcc/testsuite/gcc.target/loongarch/func-call-2.c
create mode 100644 gcc/testsuite/gcc.target/loongarch/func-call-3.c
create mode 100644 gcc/testsuite/gcc.target/loongarch/func-call-4.c
diff --git a/gcc/config/loongarch/constraints.md b/gcc/config/loongarch/constraints.md
index d0bfddbd5a9..43cb7b5f0f5 100644
--- a/gcc/config/loongarch/constraints.md
+++ b/gcc/config/loongarch/constraints.md
@@ -20,14 +20,14 @@
;; Register constraints
-;; "a" "A constant call global and noplt address."
-;; "b" <-----unused
+;; "a" <-----unused
+;; "b" "A constant call not local address."
;; "c" "A constant call local address."
;; "d" <-----unused
;; "e" JIRL_REGS
;; "f" FP_REGS
;; "g" <-----unused
-;; "h" "A constant call plt address."
+;; "h" <-----unused
;; "i" "Matches a general integer constant." (Global non-architectural)
;; "j" SIBCALL_REGS
;; "k" "A memory operand whose address is formed by a base register and
@@ -42,7 +42,7 @@
;; "q" CSR_REGS
;; "r" GENERAL_REGS (Global non-architectural)
;; "s" "Matches a symbolic integer constant." (Global non-architectural)
-;; "t" "A constant call weak address"
+;; "t" <-----unused
;; "u" "A signed 52bit constant and low 32-bit is zero (for logic instructions)"
;; "v" "A signed 64-bit constant and low 44-bit is zero (for logic instructions)."
;; "w" "Matches any valid memory."
@@ -89,10 +89,10 @@
;; "<" "Matches a pre-dec or post-dec operand." (Global non-architectural)
;; ">" "Matches a pre-inc or post-inc operand." (Global non-architectural)
-(define_constraint "a"
+(define_constraint "b"
"@internal
- A constant call global and noplt address."
- (match_operand 0 "is_const_call_global_noplt_symbol"))
+ A constant call no local address."
+ (match_operand 0 "is_const_call_no_local_symbol"))
(define_constraint "c"
"@internal
@@ -105,11 +105,6 @@ (define_register_constraint "e" "JIRL_REGS"
(define_register_constraint "f" "TARGET_HARD_FLOAT ? FP_REGS : NO_REGS"
"A floating-point register (if available).")
-(define_constraint "h"
- "@internal
- A constant call plt address."
- (match_operand 0 "is_const_call_plt_symbol"))
-
(define_register_constraint "j" "SIBCALL_REGS"
"@internal")
@@ -134,11 +129,6 @@ (define_memory_constraint "m"
(define_register_constraint "q" "CSR_REGS"
"A general-purpose register except for $r0 and $r1 for lcsr.")
-(define_constraint "t"
- "@internal
- A constant call weak address."
- (match_operand 0 "is_const_call_weak_symbol"))
-
(define_constraint "u"
"A signed 52bit constant and low 32-bit is zero (for logic instructions)."
(and (match_code "const_int")
diff --git a/gcc/config/loongarch/loongarch-protos.h b/gcc/config/loongarch/loongarch-protos.h
index 2287fd3763c..080766250d1 100644
--- a/gcc/config/loongarch/loongarch-protos.h
+++ b/gcc/config/loongarch/loongarch-protos.h
@@ -27,9 +27,13 @@ along with GCC; see the file COPYING3. If not see
SYMBOL_GOT_DISP
The symbol's value will be loaded directly from the GOT.
+ SYMBOL_PCREL
+ The symbol's value will be loaded directly from data section.
+
SYMBOL_TLS
A thread-local symbol.
+ SYMBOL_TLS_IE
SYMBOL_TLSGD
SYMBOL_TLSLDM
UNSPEC wrappers around SYMBOL_TLS, corresponding to the
@@ -37,7 +41,10 @@ along with GCC; see the file COPYING3. If not see
*/
enum loongarch_symbol_type {
SYMBOL_GOT_DISP,
+ SYMBOL_PCREL,
SYMBOL_TLS,
+ SYMBOL_TLS_IE,
+ SYMBOL_TLS_LE,
SYMBOL_TLSGD,
SYMBOL_TLSLDM,
};
@@ -61,7 +68,6 @@ extern int loongarch_idiv_insns (machine_mode);
#ifdef RTX_CODE
extern void loongarch_emit_binary (enum rtx_code, rtx, rtx, rtx);
#endif
-extern bool loongarch_split_symbol (rtx, rtx, machine_mode, rtx *);
extern rtx loongarch_unspec_address (rtx, enum loongarch_symbol_type);
extern rtx loongarch_strip_unspec_address (rtx);
extern void loongarch_move_integer (rtx, rtx, unsigned HOST_WIDE_INT);
@@ -154,7 +160,6 @@ extern rtx loongarch_expand_thread_pointer (rtx);
extern bool loongarch_eh_uses (unsigned int);
extern bool loongarch_epilogue_uses (unsigned int);
extern bool loongarch_load_store_bonding_p (rtx *, machine_mode, bool);
-extern bool loongarch_split_symbol_type (enum loongarch_symbol_type);
typedef rtx (*mulsidi3_gen_fn) (rtx, rtx, rtx);
diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc
index 8b0d7f459e0..1cb5742f6dd 100644
--- a/gcc/config/loongarch/loongarch.cc
+++ b/gcc/config/loongarch/loongarch.cc
@@ -114,19 +114,7 @@ enum loongarch_address_type
};
-/* Information about an address described by loongarch_address_type.
-
- ADDRESS_CONST_INT
- No fields are used.
-
- ADDRESS_REG
- REG is the base register and OFFSET is the constant offset.
-
- ADDRESS_REG_REG
- A base register indexed by (optionally scaled) register.
-
- ADDRESS_SYMBOLIC
- SYMBOL_TYPE is the type of symbol that the address references. */
+/* Information about an address described by loongarch_address_type. */
struct loongarch_address_info
{
enum loongarch_address_type type;
@@ -1617,11 +1605,12 @@ loongarch_weak_symbol_p (const_rtx x)
bool
loongarch_symbol_binds_local_p (const_rtx x)
{
- if (LABEL_REF_P (x))
+ if (SYMBOL_REF_P (x))
+ return (SYMBOL_REF_DECL (x)
+ ? targetm.binds_local_p (SYMBOL_REF_DECL (x))
+ : SYMBOL_REF_LOCAL_P (x));
+ else
return false;
-
- return (SYMBOL_REF_DECL (x) ? targetm.binds_local_p (SYMBOL_REF_DECL (x))
- : SYMBOL_REF_LOCAL_P (x));
}
/* Return true if rtx constants of mode MODE should be put into a small
@@ -1640,17 +1629,16 @@ static enum loongarch_symbol_type
loongarch_classify_symbol (const_rtx x)
{
if (LABEL_REF_P (x))
- return SYMBOL_GOT_DISP;
-
- gcc_assert (SYMBOL_REF_P (x));
+ return SYMBOL_PCREL;
if (SYMBOL_REF_TLS_MODEL (x))
return SYMBOL_TLS;
- if (SYMBOL_REF_P (x))
+ if (SYMBOL_REF_P (x)
+ && !loongarch_symbol_binds_local_p (x))
return SYMBOL_GOT_DISP;
- return SYMBOL_GOT_DISP;
+ return SYMBOL_PCREL;
}
/* Return true if X is a symbolic constant. If it is,
@@ -1683,9 +1671,15 @@ loongarch_symbolic_constant_p (rtx x, enum loongarch_symbol_type *symbol_type)
relocations. */
switch (*symbol_type)
{
- case SYMBOL_GOT_DISP:
+ case SYMBOL_TLS_IE:
+ case SYMBOL_TLS_LE:
case SYMBOL_TLSGD:
case SYMBOL_TLSLDM:
+ case SYMBOL_PCREL:
+ /* GAS rejects offsets outside the range [-2^31, 2^31-1]. */
+ return sext_hwi (INTVAL (offset), 32) == INTVAL (offset);
+
+ case SYMBOL_GOT_DISP:
case SYMBOL_TLS:
return false;
}
@@ -1707,9 +1701,14 @@ loongarch_symbol_insns (enum loongarch_symbol_type type, machine_mode mode)
return 3;
+ case SYMBOL_PCREL:
+ case SYMBOL_TLS_IE:
+ case SYMBOL_TLS_LE:
+ return 2;
+
case SYMBOL_TLSGD:
case SYMBOL_TLSLDM:
- return 1;
+ return 3;
case SYMBOL_TLS:
/* We don't treat a bare TLS symbol as a constant. */
@@ -1937,11 +1936,7 @@ loongarch_address_insns (rtx x, machine_mode mode, bool might_split_p)
switch (addr.type)
{
case ADDRESS_REG:
- return factor;
-
case ADDRESS_REG_REG:
- return factor;
-
case ADDRESS_CONST_INT:
return factor;
@@ -1983,7 +1978,7 @@ loongarch_12bit_offset_address_p (rtx x, machine_mode mode)
return (loongarch_classify_address (&addr, x, mode, false)
&& addr.type == ADDRESS_REG
&& CONST_INT_P (addr.offset)
- && LARCH_U12BIT_OFFSET_P (INTVAL (addr.offset)));
+ && LARCH_12BIT_OFFSET_P (INTVAL (addr.offset)));
}
/* Return true if X is a legitimate address with a 14-bit offset shifted 2.
@@ -2001,6 +1996,9 @@ loongarch_14bit_shifted_offset_address_p (rtx x, machine_mode mode)
&& LARCH_SHIFT_2_OFFSET_P (INTVAL (addr.offset)));
}
+/* Return true if X is a legitimate address with base and index.
+ MODE is the mode of the value being accessed. */
+
bool
loongarch_base_index_address_p (rtx x, machine_mode mode)
{
@@ -2310,7 +2308,7 @@ loongarch_call_tls_get_addr (rtx sym, enum loongarch_symbol_type type, rtx v0)
/* Generate the code to access LOC, a thread-local SYMBOL_REF, and return
its address. The return value will be both a valid address and a valid
- SET_SRC (either a REG or a LO_SUM). */
+ SET_SRC. */
static rtx
loongarch_legitimize_tls_address (rtx loc)
@@ -2336,7 +2334,7 @@ loongarch_legitimize_tls_address (rtx loc)
break;
case TLS_MODEL_INITIAL_EXEC:
- /* la.tls.ie; tp-relative add */
+ /* la.tls.ie; tp-relative add. */
tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM);
tmp = gen_reg_rtx (Pmode);
emit_insn (loongarch_got_load_tls_ie (tmp, loc));
@@ -2345,7 +2343,7 @@ loongarch_legitimize_tls_address (rtx loc)
break;
case TLS_MODEL_LOCAL_EXEC:
- /* la.tls.le; tp-relative add */
+ /* la.tls.le; tp-relative add. */
tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM);
tmp = gen_reg_rtx (Pmode);
emit_insn (loongarch_got_load_tls_le (tmp, loc));
@@ -3371,6 +3369,7 @@ loongarch_output_move (rtx dest, rtx src)
case 2:
return "st.h\t%z1,%0";
case 4:
+ /* Matching address type with a 12bit offset. */
if (const_arith_operand (offset, Pmode))
return "st.w\t%z1,%0";
else
@@ -3409,6 +3408,7 @@ loongarch_output_move (rtx dest, rtx src)
case 2:
return "ld.hu\t%0,%1";
case 4:
+ /* Matching address type with a 12bit offset. */
if (const_arith_operand (offset, Pmode))
return "ld.w\t%0,%1";
else
@@ -3436,56 +3436,16 @@ loongarch_output_move (rtx dest, rtx src)
else
gcc_unreachable ();
}
+ }
- if (symbolic_operand (src, VOIDmode))
- {
- if ((TARGET_CMODEL_TINY && (!loongarch_global_symbol_p (src)
- || loongarch_symbol_binds_local_p (src)))
- || (TARGET_CMODEL_TINY_STATIC && !loongarch_weak_symbol_p (src)))
- {
- /* The symbol must be aligned to 4 byte. */
- unsigned int align;
-
- if (LABEL_REF_P (src))
- align = 32 /* Whatever. */;
- else if (CONSTANT_POOL_ADDRESS_P (src))
- align = GET_MODE_ALIGNMENT (get_pool_mode (src));
- else if (TREE_CONSTANT_POOL_ADDRESS_P (src))
- {
- tree exp = SYMBOL_REF_DECL (src);
- align = TYPE_ALIGN (TREE_TYPE (exp));
- align = loongarch_constant_alignment (exp, align);
- }
- else if (SYMBOL_REF_DECL (src))
- align = DECL_ALIGN (SYMBOL_REF_DECL (src));
- else if (SYMBOL_REF_HAS_BLOCK_INFO_P (src)
- && SYMBOL_REF_BLOCK (src) != NULL)
- align = SYMBOL_REF_BLOCK (src)->alignment;
- else
- align = BITS_PER_UNIT;
-
- if (align % (4 * 8) == 0)
- return "pcaddi\t%0,%%pcrel(%1)>>2";
- }
- if (TARGET_CMODEL_TINY
- || TARGET_CMODEL_TINY_STATIC
- || TARGET_CMODEL_NORMAL
- || TARGET_CMODEL_LARGE)
- {
- if (!loongarch_global_symbol_p (src)
- || loongarch_symbol_binds_local_p (src))
- return "la.local\t%0,%1";
- else
- return "la.global\t%0,%1";
- }
- if (TARGET_CMODEL_EXTREME)
- {
- sorry ("Normal symbol loading not implemented in extreme mode.");
- gcc_unreachable ();
- }
-
- }
+ if (dest_code == REG && symbolic_operand (src, VOIDmode))
+ {
+ if (loongarch_classify_symbol (src) == SYMBOL_PCREL)
+ return "la.local\t%0,%1";
+ else
+ return "la.global\t%0,%1";
}
+
if (src_code == REG && FP_REG_P (REGNO (src)))
{
if (dest_code == REG && FP_REG_P (REGNO (dest)))
@@ -3503,6 +3463,7 @@ loongarch_output_move (rtx dest, rtx src)
return dbl_p ? "fst.d\t%1,%0" : "fst.s\t%1,%0";
}
}
+
if (dest_code == REG && FP_REG_P (REGNO (dest)))
{
if (src_code == MEM)
@@ -3517,6 +3478,7 @@ loongarch_output_move (rtx dest, rtx src)
return dbl_p ? "fld.d\t%0,%1" : "fld.s\t%0,%1";
}
}
+
gcc_unreachable ();
}
@@ -4347,27 +4309,27 @@ loongarch_memmodel_needs_release_fence (enum memmodel model)
/* Implement TARGET_PRINT_OPERAND. The LoongArch-specific operand codes are:
- 'X' Print CONST_INT OP in hexadecimal format.
- 'x' Print the low 16 bits of CONST_INT OP in hexadecimal format.
+ 'A' Print a _DB suffix if the memory model requires a release.
+ 'b' Print the address of a memory operand, without offset.
+ 'C' Print the integer branch condition for comparison OP.
'd' Print CONST_INT OP in decimal.
+ 'F' Print the FPU branch condition for comparison OP.
+ 'G' Print a DBAR insn if the memory model requires a release.
+ 'i' Print i if the operand is not a register.
'm' Print one less than CONST_INT OP in decimal.
- 'y' Print exact log2 of CONST_INT OP in decimal.
- 'C' Print the integer branch condition for comparison OP.
'N' Print the inverse of the integer branch condition for comparison OP.
- 'F' Print the FPU branch condition for comparison OP.
- 'W' Print the inverse of the FPU branch condition for comparison OP.
'T' Print 'f' for (eq:CC ...), 't' for (ne:CC ...),
'z' for (eq:?I ...), 'n' for (ne:?I ...).
't' Like 'T', but with the EQ/NE cases reversed
- 'Y' Print loongarch_fp_conditions[INTVAL (OP)]
- 'Z' Print OP and a comma for 8CC, otherwise print nothing.
- 'z' Print $0 if OP is zero, otherwise print OP normally.
- 'b' Print the address of a memory operand, without offset.
'V' Print exact log2 of CONST_INT OP element 0 of a replicated
CONST_VECTOR in decimal.
- 'A' Print a _DB suffix if the memory model requires a release.
- 'G' Print a DBAR insn if the memory model requires a release.
- 'i' Print i if the operand is not a register. */
+ 'W' Print the inverse of the FPU branch condition for comparison OP.
+ 'X' Print CONST_INT OP in hexadecimal format.
+ 'x' Print the low 16 bits of CONST_INT OP in hexadecimal format.
+ 'Y' Print loongarch_fp_conditions[INTVAL (OP)]
+ 'y' Print exact log2 of CONST_INT OP in decimal.
+ 'Z' Print OP and a comma for 8CC, otherwise print nothing.
+ 'z' Print $0 if OP is zero, otherwise print OP normally. */
static void
loongarch_print_operand (FILE *file, rtx op, int letter)
@@ -4385,18 +4347,13 @@ loongarch_print_operand (FILE *file, rtx op, int letter)
switch (letter)
{
- case 'X':
- if (CONST_INT_P (op))
- fprintf (file, HOST_WIDE_INT_PRINT_HEX, INTVAL (op));
- else
- output_operand_lossage ("invalid use of '%%%c'", letter);
+ case 'A':
+ if (loongarch_memmodel_needs_rel_acq_fence ((enum memmodel) INTVAL (op)))
+ fputs ("_db", file);
break;
- case 'x':
- if (CONST_INT_P (op))
- fprintf (file, HOST_WIDE_INT_PRINT_HEX, INTVAL (op) & 0xffff);
- else
- output_operand_lossage ("invalid use of '%%%c'", letter);
+ case 'C':
+ loongarch_print_int_branch_condition (file, code, letter);
break;
case 'd':
@@ -4406,6 +4363,20 @@ loongarch_print_operand (FILE *file, rtx op, int letter)
output_operand_lossage ("invalid use of '%%%c'", letter);
break;
+ case 'F':
+ loongarch_print_float_branch_condition (file, code, letter);
+ break;
+
+ case 'G':
+ if (loongarch_memmodel_needs_release_fence ((enum memmodel) INTVAL (op)))
+ fputs ("dbar\t0", file);
+ break;
+
+ case 'i':
+ if (code != REG)
+ fputs ("i", file);
+ break;
+
case 'm':
if (CONST_INT_P (op))
fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (op) - 1);
@@ -4413,17 +4384,17 @@ loongarch_print_operand (FILE *file, rtx op, int letter)
output_operand_lossage ("invalid use of '%%%c'", letter);
break;
- case 'y':
- if (CONST_INT_P (op))
- {
- int val = exact_log2 (INTVAL (op));
- if (val != -1)
- fprintf (file, "%d", val);
- else
- output_operand_lossage ("invalid use of '%%%c'", letter);
- }
- else
- output_operand_lossage ("invalid use of '%%%c'", letter);
+ case 'N':
+ loongarch_print_int_branch_condition (file, reverse_condition (code),
+ letter);
+ break;
+
+ case 't':
+ case 'T':
+ {
+ int truth = (code == NE) == (letter == 'T');
+ fputc ("zfnt"[truth * 2 + FCC_REG_P (REGNO (XEXP (op, 0)))], file);
+ }
break;
case 'V':
@@ -4441,30 +4412,36 @@ loongarch_print_operand (FILE *file, rtx op, int letter)
output_operand_lossage ("invalid use of '%%%c'", letter);
break;
- case 'C':
- loongarch_print_int_branch_condition (file, code, letter);
- break;
-
- case 'N':
- loongarch_print_int_branch_condition (file, reverse_condition (code),
- letter);
+ case 'W':
+ loongarch_print_float_branch_condition (file, reverse_condition (code),
+ letter);
break;
- case 'F':
- loongarch_print_float_branch_condition (file, code, letter);
+ case 'x':
+ if (CONST_INT_P (op))
+ fprintf (file, HOST_WIDE_INT_PRINT_HEX, INTVAL (op) & 0xffff);
+ else
+ output_operand_lossage ("invalid use of '%%%c'", letter);
break;
- case 'W':
- loongarch_print_float_branch_condition (file, reverse_condition (code),
- letter);
+ case 'X':
+ if (CONST_INT_P (op))
+ fprintf (file, HOST_WIDE_INT_PRINT_HEX, INTVAL (op));
+ else
+ output_operand_lossage ("invalid use of '%%%c'", letter);
break;
- case 'T':
- case 't':
- {
- int truth = (code == NE) == (letter == 'T');
- fputc ("zfnt"[truth * 2 + FCC_REG_P (REGNO (XEXP (op, 0)))], file);
- }
+ case 'y':
+ if (CONST_INT_P (op))
+ {
+ int val = exact_log2 (INTVAL (op));
+ if (val != -1)
+ fprintf (file, "%d", val);
+ else
+ output_operand_lossage ("invalid use of '%%%c'", letter);
+ }
+ else
+ output_operand_lossage ("invalid use of '%%%c'", letter);
break;
case 'Y':
@@ -4481,21 +4458,6 @@ loongarch_print_operand (FILE *file, rtx op, int letter)
fputc (',', file);
break;
- case 'A':
- if (loongarch_memmodel_needs_rel_acq_fence ((enum memmodel) INTVAL (op)))
- fputs ("_db", file);
- break;
-
- case 'G':
- if (loongarch_memmodel_needs_release_fence ((enum memmodel) INTVAL (op)))
- fputs ("dbar\t0", file);
- break;
-
- case 'i':
- if (code != REG)
- fputs ("i", file);
- break;
-
default:
switch (code)
{
diff --git a/gcc/config/loongarch/loongarch.h b/gcc/config/loongarch/loongarch.h
index f9de9a6e4fb..89a5bd728fe 100644
--- a/gcc/config/loongarch/loongarch.h
+++ b/gcc/config/loongarch/loongarch.h
@@ -614,7 +614,7 @@ enum reg_class
#define LU12I_INT(X) LU12I_OPERAND (INTVAL (X))
#define LU32I_INT(X) LU32I_OPERAND (INTVAL (X))
#define LU52I_INT(X) LU52I_OPERAND (INTVAL (X))
-#define LARCH_U12BIT_OFFSET_P(OFFSET) (IN_RANGE (OFFSET, -2048, 2047))
+#define LARCH_12BIT_OFFSET_P(OFFSET) (IN_RANGE (OFFSET, -2048, 2047))
#define LARCH_9BIT_OFFSET_P(OFFSET) (IN_RANGE (OFFSET, -256, 255))
#define LARCH_16BIT_OFFSET_P(OFFSET) (IN_RANGE (OFFSET, -32768, 32767))
#define LARCH_SHIFT_2_OFFSET_P(OFFSET) (((OFFSET) & 0x3) == 0)
diff --git a/gcc/config/loongarch/loongarch.md b/gcc/config/loongarch/loongarch.md
index 5c0445dd879..376879fbccb 100644
--- a/gcc/config/loongarch/loongarch.md
+++ b/gcc/config/loongarch/loongarch.md
@@ -2844,48 +2844,14 @@ (define_expand "sibcall"
})
(define_insn "sibcall_internal"
- [(call (mem:SI (match_operand 0 "call_insn_operand" "j,c,a,t,h"))
+ [(call (mem:SI (match_operand 0 "call_insn_operand" "j,c,b"))
(match_operand 1 "" ""))]
"SIBLING_CALL_P (insn)"
-{
- switch (which_alternative)
- {
- case 0:
- return "jr\t%0";
- case 1:
- if (TARGET_CMODEL_LARGE)
- return "pcaddu18i\t$r12,(%%pcrel(%0+0x20000))>>18\n\t"
- "jirl\t$r0,$r12,%%pcrel(%0+4)-(%%pcrel(%0+4+0x20000)>>18<<18)";
- else if (TARGET_CMODEL_EXTREME)
- return "la.local\t$r12,$r13,%0\n\tjr\t$r12";
- else
- return "b\t%0";
- case 2:
- if (TARGET_CMODEL_TINY_STATIC)
- return "b\t%0";
- else if (TARGET_CMODEL_EXTREME)
- return "la.global\t$r12,$r13,%0\n\tjr\t$r12";
- else
- return "la.global\t$r12,%0\n\tjr\t$r12";
- case 3:
- if (TARGET_CMODEL_EXTREME)
- return "la.global\t$r12,$r13,%0\n\tjr\t$r12";
- else
- return "la.global\t$r12,%0\n\tjr\t$r12";
- case 4:
- if (TARGET_CMODEL_NORMAL || TARGET_CMODEL_TINY)
- return "b\t%%plt(%0)";
- else if (TARGET_CMODEL_LARGE)
- return "pcaddu18i\t$r12,(%%plt(%0)+0x20000)>>18\n\t"
- "jirl\t$r0,$r12,%%plt(%0)+4-((%%plt(%0)+(4+0x20000))>>18<<18)";
- else
- /* Cmodel extreme and tiny static not support plt. */
- gcc_unreachable ();
- default:
- gcc_unreachable ();
- }
-}
- [(set_attr "jirl" "indirect,direct,direct,direct,direct")])
+ "@
+ jr\t%0
+ b\t%0
+ b\t%%plt(%0)"
+ [(set_attr "jirl" "indirect,direct,direct")])
(define_expand "sibcall_value"
[(parallel [(set (match_operand 0 "")
@@ -2920,96 +2886,28 @@ (define_expand "sibcall_value"
(define_insn "sibcall_value_internal"
[(set (match_operand 0 "register_operand" "")
- (call (mem:SI (match_operand 1 "call_insn_operand" "j,c,a,t,h"))
+ (call (mem:SI (match_operand 1 "call_insn_operand" "j,c,b"))
(match_operand 2 "" "")))]
"SIBLING_CALL_P (insn)"
-{
- switch (which_alternative)
- {
- case 0:
- return "jr\t%1";
- case 1:
- if (TARGET_CMODEL_LARGE)
- return "pcaddu18i\t$r12,%%pcrel(%1+0x20000)>>18\n\t"
- "jirl\t$r0,$r12,%%pcrel(%1+4)-((%%pcrel(%1+4+0x20000))>>18<<18)";
- else if (TARGET_CMODEL_EXTREME)
- return "la.local\t$r12,$r13,%1\n\tjr\t$r12";
- else
- return "b\t%1";
- case 2:
- if (TARGET_CMODEL_TINY_STATIC)
- return "b\t%1";
- else if (TARGET_CMODEL_EXTREME)
- return "la.global\t$r12,$r13,%1\n\tjr\t$r12";
- else
- return "la.global\t$r12,%1\n\tjr\t$r12";
- case 3:
- if (TARGET_CMODEL_EXTREME)
- return "la.global\t$r12,$r13,%1\n\tjr\t$r12";
- else
- return "la.global\t$r12,%1\n\tjr\t$r12";
- case 4:
- if (TARGET_CMODEL_NORMAL || TARGET_CMODEL_TINY)
- return " b\t%%plt(%1)";
- else if (TARGET_CMODEL_LARGE)
- return "pcaddu18i\t$r12,(%%plt(%1)+0x20000)>>18\n\t"
- "jirl\t$r0,$r12,%%plt(%1)+4-((%%plt(%1)+(4+0x20000))>>18<<18)";
- else
- /* Cmodel extreme and tiny static not support plt. */
- gcc_unreachable ();
- default:
- gcc_unreachable ();
- }
-}
- [(set_attr "jirl" "indirect,direct,direct,direct,direct")])
+ "@
+ jr\t%1
+ b\t%1
+ b\t%%plt(%1)"
+ [(set_attr "jirl" "indirect,direct,direct")])
(define_insn "sibcall_value_multiple_internal"
[(set (match_operand 0 "register_operand" "")
- (call (mem:SI (match_operand 1 "call_insn_operand" "j,c,a,t,h"))
+ (call (mem:SI (match_operand 1 "call_insn_operand" "j,c,b"))
(match_operand 2 "" "")))
(set (match_operand 3 "register_operand" "")
(call (mem:SI (match_dup 1))
(match_dup 2)))]
"SIBLING_CALL_P (insn)"
-{
- switch (which_alternative)
- {
- case 0:
- return "jr\t%1";
- case 1:
- if (TARGET_CMODEL_LARGE)
- return "pcaddu18i\t$r12,%%pcrel(%1+0x20000)>>18\n\t"
- "jirl\t$r0,$r12,%%pcrel(%1+4)-(%%pcrel(%1+4+0x20000)>>18<<18)";
- else if (TARGET_CMODEL_EXTREME)
- return "la.local\t$r12,$r13,%1\n\tjr\t$r12";
- else
- return "b\t%1";
- case 2:
- if (TARGET_CMODEL_TINY_STATIC)
- return "b\t%1";
- else if (TARGET_CMODEL_EXTREME)
- return "la.global\t$r12,$r13,%1\n\tjr\t$r12";
- else
- return "la.global\t$r12,%1\n\tjr\t$r12";
- case 3:
- if (TARGET_CMODEL_EXTREME)
- return "la.global\t$r12,$r13,%1\n\tjr\t$r12";
- else
- return "la.global\t$r12,%1\n\tjr\t$r12";
- case 4:
- if (TARGET_CMODEL_NORMAL || TARGET_CMODEL_TINY)
- return "b\t%%plt(%1)";
- else if (TARGET_CMODEL_LARGE)
- return "pcaddu18i\t$r12,(%%plt(%1)+0x20000)>>18\n\t"
- "jirl\t$r0,$r12,%%plt(%1)+4-((%%plt(%1)+(4+0x20000))>>18<<18)";
- else
- /* Cmodel extreme and tiny static not support plt. */
- gcc_unreachable ();
- default:
- gcc_unreachable ();
- }
-}
- [(set_attr "jirl" "indirect,direct,direct,direct,direct")])
+ "@
+ jr\t%1
+ b\t%1
+ b\t%%plt(%1)"
+ [(set_attr "jirl" "indirect,direct,direct")])
(define_expand "call"
[(parallel [(call (match_operand 0 "")
@@ -3025,50 +2923,15 @@ (define_expand "call"
})
(define_insn "call_internal"
- [(call (mem:SI (match_operand 0 "call_insn_operand" "e,c,a,t,h"))
+ [(call (mem:SI (match_operand 0 "call_insn_operand" "e,c,b"))
(match_operand 1 "" ""))
(clobber (reg:SI RETURN_ADDR_REGNUM))]
""
-{
- switch (which_alternative)
- {
- case 0:
- return "jirl\t$r1,%0,0";
- case 1:
- if (TARGET_CMODEL_LARGE)
- return "pcaddu18i\t$r1,%%pcrel(%0+0x20000)>>18\n\t"
- "jirl\t$r1,$r1,%%pcrel(%0+4)-(%%pcrel(%0+4+0x20000)>>18<<18)";
- else if (TARGET_CMODEL_EXTREME)
- return "la.local\t$r1,$r12,%0\n\tjirl\t$r1,$r1,0";
- else
- return "bl\t%0";
- case 2:
- if (TARGET_CMODEL_TINY_STATIC)
- return "bl\t%0";
- else if (TARGET_CMODEL_EXTREME)
- return "la.global\t$r1,$r12,%0\n\tjirl\t$r1,$r1,0";
- else
- return "la.global\t$r1,%0\n\tjirl\t$r1,$r1,0";
- case 3:
- if (TARGET_CMODEL_EXTREME)
- return "la.global\t$r1,$r12,%0\n\tjirl\t$r1,$r1,0";
- else
- return "la.global\t$r1,%0\n\tjirl\t$r1,$r1,0";
- case 4:
- if (TARGET_CMODEL_LARGE)
- return "pcaddu18i\t$r1,(%%plt(%0)+0x20000)>>18\n\t"
- "jirl\t$r1,$r1,%%plt(%0)+4-((%%plt(%0)+(4+0x20000))>>18<<18)";
- else if (TARGET_CMODEL_NORMAL || TARGET_CMODEL_TINY)
- return "bl\t%%plt(%0)";
- else
- /* Cmodel extreme and tiny static not support plt. */
- gcc_unreachable ();
- default:
- gcc_unreachable ();
- }
-}
- [(set_attr "jirl" "indirect,direct,direct,direct,direct")
- (set_attr "insn_count" "1,2,3,3,2")])
+ "@
+ jirl\t$r1,%0,0
+ bl\t%0
+ bl\t%%plt(%0)"
+ [(set_attr "jirl" "indirect,direct,direct")])
(define_expand "call_value"
[(parallel [(set (match_operand 0 "")
@@ -3101,100 +2964,30 @@ (define_expand "call_value"
(define_insn "call_value_internal"
[(set (match_operand 0 "register_operand" "")
- (call (mem:SI (match_operand 1 "call_insn_operand" "e,c,a,t,h"))
+ (call (mem:SI (match_operand 1 "call_insn_operand" "e,c,b"))
(match_operand 2 "" "")))
(clobber (reg:SI RETURN_ADDR_REGNUM))]
""
-{
- switch (which_alternative)
- {
- case 0:
- return "jirl\t$r1,%1,0";
- case 1:
- if (TARGET_CMODEL_LARGE)
- return "pcaddu18i\t$r1,%%pcrel(%1+0x20000)>>18\n\t"
- "jirl\t$r1,$r1,%%pcrel(%1+4)-(%%pcrel(%1+4+0x20000)>>18<<18)";
- else if (TARGET_CMODEL_EXTREME)
- return "la.local\t$r1,$r12,%1\n\tjirl\t$r1,$r1,0";
- else
- return "bl\t%1";
- case 2:
- if (TARGET_CMODEL_TINY_STATIC)
- return "bl\t%1";
- else if (TARGET_CMODEL_EXTREME)
- return "la.global\t$r1,$r12,%1\n\tjirl\t$r1,$r1,0";
- else
- return "la.global\t$r1,%1\n\tjirl\t$r1,$r1,0";
- case 3:
- if (TARGET_CMODEL_EXTREME)
- return "la.global\t$r1,$r12,%1\n\tjirl\t$r1,$r1,0";
- else
- return "la.global\t$r1,%1\n\tjirl\t$r1,$r1,0";
- case 4:
- if (TARGET_CMODEL_LARGE)
- return "pcaddu18i\t$r1,(%%plt(%1)+0x20000)>>18\n\t"
- "jirl\t$r1,$r1,%%plt(%1)+4-((%%plt(%1)+(4+0x20000))>>18<<18)";
- else if (TARGET_CMODEL_NORMAL || TARGET_CMODEL_TINY)
- return "bl\t%%plt(%1)";
- else
- /* Cmodel extreme and tiny static not support plt. */
- gcc_unreachable ();
- default:
- gcc_unreachable ();
- }
-}
- [(set_attr "jirl" "indirect,direct,direct,direct,direct")
- (set_attr "insn_count" "1,2,3,3,2")])
+ "@
+ jirl\t$r1,%1,0
+ bl\t%1
+ bl\t%%plt(%1)"
+ [(set_attr "jirl" "indirect,direct,direct")])
(define_insn "call_value_multiple_internal"
[(set (match_operand 0 "register_operand" "")
- (call (mem:SI (match_operand 1 "call_insn_operand" "e,c,a,t,h"))
+ (call (mem:SI (match_operand 1 "call_insn_operand" "e,c,b"))
(match_operand 2 "" "")))
(set (match_operand 3 "register_operand" "")
(call (mem:SI (match_dup 1))
(match_dup 2)))
(clobber (reg:SI RETURN_ADDR_REGNUM))]
""
-{
- switch (which_alternative)
- {
- case 0:
- return "jirl\t$r1,%1,0";
- case 1:
- if (TARGET_CMODEL_LARGE)
- return "pcaddu18i\t$r1,%%pcrel(%1+0x20000)>>18\n\t"
- "jirl\t$r1,$r1,%%pcrel(%1+4)-(%%pcrel(%1+4+0x20000)>>18<<18)";
- else if (TARGET_CMODEL_EXTREME)
- return "la.local\t$r1,$r12,%1\n\tjirl\t$r1,$r1,0";
- else
- return "bl\t%1";
- case 2:
- if (TARGET_CMODEL_TINY_STATIC)
- return "bl\t%1";
- else if (TARGET_CMODEL_EXTREME)
- return "la.global\t$r1,$r12,%1\n\tjirl\t$r1,$r1,0 ";
- else
- return "la.global\t$r1,%1\n\tjirl\t$r1,$r1,0";
- case 3:
- if (TARGET_CMODEL_EXTREME)
- return "la.global\t$r1,$r12,%1\n\tjirl\t$r1,$r1,0";
- else
- return "la.global\t$r1,%1\n\tjirl\t$r1,$r1,0";
- case 4:
- if (TARGET_CMODEL_LARGE)
- return "pcaddu18i\t$r1,(%%plt(%1)+0x20000)>>18\n\t"
- "jirl\t$r1,$r1,%%plt(%1)+4-((%%plt(%1)+(4+0x20000))>>18<<18)";
- else if (TARGET_CMODEL_NORMAL || TARGET_CMODEL_TINY)
- return "bl\t%%plt(%1)";
- else
- /* Cmodel extreme and tiny static not support plt. */
- gcc_unreachable ();
- default:
- gcc_unreachable ();
- }
-}
- [(set_attr "jirl" "indirect,direct,direct,direct,direct")
- (set_attr "insn_count" "1,2,3,3,2")])
+ "@
+ jirl\t$r1,%1,0
+ bl\t%1
+ bl\t%%plt(%1)"
+ [(set_attr "jirl" "indirect,direct,direct")])
;; Call subroutine returning any type.
diff --git a/gcc/config/loongarch/predicates.md b/gcc/config/loongarch/predicates.md
index edd74d4783d..2243ef71c1a 100644
--- a/gcc/config/loongarch/predicates.md
+++ b/gcc/config/loongarch/predicates.md
@@ -111,20 +111,25 @@ (define_predicate "const_call_insn_operand"
(match_code "const,symbol_ref,label_ref")
{
enum loongarch_symbol_type symbol_type;
+ loongarch_symbolic_constant_p (op, &symbol_type);
- if (!loongarch_symbolic_constant_p (op, &symbol_type))
+ rtx offset, x = op;
+ split_const (x, &x, &offset);
+
+ if (offset != const0_rtx)
return false;
switch (symbol_type)
{
- case SYMBOL_GOT_DISP:
- /* Without explicit relocs, there is no special syntax for
- loading the address of a call destination into a register.
- Using "la.global JIRL_REGS,foo; jirl JIRL_REGS" would prevent the lazy
- binding of "foo", so keep the address of global symbols with the jirl
- macro. */
+ case SYMBOL_PCREL:
return 1;
+ case SYMBOL_GOT_DISP:
+ if (!flag_plt)
+ return false;
+ else
+ return 1;
+
default:
return false;
}
@@ -140,22 +145,11 @@ (define_predicate "is_const_call_local_symbol"
(match_test "loongarch_symbol_binds_local_p (op) != 0"))
(match_test "CONSTANT_P (op)")))
-(define_predicate "is_const_call_weak_symbol"
- (and (match_operand 0 "const_call_insn_operand")
- (not (match_operand 0 "is_const_call_local_symbol"))
- (match_test "loongarch_weak_symbol_p (op) != 0")
- (match_test "CONSTANT_P (op)")))
-
-(define_predicate "is_const_call_plt_symbol"
- (and (match_operand 0 "const_call_insn_operand")
- (match_test "flag_plt != 0")
- (match_test "loongarch_global_symbol_noweak_p (op) != 0")
- (match_test "CONSTANT_P (op)")))
-
-(define_predicate "is_const_call_global_noplt_symbol"
+(define_predicate "is_const_call_no_local_symbol"
(and (match_operand 0 "const_call_insn_operand")
- (match_test "flag_plt == 0")
- (match_test "loongarch_global_symbol_noweak_p (op) != 0")
+ (ior (match_test "loongarch_global_symbol_p (op) != 0")
+ (match_test "loongarch_symbol_binds_local_p (op) == 0")
+ (match_test "loongarch_weak_symbol_p (op) != 0"))
(match_test "CONSTANT_P (op)")))
;; A legitimate CONST_INT operand that takes more than one instruction
@@ -219,7 +213,7 @@ (define_predicate "move_operand"
case CONST:
case SYMBOL_REF:
case LABEL_REF:
- return (loongarch_symbolic_constant_p (op, &symbol_type));
+ return loongarch_symbolic_constant_p (op, &symbol_type);
default:
return true;
}
diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-1.c b/gcc/testsuite/gcc.target/loongarch/func-call-1.c
new file mode 100644
index 00000000000..b0482761aab
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/func-call-1.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-mabi=lp64d -O0 -fpic -fplt" } */
+/* { dg-final { scan-assembler "test:.*bl\t%plt\\(g\\)\n" } } */
+/* { dg-final { scan-assembler "test1:.*bl\t%plt\\(f\\)\n" } } */
+/* { dg-final { scan-assembler "test2:.*bl\tl\n" } } */
+
+extern void g (void);
+void
+f (void)
+{}
+
+static void
+l (void)
+{}
+
+void
+test (void)
+{
+ g ();
+}
+
+void
+test1 (void)
+{
+ f ();
+}
+
+void
+test2 (void)
+{
+ l ();
+}
diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-2.c b/gcc/testsuite/gcc.target/loongarch/func-call-2.c
new file mode 100644
index 00000000000..f5e061c299c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/func-call-2.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-mabi=lp64d -O0 -fno-pic -fplt" } */
+/* { dg-final { scan-assembler "test:.*bl\t%plt\\(g\\)\n" } } */
+/* { dg-final { scan-assembler "test1:.*bl\tf\n" } } */
+/* { dg-final { scan-assembler "test2:.*bl\tl\n" } } */
+
+extern void g (void);
+void
+f (void)
+{}
+
+static void
+l (void)
+{}
+
+void
+test (void)
+{
+ g ();
+}
+
+void
+test1 (void)
+{
+ f ();
+}
+
+void
+test2 (void)
+{
+ l ();
+}
diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-3.c b/gcc/testsuite/gcc.target/loongarch/func-call-3.c
new file mode 100644
index 00000000000..75082c57466
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/func-call-3.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-mabi=lp64d -O0 -fpic -fno-plt" } */
+/* { dg-final { scan-assembler "test:.*la\.global\t.*g\n\tjirl" } } */
+/* { dg-final { scan-assembler "test1:.*la\.global\t.*f\n\tjirl" } } */
+/* { dg-final { scan-assembler "test2:.*bl\tl\n" } } */
+
+extern void g (void);
+void
+f (void)
+{}
+
+static void
+l (void)
+{}
+
+void
+test (void)
+{
+ g ();
+}
+
+void
+test1 (void)
+{
+ f ();
+}
+
+void
+test2 (void)
+{
+ l ();
+}
diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-4.c b/gcc/testsuite/gcc.target/loongarch/func-call-4.c
new file mode 100644
index 00000000000..e8a8395493e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/func-call-4.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-mabi=lp64d -O0 -fno-pic -fno-plt" } */
+/* { dg-final { scan-assembler "test:.*la\.global\t.*g\n\tjirl" } } */
+/* { dg-final { scan-assembler "test1:.*bl\tf\n" } } */
+/* { dg-final { scan-assembler "test2:.*bl\tl\n" } } */
+
+extern void g (void);
+void
+f (void)
+{}
+
+static void
+l (void)
+{}
+
+void
+test (void)
+{
+ g ();
+}
+
+void
+test1 (void)
+{
+ f ();
+}
+
+void
+test2 (void)
+{
+ l ();
+}
--
2.31.1
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v2 2/3] LoongArch: Support split symbol.
2022-07-21 6:41 [PATCH v2 0/3] LoongArch: Modify the method of obtaining symbolic addresses Lulu Cheng
2022-07-21 6:41 ` [PATCH v2 1/3] LoongArch: Subdivision symbol type, add SYMBOL_PCREL support Lulu Cheng
@ 2022-07-21 6:41 ` Lulu Cheng
2022-07-21 6:41 ` [PATCH v2 3/3] LoongArch: Modify the definition of the ASM_PREFERRED_EH_DATA_FORMAT macro Lulu Cheng
2 siblings, 0 replies; 4+ messages in thread
From: Lulu Cheng @ 2022-07-21 6:41 UTC (permalink / raw)
To: gcc-patches; +Cc: xry111, i, xuchenghua, Lulu Cheng
Add compilation option '-mexplicit-relocs', and if enable '-mexplicit-relocs'
the symbolic address load instruction 'la.*' will be split into two instructions.
This ckompilation option enabled by default.
gcc/ChangeLog:
* common/config/loongarch/loongarch-common.cc:
Enable '-fsection-anchors' when O1 and more advanced optimization.
* config/loongarch/genopts/loongarch.opt.in: Add new option
'-mexplicit-relocs', and enable by default.
* config/loongarch/loongarch-protos.h (loongarch_split_move_insn_p):
Delete function declaration.
(loongarch_split_move_insn): Delete function declaration.
(loongarch_split_symbol_type): Add function declaration.
* config/loongarch/loongarch.cc (enum loongarch_address_type):
Add new address type 'ADDRESS_LO_SUM'.
(loongarch_classify_symbolic_expression): New function definitions.
Classify the base of symbolic expression X, given that X appears in
context CONTEXT.
(loongarch_symbol_insns): Add a judgment condition TARGET_EXPLICIT_RELOCS.
(loongarch_split_symbol_type): New function definitions.
Determines whether the symbol load should be split into two instructions.
(loongarch_valid_lo_sum_p): New function definitions.
Return true if a LO_SUM can address a value of mode MODE when the LO_SUM
symbol has type SYMBOL_TYPE.
(loongarch_classify_address): Add handling of 'LO_SUM'.
(loongarch_address_insns): Add handling of 'ADDRESS_LO_SUM'.
(loongarch_signed_immediate_p): Sort code.
(loongarch_12bit_offset_address_p): Return true if address type is ADDRESS_LO_SUM.
(loongarch_const_insns): Add handling of 'HIGH'.
(loongarch_split_move_insn_p): Add the static attribute to the function.
(loongarch_emit_set): New function definitions.
(loongarch_call_tls_get_addr): Add symbol handling when defining TARGET_EXPLICIT_RELOCS.
(loongarch_legitimize_tls_address): Add symbol handling when defining the
TARGET_EXPLICIT_RELOCS macro.
(loongarch_split_symbol): New function definitions. Split symbol.
(loongarch_legitimize_address): Add codes see if the address can split into a high part
and a LO_SUM.
(loongarch_legitimize_const_move): Add codes split moves of symbolic constants into
high and low.
(loongarch_split_move_insn): Delete function definitions.
(loongarch_output_move): Add support for HIGH and LO_SUM.
(loongarch_print_operand_reloc): New function definitions.
Print symbolic operand OP, which is part of a HIGH or LO_SUM in context CONTEXT.
(loongarch_memmodel_needs_release_fence): Sort code.
(loongarch_print_operand): Rearrange alphabetical order and add H and L to support HIGH
and LOW output.
(loongarch_print_operand_address): Add handling of 'ADDRESS_LO_SUM'.
(TARGET_MIN_ANCHOR_OFFSET): Define macro to -IMM_REACH/2.
(TARGET_MAX_ANCHOR_OFFSET): Define macro to IMM_REACH/2-1.
* config/loongarch/loongarch.md (movti): Delete the template.
(*movti): Delete the template.
(movtf): Delete the template.
(*movtf): Delete the template.
(*low<mode>): New template of normal symbol low address.
(@tls_low<mode>): New template of tls symbol low address.
(@ld_from_got<mode>): New template load address from got table.
(@ori_l_lo12<mode>): New template.
* config/loongarch/loongarch.opt: Update from loongarch.opt.in.
* config/loongarch/predicates.md: Add support for symbol_type HIGH.
gcc/testsuite/ChangeLog:
* gcc.target/loongarch/func-call-1.c: Add build option '-mno-explicit-relocs'.
* gcc.target/loongarch/func-call-2.c: Add build option '-mno-explicit-relocs'.
* gcc.target/loongarch/func-call-3.c: Add build option '-mno-explicit-relocs'.
* gcc.target/loongarch/func-call-4.c: Add build option '-mno-explicit-relocs'.
* gcc.target/loongarch/func-call-5.c: New test.
* gcc.target/loongarch/func-call-6.c: New test.
* gcc.target/loongarch/func-call-7.c: New test.
* gcc.target/loongarch/func-call-8.c: New test.
* gcc.target/loongarch/relocs-symbol-noaddend.c: New test.
---
.../config/loongarch/loongarch-common.cc | 1 +
gcc/config/loongarch/genopts/loongarch.opt.in | 4 +
gcc/config/loongarch/loongarch-protos.h | 3 +-
gcc/config/loongarch/loongarch.cc | 412 ++++++++++++++++--
gcc/config/loongarch/loongarch.md | 122 +++---
gcc/config/loongarch/loongarch.opt | 4 +
gcc/config/loongarch/predicates.md | 20 +-
.../gcc.target/loongarch/func-call-1.c | 2 +-
.../gcc.target/loongarch/func-call-2.c | 2 +-
.../gcc.target/loongarch/func-call-3.c | 2 +-
.../gcc.target/loongarch/func-call-4.c | 2 +-
.../gcc.target/loongarch/func-call-5.c | 33 ++
.../gcc.target/loongarch/func-call-6.c | 33 ++
.../gcc.target/loongarch/func-call-7.c | 34 ++
.../gcc.target/loongarch/func-call-8.c | 33 ++
.../loongarch/relocs-symbol-noaddend.c | 23 +
16 files changed, 614 insertions(+), 116 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/loongarch/func-call-5.c
create mode 100644 gcc/testsuite/gcc.target/loongarch/func-call-6.c
create mode 100644 gcc/testsuite/gcc.target/loongarch/func-call-7.c
create mode 100644 gcc/testsuite/gcc.target/loongarch/func-call-8.c
create mode 100644 gcc/testsuite/gcc.target/loongarch/relocs-symbol-noaddend.c
diff --git a/gcc/common/config/loongarch/loongarch-common.cc b/gcc/common/config/loongarch/loongarch-common.cc
index ed3730fce8b..f8b4660fabf 100644
--- a/gcc/common/config/loongarch/loongarch-common.cc
+++ b/gcc/common/config/loongarch/loongarch-common.cc
@@ -34,6 +34,7 @@ along with GCC; see the file COPYING3. If not see
static const struct default_options loongarch_option_optimization_table[] =
{
{ OPT_LEVELS_ALL, OPT_fasynchronous_unwind_tables, NULL, 1 },
+ { OPT_LEVELS_1_PLUS, OPT_fsection_anchors, NULL, 1 },
{ OPT_LEVELS_NONE, 0, NULL, 0 }
};
diff --git a/gcc/config/loongarch/genopts/loongarch.opt.in b/gcc/config/loongarch/genopts/loongarch.opt.in
index 61e7d72a0a1..6f39500935d 100644
--- a/gcc/config/loongarch/genopts/loongarch.opt.in
+++ b/gcc/config/loongarch/genopts/loongarch.opt.in
@@ -154,6 +154,10 @@ mmax-inline-memcpy-size=
Target Joined RejectNegative UInteger Var(loongarch_max_inline_memcpy_size) Init(1024)
-mmax-inline-memcpy-size=SIZE Set the max size of memcpy to inline, default is 1024.
+mexplicit-relocs
+Target Var(TARGET_EXPLICIT_RELOCS) Init(1)
+Use %reloc() assembly operators.
+
; The code model option names for -mcmodel.
Enum
Name(cmodel) Type(int)
diff --git a/gcc/config/loongarch/loongarch-protos.h b/gcc/config/loongarch/loongarch-protos.h
index 080766250d1..cadaad7519c 100644
--- a/gcc/config/loongarch/loongarch-protos.h
+++ b/gcc/config/loongarch/loongarch-protos.h
@@ -77,8 +77,6 @@ extern rtx loongarch_legitimize_call_address (rtx);
extern rtx loongarch_subword (rtx, bool);
extern bool loongarch_split_move_p (rtx, rtx);
extern void loongarch_split_move (rtx, rtx, rtx);
-extern bool loongarch_split_move_insn_p (rtx, rtx);
-extern void loongarch_split_move_insn (rtx, rtx, rtx);
extern const char *loongarch_output_move (rtx, rtx);
extern bool loongarch_cfun_has_cprestore_slot_p (void);
#ifdef RTX_CODE
@@ -160,6 +158,7 @@ extern rtx loongarch_expand_thread_pointer (rtx);
extern bool loongarch_eh_uses (unsigned int);
extern bool loongarch_epilogue_uses (unsigned int);
extern bool loongarch_load_store_bonding_p (rtx *, machine_mode, bool);
+extern bool loongarch_split_symbol_type (enum loongarch_symbol_type);
typedef rtx (*mulsidi3_gen_fn) (rtx, rtx, rtx);
diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc
index 1cb5742f6dd..79687340dfd 100644
--- a/gcc/config/loongarch/loongarch.cc
+++ b/gcc/config/loongarch/loongarch.cc
@@ -100,6 +100,10 @@ along with GCC; see the file COPYING3. If not see
ADDRESS_REG_REG
A base register indexed by (optionally scaled) register.
+ ADDRESS_LO_SUM
+ A LO_SUM rtx. The first operand is a valid base register and the second
+ operand is a symbolic address.
+
ADDRESS_CONST_INT
A signed 16-bit constant address.
@@ -109,6 +113,7 @@ enum loongarch_address_type
{
ADDRESS_REG,
ADDRESS_REG_REG,
+ ADDRESS_LO_SUM,
ADDRESS_CONST_INT,
ADDRESS_SYMBOLIC
};
@@ -1641,6 +1646,21 @@ loongarch_classify_symbol (const_rtx x)
return SYMBOL_PCREL;
}
+/* Classify the base of symbolic expression X, given that X appears in
+ context CONTEXT. */
+
+static enum loongarch_symbol_type
+loongarch_classify_symbolic_expression (rtx x)
+{
+ rtx offset;
+
+ split_const (x, &x, &offset);
+ if (UNSPEC_ADDRESS_P (x))
+ return UNSPEC_ADDRESS_TYPE (x);
+
+ return loongarch_classify_symbol (x);
+}
+
/* Return true if X is a symbolic constant. If it is,
store the type of the symbol in *SYMBOL_TYPE. */
@@ -1696,7 +1716,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 (mode != MAX_MACHINE_MODE)
+ if (!TARGET_EXPLICIT_RELOCS && mode != MAX_MACHINE_MODE)
return 0;
return 3;
@@ -1814,6 +1834,84 @@ loongarch_valid_offset_p (rtx x, machine_mode mode)
return true;
}
+/* Should a symbol of type SYMBOL_TYPE should be split in two? */
+
+bool
+loongarch_split_symbol_type (enum loongarch_symbol_type symbol_type)
+{
+ switch (symbol_type)
+ {
+ case SYMBOL_PCREL:
+ case SYMBOL_GOT_DISP:
+ case SYMBOL_TLS_IE:
+ case SYMBOL_TLS_LE:
+ case SYMBOL_TLSGD:
+ case SYMBOL_TLSLDM:
+ return true;
+
+ case SYMBOL_TLS:
+ return false;
+
+ default:
+ gcc_unreachable ();
+ }
+}
+
+/* Return true if a LO_SUM can address a value of mode MODE when the
+ LO_SUM symbol has type SYMBOL_TYPE. */
+
+static bool
+loongarch_valid_lo_sum_p (enum loongarch_symbol_type symbol_type,
+ machine_mode mode, rtx x)
+{
+ int align, size;
+
+ /* Check that symbols of type SYMBOL_TYPE can be used to access values
+ of mode MODE. */
+ if (loongarch_symbol_insns (symbol_type, mode) == 0)
+ return false;
+
+ /* Check that there is a known low-part relocation. */
+ if (!loongarch_split_symbol_type (symbol_type))
+ return false;
+
+ /* We can't tell size or alignment when we have BLKmode, so try extracing a
+ decl from the symbol if possible. */
+ if (mode == BLKmode)
+ {
+ rtx offset;
+
+ /* Extract the symbol from the LO_SUM operand, if any. */
+ split_const (x, &x, &offset);
+
+ /* Might be a CODE_LABEL. We can compute align but not size for that,
+ so don't bother trying to handle it. */
+ if (!SYMBOL_REF_P (x))
+ return false;
+
+ /* Use worst case assumptions if we don't have a SYMBOL_REF_DECL. */
+ align = (SYMBOL_REF_DECL (x)
+ ? DECL_ALIGN (SYMBOL_REF_DECL (x))
+ : 1);
+ size = (SYMBOL_REF_DECL (x) && DECL_SIZE (SYMBOL_REF_DECL (x))
+ ? tree_to_uhwi (DECL_SIZE (SYMBOL_REF_DECL (x)))
+ : 2*BITS_PER_WORD);
+ }
+ else
+ {
+ align = GET_MODE_ALIGNMENT (mode);
+ size = GET_MODE_BITSIZE (mode);
+ }
+
+ /* We may need to split multiword moves, so make sure that each word
+ can be accessed without inducing a carry. */
+ if (size > BITS_PER_WORD
+ && (!TARGET_STRICT_ALIGN || size > align))
+ return false;
+
+ return true;
+}
+
static bool
loongarch_valid_index_p (struct loongarch_address_info *info, rtx x,
machine_mode mode, bool strict_p)
@@ -1880,6 +1978,26 @@ loongarch_classify_address (struct loongarch_address_info *info, rtx x,
info->offset = XEXP (x, 1);
return (loongarch_valid_base_register_p (info->reg, mode, strict_p)
&& loongarch_valid_offset_p (info->offset, mode));
+
+ case LO_SUM:
+ info->type = ADDRESS_LO_SUM;
+ info->reg = XEXP (x, 0);
+ info->offset = XEXP (x, 1);
+ /* We have to trust the creator of the LO_SUM to do something vaguely
+ sane. Target-independent code that creates a LO_SUM should also
+ create and verify the matching HIGH. Target-independent code that
+ adds an offset to a LO_SUM must prove that the offset will not
+ induce a carry. Failure to do either of these things would be
+ a bug, and we are not required to check for it here. The MIPS
+ backend itself should only create LO_SUMs for valid symbolic
+ constants, with the high part being either a HIGH or a copy
+ of _gp. */
+ info->symbol_type
+ = loongarch_classify_symbolic_expression (info->offset);
+ return (loongarch_valid_base_register_p (info->reg, mode, strict_p)
+ && loongarch_valid_lo_sum_p (info->symbol_type, mode,
+ info->offset));
+
default:
return false;
}
@@ -1940,6 +2058,9 @@ loongarch_address_insns (rtx x, machine_mode mode, bool might_split_p)
case ADDRESS_CONST_INT:
return factor;
+ case ADDRESS_LO_SUM:
+ return factor + 1;
+
case ADDRESS_SYMBOLIC:
return factor * loongarch_symbol_insns (addr.symbol_type, mode);
}
@@ -1967,7 +2088,8 @@ loongarch_signed_immediate_p (unsigned HOST_WIDE_INT x, int bits,
return loongarch_unsigned_immediate_p (x, bits, shift);
}
-/* Return true if X is a legitimate address with a 12-bit offset.
+/* Return true if X is a legitimate address with a 12-bit offset
+ or addr.type is ADDRESS_LO_SUM.
MODE is the mode of the value being accessed. */
bool
@@ -1976,9 +2098,10 @@ loongarch_12bit_offset_address_p (rtx x, machine_mode mode)
struct loongarch_address_info addr;
return (loongarch_classify_address (&addr, x, mode, false)
- && addr.type == ADDRESS_REG
- && CONST_INT_P (addr.offset)
- && LARCH_12BIT_OFFSET_P (INTVAL (addr.offset)));
+ && ((addr.type == ADDRESS_REG
+ && CONST_INT_P (addr.offset)
+ && LARCH_12BIT_OFFSET_P (INTVAL (addr.offset)))
+ || addr.type == ADDRESS_LO_SUM));
}
/* Return true if X is a legitimate address with a 14-bit offset shifted 2.
@@ -2020,6 +2143,14 @@ loongarch_const_insns (rtx x)
switch (GET_CODE (x))
{
+ case HIGH:
+ if (!loongarch_symbolic_constant_p (XEXP (x, 0), &symbol_type)
+ || !loongarch_split_symbol_type (symbol_type))
+ return 0;
+
+ /* This is simply a PCALAU12I. */
+ return 1;
+
case CONST_INT:
return loongarch_integer_cost (INTVAL (x));
@@ -2080,6 +2211,8 @@ loongarch_split_const_insns (rtx x)
return low + high;
}
+static bool loongarch_split_move_insn_p (rtx dest, rtx src);
+
/* Return the number of instructions needed to implement INSN,
given that it loads from or stores to MEM. */
@@ -2197,6 +2330,15 @@ loongarch_unspec_address (rtx address, enum loongarch_symbol_type symbol_type)
return loongarch_unspec_address_offset (base, offset, symbol_type);
}
+/* Emit an instruction of the form (set TARGET SRC). */
+
+static rtx
+loongarch_emit_set (rtx target, rtx src)
+{
+ emit_insn (gen_rtx_SET (target, src));
+ return target;
+}
+
/* If OP is an UNSPEC address, return the address to which it refers,
otherwise return OP itself. */
@@ -2278,6 +2420,7 @@ loongarch_call_tls_get_addr (rtx sym, enum loongarch_symbol_type type, rtx v0)
{
rtx loc, a0;
rtx_insn *insn;
+ rtx tmp = gen_reg_rtx (Pmode);
a0 = gen_rtx_REG (Pmode, GP_ARG_FIRST);
@@ -2288,12 +2431,22 @@ loongarch_call_tls_get_addr (rtx sym, enum loongarch_symbol_type type, rtx v0)
start_sequence ();
- if (type == SYMBOL_TLSLDM)
- emit_insn (loongarch_got_load_tls_ld (a0, loc));
- else if (type == SYMBOL_TLSGD)
- emit_insn (loongarch_got_load_tls_gd (a0, loc));
+ if (TARGET_EXPLICIT_RELOCS)
+ {
+ /* Split tls symbol to high and low. */
+ rtx high = gen_rtx_HIGH (Pmode, copy_rtx (loc));
+ high = loongarch_force_temporary (tmp, high);
+ emit_insn (gen_tls_low (Pmode, a0, high, loc));
+ }
else
- gcc_unreachable ();
+ {
+ if (type == SYMBOL_TLSLDM)
+ emit_insn (loongarch_got_load_tls_ld (a0, loc));
+ else if (type == SYMBOL_TLSGD)
+ emit_insn (loongarch_got_load_tls_gd (a0, loc));
+ else
+ gcc_unreachable ();
+ }
insn = emit_call_insn (gen_call_value_internal (v0, loongarch_tls_symbol,
const0_rtx));
@@ -2308,12 +2461,12 @@ loongarch_call_tls_get_addr (rtx sym, enum loongarch_symbol_type type, rtx v0)
/* Generate the code to access LOC, a thread-local SYMBOL_REF, and return
its address. The return value will be both a valid address and a valid
- SET_SRC. */
+ SET_SRC (either a REG or a LO_SUM). */
static rtx
loongarch_legitimize_tls_address (rtx loc)
{
- rtx dest, tp, tmp;
+ rtx dest, tp, tmp, tmp1, tmp2, tmp3;
enum tls_model model = SYMBOL_REF_TLS_MODEL (loc);
rtx_insn *insn;
@@ -2334,21 +2487,45 @@ loongarch_legitimize_tls_address (rtx loc)
break;
case TLS_MODEL_INITIAL_EXEC:
- /* la.tls.ie; tp-relative add. */
- tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM);
- tmp = gen_reg_rtx (Pmode);
- emit_insn (loongarch_got_load_tls_ie (tmp, loc));
- dest = gen_reg_rtx (Pmode);
- emit_insn (gen_add3_insn (dest, tmp, tp));
+ {
+ /* la.tls.ie; tp-relative add. */
+ tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM);
+ tmp1 = gen_reg_rtx (Pmode);
+ dest = gen_reg_rtx (Pmode);
+ if (TARGET_EXPLICIT_RELOCS)
+ {
+ tmp2 = loongarch_unspec_address (loc, SYMBOL_TLS_IE);
+ tmp3 = gen_reg_rtx (Pmode);
+ rtx high = gen_rtx_HIGH (Pmode, copy_rtx (tmp2));
+ high = loongarch_force_temporary (tmp3, high);
+ emit_insn (gen_ld_from_got (Pmode, tmp1, high, tmp2));
+ }
+ else
+ emit_insn (loongarch_got_load_tls_ie (tmp1, loc));
+ emit_insn (gen_add3_insn (dest, tmp1, tp));
+ }
break;
case TLS_MODEL_LOCAL_EXEC:
- /* la.tls.le; tp-relative add. */
- tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM);
- tmp = gen_reg_rtx (Pmode);
- emit_insn (loongarch_got_load_tls_le (tmp, loc));
- dest = gen_reg_rtx (Pmode);
- emit_insn (gen_add3_insn (dest, tmp, tp));
+ {
+ /* la.tls.le; tp-relative add. */
+ tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM);
+ tmp1 = gen_reg_rtx (Pmode);
+ dest = gen_reg_rtx (Pmode);
+
+ if (TARGET_EXPLICIT_RELOCS)
+ {
+ tmp2 = loongarch_unspec_address (loc, SYMBOL_TLS_LE);
+ tmp3 = gen_reg_rtx (Pmode);
+ rtx high = gen_rtx_HIGH (Pmode, copy_rtx (tmp2));
+ high = loongarch_force_temporary (tmp3, high);
+ emit_insn (gen_ori_l_lo12 (Pmode, tmp1, high, tmp2));
+ }
+ else
+ emit_insn (loongarch_got_load_tls_le (tmp1, loc));
+ emit_insn (gen_add3_insn (dest, tmp1, tp));
+
+ }
break;
default:
@@ -2397,6 +2574,68 @@ loongarch_force_address (rtx x, machine_mode mode)
return x;
}
+/* If MODE is MAX_MACHINE_MODE, ADDR appears as a move operand, otherwise
+ it appears in a MEM of that mode. Return true if ADDR is a legitimate
+ constant in that context and can be split into high and low parts.
+ 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'.
+
+ TEMP is as for loongarch_force_temporary and is used to load the high
+ part into a register.
+
+ When MODE is MAX_MACHINE_MODE, the low part is guaranteed to be
+ a legitimize SET_SRC for an .md pattern, otherwise the low part
+ is guaranteed to be a legitimate address for mode MODE. */
+
+bool
+loongarch_split_symbol (rtx temp, rtx addr, machine_mode mode, rtx *low_out)
+{
+ enum loongarch_symbol_type symbol_type;
+ rtx high;
+
+ /* 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_symbol_insns (symbol_type, mode) == 0
+ || !loongarch_split_symbol_type (symbol_type))
+ return false;
+
+ if (temp == NULL)
+ temp = gen_reg_rtx (Pmode);
+
+ /* Get the 12-31 bits of the address. */
+ high = gen_rtx_HIGH (Pmode, copy_rtx (addr));
+ high = loongarch_force_temporary (temp, high);
+
+ if (low_out)
+ switch (symbol_type)
+ {
+ case SYMBOL_PCREL:
+ *low_out = gen_rtx_LO_SUM (Pmode, high, addr);
+ break;
+
+ case SYMBOL_GOT_DISP:
+ /* SYMBOL_GOT_DISP symbols are loaded from the GOT. */
+ {
+ rtx low = gen_rtx_LO_SUM (Pmode, high, addr);
+ rtx mem = gen_rtx_MEM (Pmode, low);
+ *low_out = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, mem),
+ UNSPEC_LOAD_FROM_GOT);
+ break;
+ }
+
+ default:
+ gcc_unreachable ();
+ }
+
+ return true;
+}
+
/* This function is used to implement LEGITIMIZE_ADDRESS. If X can
be legitimized in a way that the generic machinery might not expect,
return a new address, otherwise return NULL. MODE is the mode of
@@ -2412,6 +2651,10 @@ loongarch_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
if (loongarch_tls_symbol_p (x))
return loongarch_legitimize_tls_address (x);
+ /* See if the address can split into a high part and a LO_SUM. */
+ if (loongarch_split_symbol (NULL, x, mode, &addr))
+ return loongarch_force_address (addr, mode);
+
/* Handle BASE + OFFSET using loongarch_add_offset. */
loongarch_split_plus (x, &base, &offset);
if (offset != 0)
@@ -2499,6 +2742,13 @@ loongarch_legitimize_const_move (machine_mode mode, rtx dest, rtx src)
return;
}
+ /* Split moves of symbolic constants into high and low. */
+ if (loongarch_split_symbol (dest, src, MAX_MACHINE_MODE, &src))
+ {
+ loongarch_emit_set (dest, src);
+ return;
+ }
+
/* Generate the appropriate access sequences for TLS symbols. */
if (loongarch_tls_symbol_p (src))
{
@@ -3241,21 +3491,12 @@ loongarch_split_move (rtx dest, rtx src, rtx insn_)
/* Return true if a move from SRC to DEST in INSN should be split. */
-bool
+static bool
loongarch_split_move_insn_p (rtx dest, rtx src)
{
return loongarch_split_move_p (dest, src);
}
-/* Split a move from SRC to DEST in INSN, given that
- loongarch_split_move_insn_p holds. */
-
-void
-loongarch_split_move_insn (rtx dest, rtx src, rtx insn)
-{
- loongarch_split_move (dest, src, insn);
-}
-
/* Implement TARGET_CONSTANT_ALIGNMENT. */
static HOST_WIDE_INT
@@ -3369,13 +3610,16 @@ loongarch_output_move (rtx dest, rtx src)
case 2:
return "st.h\t%z1,%0";
case 4:
- /* Matching address type with a 12bit offset. */
- if (const_arith_operand (offset, Pmode))
+ /* Matching address type with a 12bit offset and
+ ADDRESS_LO_SUM. */
+ if (const_arith_operand (offset, Pmode)
+ || GET_CODE (offset) == LO_SUM)
return "st.w\t%z1,%0";
else
return "stptr.w\t%z1,%0";
case 8:
- if (const_arith_operand (offset, Pmode))
+ if (const_arith_operand (offset, Pmode)
+ || GET_CODE (offset) == LO_SUM)
return "st.d\t%z1,%0";
else
return "stptr.d\t%z1,%0";
@@ -3408,13 +3652,16 @@ loongarch_output_move (rtx dest, rtx src)
case 2:
return "ld.hu\t%0,%1";
case 4:
- /* Matching address type with a 12bit offset. */
- if (const_arith_operand (offset, Pmode))
+ /* Matching address type with a 12bit offset and
+ ADDRESS_LO_SUM. */
+ if (const_arith_operand (offset, Pmode)
+ || GET_CODE (offset) == LO_SUM)
return "ld.w\t%0,%1";
else
return "ldptr.w\t%0,%1";
case 8:
- if (const_arith_operand (offset, Pmode))
+ if (const_arith_operand (offset, Pmode)
+ || GET_CODE (offset) == LO_SUM)
return "ld.d\t%0,%1";
else
return "ldptr.d\t%0,%1";
@@ -3423,6 +3670,21 @@ loongarch_output_move (rtx dest, rtx src)
}
}
+ if (src_code == HIGH)
+ {
+ rtx offset, x;
+ split_const (XEXP (src, 0), &x, &offset);
+ enum loongarch_symbol_type type = SYMBOL_PCREL;
+
+ if (UNSPEC_ADDRESS_P (x))
+ type = UNSPEC_ADDRESS_TYPE (x);
+
+ if (type == SYMBOL_TLS_LE)
+ return "lu12i.w\t%0,%h1";
+ else
+ return "pcalau12i\t%0,%h1";
+ }
+
if (src_code == CONST_INT)
{
if (LU12I_INT (src))
@@ -3438,7 +3700,8 @@ loongarch_output_move (rtx dest, rtx src)
}
}
- if (dest_code == REG && symbolic_operand (src, VOIDmode))
+ if (!TARGET_EXPLICIT_RELOCS
+ && dest_code == REG && symbolic_operand (src, VOIDmode))
{
if (loongarch_classify_symbol (src) == SYMBOL_PCREL)
return "la.local\t%0,%1";
@@ -4307,6 +4570,49 @@ loongarch_memmodel_needs_release_fence (enum memmodel model)
}
}
+/* Print symbolic operand OP, which is part of a HIGH or LO_SUM
+ in context CONTEXT. HI_RELOC indicates a high-part reloc. */
+
+static void
+loongarch_print_operand_reloc (FILE *file, rtx op, bool hi_reloc)
+{
+ const char *reloc;
+
+ switch (loongarch_classify_symbolic_expression (op))
+ {
+ case SYMBOL_PCREL:
+ reloc = hi_reloc ? "%pc_hi20" : "%pc_lo12";
+ break;
+
+ case SYMBOL_GOT_DISP:
+ reloc = hi_reloc ? "%got_pc_hi20" : "%got_pc_lo12";
+ break;
+
+ case SYMBOL_TLS_IE:
+ reloc = hi_reloc ? "%ie_pc_hi20" : "%ie_pc_lo12";
+ break;
+
+ case SYMBOL_TLS_LE:
+ reloc = hi_reloc ? "%le_hi20" : "%le_lo12";
+ break;
+
+ case SYMBOL_TLSGD:
+ reloc = hi_reloc ? "%gd_pc_hi20" : "%got_pc_lo12";
+ break;
+
+ case SYMBOL_TLSLDM:
+ reloc = hi_reloc ? "%ld_pc_hi20" : "%got_pc_lo12";
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ fprintf (file, "%s(", reloc);
+ output_addr_const (file, loongarch_strip_unspec_address (op));
+ fputc (')', file);
+}
+
/* Implement TARGET_PRINT_OPERAND. The LoongArch-specific operand codes are:
'A' Print a _DB suffix if the memory model requires a release.
@@ -4315,7 +4621,10 @@ loongarch_memmodel_needs_release_fence (enum memmodel model)
'd' Print CONST_INT OP in decimal.
'F' Print the FPU branch condition for comparison OP.
'G' Print a DBAR insn if the memory model requires a release.
+ 'H' Print address 52-61bit relocation associated with OP.
+ 'h' Print the high-part relocation associated with OP.
'i' Print i if the operand is not a register.
+ 'L' Print the low-part relocation associated with OP.
'm' Print one less than CONST_INT OP in decimal.
'N' Print the inverse of the integer branch condition for comparison OP.
'T' Print 'f' for (eq:CC ...), 't' for (ne:CC ...),
@@ -4372,11 +4681,21 @@ loongarch_print_operand (FILE *file, rtx op, int letter)
fputs ("dbar\t0", file);
break;
+ case 'h':
+ if (code == HIGH)
+ op = XEXP (op, 0);
+ loongarch_print_operand_reloc (file, op, true /* hi_reloc */);
+ break;
+
case 'i':
if (code != REG)
fputs ("i", file);
break;
+ case 'L':
+ loongarch_print_operand_reloc (file, op, false /* lo_reloc */);
+ break;
+
case 'm':
if (CONST_INT_P (op))
fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (op) - 1);
@@ -4517,6 +4836,11 @@ loongarch_print_operand_address (FILE *file, machine_mode /* mode */, rtx x)
reg_names[REGNO (addr.offset)]);
return;
+ case ADDRESS_LO_SUM:
+ fprintf (file, "%s,", reg_names[REGNO (addr.reg)]);
+ loongarch_print_operand_reloc (file, addr.offset, false /* hi_reloc */);
+ return;
+
case ADDRESS_CONST_INT:
fprintf (file, "%s,", reg_names[GP_REG_FIRST]);
output_addr_const (file, x);
@@ -5891,6 +6215,12 @@ loongarch_starting_frame_offset (void)
#undef TARGET_TRAMPOLINE_INIT
#define TARGET_TRAMPOLINE_INIT loongarch_trampoline_init
+#undef TARGET_MIN_ANCHOR_OFFSET
+#define TARGET_MIN_ANCHOR_OFFSET (-IMM_REACH/2)
+
+#undef TARGET_MAX_ANCHOR_OFFSET
+#define TARGET_MAX_ANCHOR_OFFSET (IMM_REACH/2-1)
+
#undef TARGET_ATOMIC_ASSIGN_EXPAND_FENV
#define TARGET_ATOMIC_ASSIGN_EXPAND_FENV loongarch_atomic_assign_expand_fenv
diff --git a/gcc/config/loongarch/loongarch.md b/gcc/config/loongarch/loongarch.md
index 376879fbccb..6b6df22a5f1 100644
--- a/gcc/config/loongarch/loongarch.md
+++ b/gcc/config/loongarch/loongarch.md
@@ -57,6 +57,10 @@ (define_c_enum "unspec" [
;; CRC
UNSPEC_CRC
UNSPEC_CRCC
+
+ UNSPEC_LOAD_FROM_GOT
+ UNSPEC_ORI_L_LO12
+ UNSPEC_TLS_LOW
])
(define_c_enum "unspecv" [
@@ -1743,73 +1747,6 @@ (define_insn "*movdf_softfloat"
[(set_attr "move_type" "move,load,store")
(set_attr "mode" "DF")])
-
-;; 128-bit integer moves
-
-(define_expand "movti"
- [(set (match_operand:TI 0)
- (match_operand:TI 1))]
- "TARGET_64BIT"
-{
- if (loongarch_legitimize_move (TImode, operands[0], operands[1]))
- DONE;
-})
-
-(define_insn "*movti"
- [(set (match_operand:TI 0 "nonimmediate_operand" "=r,r,r,m")
- (match_operand:TI 1 "move_operand" "r,i,m,rJ"))]
- "TARGET_64BIT
- && (register_operand (operands[0], TImode)
- || reg_or_0_operand (operands[1], TImode))"
- { return loongarch_output_move (operands[0], operands[1]); }
- [(set_attr "move_type" "move,const,load,store")
- (set (attr "mode")
- (if_then_else (eq_attr "move_type" "imul")
- (const_string "SI")
- (const_string "TI")))])
-
-;; 128-bit floating point moves
-
-(define_expand "movtf"
- [(set (match_operand:TF 0)
- (match_operand:TF 1))]
- "TARGET_64BIT"
-{
- if (loongarch_legitimize_move (TFmode, operands[0], operands[1]))
- DONE;
-})
-
-;; This pattern handles both hard- and soft-float cases.
-(define_insn "*movtf"
- [(set (match_operand:TF 0 "nonimmediate_operand" "=r,r,m,f,r,f,m")
- (match_operand:TF 1 "move_operand" "rG,m,rG,rG,f,m,f"))]
- "TARGET_64BIT
- && (register_operand (operands[0], TFmode)
- || reg_or_0_operand (operands[1], TFmode))"
- "#"
- [(set_attr "move_type" "move,load,store,mgtf,mftg,fpload,fpstore")
- (set_attr "mode" "TF")])
-
-(define_split
- [(set (match_operand:MOVE64 0 "nonimmediate_operand")
- (match_operand:MOVE64 1 "move_operand"))]
- "reload_completed && loongarch_split_move_insn_p (operands[0], operands[1])"
- [(const_int 0)]
-{
- loongarch_split_move_insn (operands[0], operands[1], curr_insn);
- DONE;
-})
-
-(define_split
- [(set (match_operand:MOVE128 0 "nonimmediate_operand")
- (match_operand:MOVE128 1 "move_operand"))]
- "reload_completed && loongarch_split_move_insn_p (operands[0], operands[1])"
- [(const_int 0)]
-{
- loongarch_split_move_insn (operands[0], operands[1], curr_insn);
- DONE;
-})
-
;; Emit a doubleword move in which exactly one of the operands is
;; a floating-point register. We can't just emit two normal moves
;; because of the constraints imposed by the FPU register model;
@@ -1938,6 +1875,57 @@ (define_insn "lu52i_d"
[(set_attr "type" "arith")
(set_attr "mode" "DI")])
+;; Instructions for adding the low 12 bits of an address to a register.
+;; Operand 2 is the address: loongarch_print_operand works out which relocation
+;; should be applied.
+
+(define_insn "*low<mode>"
+ [(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>")])
+
+(define_insn "@tls_low<mode>"
+ [(set (match_operand:P 0 "register_operand" "=r")
+ (unspec:P [(mem:P (lo_sum:P (match_operand:P 1 "register_operand" "r")
+ (match_operand:P 2 "symbolic_operand" "")))]
+ UNSPEC_TLS_LOW))]
+ "TARGET_EXPLICIT_RELOCS"
+ "addi.<d>\t%0,%1,%L2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "<MODE>")])
+
+;; Instructions for loading address from GOT entry.
+;; operands[1] is pc plus the high half of the address difference with the got
+;; entry;
+;; operands[2] is low 12 bits for low 12 bit of the address difference with the
+;; got entry.
+;; loongarch_print_operand works out which relocation should be applied.
+
+(define_insn "@ld_from_got<mode>"
+ [(set (match_operand:P 0 "register_operand" "=r")
+ (unspec:P [(mem:P (lo_sum:P
+ (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")]
+)
+
+(define_insn "@ori_l_lo12<mode>"
+ [(set (match_operand:P 0 "register_operand" "=r")
+ (unspec:P [(match_operand:P 1 "register_operand" "r")
+ (match_operand:P 2 "symbolic_operand")]
+ UNSPEC_ORI_L_LO12))]
+ ""
+ "ori\t%0,%1,%L2"
+ [(set_attr "type" "move")]
+)
+
;; Convert floating-point numbers to integers
(define_insn "frint_<fmt>"
[(set (match_operand:ANYF 0 "register_operand" "=f")
diff --git a/gcc/config/loongarch/loongarch.opt b/gcc/config/loongarch/loongarch.opt
index 3ff0d860413..7a8c5b44418 100644
--- a/gcc/config/loongarch/loongarch.opt
+++ b/gcc/config/loongarch/loongarch.opt
@@ -161,6 +161,10 @@ mmax-inline-memcpy-size=
Target Joined RejectNegative UInteger Var(loongarch_max_inline_memcpy_size) Init(1024)
-mmax-inline-memcpy-size=SIZE Set the max size of memcpy to inline, default is 1024.
+mexplicit-relocs
+Target Var(TARGET_EXPLICIT_RELOCS) Init(1)
+Use %reloc() assembly operators.
+
; The code model option names for -mcmodel.
Enum
Name(cmodel) Type(int)
diff --git a/gcc/config/loongarch/predicates.md b/gcc/config/loongarch/predicates.md
index 2243ef71c1a..cd3528c7c97 100644
--- a/gcc/config/loongarch/predicates.md
+++ b/gcc/config/loongarch/predicates.md
@@ -110,6 +110,10 @@ (define_predicate "low_bitmask_operand"
(define_predicate "const_call_insn_operand"
(match_code "const,symbol_ref,label_ref")
{
+ /* Split symbol to high and low if return false.
+ If defined TARGET_CMODEL_LARGE, all symbol would be splited,
+ else if offset is not zero, the symbol would be splited. */
+
enum loongarch_symbol_type symbol_type;
loongarch_symbolic_constant_p (op, &symbol_type);
@@ -125,7 +129,7 @@ (define_predicate "const_call_insn_operand"
return 1;
case SYMBOL_GOT_DISP:
- if (!flag_plt)
+ if (TARGET_CMODEL_LARGE || !flag_plt)
return false;
else
return 1;
@@ -213,7 +217,19 @@ (define_predicate "move_operand"
case CONST:
case SYMBOL_REF:
case LABEL_REF:
- return loongarch_symbolic_constant_p (op, &symbol_type);
+ return (loongarch_symbolic_constant_p (op, &symbol_type)
+ && (!TARGET_EXPLICIT_RELOCS
+ || !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_split_symbol_type (symbol_type));
+
default:
return true;
}
diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-1.c b/gcc/testsuite/gcc.target/loongarch/func-call-1.c
index b0482761aab..01b8ea23fb9 100644
--- a/gcc/testsuite/gcc.target/loongarch/func-call-1.c
+++ b/gcc/testsuite/gcc.target/loongarch/func-call-1.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-mabi=lp64d -O0 -fpic -fplt" } */
+/* { dg-options "-mabi=lp64d -O0 -fpic -fplt -mno-explicit-relocs" } */
/* { dg-final { scan-assembler "test:.*bl\t%plt\\(g\\)\n" } } */
/* { dg-final { scan-assembler "test1:.*bl\t%plt\\(f\\)\n" } } */
/* { dg-final { scan-assembler "test2:.*bl\tl\n" } } */
diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-2.c b/gcc/testsuite/gcc.target/loongarch/func-call-2.c
index f5e061c299c..4565baaec9e 100644
--- a/gcc/testsuite/gcc.target/loongarch/func-call-2.c
+++ b/gcc/testsuite/gcc.target/loongarch/func-call-2.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-mabi=lp64d -O0 -fno-pic -fplt" } */
+/* { dg-options "-mabi=lp64d -O0 -fno-pic -fplt -mno-explicit-relocs" } */
/* { dg-final { scan-assembler "test:.*bl\t%plt\\(g\\)\n" } } */
/* { dg-final { scan-assembler "test1:.*bl\tf\n" } } */
/* { dg-final { scan-assembler "test2:.*bl\tl\n" } } */
diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-3.c b/gcc/testsuite/gcc.target/loongarch/func-call-3.c
index 75082c57466..4f669a029e7 100644
--- a/gcc/testsuite/gcc.target/loongarch/func-call-3.c
+++ b/gcc/testsuite/gcc.target/loongarch/func-call-3.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-mabi=lp64d -O0 -fpic -fno-plt" } */
+/* { dg-options "-mabi=lp64d -O0 -fpic -fno-plt -mno-explicit-relocs" } */
/* { dg-final { scan-assembler "test:.*la\.global\t.*g\n\tjirl" } } */
/* { dg-final { scan-assembler "test1:.*la\.global\t.*f\n\tjirl" } } */
/* { dg-final { scan-assembler "test2:.*bl\tl\n" } } */
diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-4.c b/gcc/testsuite/gcc.target/loongarch/func-call-4.c
index e8a8395493e..943adb6403f 100644
--- a/gcc/testsuite/gcc.target/loongarch/func-call-4.c
+++ b/gcc/testsuite/gcc.target/loongarch/func-call-4.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-mabi=lp64d -O0 -fno-pic -fno-plt" } */
+/* { dg-options "-mabi=lp64d -O0 -fno-pic -fno-plt -mno-explicit-relocs" } */
/* { dg-final { scan-assembler "test:.*la\.global\t.*g\n\tjirl" } } */
/* { dg-final { scan-assembler "test1:.*bl\tf\n" } } */
/* { dg-final { scan-assembler "test2:.*bl\tl\n" } } */
diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-5.c b/gcc/testsuite/gcc.target/loongarch/func-call-5.c
new file mode 100644
index 00000000000..2c2a1c8a1b6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/func-call-5.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-mabi=lp64d -O0 -fpic -fplt -mexplicit-relocs" } */
+/* { dg-final { scan-assembler "test:.*bl\t%plt\\(g\\)\n" } } */
+/* { dg-final { scan-assembler "test1:.*bl\t%plt\\(f\\)\n" } } */
+/* { dg-final { scan-assembler "test2:.*bl\tl\n" } } */
+
+extern void g (void);
+
+void
+f (void)
+{}
+
+static void
+l (void)
+{}
+
+void
+test (void)
+{
+ g ();
+}
+
+void
+test1 (void)
+{
+ f ();
+}
+
+void
+test2 (void)
+{
+ l ();
+}
diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-6.c b/gcc/testsuite/gcc.target/loongarch/func-call-6.c
new file mode 100644
index 00000000000..4b0e4266ec8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/func-call-6.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-mabi=lp64d -O0 -fno-pic -fplt -mexplicit-relocs" } */
+/* { dg-final { scan-assembler "test:.*bl\t%plt\\(g\\)\n" } } */
+/* { dg-final { scan-assembler "test1:.*bl\tf\n" } } */
+/* { dg-final { scan-assembler "test2:.*bl\tl\n" } } */
+
+extern void g (void);
+
+void
+f (void)
+{}
+
+static void
+l (void)
+{}
+
+void
+test (void)
+{
+ g ();
+}
+
+void
+test1 (void)
+{
+ f ();
+}
+
+void
+test2 (void)
+{
+ l ();
+}
diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-7.c b/gcc/testsuite/gcc.target/loongarch/func-call-7.c
new file mode 100644
index 00000000000..51792711f72
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/func-call-7.c
@@ -0,0 +1,34 @@
+/* { dg-do compile } */
+/* { dg-options "-mabi=lp64d -O0 -fpic -fno-plt -mexplicit-relocs" } */
+/* { dg-final { scan-assembler "test:.*pcalau12i\t.*%got_pc_hi20\\(g\\)\n\tld\.d\t.*%got_pc_lo12\\(g\\)\n\tjirl" } } */
+/* { dg-final { scan-assembler "test1:.*pcalau12i\t.*%got_pc_hi20\\(f\\)\n\tld\.d\t.*%got_pc_lo12\\(f\\)\n\tjirl" } } */
+/* { dg-final { scan-assembler "test2:.*bl\tl\n" } } */
+
+
+extern void g (void);
+
+void
+f (void)
+{}
+
+static void
+l (void)
+{}
+
+void
+test (void)
+{
+ g ();
+}
+
+void
+test1 (void)
+{
+ f ();
+}
+
+void
+test2 (void)
+{
+ l ();
+}
diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-8.c b/gcc/testsuite/gcc.target/loongarch/func-call-8.c
new file mode 100644
index 00000000000..330140d883d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/func-call-8.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-mabi=lp64d -O0 -fno-pic -fno-plt -mexplicit-relocs" } */
+/* { dg-final { scan-assembler "test:.*pcalau12i\t.*%got_pc_hi20\\(g\\)\n\tld\.d\t.*%got_pc_lo12\\(g\\)\n\tjirl" } } */
+/* { dg-final { scan-assembler "test1:.*bl\tf\n" } } */
+/* { dg-final { scan-assembler "test2:.*bl\tl\n" } } */
+
+extern void g (void);
+
+void
+f (void)
+{}
+
+static void
+l (void)
+{}
+
+void
+test (void)
+{
+ g ();
+}
+
+void
+test1 (void)
+{
+ f ();
+}
+
+void
+test2 (void)
+{
+ l ();
+}
diff --git a/gcc/testsuite/gcc.target/loongarch/relocs-symbol-noaddend.c b/gcc/testsuite/gcc.target/loongarch/relocs-symbol-noaddend.c
new file mode 100644
index 00000000000..bfcc9bc338f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/relocs-symbol-noaddend.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-mabi=lp64d -mexplicit-relocs -fno-pic -O2" } */
+/* { dg-final { scan-assembler "pcalau12i.*%pc_hi20\\(\.LANCHOR0\\)\n" } } */
+/* { dg-final { scan-assembler "addi\.d.*%pc_lo12\\(\.LANCHOR0\\)\n" } } */
+/* { dg-final { scan-assembler "ldptr.d\t\\\$r4,.*,0\n" } } */
+/* { dg-final { scan-assembler "ld.d\t\\\$r5,.*,8\n" } } */
+/* { dg-final { scan-assembler-not "\.LANCHOR0+8" } } */
+
+
+struct S
+{
+ char *a;
+ unsigned short int b;
+};
+
+struct S s1;
+
+void test(struct S);
+void test1(void)
+{
+ test(s1);
+}
+
--
2.31.1
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v2 3/3] LoongArch: Modify the definition of the ASM_PREFERRED_EH_DATA_FORMAT macro.
2022-07-21 6:41 [PATCH v2 0/3] LoongArch: Modify the method of obtaining symbolic addresses Lulu Cheng
2022-07-21 6:41 ` [PATCH v2 1/3] LoongArch: Subdivision symbol type, add SYMBOL_PCREL support Lulu Cheng
2022-07-21 6:41 ` [PATCH v2 2/3] LoongArch: Support split symbol Lulu Cheng
@ 2022-07-21 6:41 ` Lulu Cheng
2 siblings, 0 replies; 4+ messages in thread
From: Lulu Cheng @ 2022-07-21 6:41 UTC (permalink / raw)
To: gcc-patches; +Cc: xry111, i, xuchenghua, Lulu Cheng
Some R_LARCH_64 in section .eh_frame will to generate R_LARCH_NONE, we
change relocation to R_LARCH_32_PCREL from R_LARCH_64 in setction .eh_frame
and not generate dynamic relocation for R_LARCH_32_PCREL.
gcc/ChangeLog:
* config/loongarch/loongarch.h (ASM_PREFERRED_EH_DATA_FORMAT):
Modify the definition of the ASM_PREFERRED_EH_DATA_FORMAT macro.
---
gcc/config/loongarch/loongarch.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/gcc/config/loongarch/loongarch.h b/gcc/config/loongarch/loongarch.h
index 89a5bd728fe..222b58b838d 100644
--- a/gcc/config/loongarch/loongarch.h
+++ b/gcc/config/loongarch/loongarch.h
@@ -1128,7 +1128,7 @@ struct GTY (()) machine_function
#endif
#define ASM_PREFERRED_EH_DATA_FORMAT(CODE, GLOBAL) \
- (((GLOBAL) ? DW_EH_PE_indirect : 0) | DW_EH_PE_absptr)
+ (((GLOBAL) ? DW_EH_PE_indirect : 0) | DW_EH_PE_pcrel | DW_EH_PE_sdata4)
/* Do emit .note.GNU-stack by default. */
#ifndef NEED_INDICATE_EXEC_STACK
--
2.31.1
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2022-07-21 6:43 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-07-21 6:41 [PATCH v2 0/3] LoongArch: Modify the method of obtaining symbolic addresses Lulu Cheng
2022-07-21 6:41 ` [PATCH v2 1/3] LoongArch: Subdivision symbol type, add SYMBOL_PCREL support Lulu Cheng
2022-07-21 6:41 ` [PATCH v2 2/3] LoongArch: Support split symbol Lulu Cheng
2022-07-21 6:41 ` [PATCH v2 3/3] LoongArch: Modify the definition of the ASM_PREFERRED_EH_DATA_FORMAT macro Lulu Cheng
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).