From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from loongson.cn (mail.loongson.cn [114.242.206.163]) by sourceware.org (Postfix) with ESMTP id 70B123857C44 for ; Sat, 20 Aug 2022 09:04:40 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 70B123857C44 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 localhost.localdomain (Coremail) with SMTP id AQAAf8CxkOCiowBjlOgFAA--.27280S2; Sat, 20 Aug 2022 17:04:38 +0800 (CST) From: Lulu Cheng To: gcc-patches@gcc.gnu.org Cc: xry111@xry111.site, i@xen0n.name, xuchenghua@loongson.cn, Lulu Cheng Subject: [PATCH v1] LoongArch: Add new code model 'emdium'. Date: Sat, 20 Aug 2022 17:04:26 +0800 Message-Id: <20220820090425.525292-1-chenglulu@loongson.cn> X-Mailer: git-send-email 2.31.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-CM-TRANSID: AQAAf8CxkOCiowBjlOgFAA--.27280S2 X-Coremail-Antispam: 1UD129KBjvAXoWfWF4kCr18KryfXw1UKF45Wrg_yoW5ury3to WrAF4DWw18GrySkw4qkrnxXry5Ary0yr4xAa9Ivw1ruF4kA345AryxKa15Zry3JF97XrWY kFykZa9rA3s7Gwn8n29KB7ZKAUJUUUUU529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjp_UUUYe7AC8VAFwI0_Jr0_Gr1l1xkIjI8I6I8E6xAIw20EY4v20xva j40_Wr0E3s1l1IIY67AEw4v_Jr0_Jr4l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0rcxSw2 x7M28EF7xvwVC0I7IYx2IY67AKxVW8JVW5JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267AKxVW8 JVWxJwA2z4x0Y4vEx4A2jsIE14v26r4UJVWxJr1l84ACjcxK6I8E87Iv6xkF7I0E14v26r 4UJVWxJr1le2I262IYc4CY6c8Ij28IcVAaY2xG8wAqx4xG64xvF2IEw4CE5I8CrVC2j2Wl Yx0E2Ix0cI8IcVAFwI0_Jr0_Jr4lYx0Ex4A2jsIE14v26r1j6r4UMcvjeVCFs4IE7xkEbV WUJVW8JwACjcxG0xvY0x0EwIxGrwACjI8F5VA0II8E6IAqYI8I648v4I1lc2xSY4AK6svP MxAIw28IcxkI7VAKI48JMxC20s026xCaFVCjc4AY6r1j6r4UMI8I3I0E5I8CrVAFwI0_Jr 0_Jr4lx2IqxVCjr7xvwVAFwI0_JrI_JrWlx4CE17CEb7AF67AKxVWUAVWUtwCIc40Y0x0E wIxGrwCI42IY6xIIjxv20xvE14v26r1j6r1xMIIF0xvE2Ix0cI8IcVCY1x0267AKxVWUJV W8JwCI42IY6xAIw20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAFwI0_Jr0_Gr1lIxAI cVC2z280aVCY1x0267AKxVW8JVW8JrUvcSsGvfC2KfnxnUUI43ZEXa7VUbrMaUUUUUU== X-CM-SenderInfo: xfkh0wpoxo3qxorr0wxvrqhubq/ X-Spam-Status: No, score=-11.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, KAM_SHORT, KAM_STOCKGEN, SPF_HELO_PASS, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE 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: , X-List-Received-Date: Sat, 20 Aug 2022 09:04:50 -0000 The function jump instruction in normal mode is 'bl', so the scope of the function jump is +-128MB. Now we've added support for 'medium' mode, this mode is to complete the function jump through two instructions: pcalau12i + jirl So in this mode the function jump range is increased to +-2GB. Compared with 'normal' mode, 'medium' mode only affects the jump range of functions. gcc/ChangeLog: * config/loongarch/genopts/loongarch-strings: Support code model medium. * config/loongarch/genopts/loongarch.opt.in: Likewise. * config/loongarch/loongarch-def.c: Likewise. * config/loongarch/loongarch-def.h (CMODEL_LARGE): Likewise. (CMODEL_EXTREME): Likewise. (N_CMODEL_TYPES): Likewise. (CMODEL_MEDIUM): Likewise. * config/loongarch/loongarch-opts.cc: Likewise. * config/loongarch/loongarch-opts.h (TARGET_CMODEL_MEDIUM): Likewise. * config/loongarch/loongarch-str.h (STR_CMODEL_MEDIUM): Likewise. * config/loongarch/loongarch.cc (loongarch_call_tls_get_addr): Tls symbol Loading support medium mode. (loongarch_legitimize_call_address): When medium mode, make a symbolic jump with two instructions. (loongarch_option_override_internal): Support medium. * config/loongarch/loongarch.md (@pcalau12i): New template. (@sibcall_internal_1): New function call templates added to support medium mode. (@sibcall_value_internal_1): Likewise. (@sibcall_value_multiple_internal_1): Likewise. (@call_internal_1): Likewise. (@call_value_internal_1): Likewise. (@call_value_multiple_internal_1): Likewise. * config/loongarch/loongarch.opt: Support medium. * config/loongarch/predicates.md: Add processing about medium mode. * doc/invoke.texi: Document for '-mcmodel=medium'. gcc/testsuite/ChangeLog: * gcc.target/loongarch/func-call-medium-1.c: New test. * gcc.target/loongarch/func-call-medium-2.c: New test. * gcc.target/loongarch/func-call-medium-3.c: New test. * gcc.target/loongarch/func-call-medium-4.c: New test. * gcc.target/loongarch/func-call-medium-5.c: New test. * gcc.target/loongarch/func-call-medium-6.c: New test. * gcc.target/loongarch/func-call-medium-7.c: New test. * gcc.target/loongarch/func-call-medium-8.c: New test. * gcc.target/loongarch/tls-gd-noplt.c: Add compile parameter '-mexplicit-relocs'. --- .../loongarch/genopts/loongarch-strings | 1 + gcc/config/loongarch/genopts/loongarch.opt.in | 3 + gcc/config/loongarch/loongarch-def.c | 1 + gcc/config/loongarch/loongarch-def.h | 7 +- gcc/config/loongarch/loongarch-opts.cc | 15 ++- gcc/config/loongarch/loongarch-opts.h | 1 + gcc/config/loongarch/loongarch-str.h | 1 + gcc/config/loongarch/loongarch.cc | 123 +++++++++++++---- gcc/config/loongarch/loongarch.md | 125 +++++++++++++++++- gcc/config/loongarch/loongarch.opt | 3 + gcc/config/loongarch/predicates.md | 15 ++- gcc/doc/invoke.texi | 3 + .../gcc.target/loongarch/func-call-medium-1.c | 41 ++++++ .../gcc.target/loongarch/func-call-medium-2.c | 41 ++++++ .../gcc.target/loongarch/func-call-medium-3.c | 41 ++++++ .../gcc.target/loongarch/func-call-medium-4.c | 41 ++++++ .../gcc.target/loongarch/func-call-medium-5.c | 42 ++++++ .../gcc.target/loongarch/func-call-medium-6.c | 42 ++++++ .../gcc.target/loongarch/func-call-medium-7.c | 43 ++++++ .../gcc.target/loongarch/func-call-medium-8.c | 42 ++++++ .../gcc.target/loongarch/tls-gd-noplt.c | 4 +- 21 files changed, 595 insertions(+), 40 deletions(-) create mode 100644 gcc/testsuite/gcc.target/loongarch/func-call-medium-1.c create mode 100644 gcc/testsuite/gcc.target/loongarch/func-call-medium-2.c create mode 100644 gcc/testsuite/gcc.target/loongarch/func-call-medium-3.c create mode 100644 gcc/testsuite/gcc.target/loongarch/func-call-medium-4.c create mode 100644 gcc/testsuite/gcc.target/loongarch/func-call-medium-5.c create mode 100644 gcc/testsuite/gcc.target/loongarch/func-call-medium-6.c create mode 100644 gcc/testsuite/gcc.target/loongarch/func-call-medium-7.c create mode 100644 gcc/testsuite/gcc.target/loongarch/func-call-medium-8.c diff --git a/gcc/config/loongarch/genopts/loongarch-strings b/gcc/config/loongarch/genopts/loongarch-strings index cb88ed56b68..44ebb7ab10b 100644 --- a/gcc/config/loongarch/genopts/loongarch-strings +++ b/gcc/config/loongarch/genopts/loongarch-strings @@ -54,5 +54,6 @@ OPTSTR_CMODEL cmodel STR_CMODEL_NORMAL normal STR_CMODEL_TINY tiny STR_CMODEL_TS tiny-static +STR_CMODEL_MEDIUM medium STR_CMODEL_LARGE large STR_CMODEL_EXTREME extreme diff --git a/gcc/config/loongarch/genopts/loongarch.opt.in b/gcc/config/loongarch/genopts/loongarch.opt.in index a571b6b7524..ebdd9538d48 100644 --- a/gcc/config/loongarch/genopts/loongarch.opt.in +++ b/gcc/config/loongarch/genopts/loongarch.opt.in @@ -172,6 +172,9 @@ Enum(cmodel) String(@@STR_CMODEL_TINY@@) Value(CMODEL_TINY) EnumValue Enum(cmodel) String(@@STR_CMODEL_TS@@) Value(CMODEL_TINY_STATIC) +EnumValue +Enum(cmodel) String(@@STR_CMODEL_MEDIUM@@) Value(CMODEL_MEDIUM) + EnumValue Enum(cmodel) String(@@STR_CMODEL_LARGE@@) Value(CMODEL_LARGE) diff --git a/gcc/config/loongarch/loongarch-def.c b/gcc/config/loongarch/loongarch-def.c index c8769b7d65e..cbf995d81b5 100644 --- a/gcc/config/loongarch/loongarch-def.c +++ b/gcc/config/loongarch/loongarch-def.c @@ -152,6 +152,7 @@ loongarch_cmodel_strings[] = { [CMODEL_NORMAL] = STR_CMODEL_NORMAL, [CMODEL_TINY] = STR_CMODEL_TINY, [CMODEL_TINY_STATIC] = STR_CMODEL_TS, + [CMODEL_MEDIUM] = STR_CMODEL_MEDIUM, [CMODEL_LARGE] = STR_CMODEL_LARGE, [CMODEL_EXTREME] = STR_CMODEL_EXTREME, }; diff --git a/gcc/config/loongarch/loongarch-def.h b/gcc/config/loongarch/loongarch-def.h index c2c35b6ba5c..b5985f07052 100644 --- a/gcc/config/loongarch/loongarch-def.h +++ b/gcc/config/loongarch/loongarch-def.h @@ -82,9 +82,10 @@ extern const char* loongarch_cmodel_strings[]; #define CMODEL_NORMAL 0 #define CMODEL_TINY 1 #define CMODEL_TINY_STATIC 2 -#define CMODEL_LARGE 3 -#define CMODEL_EXTREME 4 -#define N_CMODEL_TYPES 5 +#define CMODEL_MEDIUM 3 +#define CMODEL_LARGE 4 +#define CMODEL_EXTREME 5 +#define N_CMODEL_TYPES 6 /* enum switches */ /* The "SW_" codes represent command-line switches (options that diff --git a/gcc/config/loongarch/loongarch-opts.cc b/gcc/config/loongarch/loongarch-opts.cc index 2ae89f23443..e13eafb5882 100644 --- a/gcc/config/loongarch/loongarch-opts.cc +++ b/gcc/config/loongarch/loongarch-opts.cc @@ -376,11 +376,24 @@ fallback: /* 5. Target code model */ t.cmodel = constrained.cmodel ? opt_cmodel : CMODEL_NORMAL; - if (t.cmodel != CMODEL_NORMAL && t.cmodel != CMODEL_EXTREME) + + switch (t.cmodel) { + case CMODEL_TINY: + case CMODEL_TINY_STATIC: + case CMODEL_LARGE: warning (0, "%qs is not supported, now cmodel is set to %qs", loongarch_cmodel_strings[t.cmodel], "normal"); t.cmodel = CMODEL_NORMAL; + break; + + case CMODEL_NORMAL: + case CMODEL_MEDIUM: + case CMODEL_EXTREME: + break; + + default: + gcc_unreachable (); } /* Cleanup and return. */ diff --git a/gcc/config/loongarch/loongarch-opts.h b/gcc/config/loongarch/loongarch-opts.h index da24ecd2b50..3523a4cf78d 100644 --- a/gcc/config/loongarch/loongarch-opts.h +++ b/gcc/config/loongarch/loongarch-opts.h @@ -46,6 +46,7 @@ loongarch_config_target (struct loongarch_target *target, #define TARGET_CMODEL_NORMAL (la_target.cmodel == CMODEL_NORMAL) #define TARGET_CMODEL_TINY (la_target.cmodel == CMODEL_TINY) #define TARGET_CMODEL_TINY_STATIC (la_target.cmodel == CMODEL_TINY_STATIC) +#define TARGET_CMODEL_MEDIUM (la_target.cmodel == CMODEL_MEDIUM) #define TARGET_CMODEL_LARGE (la_target.cmodel == CMODEL_LARGE) #define TARGET_CMODEL_EXTREME (la_target.cmodel == CMODEL_EXTREME) diff --git a/gcc/config/loongarch/loongarch-str.h b/gcc/config/loongarch/loongarch-str.h index 0e8889b8c96..9f1b0989c82 100644 --- a/gcc/config/loongarch/loongarch-str.h +++ b/gcc/config/loongarch/loongarch-str.h @@ -53,6 +53,7 @@ along with GCC; see the file COPYING3. If not see #define STR_CMODEL_NORMAL "normal" #define STR_CMODEL_TINY "tiny" #define STR_CMODEL_TS "tiny-static" +#define STR_CMODEL_MEDIUM "medium" #define STR_CMODEL_LARGE "large" #define STR_CMODEL_EXTREME "extreme" diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc index 207ac2762c6..16fd4acc970 100644 --- a/gcc/config/loongarch/loongarch.cc +++ b/gcc/config/loongarch/loongarch.cc @@ -2461,44 +2461,96 @@ loongarch_call_tls_get_addr (rtx sym, enum loongarch_symbol_type type, rtx v0) } if (flag_plt) - insn = emit_call_insn (gen_call_value_internal (v0, - loongarch_tls_symbol, - const0_rtx)); - else { - rtx dest = gen_reg_rtx (Pmode); - - if (TARGET_CMODEL_EXTREME) + switch (la_opt_cmodel) { - gcc_assert (TARGET_EXPLICIT_RELOCS); + case CMODEL_NORMAL: + insn = emit_call_insn (gen_call_value_internal (v0, + loongarch_tls_symbol, + const0_rtx)); + break; - rtx tmp1 = gen_reg_rtx (Pmode); - rtx high = gen_reg_rtx (Pmode); + case CMODEL_MEDIUM: + { + rtx reg = gen_reg_rtx (Pmode); + if (TARGET_EXPLICIT_RELOCS) + { + emit_insn (gen_pcalau12i (Pmode, reg, loongarch_tls_symbol)); + rtx call = gen_call_value_internal_1 (Pmode, v0, reg, + loongarch_tls_symbol, + const0_rtx); + insn = emit_call_insn (call); + } + else + { + emit_move_insn (reg, loongarch_tls_symbol); + insn = emit_call_insn (gen_call_value_internal (v0, + reg, + const0_rtx)); + } + break; + } - loongarch_emit_move (high, - gen_rtx_HIGH (Pmode, loongarch_tls_symbol)); - loongarch_emit_move (tmp1, gen_rtx_LO_SUM (Pmode, - gen_rtx_REG (Pmode, 0), - loongarch_tls_symbol)); - emit_insn (gen_lui_h_lo20 (tmp1, tmp1, loongarch_tls_symbol)); - emit_insn (gen_lui_h_hi12 (tmp1, tmp1, loongarch_tls_symbol)); - loongarch_emit_move (dest, - gen_rtx_MEM (Pmode, - gen_rtx_PLUS (Pmode, high, tmp1))); + /* code model extreme not support plt. */ + case CMODEL_EXTREME: + case CMODEL_LARGE: + case CMODEL_TINY: + case CMODEL_TINY_STATIC: + default: + gcc_unreachable (); } - else + } + else + { + rtx dest = gen_reg_rtx (Pmode); + + switch (la_opt_cmodel) { - if (TARGET_EXPLICIT_RELOCS) + case CMODEL_NORMAL: + case CMODEL_MEDIUM: + { + if (TARGET_EXPLICIT_RELOCS) + { + rtx high = gen_reg_rtx (Pmode); + loongarch_emit_move (high, + gen_rtx_HIGH (Pmode, + loongarch_tls_symbol)); + emit_insn (gen_ld_from_got (Pmode, dest, high, + loongarch_tls_symbol)); + } + else + loongarch_emit_move (dest, loongarch_tls_symbol); + break; + } + + case CMODEL_EXTREME: { + gcc_assert (TARGET_EXPLICIT_RELOCS); + + rtx tmp1 = gen_reg_rtx (Pmode); rtx high = gen_reg_rtx (Pmode); + loongarch_emit_move (high, gen_rtx_HIGH (Pmode, loongarch_tls_symbol)); - emit_insn (gen_ld_from_got (Pmode, dest, high, - loongarch_tls_symbol)); + loongarch_emit_move (tmp1, gen_rtx_LO_SUM (Pmode, + gen_rtx_REG (Pmode, 0), + loongarch_tls_symbol)); + emit_insn (gen_lui_h_lo20 (tmp1, tmp1, loongarch_tls_symbol)); + emit_insn (gen_lui_h_hi12 (tmp1, tmp1, loongarch_tls_symbol)); + loongarch_emit_move (dest, + gen_rtx_MEM (Pmode, + gen_rtx_PLUS (Pmode, + high, tmp1))); } - else - loongarch_emit_move (dest, loongarch_tls_symbol); + break; + + case CMODEL_LARGE: + case CMODEL_TINY: + case CMODEL_TINY_STATIC: + default: + gcc_unreachable (); } + insn = emit_call_insn (gen_call_value_internal (v0, dest, const0_rtx)); } @@ -2618,6 +2670,24 @@ loongarch_legitimize_call_address (rtx addr) loongarch_emit_move (reg, addr); return reg; } + + enum loongarch_symbol_type symbol_type = loongarch_classify_symbol (addr); + + /* Split function call insn 'bl sym' or 'bl %plt(sym)' to : + pcalau12i $rd, %pc_hi20(sym) + jr $rd, %pc_lo12(sym). */ + + if (TARGET_CMODEL_MEDIUM + && TARGET_EXPLICIT_RELOCS + && (SYMBOL_REF_P (addr) || LABEL_REF_P (addr)) + && (symbol_type == SYMBOL_PCREL + || (symbol_type == SYMBOL_GOT_DISP && flag_plt))) + { + rtx reg = gen_reg_rtx (Pmode); + emit_insn (gen_pcalau12i (Pmode, reg, addr)); + return gen_rtx_LO_SUM (Pmode, reg, addr); + } + return addr; } @@ -5996,6 +6066,7 @@ loongarch_option_override_internal (struct gcc_options *opts) break; case CMODEL_TINY_STATIC: + case CMODEL_MEDIUM: case CMODEL_NORMAL: case CMODEL_TINY: case CMODEL_LARGE: diff --git a/gcc/config/loongarch/loongarch.md b/gcc/config/loongarch/loongarch.md index 8fc10444c2a..3787fd8230f 100644 --- a/gcc/config/loongarch/loongarch.md +++ b/gcc/config/loongarch/loongarch.md @@ -59,11 +59,15 @@ (define_c_enum "unspec" [ UNSPEC_CRCC UNSPEC_LOAD_FROM_GOT + UNSPEC_PCALAU12I UNSPEC_ORI_L_LO12 UNSPEC_LUI_L_HI20 UNSPEC_LUI_H_LO20 UNSPEC_LUI_H_HI12 UNSPEC_TLS_LOW + + UNSPEC_SIBCALL_VALUE_MULTIPLE_INTERNAL_1 + UNSPEC_CALL_VALUE_MULTIPLE_INTERNAL_1 ]) (define_c_enum "unspecv" [ @@ -1946,6 +1950,14 @@ (define_insn "@lui_l_hi20" [(set_attr "type" "move")] ) +(define_insn "@pcalau12i" + [(set (match_operand:P 0 "register_operand" "=j") + (unspec:P [(match_operand:P 1 "symbolic_operand" "")] + UNSPEC_PCALAU12I))] + "" + "pcalau12i\t%0,%%pc_hi20(%1)" + [(set_attr "type" "move")]) + (define_insn "@ori_l_lo12" [(set (match_operand:P 0 "register_operand" "=r") (unspec:P [(match_operand:P 1 "register_operand" "r") @@ -2877,7 +2889,12 @@ (define_expand "sibcall" { rtx target = loongarch_legitimize_call_address (XEXP (operands[0], 0)); - emit_call_insn (gen_sibcall_internal (target, operands[1])); + if (GET_CODE (target) == LO_SUM) + emit_call_insn (gen_sibcall_internal_1 (Pmode, XEXP (target, 0), + XEXP (target, 1), + operands[1])); + else + emit_call_insn (gen_sibcall_internal (target, operands[1])); DONE; }) @@ -2891,6 +2908,14 @@ (define_insn "sibcall_internal" b\t%%plt(%0)" [(set_attr "jirl" "indirect,direct,direct")]) +(define_insn "@sibcall_internal_1" + [(call (mem:P (lo_sum:P (match_operand:P 0 "register_operand" "j") + (match_operand:P 1 "symbolic_operand" ""))) + (match_operand 2 "" ""))] + "SIBLING_CALL_P (insn) && TARGET_CMODEL_MEDIUM" + "jirl\t$r0,%0,%%pc_lo12(%1)" + [(set_attr "jirl" "indirect")]) + (define_expand "sibcall_value" [(parallel [(set (match_operand 0 "") (call (match_operand 1 "") @@ -2906,7 +2931,14 @@ (define_expand "sibcall_value" rtx arg1 = XEXP (XVECEXP (operands[0],0, 0), 0); rtx arg2 = XEXP (XVECEXP (operands[0],0, 1), 0); - emit_call_insn (gen_sibcall_value_multiple_internal (arg1, target, + if (GET_CODE (target) == LO_SUM) + emit_call_insn (gen_sibcall_value_multiple_internal_1 (Pmode, arg1, + XEXP (target, 0), + XEXP (target, 1), + operands[2], + arg2)); + else + emit_call_insn (gen_sibcall_value_multiple_internal (arg1, target, operands[2], arg2)); } @@ -2916,7 +2948,13 @@ (define_expand "sibcall_value" if (GET_CODE (operands[0]) == PARALLEL && XVECLEN (operands[0], 0) == 1) operands[0] = XEXP (XVECEXP (operands[0], 0, 0), 0); - emit_call_insn (gen_sibcall_value_internal (operands[0], target, + if (GET_CODE (target) == LO_SUM) + emit_call_insn (gen_sibcall_value_internal_1 (Pmode, operands[0], + XEXP (target, 0), + XEXP (target, 1), + operands[2])); + else + emit_call_insn (gen_sibcall_value_internal (operands[0], target, operands[2])); } DONE; @@ -2933,6 +2971,15 @@ (define_insn "sibcall_value_internal" b\t%%plt(%1)" [(set_attr "jirl" "indirect,direct,direct")]) +(define_insn "@sibcall_value_internal_1" + [(set (match_operand 0 "register_operand" "") + (call (mem:P (lo_sum:P (match_operand:P 1 "register_operand" "j") + (match_operand:P 2 "symbolic_operand" ""))) + (match_operand 3 "" "")))] + "SIBLING_CALL_P (insn) && TARGET_CMODEL_MEDIUM" + "jirl\t$r0,%1,%%pc_lo12(%2)" + [(set_attr "jirl" "indirect")]) + (define_insn "sibcall_value_multiple_internal" [(set (match_operand 0 "register_operand" "") (call (mem:SI (match_operand 1 "call_insn_operand" "j,c,b")) @@ -2947,6 +2994,21 @@ (define_insn "sibcall_value_multiple_internal" b\t%%plt(%1)" [(set_attr "jirl" "indirect,direct,direct")]) +(define_insn "@sibcall_value_multiple_internal_1" + [(set (match_operand 0 "register_operand" "") + (call (mem:P (unspec:P [(match_operand:P 1 "register_operand" "j") + (match_operand:P 2 "symbolic_operand" "")] + UNSPEC_SIBCALL_VALUE_MULTIPLE_INTERNAL_1)) + (match_operand 3 "" ""))) + (set (match_operand 4 "register_operand" "") + (call (mem:P (unspec:P [(match_dup 1) + (match_dup 2)] + UNSPEC_SIBCALL_VALUE_MULTIPLE_INTERNAL_1)) + (match_dup 3)))] + "SIBLING_CALL_P (insn) && TARGET_CMODEL_MEDIUM" + "jirl\t$r0,%1,%%pc_lo12(%2)" + [(set_attr "jirl" "indirect")]) + (define_expand "call" [(parallel [(call (match_operand 0 "") (match_operand 1 "")) @@ -2956,7 +3018,11 @@ (define_expand "call" { rtx target = loongarch_legitimize_call_address (XEXP (operands[0], 0)); - emit_call_insn (gen_call_internal (target, operands[1])); + if (GET_CODE (target) == LO_SUM) + emit_call_insn (gen_call_internal_1 (Pmode, XEXP (target, 0), + XEXP (target, 1), operands[1])); + else + emit_call_insn (gen_call_internal (target, operands[1])); DONE; }) @@ -2971,6 +3037,15 @@ (define_insn "call_internal" bl\t%%plt(%0)" [(set_attr "jirl" "indirect,direct,direct")]) +(define_insn "@call_internal_1" + [(call (mem:P (lo_sum:P (match_operand:P 0 "register_operand" "j") + (match_operand:P 1 "symbolic_operand" ""))) + (match_operand 2 "" "")) + (clobber (reg:SI RETURN_ADDR_REGNUM))] + "TARGET_CMODEL_MEDIUM" + "jirl\t$r1,%0,%%pc_lo12(%1)" + [(set_attr "jirl" "indirect")]) + (define_expand "call_value" [(parallel [(set (match_operand 0 "") (call (match_operand 1 "") @@ -2985,7 +3060,13 @@ (define_expand "call_value" rtx arg1 = XEXP (XVECEXP (operands[0], 0, 0), 0); rtx arg2 = XEXP (XVECEXP (operands[0], 0, 1), 0); - emit_call_insn (gen_call_value_multiple_internal (arg1, target, + if (GET_CODE (target) == LO_SUM) + emit_call_insn (gen_call_value_multiple_internal_1 (Pmode, arg1, + XEXP (target, 0), + XEXP (target, 1), + operands[2], arg2)); + else + emit_call_insn (gen_call_value_multiple_internal (arg1, target, operands[2], arg2)); } else @@ -2994,7 +3075,13 @@ (define_expand "call_value" if (GET_CODE (operands[0]) == PARALLEL && XVECLEN (operands[0], 0) == 1) operands[0] = XEXP (XVECEXP (operands[0], 0, 0), 0); - emit_call_insn (gen_call_value_internal (operands[0], target, + if (GET_CODE (target) == LO_SUM) + emit_call_insn (gen_call_value_internal_1 (Pmode, operands[0], + XEXP (target, 0), + XEXP (target, 1), + operands[2])); + else + emit_call_insn (gen_call_value_internal (operands[0], target, operands[2])); } DONE; @@ -3012,6 +3099,16 @@ (define_insn "call_value_internal" bl\t%%plt(%1)" [(set_attr "jirl" "indirect,direct,direct")]) +(define_insn "@call_value_internal_1" + [(set (match_operand 0 "register_operand" "") + (call (mem:P (lo_sum:P (match_operand:P 1 "register_operand" "j") + (match_operand:P 2 "symbolic_operand" ""))) + (match_operand 3 "" ""))) + (clobber (reg:SI RETURN_ADDR_REGNUM))] + "TARGET_CMODEL_MEDIUM" + "jirl\t$r1,%1,%%pc_lo12(%2)" + [(set_attr "jirl" "indirect")]) + (define_insn "call_value_multiple_internal" [(set (match_operand 0 "register_operand" "") (call (mem:SI (match_operand 1 "call_insn_operand" "e,c,b")) @@ -3027,6 +3124,22 @@ (define_insn "call_value_multiple_internal" bl\t%%plt(%1)" [(set_attr "jirl" "indirect,direct,direct")]) +(define_insn "@call_value_multiple_internal_1" + [(set (match_operand 0 "register_operand" "") + (call (mem:P (unspec:P [(match_operand:P 1 "register_operand" "j") + (match_operand:P 2 "symbolic_operand" "")] + UNSPEC_CALL_VALUE_MULTIPLE_INTERNAL_1)) + (match_operand 3 "" ""))) + (set (match_operand 4 "register_operand" "") + (call (mem:P (unspec:P [(match_dup 1) + (match_dup 2)] + UNSPEC_CALL_VALUE_MULTIPLE_INTERNAL_1)) + (match_dup 3))) + (clobber (reg:SI RETURN_ADDR_REGNUM))] + "TARGET_CMODEL_MEDIUM" + "jirl\t$r1,%1,%%pc_lo12(%2)" + [(set_attr "jirl" "indirect")]) + ;; Call subroutine returning any type. (define_expand "untyped_call" diff --git a/gcc/config/loongarch/loongarch.opt b/gcc/config/loongarch/loongarch.opt index 9df7e187283..6395234218b 100644 --- a/gcc/config/loongarch/loongarch.opt +++ b/gcc/config/loongarch/loongarch.opt @@ -179,6 +179,9 @@ Enum(cmodel) String(tiny) Value(CMODEL_TINY) EnumValue Enum(cmodel) String(tiny-static) Value(CMODEL_TINY_STATIC) +EnumValue +Enum(cmodel) String(medium) Value(CMODEL_MEDIUM) + EnumValue Enum(cmodel) String(large) Value(CMODEL_LARGE) diff --git a/gcc/config/loongarch/predicates.md b/gcc/config/loongarch/predicates.md index e38c6fbdd5f..8bd0c1376c9 100644 --- a/gcc/config/loongarch/predicates.md +++ b/gcc/config/loongarch/predicates.md @@ -123,16 +123,27 @@ (define_predicate "const_call_insn_operand" if (offset != const0_rtx) return false; + /* When compiling with '-mcmodel=medium -mexplicit-relocs' + symbols are splited in loongarch_legitimize_call_address. + + When compiling with '-mcmodel=medium -mno-explicit-relocs', + first obtain the symbolic address or the address of the + plt entry, and then perform an indirect jump, so return false. */ + switch (symbol_type) { case SYMBOL_PCREL: - if (TARGET_CMODEL_EXTREME) + if (TARGET_CMODEL_EXTREME + || (TARGET_CMODEL_MEDIUM && !TARGET_EXPLICIT_RELOCS)) return false; else return 1; case SYMBOL_GOT_DISP: - if (TARGET_CMODEL_EXTREME || !flag_plt) + if (TARGET_CMODEL_EXTREME + || !flag_plt + || (flag_plt && TARGET_CMODEL_MEDIUM + && !TARGET_EXPLICIT_RELOCS)) return false; else return 1; diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 8712bc25e3c..60702a52c8f 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -25084,6 +25084,9 @@ Set the code model to one of: The text segment must be within 128MB addressing space. The data segment must be within 2GB addressing space. +@item medium +The text segment and data segment must be within 2GB addressing space. + @item large (Not implemented yet) @item extreme diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-medium-1.c b/gcc/testsuite/gcc.target/loongarch/func-call-medium-1.c new file mode 100644 index 00000000000..276d73e5ee8 --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/func-call-medium-1.c @@ -0,0 +1,41 @@ +/* { dg-do compile } */ +/* { dg-options "-mabi=lp64d -O0 -fpic -fplt -mno-explicit-relocs -mcmodel=medium" } */ +/* { 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:.*la\.local\t.*l\n\tjirl" } } */ +/* { dg-final { scan-assembler "test3:.*la\.global\t.*\_\_tls\_get\_addr" } } */ + +extern void g (void); +void +f (void) +{} + +static void +l (void) +{} + +void +test (void) +{ + g (); +} + +void +test1 (void) +{ + f (); +} + +void +test2 (void) +{ + l (); +} + +__attribute__ ((tls_model ("global-dynamic"))) __thread int a; + +void +test3 (void) +{ + a = 10; +} diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-medium-2.c b/gcc/testsuite/gcc.target/loongarch/func-call-medium-2.c new file mode 100644 index 00000000000..237821c066b --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/func-call-medium-2.c @@ -0,0 +1,41 @@ +/* { dg-do compile } */ +/* { dg-options "-mabi=lp64d -O0 -fno-pic -fplt -mno-explicit-relocs -mcmodel=medium" } */ +/* { dg-final { scan-assembler "test:.*la\.global\t.*g\n\tjirl" } } */ +/* { dg-final { scan-assembler "test1:.*la\.local\t.*f\n\tjirl" } } */ +/* { dg-final { scan-assembler "test2:.*la\.local\t.*l\n\tjirl" } } */ +/* { dg-final { scan-assembler "test3:.*la\.global\t.*\_\_tls\_get\_addr" } } */ + +extern void g (void); +void +f (void) +{} + +static void +l (void) +{} + +void +test (void) +{ + g (); +} + +void +test1 (void) +{ + f (); +} + +void +test2 (void) +{ + l (); +} + +__attribute__ ((tls_model ("global-dynamic"))) __thread int a; + +void +test3 (void) +{ + a = 10; +} diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-medium-3.c b/gcc/testsuite/gcc.target/loongarch/func-call-medium-3.c new file mode 100644 index 00000000000..9a6e16103bc --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/func-call-medium-3.c @@ -0,0 +1,41 @@ +/* { dg-do compile } */ +/* { dg-options "-mabi=lp64d -O0 -fpic -fno-plt -mno-explicit-relocs -mcmodel=medium" } */ +/* { 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:.*la\.local\t.*l\n\tjirl" } } */ +/* { dg-final { scan-assembler "test3:.*la\.global\t.*\_\_tls\_get\_addr" } } */ + +extern void g (void); +void +f (void) +{} + +static void +l (void) +{} + +void +test (void) +{ + g (); +} + +void +test1 (void) +{ + f (); +} + +void +test2 (void) +{ + l (); +} + +__attribute__ ((tls_model ("global-dynamic"))) __thread int a; + +void +test3 (void) +{ + a = 10; +} diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-medium-4.c b/gcc/testsuite/gcc.target/loongarch/func-call-medium-4.c new file mode 100644 index 00000000000..2577e345239 --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/func-call-medium-4.c @@ -0,0 +1,41 @@ +/* { dg-do compile } */ +/* { dg-options "-mabi=lp64d -O0 -fno-pic -fno-plt -mno-explicit-relocs -mcmodel=medium" } */ +/* { dg-final { scan-assembler "test:.*la\.global\t.*g\n\tjirl" } } */ +/* { dg-final { scan-assembler "test1:.*la\.local\t.*f\n\tjirl" } } */ +/* { dg-final { scan-assembler "test2:.*la\.local\t.*l\n\tjirl" } } */ +/* { dg-final { scan-assembler "test3:.*la\.global\t.*\_\_tls\_get\_addr" } } */ + +extern void g (void); +void +f (void) +{} + +static void +l (void) +{} + +void +test (void) +{ + g (); +} + +void +test1 (void) +{ + f (); +} + +void +test2 (void) +{ + l (); +} + +__attribute__ ((tls_model ("global-dynamic"))) __thread int a; + +void +test3 (void) +{ + a = 10; +} diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-medium-5.c b/gcc/testsuite/gcc.target/loongarch/func-call-medium-5.c new file mode 100644 index 00000000000..d70b6ea4663 --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/func-call-medium-5.c @@ -0,0 +1,42 @@ +/* { dg-do compile } */ +/* { dg-options "-mabi=lp64d -O0 -fpic -fplt -mexplicit-relocs -mcmodel=medium" } */ +/* { dg-final { scan-assembler "test:.*pcalau12i.*%pc_hi20\\(g\\)\n\tjirl.*pc_lo12\\(g\\)" } } */ +/* { dg-final { scan-assembler "test1:.*pcalau12i.*%pc_hi20\\(f\\)\n\tjirl.*%pc_lo12\\(f\\)" } } */ +/* { dg-final { scan-assembler "test2:.*pcalau12i.*%pc_hi20\\(l\\)\n\tjirl.*%pc_lo12\\(l\\)" } } */ +/* { dg-final { scan-assembler "test3:.*pcalau12i.*%pc_hi20\\(__tls_get_addr\\)\n\t.*\n\tjirl.*%pc_lo12\\(__tls_get_addr\\)" } } */ + +extern void g (void); + +void +f (void) +{} + +static void +l (void) +{} + +void +test (void) +{ + g (); +} + +void +test1 (void) +{ + f (); +} + +void +test2 (void) +{ + l (); +} + +__attribute__ ((tls_model ("global-dynamic"))) __thread int a; + +void +test3 (void) +{ + a = 10; +} diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-medium-6.c b/gcc/testsuite/gcc.target/loongarch/func-call-medium-6.c new file mode 100644 index 00000000000..f963a99441a --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/func-call-medium-6.c @@ -0,0 +1,42 @@ +/* { dg-do compile } */ +/* { dg-options "-mabi=lp64d -O0 -fno-pic -fplt -mexplicit-relocs -mcmodel=medium" } */ +/* { dg-final { scan-assembler "test:.*pcalau12i.*%pc_hi20\\(g\\)\n\tjirl.*pc_lo12\\(g\\)" } } */ +/* { dg-final { scan-assembler "test1:.*pcalau12i.*%pc_hi20\\(f\\)\n\tjirl.*%pc_lo12\\(f\\)" } } */ +/* { dg-final { scan-assembler "test2:.*pcalau12i.*%pc_hi20\\(l\\)\n\tjirl.*%pc_lo12\\(l\\)" } } */ +/* { dg-final { scan-assembler "test3:.*pcalau12i.*%pc_hi20\\(__tls_get_addr\\)\n\t.*\n\tjirl.*%pc_lo12\\(__tls_get_addr\\)" } } */ + +extern void g (void); + +void +f (void) +{} + +static void +l (void) +{} + +void +test (void) +{ + g (); +} + +void +test1 (void) +{ + f (); +} + +void +test2 (void) +{ + l (); +} + +__attribute__ ((tls_model ("global-dynamic"))) __thread int a; + +void +test3 (void) +{ + a = 10; +} diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-medium-7.c b/gcc/testsuite/gcc.target/loongarch/func-call-medium-7.c new file mode 100644 index 00000000000..f2818b2da76 --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/func-call-medium-7.c @@ -0,0 +1,43 @@ +/* { dg-do compile } */ +/* { dg-options "-mabi=lp64d -O0 -fpic -fno-plt -mexplicit-relocs -mcmodel=medium" } */ +/* { dg-final { scan-assembler "test:.*pcalau12i\t.*%got_pc_hi20\\(g\\)\n\tld\.d\t.*%got_pc_lo12\\(g\\)\n\tjirl" } } */ +/* { dg-final { scan-assembler "test1:.*pcalau12i\t.*%got_pc_hi20\\(f\\)\n\tld\.d\t.*%got_pc_lo12\\(f\\)\n\tjirl" } } */ +/* { dg-final { scan-assembler "test2:.*pcalau12i\t.*%pc_hi20\\(l\\)\n\tjirl.*%pc_lo12\\(l\\)" } } */ +/* { dg-final { scan-assembler "test3:.*pcalau12i.*%got_pc_hi20\\(__tls_get_addr\\)\n\tld\.d.*%got_pc_lo12\\(__tls_get_addr\\)" } } */ + + +extern void g (void); + +void +f (void) +{} + +static void +l (void) +{} + +void +test (void) +{ + g (); +} + +void +test1 (void) +{ + f (); +} + +void +test2 (void) +{ + l (); +} + +__attribute__ ((tls_model ("global-dynamic"))) __thread int a; + +void +test3 (void) +{ + a = 10; +} diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-medium-8.c b/gcc/testsuite/gcc.target/loongarch/func-call-medium-8.c new file mode 100644 index 00000000000..7fa873d84bb --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/func-call-medium-8.c @@ -0,0 +1,42 @@ +/* { dg-do compile } */ +/* { dg-options "-mabi=lp64d -O0 -fno-pic -fno-plt -mexplicit-relocs -mcmodel=medium" } */ +/* { dg-final { scan-assembler "test:.*pcalau12i\t.*%got_pc_hi20\\(g\\)\n\tld\.d\t.*%got_pc_lo12\\(g\\)\n\tjirl" } } */ +/* { dg-final { scan-assembler "test1:.*pcalau12i\t.*%pc_hi20\\(f\\)\n\tjirl.*%pc_lo12\\(f\\)" } } */ +/* { dg-final { scan-assembler "test2:.*pcalau12i\t.*%pc_hi20\\(l\\)\n\tjirl.*%pc_lo12\\(l\\)" } } */ +/* { dg-final { scan-assembler "test3:.*pcalau12i.*%got_pc_hi20\\(__tls_get_addr\\)\n\tld\.d.*%got_pc_lo12\\(__tls_get_addr\\)" } } */ + +extern void g (void); + +void +f (void) +{} + +static void +l (void) +{} + +void +test (void) +{ + g (); +} + +void +test1 (void) +{ + f (); +} + +void +test2 (void) +{ + l (); +} + +__attribute__ ((tls_model ("global-dynamic"))) __thread int a; + +void +test3 (void) +{ + a = 10; +} diff --git a/gcc/testsuite/gcc.target/loongarch/tls-gd-noplt.c b/gcc/testsuite/gcc.target/loongarch/tls-gd-noplt.c index 32a0acf9b18..375663286f0 100644 --- a/gcc/testsuite/gcc.target/loongarch/tls-gd-noplt.c +++ b/gcc/testsuite/gcc.target/loongarch/tls-gd-noplt.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fno-plt -mcmodel=normal" } */ -/* { dg-final { scan-assembler "pcalau12i\t.*%got_pc_hi20\\(__tls_get_addr\\)" } } */ +/* { dg-options "-O0 -fno-plt -mcmodel=normal -mexplicit-relocs" } */ +/* { dg-final { scan-assembler "pcalau12i\t.*%got_pc_hi20\\(__tls_get_addr\\)\n\tld\.d.*%got_pc_lo12\\(__tls_get_addr\\)" } } */ __attribute__ ((tls_model ("global-dynamic"))) __thread int a; -- 2.31.1