diff options
author | Lulu Cheng <chenglulu@loongson.cn> | 2022-08-20 15:19:51 +0800 |
---|---|---|
committer | Lulu Cheng <chenglulu@loongson.cn> | 2022-08-24 14:55:34 +0800 |
commit | d1028c5773049bae4bb4261e3bbaae442455de83 (patch) | |
tree | 390c68a04268c24ddc6b6fe6a3167d30ad2f7d9e /gcc | |
parent | b6864f4ee87fb56299fc82e1e0ced127b747d87a (diff) | |
download | gcc-d1028c5773049bae4bb4261e3bbaae442455de83.zip gcc-d1028c5773049bae4bb4261e3bbaae442455de83.tar.gz gcc-d1028c5773049bae4bb4261e3bbaae442455de83.tar.bz2 |
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'.
Diffstat (limited to 'gcc')
21 files changed, 595 insertions, 40 deletions
diff --git a/gcc/config/loongarch/genopts/loongarch-strings b/gcc/config/loongarch/genopts/loongarch-strings index cb88ed5..44ebb7a 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 a571b6b..ebdd953 100644 --- a/gcc/config/loongarch/genopts/loongarch.opt.in +++ b/gcc/config/loongarch/genopts/loongarch.opt.in @@ -173,6 +173,9 @@ 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) EnumValue diff --git a/gcc/config/loongarch/loongarch-def.c b/gcc/config/loongarch/loongarch-def.c index c8769b7..cbf995d 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 c2c35b6..b5985f0 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 2ae89f2..e13eafb 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 da24ecd..3523a4c 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 0e8889b..9f1b098 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 207ac27..16fd4ac 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 8fc1044..3787fd8 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 9df7e18..6395234 100644 --- a/gcc/config/loongarch/loongarch.opt +++ b/gcc/config/loongarch/loongarch.opt @@ -180,6 +180,9 @@ 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) EnumValue diff --git a/gcc/config/loongarch/predicates.md b/gcc/config/loongarch/predicates.md index e38c6fb..8bd0c13 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 78eb7ad..3359313 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -25098,6 +25098,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 0000000..276d73e --- /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 0000000..237821c --- /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 0000000..9a6e161 --- /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 0000000..2577e34 --- /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 0000000..d70b6ea --- /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 0000000..f963a99 --- /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 0000000..f2818b2 --- /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 0000000..7fa873d --- /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 32a0acf..3756632 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; |