From patchwork Thu Jul 21 06:41:21 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lulu Cheng X-Patchwork-Id: 56209 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id EB7743850226 for ; Thu, 21 Jul 2022 06:43:41 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from loongson.cn (mail.loongson.cn [114.242.206.163]) by sourceware.org (Postfix) with ESMTP id 30F653857366 for ; Thu, 21 Jul 2022 06:43:19 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 30F653857366 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=loongson.cn Received: from 5.5.5 (unknown [10.2.5.5]) by mail.loongson.cn (Coremail) with SMTP id AQAAf9Dxf9N+9dhiwgssAA--.40495S3; Thu, 21 Jul 2022 14:43:17 +0800 (CST) From: Lulu Cheng To: gcc-patches@gcc.gnu.org Subject: [PATCH v2 1/3] LoongArch: Subdivision symbol type, add SYMBOL_PCREL support. Date: Thu, 21 Jul 2022 14:41:21 +0800 Message-Id: <20220721064123.2981805-2-chenglulu@loongson.cn> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20220721064123.2981805-1-chenglulu@loongson.cn> References: <20220721064123.2981805-1-chenglulu@loongson.cn> MIME-Version: 1.0 X-CM-TRANSID: AQAAf9Dxf9N+9dhiwgssAA--.40495S3 X-Coremail-Antispam: 1UD129KBjvAXoWfAr1rKrW5GFWrCF15JrWkJFb_yoWrJw1fto WFyF4kAF1rGryUK39akFnxXFyDZFyjy3yfAasxA3Z09a1ktrW5trWxKa13Z3y3Xr97XrWU Xa4vga93Aas7JFs7n29KB7ZKAUJUUUU5529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjp_UUUYA7AC8VAFwI0_Gr0_Xr1l1xkIjI8I6I8E6xAIw20EY4v20xva j40_Wr0E3s1l1IIY67AEw4v_Jr0_Jr4l82xGYIkIc2x26280x7IE14v26r18M28IrcIa0x kI8VCY1x0267AKxVWUXVWUCwA2ocxC64kIII0Yj41l84x0c7CEw4AK67xGY2AK021l84AC jcxK6xIIjxv20xvE14v26F1j6w1UM28EF7xvwVC0I7IYx2IY6xkF7I0E14v26F4j6r4UJw A2z4x0Y4vEx4A2jsIE14v26F4UJVW0owA2z4x0Y4vEx4A2jsIEc7CjxVAFwI0_GcCE3s1l e2I262IYc4CY6c8Ij28IcVAaY2xG8wAqx4xG64xvF2IEw4CE5I8CrVC2j2WlYx0E2Ix0cI 8IcVAFwI0_Jrv_JF1lYx0Ex4A2jsIE14v26r1j6r4UMcvjeVCFs4IE7xkEbVWUJVW8JwAC jcxG0xvY0x0EwIxGrwACjI8F5VA0II8E6IAqYI8I648v4I1lc2xSY4AK6svPMxAIw28Icx kI7VAKI48JMxC20s026xCaFVCjc4AY6r1j6r4UMI8I3I0E5I8CrVAFwI0_Jr0_Jr4lx2Iq xVCjr7xvwVAFwI0_JrI_JrWlx4CE17CEb7AF67AKxVWUAVWUtwCIc40Y0x0EwIxGrwCI42 IY6xIIjxv20xvE14v26r1I6r4UMIIF0xvE2Ix0cI8IcVCY1x0267AKxVW8JVWxJwCI42IY 6xAIw20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAFwI0_Jr0_Gr1lIxAIcVC2z280aV CY1x0267AKxVW8JVW8JrUvcSsGvfC2KfnxnUUI43ZEXa7VUbKii3UUUUU== X-CM-SenderInfo: xfkh0wpoxo3qxorr0wxvrqhubq/ X-Spam-Status: No, score=-12.3 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, KAM_SHORT, KAM_STOCKGEN, SPF_HELO_PASS, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: xuchenghua@loongson.cn, Lulu Cheng , i@xen0n.name Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" 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 (); +}