From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from ams.source.kernel.org (ams.source.kernel.org [145.40.68.75]) by sourceware.org (Postfix) with ESMTPS id D380B3858D28 for ; Sat, 20 Aug 2022 09:18:59 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org D380B3858D28 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 21C16B81F2E for ; Sat, 20 Aug 2022 09:18:56 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id CC035C433D7 for ; Sat, 20 Aug 2022 09:18:54 +0000 (UTC) Received: by mail-vs1-f50.google.com with SMTP id v128so6575589vsb.10 for ; Sat, 20 Aug 2022 02:18:54 -0700 (PDT) X-Gm-Message-State: ACgBeo1mYi10/zTqY1LS3U4o15G8V3UfKle/OAfEd3Cw/2m0GX1/ce0j /GlmXAD0he7O1jI7PEuKNrWzX7gWaRU/iWgxh0U= X-Google-Smtp-Source: AA6agR4yh63gt6vpvGDnE1q5F9/Yj+89ZgB/B3gkP40AuR93Y624TfPRT+X31Z32zhhnwQdkyVpO4GRV9BO41mkoQgs= X-Received: by 2002:a67:d58b:0:b0:390:2574:6736 with SMTP id m11-20020a67d58b000000b0039025746736mr2394501vsj.78.1660987133458; Sat, 20 Aug 2022 02:18:53 -0700 (PDT) MIME-Version: 1.0 References: <20220820090425.525292-1-chenglulu@loongson.cn> In-Reply-To: <20220820090425.525292-1-chenglulu@loongson.cn> From: Huacai Chen Date: Sat, 20 Aug 2022 17:18:41 +0800 X-Gmail-Original-Message-ID: Message-ID: Subject: Re: [PATCH v1] LoongArch: Add new code model 'emdium'. To: Lulu Cheng Cc: gcc-patches@gcc.gnu.org, Xu Chenghua , Wang Xuerui Content-Type: text/plain; charset="UTF-8" X-Spam-Status: No, score=-8.7 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, KAM_STOCKGEN, SPF_HELO_NONE, 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:19:03 -0000 Hi, Lulu, I think there is a typo in your subject line. Huacai On Sat, Aug 20, 2022 at 5:05 PM Lulu Cheng wrote: > > 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 >