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'.
This commit is contained in:
parent
b6864f4ee8
commit
d1028c5773
21 changed files with 596 additions and 41 deletions
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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));
|
||||
{
|
||||
switch (la_opt_cmodel)
|
||||
{
|
||||
case CMODEL_NORMAL:
|
||||
insn = emit_call_insn (gen_call_value_internal (v0,
|
||||
loongarch_tls_symbol,
|
||||
const0_rtx));
|
||||
break;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* code model extreme not support plt. */
|
||||
case CMODEL_EXTREME:
|
||||
case CMODEL_LARGE:
|
||||
case CMODEL_TINY:
|
||||
case CMODEL_TINY_STATIC:
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rtx dest = gen_reg_rtx (Pmode);
|
||||
|
||||
if (TARGET_CMODEL_EXTREME)
|
||||
switch (la_opt_cmodel)
|
||||
{
|
||||
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));
|
||||
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
|
||||
{
|
||||
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:
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
41
gcc/testsuite/gcc.target/loongarch/func-call-medium-1.c
Normal file
41
gcc/testsuite/gcc.target/loongarch/func-call-medium-1.c
Normal file
|
@ -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;
|
||||
}
|
41
gcc/testsuite/gcc.target/loongarch/func-call-medium-2.c
Normal file
41
gcc/testsuite/gcc.target/loongarch/func-call-medium-2.c
Normal file
|
@ -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;
|
||||
}
|
41
gcc/testsuite/gcc.target/loongarch/func-call-medium-3.c
Normal file
41
gcc/testsuite/gcc.target/loongarch/func-call-medium-3.c
Normal file
|
@ -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;
|
||||
}
|
41
gcc/testsuite/gcc.target/loongarch/func-call-medium-4.c
Normal file
41
gcc/testsuite/gcc.target/loongarch/func-call-medium-4.c
Normal file
|
@ -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;
|
||||
}
|
42
gcc/testsuite/gcc.target/loongarch/func-call-medium-5.c
Normal file
42
gcc/testsuite/gcc.target/loongarch/func-call-medium-5.c
Normal file
|
@ -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;
|
||||
}
|
42
gcc/testsuite/gcc.target/loongarch/func-call-medium-6.c
Normal file
42
gcc/testsuite/gcc.target/loongarch/func-call-medium-6.c
Normal file
|
@ -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;
|
||||
}
|
43
gcc/testsuite/gcc.target/loongarch/func-call-medium-7.c
Normal file
43
gcc/testsuite/gcc.target/loongarch/func-call-medium-7.c
Normal file
|
@ -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;
|
||||
}
|
42
gcc/testsuite/gcc.target/loongarch/func-call-medium-8.c
Normal file
42
gcc/testsuite/gcc.target/loongarch/func-call-medium-8.c
Normal file
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue