diff options
Diffstat (limited to 'gcc/config')
-rw-r--r-- | gcc/config/loongarch/constraints.md | 24 | ||||
-rw-r--r-- | gcc/config/loongarch/loongarch-opts.cc | 7 | ||||
-rw-r--r-- | gcc/config/loongarch/loongarch-protos.h | 9 | ||||
-rw-r--r-- | gcc/config/loongarch/loongarch.cc | 256 | ||||
-rw-r--r-- | gcc/config/loongarch/loongarch.h | 2 | ||||
-rw-r--r-- | gcc/config/loongarch/loongarch.md | 279 | ||||
-rw-r--r-- | gcc/config/loongarch/predicates.md | 40 |
7 files changed, 184 insertions, 433 deletions
diff --git a/gcc/config/loongarch/constraints.md b/gcc/config/loongarch/constraints.md index d0bfddb..43cb7b5 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 eb9c2a5..fc477bf 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 2287fd37..0807662 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 8b0d7f4..1cb5742 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 f9de9a6..89a5bd7 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 5c0445d..376879f 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 edd74d47..2243ef7 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; } |