public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH v4] LoongArch: Add support code model extreme.
@ 2022-08-20  8:39 Lulu Cheng
  2022-08-20  9:04 ` [commited PATCH " Lulu Cheng
  0 siblings, 1 reply; 2+ messages in thread
From: Lulu Cheng @ 2022-08-20  8:39 UTC (permalink / raw)
  To: gcc-patches; +Cc: xry111, i, xuchenghua, Lulu Cheng

v1 -> v2:
- Modify some description information.
- Add options -W[no]extreme-plt, warn about code model extreme not support plt mode,
and then disable plt.

v2 -> v3:
- When -mcmodel=extreme, default set to -fno-plt mode, if the user forces to use
'-mcmodel=extreme -fplt', an error will be reported.
- Delete -Wextreme-plt.
- Fix bug when compiling with '-mcmodel=normal -fno-plt -mno-explicit-relocs'.

v3 -> v4:
- Fix the bug of loongarch_tls_symbol function loading in function
loongarch_call_tls_get_addr. 

----------------------------------------------------------------------------
Use five instructions to calculate a signed 64-bit offset relative to the pc.

gcc/ChangeLog:

	* config/loongarch/loongarch-opts.cc: Allow cmodel to be extreme.
	* config/loongarch/loongarch.cc (loongarch_call_tls_get_addr):
	Add extreme support for TLS GD and LD types.
	(loongarch_legitimize_tls_address): Add extreme support for TLS LE
	and IE.
	(loongarch_split_symbol): When compiling with -mcmodel=extreme,
	the symbol address will be obtained through five instructions.
	(loongarch_print_operand_reloc): Add support.
	(loongarch_print_operand): Add support.
	(loongarch_print_operand_address): Add support.
	(loongarch_option_override_internal): Set '-mcmodel=extreme' option
	incompatible with '-mno-explicit-relocs'.
	* config/loongarch/loongarch.md (@lui_l_hi20<mode>):
	Loads bits 12-31 of data into registers.
	(lui_h_lo20): Load bits 32-51 of the data and spell bits 0-31 of
	the source register.
	(lui_h_hi12): Load bits 52-63 of the data and spell bits 0-51 of
	the source register.
	* config/loongarch/predicates.md: Symbols need to be decomposed
	when defining the macro TARGET_CMODEL_EXTREME
	* doc/invoke.texi: Modify the description information of cmodel in the document.
	Document -W[no-]extreme-plt.

gcc/testsuite/ChangeLog:

	* gcc.target/loongarch/func-call-1.c: Add option '-mcmodel=normal'.
	* gcc.target/loongarch/func-call-2.c: Likewise.
	* gcc.target/loongarch/func-call-3.c: Likewise.
	* gcc.target/loongarch/func-call-4.c: Likewise.
	* gcc.target/loongarch/func-call-5.c: Likewise.
	* gcc.target/loongarch/func-call-6.c: Likewise.
	* gcc.target/loongarch/func-call-7.c: Likewise.
	* gcc.target/loongarch/func-call-8.c: Likewise.
	* gcc.target/loongarch/relocs-symbol-noaddend.c: Likewise.
	* gcc.target/loongarch/func-call-extreme-1.c: New test.
	* gcc.target/loongarch/func-call-extreme-2.c: New test.
---
 gcc/config/loongarch/loongarch-opts.cc        |   3 +-
 gcc/config/loongarch/loongarch.cc             | 222 +++++++++++++++---
 gcc/config/loongarch/loongarch.md             |  34 ++-
 gcc/config/loongarch/predicates.md            |   9 +-
 gcc/doc/invoke.texi                           |  50 +---
 .../gcc.target/loongarch/func-call-1.c        |   2 +-
 .../gcc.target/loongarch/func-call-2.c        |   2 +-
 .../gcc.target/loongarch/func-call-3.c        |   2 +-
 .../gcc.target/loongarch/func-call-4.c        |   2 +-
 .../gcc.target/loongarch/func-call-5.c        |   2 +-
 .../gcc.target/loongarch/func-call-6.c        |   2 +-
 .../gcc.target/loongarch/func-call-7.c        |   2 +-
 .../gcc.target/loongarch/func-call-8.c        |   2 +-
 .../loongarch/func-call-extreme-1.c           |  32 +++
 .../loongarch/func-call-extreme-2.c           |  32 +++
 .../loongarch/relocs-symbol-noaddend.c        |   2 +-
 16 files changed, 318 insertions(+), 82 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/loongarch/func-call-extreme-1.c
 create mode 100644 gcc/testsuite/gcc.target/loongarch/func-call-extreme-2.c

diff --git a/gcc/config/loongarch/loongarch-opts.cc b/gcc/config/loongarch/loongarch-opts.cc
index 3f70943ded6..2ae89f23443 100644
--- a/gcc/config/loongarch/loongarch-opts.cc
+++ b/gcc/config/loongarch/loongarch-opts.cc
@@ -376,14 +376,13 @@ fallback:
 
   /* 5.  Target code model */
   t.cmodel = constrained.cmodel ? opt_cmodel : CMODEL_NORMAL;
-  if (t.cmodel != CMODEL_NORMAL)
+  if (t.cmodel != CMODEL_NORMAL && t.cmodel != CMODEL_EXTREME)
     {
       warning (0, "%qs is not supported, now cmodel is set to %qs",
 	       loongarch_cmodel_strings[t.cmodel], "normal");
       t.cmodel = CMODEL_NORMAL;
     }
 
-
   /* Cleanup and return.  */
   obstack_free (&msg_obstack, NULL);
   *target = t;
diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc
index 24378143641..207ac2762c6 100644
--- a/gcc/config/loongarch/loongarch.cc
+++ b/gcc/config/loongarch/loongarch.cc
@@ -2436,7 +2436,19 @@ loongarch_call_tls_get_addr (rtx sym, enum loongarch_symbol_type type, rtx v0)
       /* Split tls symbol to high and low.  */
       rtx high = gen_rtx_HIGH (Pmode, copy_rtx (loc));
       high = loongarch_force_temporary (tmp, high);
-      emit_insn (gen_tls_low (Pmode, a0, high, loc));
+
+      if (TARGET_CMODEL_EXTREME)
+	{
+	  gcc_assert (TARGET_EXPLICIT_RELOCS);
+
+	  rtx tmp1 = gen_reg_rtx (Pmode);
+	  emit_insn (gen_tls_low (Pmode, tmp1, gen_rtx_REG (Pmode, 0), loc));
+	  emit_insn (gen_lui_h_lo20 (tmp1, tmp1, loc));
+	  emit_insn (gen_lui_h_hi12 (tmp1, tmp1, loc));
+	  emit_move_insn (a0, gen_rtx_PLUS (Pmode, high, tmp1));
+	}
+      else
+	emit_insn (gen_tls_low (Pmode, a0, high, loc));
     }
   else
     {
@@ -2449,14 +2461,44 @@ 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,
+    insn = emit_call_insn (gen_call_value_internal (v0,
+						    loongarch_tls_symbol,
 						    const0_rtx));
   else
     {
       rtx dest = 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));
+
+      if (TARGET_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));
+	  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)
+	    {
+	      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);
+	}
       insn = emit_call_insn (gen_call_value_internal (v0, dest, const0_rtx));
     }
 
@@ -2508,7 +2550,23 @@ loongarch_legitimize_tls_address (rtx loc)
 	      tmp3 = gen_reg_rtx (Pmode);
 	      rtx high = gen_rtx_HIGH (Pmode, copy_rtx (tmp2));
 	      high = loongarch_force_temporary (tmp3, high);
-	      emit_insn (gen_ld_from_got (Pmode, tmp1, high, tmp2));
+
+	      if (TARGET_CMODEL_EXTREME)
+		{
+		  gcc_assert (TARGET_EXPLICIT_RELOCS);
+
+		  rtx tmp3 = gen_reg_rtx (Pmode);
+		  emit_insn (gen_tls_low (Pmode, tmp3,
+					  gen_rtx_REG (Pmode, 0), tmp2));
+		  emit_insn (gen_lui_h_lo20 (tmp3, tmp3, tmp2));
+		  emit_insn (gen_lui_h_hi12 (tmp3, tmp3, tmp2));
+		  emit_move_insn (tmp1,
+				  gen_rtx_MEM (Pmode,
+					       gen_rtx_PLUS (Pmode,
+							     high, tmp3)));
+		}
+	      else
+		emit_insn (gen_ld_from_got (Pmode, tmp1, high, tmp2));
 	    }
 	  else
 	    emit_insn (loongarch_got_load_tls_ie (tmp1, loc));
@@ -2530,11 +2588,18 @@ loongarch_legitimize_tls_address (rtx loc)
 	      rtx high = gen_rtx_HIGH (Pmode, copy_rtx (tmp2));
 	      high = loongarch_force_temporary (tmp3, high);
 	      emit_insn (gen_ori_l_lo12 (Pmode, tmp1, high, tmp2));
+
+	      if (TARGET_CMODEL_EXTREME)
+		{
+		  gcc_assert (TARGET_EXPLICIT_RELOCS);
+
+		  emit_insn (gen_lui_h_lo20 (tmp1, tmp1, tmp2));
+		  emit_insn (gen_lui_h_hi12 (tmp1, tmp1, tmp2));
+		}
 	    }
 	  else
 	    emit_insn (loongarch_got_load_tls_le (tmp1, loc));
 	  emit_insn (gen_add3_insn (dest, tmp1, tp));
-
 	}
       break;
 
@@ -2603,7 +2668,6 @@ bool
 loongarch_split_symbol (rtx temp, rtx addr, machine_mode mode, rtx *low_out)
 {
   enum loongarch_symbol_type symbol_type;
-  rtx high;
 
   /* If build with '-mno-explicit-relocs', don't split symbol.  */
   if (!TARGET_EXPLICIT_RELOCS)
@@ -2615,6 +2679,8 @@ loongarch_split_symbol (rtx temp, rtx addr, machine_mode mode, rtx *low_out)
       || !loongarch_split_symbol_type (symbol_type))
     return false;
 
+  rtx high, temp1 = NULL;
+
   if (temp == NULL)
     temp = gen_reg_rtx (Pmode);
 
@@ -2622,20 +2688,42 @@ loongarch_split_symbol (rtx temp, rtx addr, machine_mode mode, rtx *low_out)
   high = gen_rtx_HIGH (Pmode, copy_rtx (addr));
   high = loongarch_force_temporary (temp, high);
 
+  if (TARGET_CMODEL_EXTREME && can_create_pseudo_p ())
+    {
+      gcc_assert (TARGET_EXPLICIT_RELOCS);
+
+      temp1 = gen_reg_rtx (Pmode);
+      emit_move_insn (temp1, gen_rtx_LO_SUM (Pmode, gen_rtx_REG (Pmode, 0),
+					     addr));
+      emit_insn (gen_lui_h_lo20 (temp1, temp1, addr));
+      emit_insn (gen_lui_h_hi12 (temp1, temp1, addr));
+    }
+
   if (low_out)
     switch (symbol_type)
       {
       case SYMBOL_PCREL:
-	*low_out = gen_rtx_LO_SUM (Pmode, high, addr);
-	break;
+	{
+	  if (TARGET_CMODEL_EXTREME && can_create_pseudo_p ())
+	    *low_out = gen_rtx_PLUS (Pmode, high, temp1);
+	  else
+	    *low_out = gen_rtx_LO_SUM (Pmode, high, addr);
+	  break;
+	}
 
       case SYMBOL_GOT_DISP:
 	/* SYMBOL_GOT_DISP symbols are loaded from the GOT.  */
 	{
-	  rtx low = gen_rtx_LO_SUM (Pmode, high, addr);
-	  rtx mem = gen_rtx_MEM (Pmode, low);
-	  *low_out = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, mem),
-				     UNSPEC_LOAD_FROM_GOT);
+	  if (TARGET_CMODEL_EXTREME && can_create_pseudo_p ())
+	    *low_out = gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, high, temp1));
+	  else
+	    {
+	      rtx low = gen_rtx_LO_SUM (Pmode, high, addr);
+	      rtx mem = gen_rtx_MEM (Pmode, low);
+	      *low_out = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, mem),
+					 UNSPEC_LOAD_FROM_GOT);
+	    }
+
 	  break;
 	}
 
@@ -4584,34 +4672,86 @@ loongarch_memmodel_needs_release_fence (enum memmodel model)
    in context CONTEXT.  HI_RELOC indicates a high-part reloc.  */
 
 static void
-loongarch_print_operand_reloc (FILE *file, rtx op, bool hi_reloc)
+loongarch_print_operand_reloc (FILE *file, rtx op, bool hi64_part,
+			       bool hi_reloc)
 {
   const char *reloc;
 
+  if (TARGET_CMODEL_EXTREME)
+    gcc_assert (TARGET_EXPLICIT_RELOCS);
+
   switch (loongarch_classify_symbolic_expression (op))
     {
     case SYMBOL_PCREL:
-      reloc = hi_reloc ? "%pc_hi20" : "%pc_lo12";
+      if (hi64_part)
+	{
+	  if (TARGET_CMODEL_EXTREME)
+	    reloc = hi_reloc ? "%pc64_hi12" : "%pc64_lo20";
+	  else
+	    gcc_unreachable ();
+	}
+      else
+	reloc = hi_reloc ? "%pc_hi20" : "%pc_lo12";
       break;
 
     case SYMBOL_GOT_DISP:
-      reloc = hi_reloc ? "%got_pc_hi20" : "%got_pc_lo12";
+      if (hi64_part)
+	{
+	  if (TARGET_CMODEL_EXTREME)
+	    reloc = hi_reloc ? "%got64_pc_hi12" : "%got64_pc_lo20";
+	  else
+	    gcc_unreachable ();
+	}
+      else
+	reloc = hi_reloc ? "%got_pc_hi20" : "%got_pc_lo12";
       break;
 
     case SYMBOL_TLS_IE:
-      reloc = hi_reloc ? "%ie_pc_hi20" : "%ie_pc_lo12";
+      if (hi64_part)
+	{
+	  if (TARGET_CMODEL_EXTREME)
+	    reloc = hi_reloc ? "%ie64_pc_hi12" : "%ie64_pc_lo20";
+	  else
+	    gcc_unreachable ();
+	}
+      else
+	reloc = hi_reloc ? "%ie_pc_hi20" : "%ie_pc_lo12";
       break;
 
     case SYMBOL_TLS_LE:
-      reloc = hi_reloc ? "%le_hi20" : "%le_lo12";
+      if (hi64_part)
+	{
+	  if (TARGET_CMODEL_EXTREME)
+	    reloc = hi_reloc ? "%le64_hi12" : "%le64_lo20";
+	  else
+	    gcc_unreachable ();
+	}
+      else
+	reloc = hi_reloc ? "%le_hi20" : "%le_lo12";
       break;
 
     case SYMBOL_TLSGD:
-      reloc = hi_reloc ? "%gd_pc_hi20" : "%got_pc_lo12";
+      if (hi64_part)
+	{
+	  if (TARGET_CMODEL_EXTREME)
+	    reloc = hi_reloc ? "%got64_pc_hi12" : "%got64_pc_lo20";
+	  else
+	    gcc_unreachable ();
+	}
+      else
+	reloc = hi_reloc ? "%gd_pc_hi20" : "%got_pc_lo12";
       break;
 
     case SYMBOL_TLSLDM:
-      reloc = hi_reloc ? "%ld_pc_hi20" : "%got_pc_lo12";
+      if (hi64_part)
+	{
+	  if (TARGET_CMODEL_EXTREME)
+	    reloc = hi_reloc ? "%got64_pc_hi12" : "%got64_pc_lo20";
+	  else
+	    gcc_unreachable ();
+	}
+      else
+	reloc = hi_reloc ? "%ld_pc_hi20" : "%got_pc_lo12";
       break;
 
     default:
@@ -4637,6 +4777,8 @@ loongarch_print_operand_reloc (FILE *file, rtx op, bool hi_reloc)
    'L'  Print the low-part relocation associated with OP.
    'm'	Print one less than CONST_INT OP in decimal.
    'N'	Print the inverse of the integer branch condition for comparison OP.
+   'r'  Print address 12-31bit relocation associated with OP.
+   'R'  Print address 32-51bit relocation associated with OP.
    'T'	Print 'f' for (eq:CC ...), 't' for (ne:CC ...),
 	      'z' for (eq:?I ...), 'n' for (ne:?I ...).
    't'	Like 'T', but with the EQ/NE cases reversed
@@ -4694,7 +4836,13 @@ loongarch_print_operand (FILE *file, rtx op, int letter)
     case 'h':
       if (code == HIGH)
 	op = XEXP (op, 0);
-      loongarch_print_operand_reloc (file, op, true /* hi_reloc */);
+      loongarch_print_operand_reloc (file, op, false /* hi64_part */,
+				     true /* hi_reloc */);
+      break;
+
+    case 'H':
+      loongarch_print_operand_reloc (file, op, true /* hi64_part */,
+				     true /* hi_reloc */);
       break;
 
     case 'i':
@@ -4703,7 +4851,8 @@ loongarch_print_operand (FILE *file, rtx op, int letter)
       break;
 
     case 'L':
-      loongarch_print_operand_reloc (file, op, false /* lo_reloc */);
+      loongarch_print_operand_reloc (file, op, false /* hi64_part*/,
+				     false /* lo_reloc */);
       break;
 
     case 'm':
@@ -4718,6 +4867,16 @@ loongarch_print_operand (FILE *file, rtx op, int letter)
 					    letter);
       break;
 
+    case 'r':
+      loongarch_print_operand_reloc (file, op, false /* hi64_part */,
+				     true /* lo_reloc */);
+      break;
+
+    case 'R':
+      loongarch_print_operand_reloc (file, op, true /* hi64_part */,
+				     false /* lo_reloc */);
+      break;
+
     case 't':
     case 'T':
       {
@@ -4848,7 +5007,8 @@ loongarch_print_operand_address (FILE *file, machine_mode /* mode  */, rtx x)
 
       case ADDRESS_LO_SUM:
 	fprintf (file, "%s,", reg_names[REGNO (addr.reg)]);
-	loongarch_print_operand_reloc (file, addr.offset, false /* hi_reloc */);
+	loongarch_print_operand_reloc (file, addr.offset, false /* hi64_part */,
+				       false /* hi_reloc */);
 	return;
 
       case ADDRESS_CONST_INT:
@@ -5821,13 +5981,21 @@ loongarch_option_override_internal (struct gcc_options *opts)
 
   switch (la_target.cmodel)
     {
-      case CMODEL_TINY_STATIC:
       case CMODEL_EXTREME:
+	if (!TARGET_EXPLICIT_RELOCS)
+	  error ("code model %qs needs %s",
+		 "extreme", "-mexplicit-relocs");
+
 	if (opts->x_flag_plt)
-	  error ("code model %qs and %qs not support %s mode",
-		 "tiny-static", "extreme", "plt");
+	  {
+	    if (global_options_set.x_flag_plt)
+	      error ("code model %qs is not compatible with %s",
+		     "extreme", "-fplt");
+	    opts->x_flag_plt = 0;
+	  }
 	break;
 
+      case CMODEL_TINY_STATIC:
       case CMODEL_NORMAL:
       case CMODEL_TINY:
       case CMODEL_LARGE:
diff --git a/gcc/config/loongarch/loongarch.md b/gcc/config/loongarch/loongarch.md
index 8e8868de9f5..8fc10444c2a 100644
--- a/gcc/config/loongarch/loongarch.md
+++ b/gcc/config/loongarch/loongarch.md
@@ -60,6 +60,9 @@ (define_c_enum "unspec" [
 
   UNSPEC_LOAD_FROM_GOT
   UNSPEC_ORI_L_LO12
+  UNSPEC_LUI_L_HI20
+  UNSPEC_LUI_H_LO20
+  UNSPEC_LUI_H_HI12
   UNSPEC_TLS_LOW
 ])
 
@@ -1934,16 +1937,45 @@ (define_insn "@ld_from_got<mode>"
   [(set_attr "type" "move")]
 )
 
+(define_insn "@lui_l_hi20<mode>"
+  [(set (match_operand:P 0 "register_operand" "=r")
+	(unspec:P [(match_operand:P 1 "symbolic_operand")]
+	UNSPEC_LUI_L_HI20))]
+  ""
+  "lu12i.w\t%0,%r1"
+  [(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")
-		    (match_operand:P 2 "symbolic_operand")]
+		   (match_operand:P 2 "symbolic_operand")]
 	UNSPEC_ORI_L_LO12))]
   ""
   "ori\t%0,%1,%L2"
   [(set_attr "type" "move")]
 )
 
+(define_insn "lui_h_lo20"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(unspec:DI [(match_operand:DI 1 "register_operand" "0")
+		    (match_operand:DI 2 "symbolic_operand")]
+	UNSPEC_LUI_H_LO20))]
+  "TARGET_64BIT"
+  "lu32i.d\t%0,%R2"
+  [(set_attr "type" "move")]
+)
+
+(define_insn "lui_h_hi12"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(unspec:DI [(match_operand:DI 1 "register_operand" "r")
+		    (match_operand:DI 2 "symbolic_operand")]
+	UNSPEC_LUI_H_HI12))]
+  "TARGET_64BIT"
+  "lu52i.d\t%0,%1,%H2"
+  [(set_attr "type" "move")]
+)
+
 ;; Convert floating-point numbers to integers
 (define_insn "frint_<fmt>"
   [(set (match_operand:ANYF 0 "register_operand" "=f")
diff --git a/gcc/config/loongarch/predicates.md b/gcc/config/loongarch/predicates.md
index cd3528c7c97..e38c6fbdd5f 100644
--- a/gcc/config/loongarch/predicates.md
+++ b/gcc/config/loongarch/predicates.md
@@ -111,7 +111,7 @@ (define_predicate "const_call_insn_operand"
   (match_code "const,symbol_ref,label_ref")
 {
   /* Split symbol to high and low if return false.
-     If defined TARGET_CMODEL_LARGE, all symbol would be splited,
+     If defined TARGET_CMODEL_EXTREME, all symbol would be splited,
      else if offset is not zero, the symbol would be splited.  */
 
   enum loongarch_symbol_type symbol_type;
@@ -126,10 +126,13 @@ (define_predicate "const_call_insn_operand"
   switch (symbol_type)
     {
     case SYMBOL_PCREL:
-      return 1;
+      if (TARGET_CMODEL_EXTREME)
+	return false;
+      else
+	return 1;
 
     case SYMBOL_GOT_DISP:
-      if (TARGET_CMODEL_LARGE || !flag_plt)
+      if (TARGET_CMODEL_EXTREME || !flag_plt)
 	return false;
       else
 	return 1;
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 1ac81ad0bb4..8712bc25e3c 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -1020,6 +1020,7 @@ Objective-C and Objective-C++ Dialects}.
 -mcond-move-float  -mno-cond-move-float @gol
 -memcpy  -mno-memcpy -mstrict-align -mno-strict-align @gol
 -mmax-inline-memcpy-size=@var{n} @gol
+-mexplicit-relocs -mno-explicit-relocs @gol
 -mcmodel=@var{code-model}}
 
 @emph{M32R/D Options}
@@ -25076,50 +25077,19 @@ less than or equal to @var{n} bytes.  The default value of @var{n} is 1024.
 @item -mcmodel=@var{code-model}
 Set the code model to one of:
 @table @samp
-@item tiny-static
-@itemize @bullet
-@item
-local symbol and global strong symbol: The data section must be within +/-2MiB addressing space.
-The text section must be within +/-128MiB addressing space.
-@item
-global weak symbol: The got table must be within +/-2GiB addressing space.
-@end itemize
-
-@item tiny
-@itemize @bullet
-@item
-local symbol: The data section must be within +/-2MiB addressing space.
-The text section must be within +/-128MiB
-addressing space.
-@item
-global symbol: The got table must be within +/-2GiB addressing space.
-@end itemize
+@item tiny-static (Not implemented yet)
+@item tiny (Not implemented yet)
 
 @item normal
-@itemize @bullet
-@item
-local symbol: The data section must be within +/-2GiB addressing space.
-The text section must be within +/-128MiB addressing space.
-@item
-global symbol: The got table must be within +/-2GiB addressing space.
-@end itemize
+The text segment must be within 128MB addressing space.  The data segment must
+be within 2GB addressing space.
 
-@item large
-@itemize @bullet
-@item
-local symbol: The data section must be within +/-2GiB addressing space.
-The text section must be within +/-128GiB addressing space.
-@item
-global symbol: The got table must be within +/-2GiB addressing space.
-@end itemize
+@item large (Not implemented yet)
 
-@item extreme(Not implemented yet)
-@itemize @bullet
-@item
-local symbol: The data and text section must be within +/-8EiB addressing space.
-@item
-global symbol: The data got table must be within +/-8EiB addressing space.
-@end itemize
+@item extreme
+This mode does not limit the size of the code segment and data segment.
+The @option{-mcmodel=extreme} option is incompatible with @option{-fplt} and
+@option{-mno-explicit-relocs}.
 @end table
 The default code model is @code{normal}.
 
diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-1.c b/gcc/testsuite/gcc.target/loongarch/func-call-1.c
index 01b8ea23fb9..76bf11b0c03 100644
--- a/gcc/testsuite/gcc.target/loongarch/func-call-1.c
+++ b/gcc/testsuite/gcc.target/loongarch/func-call-1.c
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-mabi=lp64d -O0 -fpic -fplt -mno-explicit-relocs" } */
+/* { dg-options "-mabi=lp64d -O0 -fpic -fplt -mno-explicit-relocs -mcmodel=normal" } */
 /* { dg-final { scan-assembler "test:.*bl\t%plt\\(g\\)\n" } } */
 /* { dg-final { scan-assembler "test1:.*bl\t%plt\\(f\\)\n" } } */
 /* { dg-final { scan-assembler "test2:.*bl\tl\n" } } */
diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-2.c b/gcc/testsuite/gcc.target/loongarch/func-call-2.c
index 4565baaec9e..4b468fef8b4 100644
--- a/gcc/testsuite/gcc.target/loongarch/func-call-2.c
+++ b/gcc/testsuite/gcc.target/loongarch/func-call-2.c
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-mabi=lp64d -O0 -fno-pic -fplt -mno-explicit-relocs" } */
+/* { dg-options "-mabi=lp64d -O0 -fno-pic -fplt -mno-explicit-relocs -mcmodel=normal" } */
 /* { dg-final { scan-assembler "test:.*bl\t%plt\\(g\\)\n" } } */
 /* { dg-final { scan-assembler "test1:.*bl\tf\n" } } */
 /* { dg-final { scan-assembler "test2:.*bl\tl\n" } } */
diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-3.c b/gcc/testsuite/gcc.target/loongarch/func-call-3.c
index 4f669a029e7..dd3a4882d60 100644
--- a/gcc/testsuite/gcc.target/loongarch/func-call-3.c
+++ b/gcc/testsuite/gcc.target/loongarch/func-call-3.c
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-mabi=lp64d -O0 -fpic -fno-plt -mno-explicit-relocs" } */
+/* { dg-options "-mabi=lp64d -O0 -fpic -fno-plt -mno-explicit-relocs -mcmodel=normal" } */
 /* { 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:.*bl\tl\n" } } */
diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-4.c b/gcc/testsuite/gcc.target/loongarch/func-call-4.c
index 943adb6403f..f8158ec349f 100644
--- a/gcc/testsuite/gcc.target/loongarch/func-call-4.c
+++ b/gcc/testsuite/gcc.target/loongarch/func-call-4.c
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-mabi=lp64d -O0 -fno-pic -fno-plt -mno-explicit-relocs" } */
+/* { dg-options "-mabi=lp64d -O0 -fno-pic -fno-plt -mno-explicit-relocs -mcmodel=normal" } */
 /* { dg-final { scan-assembler "test:.*la\.global\t.*g\n\tjirl" } } */
 /* { dg-final { scan-assembler "test1:.*bl\tf\n" } } */
 /* { dg-final { scan-assembler "test2:.*bl\tl\n" } } */
diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-5.c b/gcc/testsuite/gcc.target/loongarch/func-call-5.c
index 2c2a1c8a1b6..37994af430d 100644
--- a/gcc/testsuite/gcc.target/loongarch/func-call-5.c
+++ b/gcc/testsuite/gcc.target/loongarch/func-call-5.c
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-mabi=lp64d -O0 -fpic -fplt -mexplicit-relocs" } */
+/* { dg-options "-mabi=lp64d -O0 -fpic -fplt -mexplicit-relocs -mcmodel=normal" } */
 /* { dg-final { scan-assembler "test:.*bl\t%plt\\(g\\)\n" } } */
 /* { dg-final { scan-assembler "test1:.*bl\t%plt\\(f\\)\n" } } */
 /* { dg-final { scan-assembler "test2:.*bl\tl\n" } } */
diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-6.c b/gcc/testsuite/gcc.target/loongarch/func-call-6.c
index 4b0e4266ec8..8e366e376e7 100644
--- a/gcc/testsuite/gcc.target/loongarch/func-call-6.c
+++ b/gcc/testsuite/gcc.target/loongarch/func-call-6.c
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-mabi=lp64d -O0 -fno-pic -fplt -mexplicit-relocs" } */
+/* { dg-options "-mabi=lp64d -O0 -fno-pic -fplt -mexplicit-relocs -mcmodel=normal" } */
 /* { dg-final { scan-assembler "test:.*bl\t%plt\\(g\\)\n" } } */
 /* { dg-final { scan-assembler "test1:.*bl\tf\n" } } */
 /* { dg-final { scan-assembler "test2:.*bl\tl\n" } } */
diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-7.c b/gcc/testsuite/gcc.target/loongarch/func-call-7.c
index 51792711f72..4177c3d962e 100644
--- a/gcc/testsuite/gcc.target/loongarch/func-call-7.c
+++ b/gcc/testsuite/gcc.target/loongarch/func-call-7.c
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-mabi=lp64d -O0 -fpic -fno-plt -mexplicit-relocs" } */
+/* { dg-options "-mabi=lp64d -O0 -fpic -fno-plt -mexplicit-relocs -mcmodel=normal" } */
 /* { 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:.*bl\tl\n" } } */
diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-8.c b/gcc/testsuite/gcc.target/loongarch/func-call-8.c
index 330140d883d..4254eaa16d4 100644
--- a/gcc/testsuite/gcc.target/loongarch/func-call-8.c
+++ b/gcc/testsuite/gcc.target/loongarch/func-call-8.c
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-mabi=lp64d -O0 -fno-pic -fno-plt -mexplicit-relocs" } */
+/* { dg-options "-mabi=lp64d -O0 -fno-pic -fno-plt -mexplicit-relocs -mcmodel=normal" } */
 /* { 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:.*bl\tf\n" } } */
 /* { dg-final { scan-assembler "test2:.*bl\tl\n" } } */
diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-extreme-1.c b/gcc/testsuite/gcc.target/loongarch/func-call-extreme-1.c
new file mode 100644
index 00000000000..db1e0f85396
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/func-call-extreme-1.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-mabi=lp64d -O0 -fno-pic -fno-plt -mexplicit-relocs -mcmodel=extreme" } */
+/* { dg-final { scan-assembler "test:.*pcalau12i.*%got_pc_hi20.*\n\taddi\.d.*%got_pc_lo12.*\n\tlu32i\.d.*%got64_pc_lo20.*\n\tlu52i\.d.*%got64_pc_hi12.*\n\tldx\.d" } } */
+/* { dg-final { scan-assembler "test1:.*pcalau12i.*%pc_hi20.*\n\taddi\.d.*%pc_lo12.*\n\tlu32i\.d.*%pc64_lo20.*\n\tlu52i\.d.*pc64_hi12.*\n\tadd\.d" } } */
+/* { dg-final { scan-assembler "test2:.*pcalau12i.*%pc_hi20.*\n\taddi\.d.*%pc_lo12.*\n\tlu32i\.d.*%pc64_lo20.*\n\tlu52i\.d.*pc64_hi12.*\n\tadd\.d" } } */
+
+extern void g (void);
+void
+f (void)
+{}
+
+static void
+l (void)
+{}
+
+void
+test (void)
+{
+  g ();
+}
+
+void
+test1 (void)
+{
+  f ();
+}
+
+void
+test2 (void)
+{
+  l ();
+}
diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-extreme-2.c b/gcc/testsuite/gcc.target/loongarch/func-call-extreme-2.c
new file mode 100644
index 00000000000..21bf81ae837
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/func-call-extreme-2.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-mabi=lp64d -O0 -fpic -fno-plt -mexplicit-relocs -mcmodel=extreme" } */
+/* { dg-final { scan-assembler "test:.*pcalau12i.*%got_pc_hi20.*\n\taddi\.d.*%got_pc_lo12.*\n\tlu32i\.d.*%got64_pc_lo20.*\n\tlu52i\.d.*%got64_pc_hi12.*\n\tldx\.d" } } */
+/* { dg-final { scan-assembler "test1:.*pcalau12i.*%got_pc_hi20.*\n\taddi\.d.*%got_pc_lo12.*\n\tlu32i\.d.*%got64_pc_lo20.*\n\tlu52i\.d.*%got64_pc_hi12.*\n\tldx\.d" } } */
+/* { dg-final { scan-assembler "test2:.*pcalau12i.*%pc_hi20.*\n\taddi\.d.*%pc_lo12.*\n\tlu32i\.d.*%pc64_lo20.*\n\tlu52i\.d.*pc64_hi12.*\n\tadd\.d" } } */
+
+extern void g (void);
+void
+f (void)
+{}
+
+static void
+l (void)
+{}
+
+void
+test (void)
+{
+  g ();
+}
+
+void
+test1 (void)
+{
+  f ();
+}
+
+void
+test2 (void)
+{
+  l ();
+}
diff --git a/gcc/testsuite/gcc.target/loongarch/relocs-symbol-noaddend.c b/gcc/testsuite/gcc.target/loongarch/relocs-symbol-noaddend.c
index bfcc9bc338f..3ec8bd229fd 100644
--- a/gcc/testsuite/gcc.target/loongarch/relocs-symbol-noaddend.c
+++ b/gcc/testsuite/gcc.target/loongarch/relocs-symbol-noaddend.c
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-mabi=lp64d -mexplicit-relocs -fno-pic -O2" } */
+/* { dg-options "-mabi=lp64d -mexplicit-relocs -fno-pic -O2 -mcmodel=normal" } */
 /* { dg-final { scan-assembler "pcalau12i.*%pc_hi20\\(\.LANCHOR0\\)\n" } } */
 /* { dg-final { scan-assembler "addi\.d.*%pc_lo12\\(\.LANCHOR0\\)\n" } } */
 /* { dg-final { scan-assembler "ldptr.d\t\\\$r4,.*,0\n" } } */
-- 
2.31.1


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [commited PATCH v4] LoongArch: Add support code model extreme.
  2022-08-20  8:39 [PATCH v4] LoongArch: Add support code model extreme Lulu Cheng
@ 2022-08-20  9:04 ` Lulu Cheng
  0 siblings, 0 replies; 2+ messages in thread
From: Lulu Cheng @ 2022-08-20  9:04 UTC (permalink / raw)
  To: gcc-patches; +Cc: xry111, i, xuchenghua

Pushd to r13-2128.

在 2022/8/20 下午4:39, Lulu Cheng 写道:
> v1 -> v2:
> - Modify some description information.
> - Add options -W[no]extreme-plt, warn about code model extreme not support plt mode,
> and then disable plt.
>
> v2 -> v3:
> - When -mcmodel=extreme, default set to -fno-plt mode, if the user forces to use
> '-mcmodel=extreme -fplt', an error will be reported.
> - Delete -Wextreme-plt.
> - Fix bug when compiling with '-mcmodel=normal -fno-plt -mno-explicit-relocs'.
>
> v3 -> v4:
> - Fix the bug of loongarch_tls_symbol function loading in function
> loongarch_call_tls_get_addr.
>
> ----------------------------------------------------------------------------
> Use five instructions to calculate a signed 64-bit offset relative to the pc.
>
> gcc/ChangeLog:
>
> 	* config/loongarch/loongarch-opts.cc: Allow cmodel to be extreme.
> 	* config/loongarch/loongarch.cc (loongarch_call_tls_get_addr):
> 	Add extreme support for TLS GD and LD types.
> 	(loongarch_legitimize_tls_address): Add extreme support for TLS LE
> 	and IE.
> 	(loongarch_split_symbol): When compiling with -mcmodel=extreme,
> 	the symbol address will be obtained through five instructions.
> 	(loongarch_print_operand_reloc): Add support.
> 	(loongarch_print_operand): Add support.
> 	(loongarch_print_operand_address): Add support.
> 	(loongarch_option_override_internal): Set '-mcmodel=extreme' option
> 	incompatible with '-mno-explicit-relocs'.
> 	* config/loongarch/loongarch.md (@lui_l_hi20<mode>):
> 	Loads bits 12-31 of data into registers.
> 	(lui_h_lo20): Load bits 32-51 of the data and spell bits 0-31 of
> 	the source register.
> 	(lui_h_hi12): Load bits 52-63 of the data and spell bits 0-51 of
> 	the source register.
> 	* config/loongarch/predicates.md: Symbols need to be decomposed
> 	when defining the macro TARGET_CMODEL_EXTREME
> 	* doc/invoke.texi: Modify the description information of cmodel in the document.
> 	Document -W[no-]extreme-plt.
>
> gcc/testsuite/ChangeLog:
>
> 	* gcc.target/loongarch/func-call-1.c: Add option '-mcmodel=normal'.
> 	* gcc.target/loongarch/func-call-2.c: Likewise.
> 	* gcc.target/loongarch/func-call-3.c: Likewise.
> 	* gcc.target/loongarch/func-call-4.c: Likewise.
> 	* gcc.target/loongarch/func-call-5.c: Likewise.
> 	* gcc.target/loongarch/func-call-6.c: Likewise.
> 	* gcc.target/loongarch/func-call-7.c: Likewise.
> 	* gcc.target/loongarch/func-call-8.c: Likewise.
> 	* gcc.target/loongarch/relocs-symbol-noaddend.c: Likewise.
> 	* gcc.target/loongarch/func-call-extreme-1.c: New test.
> 	* gcc.target/loongarch/func-call-extreme-2.c: New test.
> ---
>   gcc/config/loongarch/loongarch-opts.cc        |   3 +-
>   gcc/config/loongarch/loongarch.cc             | 222 +++++++++++++++---
>   gcc/config/loongarch/loongarch.md             |  34 ++-
>   gcc/config/loongarch/predicates.md            |   9 +-
>   gcc/doc/invoke.texi                           |  50 +---
>   .../gcc.target/loongarch/func-call-1.c        |   2 +-
>   .../gcc.target/loongarch/func-call-2.c        |   2 +-
>   .../gcc.target/loongarch/func-call-3.c        |   2 +-
>   .../gcc.target/loongarch/func-call-4.c        |   2 +-
>   .../gcc.target/loongarch/func-call-5.c        |   2 +-
>   .../gcc.target/loongarch/func-call-6.c        |   2 +-
>   .../gcc.target/loongarch/func-call-7.c        |   2 +-
>   .../gcc.target/loongarch/func-call-8.c        |   2 +-
>   .../loongarch/func-call-extreme-1.c           |  32 +++
>   .../loongarch/func-call-extreme-2.c           |  32 +++
>   .../loongarch/relocs-symbol-noaddend.c        |   2 +-
>   16 files changed, 318 insertions(+), 82 deletions(-)
>   create mode 100644 gcc/testsuite/gcc.target/loongarch/func-call-extreme-1.c
>   create mode 100644 gcc/testsuite/gcc.target/loongarch/func-call-extreme-2.c
>
> diff --git a/gcc/config/loongarch/loongarch-opts.cc b/gcc/config/loongarch/loongarch-opts.cc
> index 3f70943ded6..2ae89f23443 100644
> --- a/gcc/config/loongarch/loongarch-opts.cc
> +++ b/gcc/config/loongarch/loongarch-opts.cc
> @@ -376,14 +376,13 @@ fallback:
>   
>     /* 5.  Target code model */
>     t.cmodel = constrained.cmodel ? opt_cmodel : CMODEL_NORMAL;
> -  if (t.cmodel != CMODEL_NORMAL)
> +  if (t.cmodel != CMODEL_NORMAL && t.cmodel != CMODEL_EXTREME)
>       {
>         warning (0, "%qs is not supported, now cmodel is set to %qs",
>   	       loongarch_cmodel_strings[t.cmodel], "normal");
>         t.cmodel = CMODEL_NORMAL;
>       }
>   
> -
>     /* Cleanup and return.  */
>     obstack_free (&msg_obstack, NULL);
>     *target = t;
> diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc
> index 24378143641..207ac2762c6 100644
> --- a/gcc/config/loongarch/loongarch.cc
> +++ b/gcc/config/loongarch/loongarch.cc
> @@ -2436,7 +2436,19 @@ loongarch_call_tls_get_addr (rtx sym, enum loongarch_symbol_type type, rtx v0)
>         /* Split tls symbol to high and low.  */
>         rtx high = gen_rtx_HIGH (Pmode, copy_rtx (loc));
>         high = loongarch_force_temporary (tmp, high);
> -      emit_insn (gen_tls_low (Pmode, a0, high, loc));
> +
> +      if (TARGET_CMODEL_EXTREME)
> +	{
> +	  gcc_assert (TARGET_EXPLICIT_RELOCS);
> +
> +	  rtx tmp1 = gen_reg_rtx (Pmode);
> +	  emit_insn (gen_tls_low (Pmode, tmp1, gen_rtx_REG (Pmode, 0), loc));
> +	  emit_insn (gen_lui_h_lo20 (tmp1, tmp1, loc));
> +	  emit_insn (gen_lui_h_hi12 (tmp1, tmp1, loc));
> +	  emit_move_insn (a0, gen_rtx_PLUS (Pmode, high, tmp1));
> +	}
> +      else
> +	emit_insn (gen_tls_low (Pmode, a0, high, loc));
>       }
>     else
>       {
> @@ -2449,14 +2461,44 @@ 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,
> +    insn = emit_call_insn (gen_call_value_internal (v0,
> +						    loongarch_tls_symbol,
>   						    const0_rtx));
>     else
>       {
>         rtx dest = 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));
> +
> +      if (TARGET_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));
> +	  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)
> +	    {
> +	      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);
> +	}
>         insn = emit_call_insn (gen_call_value_internal (v0, dest, const0_rtx));
>       }
>   
> @@ -2508,7 +2550,23 @@ loongarch_legitimize_tls_address (rtx loc)
>   	      tmp3 = gen_reg_rtx (Pmode);
>   	      rtx high = gen_rtx_HIGH (Pmode, copy_rtx (tmp2));
>   	      high = loongarch_force_temporary (tmp3, high);
> -	      emit_insn (gen_ld_from_got (Pmode, tmp1, high, tmp2));
> +
> +	      if (TARGET_CMODEL_EXTREME)
> +		{
> +		  gcc_assert (TARGET_EXPLICIT_RELOCS);
> +
> +		  rtx tmp3 = gen_reg_rtx (Pmode);
> +		  emit_insn (gen_tls_low (Pmode, tmp3,
> +					  gen_rtx_REG (Pmode, 0), tmp2));
> +		  emit_insn (gen_lui_h_lo20 (tmp3, tmp3, tmp2));
> +		  emit_insn (gen_lui_h_hi12 (tmp3, tmp3, tmp2));
> +		  emit_move_insn (tmp1,
> +				  gen_rtx_MEM (Pmode,
> +					       gen_rtx_PLUS (Pmode,
> +							     high, tmp3)));
> +		}
> +	      else
> +		emit_insn (gen_ld_from_got (Pmode, tmp1, high, tmp2));
>   	    }
>   	  else
>   	    emit_insn (loongarch_got_load_tls_ie (tmp1, loc));
> @@ -2530,11 +2588,18 @@ loongarch_legitimize_tls_address (rtx loc)
>   	      rtx high = gen_rtx_HIGH (Pmode, copy_rtx (tmp2));
>   	      high = loongarch_force_temporary (tmp3, high);
>   	      emit_insn (gen_ori_l_lo12 (Pmode, tmp1, high, tmp2));
> +
> +	      if (TARGET_CMODEL_EXTREME)
> +		{
> +		  gcc_assert (TARGET_EXPLICIT_RELOCS);
> +
> +		  emit_insn (gen_lui_h_lo20 (tmp1, tmp1, tmp2));
> +		  emit_insn (gen_lui_h_hi12 (tmp1, tmp1, tmp2));
> +		}
>   	    }
>   	  else
>   	    emit_insn (loongarch_got_load_tls_le (tmp1, loc));
>   	  emit_insn (gen_add3_insn (dest, tmp1, tp));
> -
>   	}
>         break;
>   
> @@ -2603,7 +2668,6 @@ bool
>   loongarch_split_symbol (rtx temp, rtx addr, machine_mode mode, rtx *low_out)
>   {
>     enum loongarch_symbol_type symbol_type;
> -  rtx high;
>   
>     /* If build with '-mno-explicit-relocs', don't split symbol.  */
>     if (!TARGET_EXPLICIT_RELOCS)
> @@ -2615,6 +2679,8 @@ loongarch_split_symbol (rtx temp, rtx addr, machine_mode mode, rtx *low_out)
>         || !loongarch_split_symbol_type (symbol_type))
>       return false;
>   
> +  rtx high, temp1 = NULL;
> +
>     if (temp == NULL)
>       temp = gen_reg_rtx (Pmode);
>   
> @@ -2622,20 +2688,42 @@ loongarch_split_symbol (rtx temp, rtx addr, machine_mode mode, rtx *low_out)
>     high = gen_rtx_HIGH (Pmode, copy_rtx (addr));
>     high = loongarch_force_temporary (temp, high);
>   
> +  if (TARGET_CMODEL_EXTREME && can_create_pseudo_p ())
> +    {
> +      gcc_assert (TARGET_EXPLICIT_RELOCS);
> +
> +      temp1 = gen_reg_rtx (Pmode);
> +      emit_move_insn (temp1, gen_rtx_LO_SUM (Pmode, gen_rtx_REG (Pmode, 0),
> +					     addr));
> +      emit_insn (gen_lui_h_lo20 (temp1, temp1, addr));
> +      emit_insn (gen_lui_h_hi12 (temp1, temp1, addr));
> +    }
> +
>     if (low_out)
>       switch (symbol_type)
>         {
>         case SYMBOL_PCREL:
> -	*low_out = gen_rtx_LO_SUM (Pmode, high, addr);
> -	break;
> +	{
> +	  if (TARGET_CMODEL_EXTREME && can_create_pseudo_p ())
> +	    *low_out = gen_rtx_PLUS (Pmode, high, temp1);
> +	  else
> +	    *low_out = gen_rtx_LO_SUM (Pmode, high, addr);
> +	  break;
> +	}
>   
>         case SYMBOL_GOT_DISP:
>   	/* SYMBOL_GOT_DISP symbols are loaded from the GOT.  */
>   	{
> -	  rtx low = gen_rtx_LO_SUM (Pmode, high, addr);
> -	  rtx mem = gen_rtx_MEM (Pmode, low);
> -	  *low_out = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, mem),
> -				     UNSPEC_LOAD_FROM_GOT);
> +	  if (TARGET_CMODEL_EXTREME && can_create_pseudo_p ())
> +	    *low_out = gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, high, temp1));
> +	  else
> +	    {
> +	      rtx low = gen_rtx_LO_SUM (Pmode, high, addr);
> +	      rtx mem = gen_rtx_MEM (Pmode, low);
> +	      *low_out = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, mem),
> +					 UNSPEC_LOAD_FROM_GOT);
> +	    }
> +
>   	  break;
>   	}
>   
> @@ -4584,34 +4672,86 @@ loongarch_memmodel_needs_release_fence (enum memmodel model)
>      in context CONTEXT.  HI_RELOC indicates a high-part reloc.  */
>   
>   static void
> -loongarch_print_operand_reloc (FILE *file, rtx op, bool hi_reloc)
> +loongarch_print_operand_reloc (FILE *file, rtx op, bool hi64_part,
> +			       bool hi_reloc)
>   {
>     const char *reloc;
>   
> +  if (TARGET_CMODEL_EXTREME)
> +    gcc_assert (TARGET_EXPLICIT_RELOCS);
> +
>     switch (loongarch_classify_symbolic_expression (op))
>       {
>       case SYMBOL_PCREL:
> -      reloc = hi_reloc ? "%pc_hi20" : "%pc_lo12";
> +      if (hi64_part)
> +	{
> +	  if (TARGET_CMODEL_EXTREME)
> +	    reloc = hi_reloc ? "%pc64_hi12" : "%pc64_lo20";
> +	  else
> +	    gcc_unreachable ();
> +	}
> +      else
> +	reloc = hi_reloc ? "%pc_hi20" : "%pc_lo12";
>         break;
>   
>       case SYMBOL_GOT_DISP:
> -      reloc = hi_reloc ? "%got_pc_hi20" : "%got_pc_lo12";
> +      if (hi64_part)
> +	{
> +	  if (TARGET_CMODEL_EXTREME)
> +	    reloc = hi_reloc ? "%got64_pc_hi12" : "%got64_pc_lo20";
> +	  else
> +	    gcc_unreachable ();
> +	}
> +      else
> +	reloc = hi_reloc ? "%got_pc_hi20" : "%got_pc_lo12";
>         break;
>   
>       case SYMBOL_TLS_IE:
> -      reloc = hi_reloc ? "%ie_pc_hi20" : "%ie_pc_lo12";
> +      if (hi64_part)
> +	{
> +	  if (TARGET_CMODEL_EXTREME)
> +	    reloc = hi_reloc ? "%ie64_pc_hi12" : "%ie64_pc_lo20";
> +	  else
> +	    gcc_unreachable ();
> +	}
> +      else
> +	reloc = hi_reloc ? "%ie_pc_hi20" : "%ie_pc_lo12";
>         break;
>   
>       case SYMBOL_TLS_LE:
> -      reloc = hi_reloc ? "%le_hi20" : "%le_lo12";
> +      if (hi64_part)
> +	{
> +	  if (TARGET_CMODEL_EXTREME)
> +	    reloc = hi_reloc ? "%le64_hi12" : "%le64_lo20";
> +	  else
> +	    gcc_unreachable ();
> +	}
> +      else
> +	reloc = hi_reloc ? "%le_hi20" : "%le_lo12";
>         break;
>   
>       case SYMBOL_TLSGD:
> -      reloc = hi_reloc ? "%gd_pc_hi20" : "%got_pc_lo12";
> +      if (hi64_part)
> +	{
> +	  if (TARGET_CMODEL_EXTREME)
> +	    reloc = hi_reloc ? "%got64_pc_hi12" : "%got64_pc_lo20";
> +	  else
> +	    gcc_unreachable ();
> +	}
> +      else
> +	reloc = hi_reloc ? "%gd_pc_hi20" : "%got_pc_lo12";
>         break;
>   
>       case SYMBOL_TLSLDM:
> -      reloc = hi_reloc ? "%ld_pc_hi20" : "%got_pc_lo12";
> +      if (hi64_part)
> +	{
> +	  if (TARGET_CMODEL_EXTREME)
> +	    reloc = hi_reloc ? "%got64_pc_hi12" : "%got64_pc_lo20";
> +	  else
> +	    gcc_unreachable ();
> +	}
> +      else
> +	reloc = hi_reloc ? "%ld_pc_hi20" : "%got_pc_lo12";
>         break;
>   
>       default:
> @@ -4637,6 +4777,8 @@ loongarch_print_operand_reloc (FILE *file, rtx op, bool hi_reloc)
>      'L'  Print the low-part relocation associated with OP.
>      'm'	Print one less than CONST_INT OP in decimal.
>      'N'	Print the inverse of the integer branch condition for comparison OP.
> +   'r'  Print address 12-31bit relocation associated with OP.
> +   'R'  Print address 32-51bit relocation associated with OP.
>      'T'	Print 'f' for (eq:CC ...), 't' for (ne:CC ...),
>   	      'z' for (eq:?I ...), 'n' for (ne:?I ...).
>      't'	Like 'T', but with the EQ/NE cases reversed
> @@ -4694,7 +4836,13 @@ loongarch_print_operand (FILE *file, rtx op, int letter)
>       case 'h':
>         if (code == HIGH)
>   	op = XEXP (op, 0);
> -      loongarch_print_operand_reloc (file, op, true /* hi_reloc */);
> +      loongarch_print_operand_reloc (file, op, false /* hi64_part */,
> +				     true /* hi_reloc */);
> +      break;
> +
> +    case 'H':
> +      loongarch_print_operand_reloc (file, op, true /* hi64_part */,
> +				     true /* hi_reloc */);
>         break;
>   
>       case 'i':
> @@ -4703,7 +4851,8 @@ loongarch_print_operand (FILE *file, rtx op, int letter)
>         break;
>   
>       case 'L':
> -      loongarch_print_operand_reloc (file, op, false /* lo_reloc */);
> +      loongarch_print_operand_reloc (file, op, false /* hi64_part*/,
> +				     false /* lo_reloc */);
>         break;
>   
>       case 'm':
> @@ -4718,6 +4867,16 @@ loongarch_print_operand (FILE *file, rtx op, int letter)
>   					    letter);
>         break;
>   
> +    case 'r':
> +      loongarch_print_operand_reloc (file, op, false /* hi64_part */,
> +				     true /* lo_reloc */);
> +      break;
> +
> +    case 'R':
> +      loongarch_print_operand_reloc (file, op, true /* hi64_part */,
> +				     false /* lo_reloc */);
> +      break;
> +
>       case 't':
>       case 'T':
>         {
> @@ -4848,7 +5007,8 @@ loongarch_print_operand_address (FILE *file, machine_mode /* mode  */, rtx x)
>   
>         case ADDRESS_LO_SUM:
>   	fprintf (file, "%s,", reg_names[REGNO (addr.reg)]);
> -	loongarch_print_operand_reloc (file, addr.offset, false /* hi_reloc */);
> +	loongarch_print_operand_reloc (file, addr.offset, false /* hi64_part */,
> +				       false /* hi_reloc */);
>   	return;
>   
>         case ADDRESS_CONST_INT:
> @@ -5821,13 +5981,21 @@ loongarch_option_override_internal (struct gcc_options *opts)
>   
>     switch (la_target.cmodel)
>       {
> -      case CMODEL_TINY_STATIC:
>         case CMODEL_EXTREME:
> +	if (!TARGET_EXPLICIT_RELOCS)
> +	  error ("code model %qs needs %s",
> +		 "extreme", "-mexplicit-relocs");
> +
>   	if (opts->x_flag_plt)
> -	  error ("code model %qs and %qs not support %s mode",
> -		 "tiny-static", "extreme", "plt");
> +	  {
> +	    if (global_options_set.x_flag_plt)
> +	      error ("code model %qs is not compatible with %s",
> +		     "extreme", "-fplt");
> +	    opts->x_flag_plt = 0;
> +	  }
>   	break;
>   
> +      case CMODEL_TINY_STATIC:
>         case CMODEL_NORMAL:
>         case CMODEL_TINY:
>         case CMODEL_LARGE:
> diff --git a/gcc/config/loongarch/loongarch.md b/gcc/config/loongarch/loongarch.md
> index 8e8868de9f5..8fc10444c2a 100644
> --- a/gcc/config/loongarch/loongarch.md
> +++ b/gcc/config/loongarch/loongarch.md
> @@ -60,6 +60,9 @@ (define_c_enum "unspec" [
>   
>     UNSPEC_LOAD_FROM_GOT
>     UNSPEC_ORI_L_LO12
> +  UNSPEC_LUI_L_HI20
> +  UNSPEC_LUI_H_LO20
> +  UNSPEC_LUI_H_HI12
>     UNSPEC_TLS_LOW
>   ])
>   
> @@ -1934,16 +1937,45 @@ (define_insn "@ld_from_got<mode>"
>     [(set_attr "type" "move")]
>   )
>   
> +(define_insn "@lui_l_hi20<mode>"
> +  [(set (match_operand:P 0 "register_operand" "=r")
> +	(unspec:P [(match_operand:P 1 "symbolic_operand")]
> +	UNSPEC_LUI_L_HI20))]
> +  ""
> +  "lu12i.w\t%0,%r1"
> +  [(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")
> -		    (match_operand:P 2 "symbolic_operand")]
> +		   (match_operand:P 2 "symbolic_operand")]
>   	UNSPEC_ORI_L_LO12))]
>     ""
>     "ori\t%0,%1,%L2"
>     [(set_attr "type" "move")]
>   )
>   
> +(define_insn "lui_h_lo20"
> +  [(set (match_operand:DI 0 "register_operand" "=r")
> +	(unspec:DI [(match_operand:DI 1 "register_operand" "0")
> +		    (match_operand:DI 2 "symbolic_operand")]
> +	UNSPEC_LUI_H_LO20))]
> +  "TARGET_64BIT"
> +  "lu32i.d\t%0,%R2"
> +  [(set_attr "type" "move")]
> +)
> +
> +(define_insn "lui_h_hi12"
> +  [(set (match_operand:DI 0 "register_operand" "=r")
> +	(unspec:DI [(match_operand:DI 1 "register_operand" "r")
> +		    (match_operand:DI 2 "symbolic_operand")]
> +	UNSPEC_LUI_H_HI12))]
> +  "TARGET_64BIT"
> +  "lu52i.d\t%0,%1,%H2"
> +  [(set_attr "type" "move")]
> +)
> +
>   ;; Convert floating-point numbers to integers
>   (define_insn "frint_<fmt>"
>     [(set (match_operand:ANYF 0 "register_operand" "=f")
> diff --git a/gcc/config/loongarch/predicates.md b/gcc/config/loongarch/predicates.md
> index cd3528c7c97..e38c6fbdd5f 100644
> --- a/gcc/config/loongarch/predicates.md
> +++ b/gcc/config/loongarch/predicates.md
> @@ -111,7 +111,7 @@ (define_predicate "const_call_insn_operand"
>     (match_code "const,symbol_ref,label_ref")
>   {
>     /* Split symbol to high and low if return false.
> -     If defined TARGET_CMODEL_LARGE, all symbol would be splited,
> +     If defined TARGET_CMODEL_EXTREME, all symbol would be splited,
>        else if offset is not zero, the symbol would be splited.  */
>   
>     enum loongarch_symbol_type symbol_type;
> @@ -126,10 +126,13 @@ (define_predicate "const_call_insn_operand"
>     switch (symbol_type)
>       {
>       case SYMBOL_PCREL:
> -      return 1;
> +      if (TARGET_CMODEL_EXTREME)
> +	return false;
> +      else
> +	return 1;
>   
>       case SYMBOL_GOT_DISP:
> -      if (TARGET_CMODEL_LARGE || !flag_plt)
> +      if (TARGET_CMODEL_EXTREME || !flag_plt)
>   	return false;
>         else
>   	return 1;
> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> index 1ac81ad0bb4..8712bc25e3c 100644
> --- a/gcc/doc/invoke.texi
> +++ b/gcc/doc/invoke.texi
> @@ -1020,6 +1020,7 @@ Objective-C and Objective-C++ Dialects}.
>   -mcond-move-float  -mno-cond-move-float @gol
>   -memcpy  -mno-memcpy -mstrict-align -mno-strict-align @gol
>   -mmax-inline-memcpy-size=@var{n} @gol
> +-mexplicit-relocs -mno-explicit-relocs @gol
>   -mcmodel=@var{code-model}}
>   
>   @emph{M32R/D Options}
> @@ -25076,50 +25077,19 @@ less than or equal to @var{n} bytes.  The default value of @var{n} is 1024.
>   @item -mcmodel=@var{code-model}
>   Set the code model to one of:
>   @table @samp
> -@item tiny-static
> -@itemize @bullet
> -@item
> -local symbol and global strong symbol: The data section must be within +/-2MiB addressing space.
> -The text section must be within +/-128MiB addressing space.
> -@item
> -global weak symbol: The got table must be within +/-2GiB addressing space.
> -@end itemize
> -
> -@item tiny
> -@itemize @bullet
> -@item
> -local symbol: The data section must be within +/-2MiB addressing space.
> -The text section must be within +/-128MiB
> -addressing space.
> -@item
> -global symbol: The got table must be within +/-2GiB addressing space.
> -@end itemize
> +@item tiny-static (Not implemented yet)
> +@item tiny (Not implemented yet)
>   
>   @item normal
> -@itemize @bullet
> -@item
> -local symbol: The data section must be within +/-2GiB addressing space.
> -The text section must be within +/-128MiB addressing space.
> -@item
> -global symbol: The got table must be within +/-2GiB addressing space.
> -@end itemize
> +The text segment must be within 128MB addressing space.  The data segment must
> +be within 2GB addressing space.
>   
> -@item large
> -@itemize @bullet
> -@item
> -local symbol: The data section must be within +/-2GiB addressing space.
> -The text section must be within +/-128GiB addressing space.
> -@item
> -global symbol: The got table must be within +/-2GiB addressing space.
> -@end itemize
> +@item large (Not implemented yet)
>   
> -@item extreme(Not implemented yet)
> -@itemize @bullet
> -@item
> -local symbol: The data and text section must be within +/-8EiB addressing space.
> -@item
> -global symbol: The data got table must be within +/-8EiB addressing space.
> -@end itemize
> +@item extreme
> +This mode does not limit the size of the code segment and data segment.
> +The @option{-mcmodel=extreme} option is incompatible with @option{-fplt} and
> +@option{-mno-explicit-relocs}.
>   @end table
>   The default code model is @code{normal}.
>   
> diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-1.c b/gcc/testsuite/gcc.target/loongarch/func-call-1.c
> index 01b8ea23fb9..76bf11b0c03 100644
> --- a/gcc/testsuite/gcc.target/loongarch/func-call-1.c
> +++ b/gcc/testsuite/gcc.target/loongarch/func-call-1.c
> @@ -1,5 +1,5 @@
>   /* { dg-do compile } */
> -/* { dg-options "-mabi=lp64d -O0 -fpic -fplt -mno-explicit-relocs" } */
> +/* { dg-options "-mabi=lp64d -O0 -fpic -fplt -mno-explicit-relocs -mcmodel=normal" } */
>   /* { dg-final { scan-assembler "test:.*bl\t%plt\\(g\\)\n" } } */
>   /* { dg-final { scan-assembler "test1:.*bl\t%plt\\(f\\)\n" } } */
>   /* { dg-final { scan-assembler "test2:.*bl\tl\n" } } */
> diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-2.c b/gcc/testsuite/gcc.target/loongarch/func-call-2.c
> index 4565baaec9e..4b468fef8b4 100644
> --- a/gcc/testsuite/gcc.target/loongarch/func-call-2.c
> +++ b/gcc/testsuite/gcc.target/loongarch/func-call-2.c
> @@ -1,5 +1,5 @@
>   /* { dg-do compile } */
> -/* { dg-options "-mabi=lp64d -O0 -fno-pic -fplt -mno-explicit-relocs" } */
> +/* { dg-options "-mabi=lp64d -O0 -fno-pic -fplt -mno-explicit-relocs -mcmodel=normal" } */
>   /* { dg-final { scan-assembler "test:.*bl\t%plt\\(g\\)\n" } } */
>   /* { dg-final { scan-assembler "test1:.*bl\tf\n" } } */
>   /* { dg-final { scan-assembler "test2:.*bl\tl\n" } } */
> diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-3.c b/gcc/testsuite/gcc.target/loongarch/func-call-3.c
> index 4f669a029e7..dd3a4882d60 100644
> --- a/gcc/testsuite/gcc.target/loongarch/func-call-3.c
> +++ b/gcc/testsuite/gcc.target/loongarch/func-call-3.c
> @@ -1,5 +1,5 @@
>   /* { dg-do compile } */
> -/* { dg-options "-mabi=lp64d -O0 -fpic -fno-plt -mno-explicit-relocs" } */
> +/* { dg-options "-mabi=lp64d -O0 -fpic -fno-plt -mno-explicit-relocs -mcmodel=normal" } */
>   /* { 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:.*bl\tl\n" } } */
> diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-4.c b/gcc/testsuite/gcc.target/loongarch/func-call-4.c
> index 943adb6403f..f8158ec349f 100644
> --- a/gcc/testsuite/gcc.target/loongarch/func-call-4.c
> +++ b/gcc/testsuite/gcc.target/loongarch/func-call-4.c
> @@ -1,5 +1,5 @@
>   /* { dg-do compile } */
> -/* { dg-options "-mabi=lp64d -O0 -fno-pic -fno-plt -mno-explicit-relocs" } */
> +/* { dg-options "-mabi=lp64d -O0 -fno-pic -fno-plt -mno-explicit-relocs -mcmodel=normal" } */
>   /* { dg-final { scan-assembler "test:.*la\.global\t.*g\n\tjirl" } } */
>   /* { dg-final { scan-assembler "test1:.*bl\tf\n" } } */
>   /* { dg-final { scan-assembler "test2:.*bl\tl\n" } } */
> diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-5.c b/gcc/testsuite/gcc.target/loongarch/func-call-5.c
> index 2c2a1c8a1b6..37994af430d 100644
> --- a/gcc/testsuite/gcc.target/loongarch/func-call-5.c
> +++ b/gcc/testsuite/gcc.target/loongarch/func-call-5.c
> @@ -1,5 +1,5 @@
>   /* { dg-do compile } */
> -/* { dg-options "-mabi=lp64d -O0 -fpic -fplt -mexplicit-relocs" } */
> +/* { dg-options "-mabi=lp64d -O0 -fpic -fplt -mexplicit-relocs -mcmodel=normal" } */
>   /* { dg-final { scan-assembler "test:.*bl\t%plt\\(g\\)\n" } } */
>   /* { dg-final { scan-assembler "test1:.*bl\t%plt\\(f\\)\n" } } */
>   /* { dg-final { scan-assembler "test2:.*bl\tl\n" } } */
> diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-6.c b/gcc/testsuite/gcc.target/loongarch/func-call-6.c
> index 4b0e4266ec8..8e366e376e7 100644
> --- a/gcc/testsuite/gcc.target/loongarch/func-call-6.c
> +++ b/gcc/testsuite/gcc.target/loongarch/func-call-6.c
> @@ -1,5 +1,5 @@
>   /* { dg-do compile } */
> -/* { dg-options "-mabi=lp64d -O0 -fno-pic -fplt -mexplicit-relocs" } */
> +/* { dg-options "-mabi=lp64d -O0 -fno-pic -fplt -mexplicit-relocs -mcmodel=normal" } */
>   /* { dg-final { scan-assembler "test:.*bl\t%plt\\(g\\)\n" } } */
>   /* { dg-final { scan-assembler "test1:.*bl\tf\n" } } */
>   /* { dg-final { scan-assembler "test2:.*bl\tl\n" } } */
> diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-7.c b/gcc/testsuite/gcc.target/loongarch/func-call-7.c
> index 51792711f72..4177c3d962e 100644
> --- a/gcc/testsuite/gcc.target/loongarch/func-call-7.c
> +++ b/gcc/testsuite/gcc.target/loongarch/func-call-7.c
> @@ -1,5 +1,5 @@
>   /* { dg-do compile } */
> -/* { dg-options "-mabi=lp64d -O0 -fpic -fno-plt -mexplicit-relocs" } */
> +/* { dg-options "-mabi=lp64d -O0 -fpic -fno-plt -mexplicit-relocs -mcmodel=normal" } */
>   /* { 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:.*bl\tl\n" } } */
> diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-8.c b/gcc/testsuite/gcc.target/loongarch/func-call-8.c
> index 330140d883d..4254eaa16d4 100644
> --- a/gcc/testsuite/gcc.target/loongarch/func-call-8.c
> +++ b/gcc/testsuite/gcc.target/loongarch/func-call-8.c
> @@ -1,5 +1,5 @@
>   /* { dg-do compile } */
> -/* { dg-options "-mabi=lp64d -O0 -fno-pic -fno-plt -mexplicit-relocs" } */
> +/* { dg-options "-mabi=lp64d -O0 -fno-pic -fno-plt -mexplicit-relocs -mcmodel=normal" } */
>   /* { 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:.*bl\tf\n" } } */
>   /* { dg-final { scan-assembler "test2:.*bl\tl\n" } } */
> diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-extreme-1.c b/gcc/testsuite/gcc.target/loongarch/func-call-extreme-1.c
> new file mode 100644
> index 00000000000..db1e0f85396
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/loongarch/func-call-extreme-1.c
> @@ -0,0 +1,32 @@
> +/* { dg-do compile } */
> +/* { dg-options "-mabi=lp64d -O0 -fno-pic -fno-plt -mexplicit-relocs -mcmodel=extreme" } */
> +/* { dg-final { scan-assembler "test:.*pcalau12i.*%got_pc_hi20.*\n\taddi\.d.*%got_pc_lo12.*\n\tlu32i\.d.*%got64_pc_lo20.*\n\tlu52i\.d.*%got64_pc_hi12.*\n\tldx\.d" } } */
> +/* { dg-final { scan-assembler "test1:.*pcalau12i.*%pc_hi20.*\n\taddi\.d.*%pc_lo12.*\n\tlu32i\.d.*%pc64_lo20.*\n\tlu52i\.d.*pc64_hi12.*\n\tadd\.d" } } */
> +/* { dg-final { scan-assembler "test2:.*pcalau12i.*%pc_hi20.*\n\taddi\.d.*%pc_lo12.*\n\tlu32i\.d.*%pc64_lo20.*\n\tlu52i\.d.*pc64_hi12.*\n\tadd\.d" } } */
> +
> +extern void g (void);
> +void
> +f (void)
> +{}
> +
> +static void
> +l (void)
> +{}
> +
> +void
> +test (void)
> +{
> +  g ();
> +}
> +
> +void
> +test1 (void)
> +{
> +  f ();
> +}
> +
> +void
> +test2 (void)
> +{
> +  l ();
> +}
> diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-extreme-2.c b/gcc/testsuite/gcc.target/loongarch/func-call-extreme-2.c
> new file mode 100644
> index 00000000000..21bf81ae837
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/loongarch/func-call-extreme-2.c
> @@ -0,0 +1,32 @@
> +/* { dg-do compile } */
> +/* { dg-options "-mabi=lp64d -O0 -fpic -fno-plt -mexplicit-relocs -mcmodel=extreme" } */
> +/* { dg-final { scan-assembler "test:.*pcalau12i.*%got_pc_hi20.*\n\taddi\.d.*%got_pc_lo12.*\n\tlu32i\.d.*%got64_pc_lo20.*\n\tlu52i\.d.*%got64_pc_hi12.*\n\tldx\.d" } } */
> +/* { dg-final { scan-assembler "test1:.*pcalau12i.*%got_pc_hi20.*\n\taddi\.d.*%got_pc_lo12.*\n\tlu32i\.d.*%got64_pc_lo20.*\n\tlu52i\.d.*%got64_pc_hi12.*\n\tldx\.d" } } */
> +/* { dg-final { scan-assembler "test2:.*pcalau12i.*%pc_hi20.*\n\taddi\.d.*%pc_lo12.*\n\tlu32i\.d.*%pc64_lo20.*\n\tlu52i\.d.*pc64_hi12.*\n\tadd\.d" } } */
> +
> +extern void g (void);
> +void
> +f (void)
> +{}
> +
> +static void
> +l (void)
> +{}
> +
> +void
> +test (void)
> +{
> +  g ();
> +}
> +
> +void
> +test1 (void)
> +{
> +  f ();
> +}
> +
> +void
> +test2 (void)
> +{
> +  l ();
> +}
> diff --git a/gcc/testsuite/gcc.target/loongarch/relocs-symbol-noaddend.c b/gcc/testsuite/gcc.target/loongarch/relocs-symbol-noaddend.c
> index bfcc9bc338f..3ec8bd229fd 100644
> --- a/gcc/testsuite/gcc.target/loongarch/relocs-symbol-noaddend.c
> +++ b/gcc/testsuite/gcc.target/loongarch/relocs-symbol-noaddend.c
> @@ -1,5 +1,5 @@
>   /* { dg-do compile } */
> -/* { dg-options "-mabi=lp64d -mexplicit-relocs -fno-pic -O2" } */
> +/* { dg-options "-mabi=lp64d -mexplicit-relocs -fno-pic -O2 -mcmodel=normal" } */
>   /* { dg-final { scan-assembler "pcalau12i.*%pc_hi20\\(\.LANCHOR0\\)\n" } } */
>   /* { dg-final { scan-assembler "addi\.d.*%pc_lo12\\(\.LANCHOR0\\)\n" } } */
>   /* { dg-final { scan-assembler "ldptr.d\t\\\$r4,.*,0\n" } } */


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2022-08-20  9:04 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-08-20  8:39 [PATCH v4] LoongArch: Add support code model extreme Lulu Cheng
2022-08-20  9:04 ` [commited PATCH " Lulu Cheng

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).