1235 lines
38 KiB
Diff
1235 lines
38 KiB
Diff
From 68bb2a2d0b94b9bde3c22ff1dfe08abb6f036e7f Mon Sep 17 00:00:00 2001
|
|
From: Lulu Cheng <chenglulu@loongson.cn>
|
|
Date: Thu, 21 Jul 2022 10:32:51 +0800
|
|
Subject: [PATCH 003/124] LoongArch: Subdivision symbol type, add SYMBOL_PCREL
|
|
support.
|
|
|
|
1. Remove cModel type support other than normal.
|
|
2. The method for calling global functions changed from 'la.global + jirl' to 'bl'
|
|
when complied add '-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-opts.cc (loongarch_config_target):
|
|
Remove cModel type support other than normal.
|
|
* 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.
|
|
|
|
Signed-off-by: Peng Fan <fanpeng@loongson.cn>
|
|
Signed-off-by: ticat_fp <fanpeng@loongson.cn>
|
|
---
|
|
gcc/config/loongarch/constraints.md | 24 +-
|
|
gcc/config/loongarch/loongarch-opts.cc | 7 +
|
|
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 ++
|
|
11 files changed, 312 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 d0bfddbd5..43cb7b5f0 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 "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_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-opts.cc b/gcc/config/loongarch/loongarch-opts.cc
|
|
index eb9c2a52f..fc477bfd4 100644
|
|
--- a/gcc/config/loongarch/loongarch-opts.cc
|
|
+++ b/gcc/config/loongarch/loongarch-opts.cc
|
|
@@ -376,6 +376,13 @@ fallback:
|
|
|
|
/* 5. Target code model */
|
|
t.cmodel = constrained.cmodel ? opt_cmodel : CMODEL_NORMAL;
|
|
+ if (t.cmodel != CMODEL_NORMAL)
|
|
+ {
|
|
+ warning (0, "%qs is not supported, now cmodel is set to 'normal'.",
|
|
+ loongarch_cmodel_strings[t.cmodel]);
|
|
+ t.cmodel = CMODEL_NORMAL;
|
|
+ }
|
|
+
|
|
|
|
/* Cleanup and return. */
|
|
obstack_free (&msg_obstack, NULL);
|
|
diff --git a/gcc/config/loongarch/loongarch-protos.h b/gcc/config/loongarch/loongarch-protos.h
|
|
index 2287fd376..080766250 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 750d53bbe..2e2f16e72 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 714401f2d..12f209047 100644
|
|
--- a/gcc/config/loongarch/loongarch.h
|
|
+++ b/gcc/config/loongarch/loongarch.h
|
|
@@ -617,7 +617,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 5c0445dd8..376879fbc 100644
|
|
--- a/gcc/config/loongarch/loongarch.md
|
|
+++ b/gcc/config/loongarch/loongarch.md
|
|
@@ -2844,48 +2844,14 @@
|
|
})
|
|
|
|
(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_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_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_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 edd74d478..2243ef71c 100644
|
|
--- a/gcc/config/loongarch/predicates.md
|
|
+++ b/gcc/config/loongarch/predicates.md
|
|
@@ -111,20 +111,25 @@
|
|
(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 @@
|
|
(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 @@
|
|
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 000000000..b0482761a
|
|
--- /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 000000000..f5e061c29
|
|
--- /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 000000000..75082c574
|
|
--- /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 000000000..e8a839549
|
|
--- /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.33.0
|
|
|