Projects
home:lf14:branches:Mega:23.09
gcc
_service:tar_scm:LoongArch-Add-new-code-model-m...
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:tar_scm:LoongArch-Add-new-code-model-medium.patch of Package gcc
From 893322f214fbb916dc8eb6be5acbf7bdb7785e77 Mon Sep 17 00:00:00 2001 From: Lulu Cheng <chenglulu@loongson.cn> Date: Sat, 20 Aug 2022 15:19:51 +0800 Subject: [PATCH 012/124] LoongArch: Add new code model 'medium'. 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<mode>): New template. (@sibcall_internal_1<mode>): New function call templates added to support medium mode. (@sibcall_value_internal_1<mode>): Likewise. (@sibcall_value_multiple_internal_1<mode>): Likewise. (@call_internal_1<mode>): Likewise. (@call_value_internal_1<mode>): Likewise. (@call_value_multiple_internal_1<mode>): 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'. Signed-off-by: Peng Fan <fanpeng@loongson.cn> Signed-off-by: ticat_fp <fanpeng@loongson.cn> --- .../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 cb88ed56b..44ebb7ab1 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 a571b6b75..ebdd9538d 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 c8769b7d6..cbf995d81 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 c2c35b6ba..b5985f070 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 2ae89f234..e13eafb58 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 da24ecd2b..3523a4cf7 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 0e8889b8c..9f1b0989c 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 1a33f668f..04c4ddaed 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 8fc10444c..3787fd823 100644 --- a/gcc/config/loongarch/loongarch.md +++ b/gcc/config/loongarch/loongarch.md @@ -59,11 +59,15 @@ 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 @@ [(set_attr "type" "move")] ) +(define_insn "@pcalau12i<mode>" + [(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<mode>" [(set (match_operand:P 0 "register_operand" "=r") (unspec:P [(match_operand:P 1 "register_operand" "r") @@ -2877,7 +2889,12 @@ { 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 @@ b\t%%plt(%0)" [(set_attr "jirl" "indirect,direct,direct")]) +(define_insn "@sibcall_internal_1<mode>" + [(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 @@ 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 @@ 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 @@ b\t%%plt(%1)" [(set_attr "jirl" "indirect,direct,direct")]) +(define_insn "@sibcall_value_internal_1<mode>" + [(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 @@ b\t%%plt(%1)" [(set_attr "jirl" "indirect,direct,direct")]) +(define_insn "@sibcall_value_multiple_internal_1<mode>" + [(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 @@ { 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 @@ bl\t%%plt(%0)" [(set_attr "jirl" "indirect,direct,direct")]) +(define_insn "@call_internal_1<mode>" + [(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 @@ 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 @@ 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 @@ bl\t%%plt(%1)" [(set_attr "jirl" "indirect,direct,direct")]) +(define_insn "@call_value_internal_1<mode>" + [(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 @@ bl\t%%plt(%1)" [(set_attr "jirl" "indirect,direct,direct")]) +(define_insn "@call_value_multiple_internal_1<mode>" + [(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 9df7e1872..639523421 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 e38c6fbdd..8bd0c1376 100644 --- a/gcc/config/loongarch/predicates.md +++ b/gcc/config/loongarch/predicates.md @@ -123,16 +123,27 @@ 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 c4f83e62a..2a5592516 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -24625,6 +24625,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 000000000..276d73e5e --- /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 000000000..237821c06 --- /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 000000000..9a6e16103 --- /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 000000000..2577e3452 --- /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 000000000..d70b6ea46 --- /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 000000000..f963a9944 --- /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 000000000..f2818b2da --- /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 000000000..7fa873d84 --- /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 32a0acf9b..375663286 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.33.0
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2