public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [RFC][V2] RISC-V: Support -mcmodel=large.
@ 2023-11-10  9:00 KuanLin Chen
  2023-11-10  9:10 ` KuanLin Chen
  0 siblings, 1 reply; 11+ messages in thread
From: KuanLin Chen @ 2023-11-10  9:00 UTC (permalink / raw)
  To: gcc-patches, jeffreyalaw, Kito Cheng


[-- Attachment #1.1: Type: text/plain, Size: 5084 bytes --]

gcc/ChangeLog:

* gcc/config/riscv/predicates.md(move_operand): Check SYMBOL_REF
and LABEL_REF type.
(call_insn_operand): Support for CM_Large.
(pcrel_symbol_operand): New.
* gcc/config/riscv/riscv-c.cc (riscv_cpu_cpp_builtins): Add builtin_define
"__riscv_cmodel_large".
* gcc/config/riscv/riscv-opts.h (riscv_code_model): Define CM_LARGE.
* gcc/config/riscv/riscv-protos.h (riscv_symbol_type): Define
SYMBOL_FORCE_TO_MEM.
* gcc/config/riscv/riscv.cc (riscv_classify_symbol) Support CM_LARGE model.
(riscv_symbol_insns) Add SYMBOL_FORCE_TO_MEM.
(riscv_cannot_force_const_mem): Ditto.
(riscv_split_symbol): Ditto.
(riscv_force_address): Check pseudo reg available before force_reg.
(riscv_can_use_per_function_literal_pools_p): New.
(riscv_elf_select_rtx_section): Literal pool stays with the function.
(riscv_output_mi_thunk): Add riscv_in_thunk_func.
(riscv_option_override): Support CM_LARGE model.
(riscv_function_ok_for_sibcall): Disable sibcalls in CM_LARGE model.
* gcc/config/riscv/riscv.h (ASM_OUTPUT_POOL_EPILOGUE): Hookfg
* gcc/config/riscv/riscv.md (unspec): Define UNSPEC_FORCE_FOR_MEM.
(*large_load_address"): New.
* gcc/config/riscv/riscv.opt (code_model): New.

gcc/testsuite/ChangeLog:


  * gcc/testsuite/gcc.target/riscv/large-model.c: New test.


Hi Jeff,

Thanks for your review.

>     return (absolute_symbolic_oeprand (op, mode)>           || plt_symbolic_operand (op, mode)
>            || register_operand (op, mode);
Sorry for the unformatted indet. Fixed it at the V2 patch.
>> @@ -1972,7 +1992,19 @@ static rtx
>>   riscv_force_address (rtx x, machine_mode mode)
>>   {
>>     if (!riscv_legitimate_address_p (mode, x, false))
>>  -    x = force_reg (Pmode, x);
>> +    {
>> +      if (can_create_pseudo_p ())
>> +     return force_reg (Pmode, x);
> Note that $ra is fixed now.  So if you need a scratch register, you can
> fall back to $ra.

> More importantly, what are the circumstances where you can be asked to
> force an address after the register allocation/reloading phase is
> complete?  Or does it happen within the register allocators (the latter
> would be an indicator we need a secondary reload).

This address forcing is from riscv_output_mi_thunk:

insn = emit_call_insn (gen_sibcall (fnaddr, const0_rtx, callee_cc)).

This hook is called after IRA/LRA so it cannot use pseudo registers.

When compiler tries to expand 'sibcall', it calls
riscv_legitimize_call_address and 'fnaddr'

is not a legal call_insn_operand. Then, the address goes a
long-distance trip to legitimize.

Here is a example that using output thunks

===
class base
{
  virtual int foo(int a);
};

class derived : public virtual base
{
  virtual int foo(int a);
};

int base::foo(int a) { return a; }
int derived::foo(int a) { return a; }

base* make() { return new derived; }
===

>>   riscv_in_small_data_p (const_tree x)

> How does large code model impact our ability to access small data
> through $gp?  Aren't they independent?

I thought constant pool entries may be put into the small data section.

But it seems I was wrong. Removed this part at V2 patch.


>> +  if ((offset & 3) && riscv_can_use_per_function_literal_pools_p ())
>> +    ASM_OUTPUT_ALIGN (f, 2);
>> +}
> So the comment implies you're aligning the section.  If that were the
> case, then why doesn't the function alignment come from
> FUNCTION_BOUNDARY when we first start emitting the function?

> Or is it the case that the comment is incorrect and you've actually got
> mixed code/rodata?

I forgot there is an alignment from FUNCTION_BOUNDARY.  Removed this
part at V2 patch.

>> +(define_insn "*large_load_address"
>> +  [(set (match_operand:DI 0 "register_operand" "=r")
>> +        (mem:DI (match_operand 1 "pcrel_symbol_operand" "")))]
>> +  "TARGET_64BIT && riscv_cmodel == CM_LARGE"
>> +  "ld\t%0,%1"
>> +  [(set_attr "type" "load")
>> +   (set (attr "length") (const_int 8))])
> So it would seem like you're relying on the assembler to expand the ld?
> Is there any reasonable way to expose this properly to the compiler?
> I'd start by emitting the right instructions in the template.  Once
> that's working, then we could look to split the components into distinct
> insns.

> I also worry that we've got a mem->reg move instruction that is not
> implemented in the standard movXX patterns.  Traditionally that's been a
> recipe for problems.  It was certainly a requirement for reload, but I
> don't know offhand if it's a hard requirement for LRA.

> Can you try to merge that in with the standard movdi pattern?

This is a tricky idea for loading the constant pool anchor.

The idea comes from the pattern '*local_pic_load'.

If removing this rtl pattern, GCC will generate 'lla a5,.LC0 + ld
a0,0(a5)' to get the anchor address.

But with this pattern, GCC can generate 'ld a0,.LC0'.

And the code generation is easier for the linker to relax.


> Overall it looks pretty good.   Does Andestech have a copyright
> assignment in place?  Or are you contributing under the DCO rule?

As Kito mentioned, Andestech and I have signed FSF copyright assignment.

Thank you once again.

[-- Attachment #2: 0001-RISC-V-Support-mcmodel-large.patch --]
[-- Type: application/octet-stream, Size: 11569 bytes --]

From 3cbf1662cd275139e0982951132149bb7e4454d0 Mon Sep 17 00:00:00 2001
From: Kuan-Lin Chen <rufus@andestech.com>
Date: Sun, 18 Feb 2018 20:19:49 +0800
Subject: [PATCH] RISC-V: Support -mcmodel=large.

---
 gcc/config/riscv/predicates.md               | 23 +++++--
 gcc/config/riscv/riscv-c.cc                  |  4 ++
 gcc/config/riscv/riscv-opts.h                |  1 +
 gcc/config/riscv/riscv-protos.h              |  4 +-
 gcc/config/riscv/riscv.cc                    | 70 +++++++++++++++++++-
 gcc/config/riscv/riscv.h                     |  2 +
 gcc/config/riscv/riscv.md                    |  9 +++
 gcc/config/riscv/riscv.opt                   |  3 +
 gcc/testsuite/gcc.target/riscv/large-model.c | 11 +++
 9 files changed, 120 insertions(+), 7 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/large-model.c

diff --git a/gcc/config/riscv/predicates.md b/gcc/config/riscv/predicates.md
index 90567a817a7..f7ec66257c5 100644
--- a/gcc/config/riscv/predicates.md
+++ b/gcc/config/riscv/predicates.md
@@ -283,7 +283,8 @@
     case SYMBOL_REF:
     case LABEL_REF:
       return riscv_symbolic_constant_p (op, &symbol_type)
-	      && !riscv_split_symbol_type (symbol_type);
+	     && !riscv_split_symbol_type (symbol_type)
+	     && symbol_type != SYMBOL_FORCE_TO_MEM;
 
     case HIGH:
       op = XEXP (op, 0);
@@ -320,9 +321,15 @@
 })
 
 (define_predicate "call_insn_operand"
-  (ior (match_operand 0 "absolute_symbolic_operand")
-       (match_operand 0 "plt_symbolic_operand")
-       (match_operand 0 "register_operand")))
+  (match_operand 0 "general_operand")
+{
+  if (riscv_cmodel == CM_LARGE)
+    return register_operand (op, mode);
+  else
+    return (absolute_symbolic_operand (op, mode)
+	    || plt_symbolic_operand (op, mode)
+	    || register_operand (op, mode));
+})
 
 (define_predicate "modular_operator"
   (match_code "plus,minus,mult,ashift"))
@@ -605,3 +612,11 @@
   (and (match_code "const_int")
        (ior (match_operand 0 "not_uimm_extra_bit_operand")
 	    (match_operand 0 "const_nottwobits_not_arith_operand"))))
+
+(define_predicate "pcrel_symbol_operand"
+  (match_code "symbol_ref")
+{
+  enum riscv_symbol_type type;
+  return (riscv_symbolic_constant_p (op, &type)
+         && type == SYMBOL_PCREL);
+})
diff --git a/gcc/config/riscv/riscv-c.cc b/gcc/config/riscv/riscv-c.cc
index bedf7217390..59f2062bf4d 100644
--- a/gcc/config/riscv/riscv-c.cc
+++ b/gcc/config/riscv/riscv-c.cc
@@ -101,6 +101,10 @@ riscv_cpu_cpp_builtins (cpp_reader *pfile)
       builtin_define ("__riscv_cmodel_medlow");
       break;
 
+    case CM_LARGE:
+      builtin_define ("__riscv_cmodel_large");
+      break;
+
     case CM_PIC:
     case CM_MEDANY:
       builtin_define ("__riscv_cmodel_medany");
diff --git a/gcc/config/riscv/riscv-opts.h b/gcc/config/riscv/riscv-opts.h
index 532b1b6b84a..e30cca4d195 100644
--- a/gcc/config/riscv/riscv-opts.h
+++ b/gcc/config/riscv/riscv-opts.h
@@ -35,6 +35,7 @@ extern enum riscv_abi_type riscv_abi;
 enum riscv_code_model {
   CM_MEDLOW,
   CM_MEDANY,
+  CM_LARGE,
   CM_PIC
 };
 extern enum riscv_code_model riscv_cmodel;
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index 85d4f6ed9ea..7281405ed49 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -28,6 +28,7 @@ along with GCC; see the file COPYING3.  If not see
    the unspec enum in riscv.md, subsequent to UNSPEC_ADDRESS_FIRST.  */
 enum riscv_symbol_type {
   SYMBOL_ABSOLUTE,
+  SYMBOL_FORCE_TO_MEM,
   SYMBOL_PCREL,
   SYMBOL_GOT_DISP,
   SYMBOL_TLS,
@@ -158,7 +159,8 @@ extern bool riscv_shamt_matches_mask_p (int, HOST_WIDE_INT);
 extern void riscv_subword_address (rtx, rtx *, rtx *, rtx *, rtx *);
 extern void riscv_lshift_subword (machine_mode, rtx, rtx, rtx *);
 extern enum memmodel riscv_union_memmodels (enum memmodel, enum memmodel);
-
+extern void riscv_asm_output_pool_epilogue (FILE *, const char *,
+					    tree, HOST_WIDE_INT);
 /* Routines implemented in riscv-c.cc.  */
 void riscv_cpu_cpp_builtins (cpp_reader *);
 void riscv_register_pragmas (void);
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 08ff05dcc3f..3b6e3b00613 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -287,6 +287,9 @@ bool riscv_user_wants_strict_align;
 /* Stack alignment to assume/maintain.  */
 unsigned riscv_stack_boundary;
 
+/* Whether in riscv_output_mi_thunk. */
+static bool riscv_in_thunk_func = false;
+
 /* If non-zero, this is an offset to be added to SP to redefine the CFA
    when restoring the FP register from the stack.  Only valid when generating
    the epilogue.  */
@@ -803,7 +806,17 @@ riscv_classify_symbol (const_rtx x)
   if (GET_CODE (x) == SYMBOL_REF && flag_pic && !riscv_symbol_binds_local_p (x))
     return SYMBOL_GOT_DISP;
 
-  return riscv_cmodel == CM_MEDLOW ? SYMBOL_ABSOLUTE : SYMBOL_PCREL;
+  switch (riscv_cmodel)
+    {
+    case CM_MEDLOW:
+      return SYMBOL_ABSOLUTE;
+    case CM_LARGE:
+      if (SYMBOL_REF_P (x))
+	return CONSTANT_POOL_ADDRESS_P (x) ? SYMBOL_PCREL : SYMBOL_FORCE_TO_MEM;
+      return SYMBOL_PCREL;
+    default:
+      return SYMBOL_PCREL;
+    }
 }
 
 /* Classify the base of symbolic expression X.  */
@@ -867,6 +880,7 @@ static int riscv_symbol_insns (enum riscv_symbol_type type)
     case SYMBOL_PCREL: return 2; /* AUIPC + the reference.  */
     case SYMBOL_TLS_LE: return 3; /* LUI + ADD TP + the reference.  */
     case SYMBOL_GOT_DISP: return 3; /* AUIPC + LD GOT + the reference.  */
+    case SYMBOL_FORCE_TO_MEM: return 3; /* AUIPC + LD + the reference.  */
     default: gcc_unreachable ();
     }
 }
@@ -1036,6 +1050,9 @@ riscv_cannot_force_const_mem (machine_mode mode ATTRIBUTE_UNUSED, rtx x)
   split_const (x, &base, &offset);
   if (riscv_symbolic_constant_p (base, &type))
     {
+      if (type == SYMBOL_FORCE_TO_MEM)
+	return false;
+
       /* As an optimization, don't spill symbolic constants that are as
 	 cheap to rematerialize as to access in the constant pool.  */
       if (SMALL_OPERAND (INTVAL (offset)) && riscv_symbol_insns (type) > 0)
@@ -1843,6 +1860,9 @@ riscv_split_symbol (rtx temp, rtx addr, machine_mode mode, rtx *low_out)
   if (low_out)
     switch (symbol_type)
       {
+      case SYMBOL_FORCE_TO_MEM:
+	return false;
+
       case SYMBOL_ABSOLUTE:
 	{
 	  rtx high = gen_rtx_HIGH (Pmode, copy_rtx (addr));
@@ -2000,7 +2020,20 @@ static rtx
 riscv_force_address (rtx x, machine_mode mode)
 {
   if (!riscv_legitimate_address_p (mode, x, false))
-    x = force_reg (Pmode, x);
+    {
+      if (can_create_pseudo_p ())
+	return force_reg (Pmode, x);
+      else
+	{
+	  /* It's only safe for the thunk function.
+	     Use ra as the temp regiater.  */
+	  gcc_assert (riscv_in_thunk_func);
+	  rtx reg = RISCV_PROLOGUE_TEMP2 (Pmode);
+	  riscv_emit_move (reg, x);
+	  return reg;
+	}
+    }
+
   return x;
 }
 
@@ -5702,12 +5735,24 @@ riscv_unique_section (tree decl, int reloc)
   default_unique_section (decl, reloc);
 }
 
+/* Constant pools are per-function when in large code model.  */
+
+static inline bool
+riscv_can_use_per_function_literal_pools_p (void)
+{
+  return riscv_cmodel == CM_LARGE;
+}
+
 /* Return a section for X, handling small data. */
 
 static section *
 riscv_elf_select_rtx_section (machine_mode mode, rtx x,
 			      unsigned HOST_WIDE_INT align)
 {
+  /* The literal pool stays with the function.  */
+  if (riscv_can_use_per_function_literal_pools_p ())
+    return function_section (current_function_decl)
+
   section *s = default_elf_select_rtx_section (mode, x, align);
 
   if (riscv_size_ok_for_small_data_p (GET_MODE_SIZE (mode).to_constant ()))
@@ -7927,6 +7972,8 @@ riscv_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
   rtx this_rtx, temp1, temp2, fnaddr;
   rtx_insn *insn;
 
+  riscv_in_thunk_func = true;
+
   /* Pretend to be a post-reload pass while generating rtl.  */
   reload_completed = 1;
 
@@ -7993,6 +8040,7 @@ riscv_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
   /* Clean up the vars set above.  Note that final_end_function resets
      the global pointer for us.  */
   reload_completed = 0;
+  riscv_in_thunk_func = false;
 }
 
 /* Allocate a chunk of memory for per-function machine-dependent data.  */
@@ -8133,6 +8181,18 @@ riscv_option_override (void)
   if (flag_pic)
     g_switch_value = 0;
 
+  /* Always prefer medlow than medany for RV32 since medlow can access
+     full address space. */
+  if (riscv_cmodel == CM_LARGE && !TARGET_64BIT)
+    riscv_cmodel = CM_MEDLOW;
+
+  if (riscv_cmodel == CM_LARGE && TARGET_EXPLICIT_RELOCS)
+    sorry ("code model %qs with %qs", "large", "-mexplicit-relocs");
+
+  if (riscv_cmodel == CM_LARGE && flag_pic)
+    sorry ("code model %qs with %qs", "large",
+	   global_options.x_flag_pic > 1 ? "-fPIC" : "-fpic");
+
   if (flag_pic)
     riscv_cmodel = CM_PIC;
 
@@ -8467,6 +8527,12 @@ riscv_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
   if (cfun->machine->interrupt_handler_p)
     return false;
 
+  /* Don't use sibcalls in the large model, because a sibcall instruction
+     expanding and a epilogue expanding both use RISCV_PROLOGUE_TEMP
+     register.  */
+  if (riscv_cmodel == CM_LARGE)
+    return false;
+
   return true;
 }
 
diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h
index 1e9813b4f39..807fee06e0e 100644
--- a/gcc/config/riscv/riscv.h
+++ b/gcc/config/riscv/riscv.h
@@ -1200,4 +1200,6 @@ extern void riscv_remove_unneeded_save_restore_calls (void);
 #define HAVE_POST_MODIFY_DISP TARGET_XTHEADMEMIDX
 #define HAVE_PRE_MODIFY_DISP  TARGET_XTHEADMEMIDX
 
+#define ASM_OUTPUT_POOL_EPILOGUE riscv_asm_output_pool_epilogue
+
 #endif /* ! GCC_RISCV_H */
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index ae2217d0907..f699f6d0f97 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -41,6 +41,7 @@
   ;; Symbolic accesses.  The order of this list must match that of
   ;; enum riscv_symbol_type in riscv-protos.h.
   UNSPEC_ADDRESS_FIRST
+  UNSPEC_FORCE_FOR_MEM
   UNSPEC_PCREL
   UNSPEC_LOAD_GOT
   UNSPEC_TLS
@@ -3618,6 +3619,14 @@
     FAIL;
 })
 
+(define_insn "*large_load_address"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+        (mem:DI (match_operand 1 "pcrel_symbol_operand" "")))]
+  "TARGET_64BIT && riscv_cmodel == CM_LARGE"
+  "ld\t%0,%1"
+  [(set_attr "type" "load")
+   (set (attr "length") (const_int 8))])
+
 (include "bitmanip.md")
 (include "crypto.md")
 (include "sync.md")
diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt
index 70d78151cee..2a90a4836c1 100644
--- a/gcc/config/riscv/riscv.opt
+++ b/gcc/config/riscv/riscv.opt
@@ -123,6 +123,9 @@ Enum(code_model) String(medlow) Value(CM_MEDLOW)
 EnumValue
 Enum(code_model) String(medany) Value(CM_MEDANY)
 
+EnumValue
+Enum(code_model) String(large) Value(CM_LARGE)
+
 mexplicit-relocs
 Target Mask(EXPLICIT_RELOCS)
 Use %reloc() operators, rather than assembly macros, to load addresses.
diff --git a/gcc/testsuite/gcc.target/riscv/large-model.c b/gcc/testsuite/gcc.target/riscv/large-model.c
new file mode 100644
index 00000000000..244d14e1878
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/large-model.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64 -fno-section-anchors -mcmodel=large" } */
+/* { dg-skip-if "" { *-*-* } {"-O0"} } */
+int a, b;
+int foo1()
+{
+  return a*b;
+}
+
+/* { dg-final { scan-assembler-times "ld.*LC0" 1 } } */
+/* { dg-final { scan-assembler-times "ld.*LC1" 1 } } */
-- 
2.30.1


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

* Re: [RFC][V2] RISC-V: Support -mcmodel=large.
  2023-11-10  9:00 [RFC][V2] RISC-V: Support -mcmodel=large KuanLin Chen
@ 2023-11-10  9:10 ` KuanLin Chen
  2023-12-17 19:15   ` Jeff Law
  0 siblings, 1 reply; 11+ messages in thread
From: KuanLin Chen @ 2023-11-10  9:10 UTC (permalink / raw)
  To: gcc-patches, jeffreyalaw, Kito Cheng


[-- Attachment #1.1: Type: text/plain, Size: 102 bytes --]

Sorry. It missed a semicolon in the previos patch. Please find the new one
in the attachment. Thanks.

[-- Attachment #2: 0001-RISC-V-Support-mcmodel-large.patch --]
[-- Type: application/octet-stream, Size: 11570 bytes --]

From 98ada9501424404362a102eb356c77c32ff6e223 Mon Sep 17 00:00:00 2001
From: Kuan-Lin Chen <rufus@andestech.com>
Date: Sun, 18 Feb 2018 20:19:49 +0800
Subject: [PATCH] RISC-V: Support -mcmodel=large.

---
 gcc/config/riscv/predicates.md               | 23 +++++--
 gcc/config/riscv/riscv-c.cc                  |  4 ++
 gcc/config/riscv/riscv-opts.h                |  1 +
 gcc/config/riscv/riscv-protos.h              |  4 +-
 gcc/config/riscv/riscv.cc                    | 70 +++++++++++++++++++-
 gcc/config/riscv/riscv.h                     |  2 +
 gcc/config/riscv/riscv.md                    |  9 +++
 gcc/config/riscv/riscv.opt                   |  3 +
 gcc/testsuite/gcc.target/riscv/large-model.c | 11 +++
 9 files changed, 120 insertions(+), 7 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/large-model.c

diff --git a/gcc/config/riscv/predicates.md b/gcc/config/riscv/predicates.md
index 90567a817a7..f7ec66257c5 100644
--- a/gcc/config/riscv/predicates.md
+++ b/gcc/config/riscv/predicates.md
@@ -283,7 +283,8 @@
     case SYMBOL_REF:
     case LABEL_REF:
       return riscv_symbolic_constant_p (op, &symbol_type)
-	      && !riscv_split_symbol_type (symbol_type);
+	     && !riscv_split_symbol_type (symbol_type)
+	     && symbol_type != SYMBOL_FORCE_TO_MEM;
 
     case HIGH:
       op = XEXP (op, 0);
@@ -320,9 +321,15 @@
 })
 
 (define_predicate "call_insn_operand"
-  (ior (match_operand 0 "absolute_symbolic_operand")
-       (match_operand 0 "plt_symbolic_operand")
-       (match_operand 0 "register_operand")))
+  (match_operand 0 "general_operand")
+{
+  if (riscv_cmodel == CM_LARGE)
+    return register_operand (op, mode);
+  else
+    return (absolute_symbolic_operand (op, mode)
+	    || plt_symbolic_operand (op, mode)
+	    || register_operand (op, mode));
+})
 
 (define_predicate "modular_operator"
   (match_code "plus,minus,mult,ashift"))
@@ -605,3 +612,11 @@
   (and (match_code "const_int")
        (ior (match_operand 0 "not_uimm_extra_bit_operand")
 	    (match_operand 0 "const_nottwobits_not_arith_operand"))))
+
+(define_predicate "pcrel_symbol_operand"
+  (match_code "symbol_ref")
+{
+  enum riscv_symbol_type type;
+  return (riscv_symbolic_constant_p (op, &type)
+         && type == SYMBOL_PCREL);
+})
diff --git a/gcc/config/riscv/riscv-c.cc b/gcc/config/riscv/riscv-c.cc
index bedf7217390..59f2062bf4d 100644
--- a/gcc/config/riscv/riscv-c.cc
+++ b/gcc/config/riscv/riscv-c.cc
@@ -101,6 +101,10 @@ riscv_cpu_cpp_builtins (cpp_reader *pfile)
       builtin_define ("__riscv_cmodel_medlow");
       break;
 
+    case CM_LARGE:
+      builtin_define ("__riscv_cmodel_large");
+      break;
+
     case CM_PIC:
     case CM_MEDANY:
       builtin_define ("__riscv_cmodel_medany");
diff --git a/gcc/config/riscv/riscv-opts.h b/gcc/config/riscv/riscv-opts.h
index 532b1b6b84a..e30cca4d195 100644
--- a/gcc/config/riscv/riscv-opts.h
+++ b/gcc/config/riscv/riscv-opts.h
@@ -35,6 +35,7 @@ extern enum riscv_abi_type riscv_abi;
 enum riscv_code_model {
   CM_MEDLOW,
   CM_MEDANY,
+  CM_LARGE,
   CM_PIC
 };
 extern enum riscv_code_model riscv_cmodel;
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index 85d4f6ed9ea..7281405ed49 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -28,6 +28,7 @@ along with GCC; see the file COPYING3.  If not see
    the unspec enum in riscv.md, subsequent to UNSPEC_ADDRESS_FIRST.  */
 enum riscv_symbol_type {
   SYMBOL_ABSOLUTE,
+  SYMBOL_FORCE_TO_MEM,
   SYMBOL_PCREL,
   SYMBOL_GOT_DISP,
   SYMBOL_TLS,
@@ -158,7 +159,8 @@ extern bool riscv_shamt_matches_mask_p (int, HOST_WIDE_INT);
 extern void riscv_subword_address (rtx, rtx *, rtx *, rtx *, rtx *);
 extern void riscv_lshift_subword (machine_mode, rtx, rtx, rtx *);
 extern enum memmodel riscv_union_memmodels (enum memmodel, enum memmodel);
-
+extern void riscv_asm_output_pool_epilogue (FILE *, const char *,
+					    tree, HOST_WIDE_INT);
 /* Routines implemented in riscv-c.cc.  */
 void riscv_cpu_cpp_builtins (cpp_reader *);
 void riscv_register_pragmas (void);
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 08ff05dcc3f..68de813d875 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -287,6 +287,9 @@ bool riscv_user_wants_strict_align;
 /* Stack alignment to assume/maintain.  */
 unsigned riscv_stack_boundary;
 
+/* Whether in riscv_output_mi_thunk. */
+static bool riscv_in_thunk_func = false;
+
 /* If non-zero, this is an offset to be added to SP to redefine the CFA
    when restoring the FP register from the stack.  Only valid when generating
    the epilogue.  */
@@ -803,7 +806,17 @@ riscv_classify_symbol (const_rtx x)
   if (GET_CODE (x) == SYMBOL_REF && flag_pic && !riscv_symbol_binds_local_p (x))
     return SYMBOL_GOT_DISP;
 
-  return riscv_cmodel == CM_MEDLOW ? SYMBOL_ABSOLUTE : SYMBOL_PCREL;
+  switch (riscv_cmodel)
+    {
+    case CM_MEDLOW:
+      return SYMBOL_ABSOLUTE;
+    case CM_LARGE:
+      if (SYMBOL_REF_P (x))
+	return CONSTANT_POOL_ADDRESS_P (x) ? SYMBOL_PCREL : SYMBOL_FORCE_TO_MEM;
+      return SYMBOL_PCREL;
+    default:
+      return SYMBOL_PCREL;
+    }
 }
 
 /* Classify the base of symbolic expression X.  */
@@ -867,6 +880,7 @@ static int riscv_symbol_insns (enum riscv_symbol_type type)
     case SYMBOL_PCREL: return 2; /* AUIPC + the reference.  */
     case SYMBOL_TLS_LE: return 3; /* LUI + ADD TP + the reference.  */
     case SYMBOL_GOT_DISP: return 3; /* AUIPC + LD GOT + the reference.  */
+    case SYMBOL_FORCE_TO_MEM: return 3; /* AUIPC + LD + the reference.  */
     default: gcc_unreachable ();
     }
 }
@@ -1036,6 +1050,9 @@ riscv_cannot_force_const_mem (machine_mode mode ATTRIBUTE_UNUSED, rtx x)
   split_const (x, &base, &offset);
   if (riscv_symbolic_constant_p (base, &type))
     {
+      if (type == SYMBOL_FORCE_TO_MEM)
+	return false;
+
       /* As an optimization, don't spill symbolic constants that are as
 	 cheap to rematerialize as to access in the constant pool.  */
       if (SMALL_OPERAND (INTVAL (offset)) && riscv_symbol_insns (type) > 0)
@@ -1843,6 +1860,9 @@ riscv_split_symbol (rtx temp, rtx addr, machine_mode mode, rtx *low_out)
   if (low_out)
     switch (symbol_type)
       {
+      case SYMBOL_FORCE_TO_MEM:
+	return false;
+
       case SYMBOL_ABSOLUTE:
 	{
 	  rtx high = gen_rtx_HIGH (Pmode, copy_rtx (addr));
@@ -2000,7 +2020,20 @@ static rtx
 riscv_force_address (rtx x, machine_mode mode)
 {
   if (!riscv_legitimate_address_p (mode, x, false))
-    x = force_reg (Pmode, x);
+    {
+      if (can_create_pseudo_p ())
+	return force_reg (Pmode, x);
+      else
+	{
+	  /* It's only safe for the thunk function.
+	     Use ra as the temp regiater.  */
+	  gcc_assert (riscv_in_thunk_func);
+	  rtx reg = RISCV_PROLOGUE_TEMP2 (Pmode);
+	  riscv_emit_move (reg, x);
+	  return reg;
+	}
+    }
+
   return x;
 }
 
@@ -5702,12 +5735,24 @@ riscv_unique_section (tree decl, int reloc)
   default_unique_section (decl, reloc);
 }
 
+/* Constant pools are per-function when in large code model.  */
+
+static inline bool
+riscv_can_use_per_function_literal_pools_p (void)
+{
+  return riscv_cmodel == CM_LARGE;
+}
+
 /* Return a section for X, handling small data. */
 
 static section *
 riscv_elf_select_rtx_section (machine_mode mode, rtx x,
 			      unsigned HOST_WIDE_INT align)
 {
+  /* The literal pool stays with the function.  */
+  if (riscv_can_use_per_function_literal_pools_p ())
+    return function_section (current_function_decl);
+
   section *s = default_elf_select_rtx_section (mode, x, align);
 
   if (riscv_size_ok_for_small_data_p (GET_MODE_SIZE (mode).to_constant ()))
@@ -7927,6 +7972,8 @@ riscv_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
   rtx this_rtx, temp1, temp2, fnaddr;
   rtx_insn *insn;
 
+  riscv_in_thunk_func = true;
+
   /* Pretend to be a post-reload pass while generating rtl.  */
   reload_completed = 1;
 
@@ -7993,6 +8040,7 @@ riscv_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
   /* Clean up the vars set above.  Note that final_end_function resets
      the global pointer for us.  */
   reload_completed = 0;
+  riscv_in_thunk_func = false;
 }
 
 /* Allocate a chunk of memory for per-function machine-dependent data.  */
@@ -8133,6 +8181,18 @@ riscv_option_override (void)
   if (flag_pic)
     g_switch_value = 0;
 
+  /* Always prefer medlow than medany for RV32 since medlow can access
+     full address space. */
+  if (riscv_cmodel == CM_LARGE && !TARGET_64BIT)
+    riscv_cmodel = CM_MEDLOW;
+
+  if (riscv_cmodel == CM_LARGE && TARGET_EXPLICIT_RELOCS)
+    sorry ("code model %qs with %qs", "large", "-mexplicit-relocs");
+
+  if (riscv_cmodel == CM_LARGE && flag_pic)
+    sorry ("code model %qs with %qs", "large",
+	   global_options.x_flag_pic > 1 ? "-fPIC" : "-fpic");
+
   if (flag_pic)
     riscv_cmodel = CM_PIC;
 
@@ -8467,6 +8527,12 @@ riscv_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
   if (cfun->machine->interrupt_handler_p)
     return false;
 
+  /* Don't use sibcalls in the large model, because a sibcall instruction
+     expanding and a epilogue expanding both use RISCV_PROLOGUE_TEMP
+     register.  */
+  if (riscv_cmodel == CM_LARGE)
+    return false;
+
   return true;
 }
 
diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h
index 1e9813b4f39..807fee06e0e 100644
--- a/gcc/config/riscv/riscv.h
+++ b/gcc/config/riscv/riscv.h
@@ -1200,4 +1200,6 @@ extern void riscv_remove_unneeded_save_restore_calls (void);
 #define HAVE_POST_MODIFY_DISP TARGET_XTHEADMEMIDX
 #define HAVE_PRE_MODIFY_DISP  TARGET_XTHEADMEMIDX
 
+#define ASM_OUTPUT_POOL_EPILOGUE riscv_asm_output_pool_epilogue
+
 #endif /* ! GCC_RISCV_H */
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index ae2217d0907..f699f6d0f97 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -41,6 +41,7 @@
   ;; Symbolic accesses.  The order of this list must match that of
   ;; enum riscv_symbol_type in riscv-protos.h.
   UNSPEC_ADDRESS_FIRST
+  UNSPEC_FORCE_FOR_MEM
   UNSPEC_PCREL
   UNSPEC_LOAD_GOT
   UNSPEC_TLS
@@ -3618,6 +3619,14 @@
     FAIL;
 })
 
+(define_insn "*large_load_address"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+        (mem:DI (match_operand 1 "pcrel_symbol_operand" "")))]
+  "TARGET_64BIT && riscv_cmodel == CM_LARGE"
+  "ld\t%0,%1"
+  [(set_attr "type" "load")
+   (set (attr "length") (const_int 8))])
+
 (include "bitmanip.md")
 (include "crypto.md")
 (include "sync.md")
diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt
index 70d78151cee..2a90a4836c1 100644
--- a/gcc/config/riscv/riscv.opt
+++ b/gcc/config/riscv/riscv.opt
@@ -123,6 +123,9 @@ Enum(code_model) String(medlow) Value(CM_MEDLOW)
 EnumValue
 Enum(code_model) String(medany) Value(CM_MEDANY)
 
+EnumValue
+Enum(code_model) String(large) Value(CM_LARGE)
+
 mexplicit-relocs
 Target Mask(EXPLICIT_RELOCS)
 Use %reloc() operators, rather than assembly macros, to load addresses.
diff --git a/gcc/testsuite/gcc.target/riscv/large-model.c b/gcc/testsuite/gcc.target/riscv/large-model.c
new file mode 100644
index 00000000000..244d14e1878
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/large-model.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64 -fno-section-anchors -mcmodel=large" } */
+/* { dg-skip-if "" { *-*-* } {"-O0"} } */
+int a, b;
+int foo1()
+{
+  return a*b;
+}
+
+/* { dg-final { scan-assembler-times "ld.*LC0" 1 } } */
+/* { dg-final { scan-assembler-times "ld.*LC1" 1 } } */
-- 
2.30.1


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

* Re: [RFC][V2] RISC-V: Support -mcmodel=large.
  2023-11-10  9:10 ` KuanLin Chen
@ 2023-12-17 19:15   ` Jeff Law
  2023-12-18  7:46     ` KuanLin Chen
  0 siblings, 1 reply; 11+ messages in thread
From: Jeff Law @ 2023-12-17 19:15 UTC (permalink / raw)
  To: KuanLin Chen, gcc-patches, Kito Cheng



On 11/10/23 02:10, KuanLin Chen wrote:
> Sorry. It missed a semicolon in the previos patch. Please find the new 
> one in the attachment. Thanks.
Thanks.  I was going to do some final testing with the plan to integrate 
this patch today, but I think there's a piece missing.  Specifically I 
think it's missing a definition for riscv_asm_output_pool_epilogue.

Can you please send an updated patch that includes that function?

Thanks,
Jeff

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

* Re: [RFC][V2] RISC-V: Support -mcmodel=large.
  2023-12-17 19:15   ` Jeff Law
@ 2023-12-18  7:46     ` KuanLin Chen
  2023-12-20 17:55       ` Jeff Law
  0 siblings, 1 reply; 11+ messages in thread
From: KuanLin Chen @ 2023-12-18  7:46 UTC (permalink / raw)
  To: Jeff Law; +Cc: gcc-patches, Kito Cheng


[-- Attachment #1.1: Type: text/plain, Size: 751 bytes --]

Hi Jeff,

Sorry for this missing.
I've removed riscv_asm_output_pool_epilogue because the pool beginning is
always aligned from FUNCTION_BOUNDARY.
Please find attached. Thank you.

Jeff Law <jeffreyalaw@gmail.com> 於 2023年12月18日 週一 上午3:15寫道:

>
>
> On 11/10/23 02:10, KuanLin Chen wrote:
> > Sorry. It missed a semicolon in the previos patch. Please find the new
> > one in the attachment. Thanks.
> Thanks.  I was going to do some final testing with the plan to integrate
> this patch today, but I think there's a piece missing.  Specifically I
> think it's missing a definition for riscv_asm_output_pool_epilogue.
>
> Can you please send an updated patch that includes that function?
>
> Thanks,
> Jeff
>

[-- Attachment #2: 0001-RISC-V-Support-mcmodel-large.patch --]
[-- Type: application/octet-stream, Size: 11706 bytes --]

From d4ddb60c48a80bd67032df97b3dbfe862641b456 Mon Sep 17 00:00:00 2001
From: Kuan-Lin Chen <rufus@andestech.com>
Date: Sun, 18 Feb 2018 20:19:49 +0800
Subject: [PATCH] RISC-V: Support -mcmodel=large.

---
 gcc/config/riscv/predicates.md               | 23 +++++-
 gcc/config/riscv/riscv-c.cc                  |  4 +
 gcc/config/riscv/riscv-opts.h                |  1 +
 gcc/config/riscv/riscv-protos.h              |  1 +
 gcc/config/riscv/riscv.cc                    | 86 +++++++++++++++++++-
 gcc/config/riscv/riscv.md                    |  9 ++
 gcc/config/riscv/riscv.opt                   |  3 +
 gcc/testsuite/gcc.target/riscv/large-model.c | 11 +++
 8 files changed, 131 insertions(+), 7 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/large-model.c

diff --git a/gcc/config/riscv/predicates.md b/gcc/config/riscv/predicates.md
index ff213e5f8a3..8af3027cdaf 100644
--- a/gcc/config/riscv/predicates.md
+++ b/gcc/config/riscv/predicates.md
@@ -289,7 +289,8 @@
     case SYMBOL_REF:
     case LABEL_REF:
       return riscv_symbolic_constant_p (op, &symbol_type)
-	      && !riscv_split_symbol_type (symbol_type);
+	     && !riscv_split_symbol_type (symbol_type)
+	     && symbol_type != SYMBOL_FORCE_TO_MEM;
 
     case HIGH:
       op = XEXP (op, 0);
@@ -326,9 +327,15 @@
 })
 
 (define_predicate "call_insn_operand"
-  (ior (match_operand 0 "absolute_symbolic_operand")
-       (match_operand 0 "plt_symbolic_operand")
-       (match_operand 0 "register_operand")))
+  (match_operand 0 "general_operand")
+{
+  if (riscv_cmodel == CM_LARGE)
+    return register_operand (op, mode);
+  else
+    return (absolute_symbolic_operand (op, mode)
+	    || plt_symbolic_operand (op, mode)
+	    || register_operand (op, mode));
+})
 
 (define_predicate "modular_operator"
   (match_code "plus,minus,mult,ashift"))
@@ -611,3 +618,11 @@
   (and (match_code "const_int")
        (ior (match_operand 0 "not_uimm_extra_bit_operand")
 	    (match_operand 0 "const_nottwobits_not_arith_operand"))))
+
+(define_predicate "pcrel_symbol_operand"
+  (match_code "symbol_ref")
+{
+  enum riscv_symbol_type type;
+  return (riscv_symbolic_constant_p (op, &type)
+         && type == SYMBOL_PCREL);
+})
diff --git a/gcc/config/riscv/riscv-c.cc b/gcc/config/riscv/riscv-c.cc
index dd1bd0596fc..08fe56cce59 100644
--- a/gcc/config/riscv/riscv-c.cc
+++ b/gcc/config/riscv/riscv-c.cc
@@ -101,6 +101,10 @@ riscv_cpu_cpp_builtins (cpp_reader *pfile)
       builtin_define ("__riscv_cmodel_medlow");
       break;
 
+    case CM_LARGE:
+      builtin_define ("__riscv_cmodel_large");
+      break;
+
     case CM_PIC:
     case CM_MEDANY:
       builtin_define ("__riscv_cmodel_medany");
diff --git a/gcc/config/riscv/riscv-opts.h b/gcc/config/riscv/riscv-opts.h
index 0b242f068e1..0db9b363a43 100644
--- a/gcc/config/riscv/riscv-opts.h
+++ b/gcc/config/riscv/riscv-opts.h
@@ -35,6 +35,7 @@ extern enum riscv_abi_type riscv_abi;
 enum riscv_code_model {
   CM_MEDLOW,
   CM_MEDANY,
+  CM_LARGE,
   CM_PIC
 };
 extern enum riscv_code_model riscv_cmodel;
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index 52097fe48cf..5d3f83685e6 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -28,6 +28,7 @@ along with GCC; see the file COPYING3.  If not see
    the unspec enum in riscv.md, subsequent to UNSPEC_ADDRESS_FIRST.  */
 enum riscv_symbol_type {
   SYMBOL_ABSOLUTE,
+  SYMBOL_FORCE_TO_MEM,
   SYMBOL_PCREL,
   SYMBOL_GOT_DISP,
   SYMBOL_TLS,
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index d0efb939bf2..acbe4424a4f 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -295,6 +295,9 @@ bool riscv_user_wants_strict_align;
 /* Stack alignment to assume/maintain.  */
 unsigned riscv_stack_boundary;
 
+/* Whether in riscv_output_mi_thunk. */
+static bool riscv_in_thunk_func = false;
+
 /* If non-zero, this is an offset to be added to SP to redefine the CFA
    when restoring the FP register from the stack.  Only valid when generating
    the epilogue.  */
@@ -832,7 +835,17 @@ riscv_classify_symbol (const_rtx x)
   if (GET_CODE (x) == SYMBOL_REF && flag_pic && !riscv_symbol_binds_local_p (x))
     return SYMBOL_GOT_DISP;
 
-  return riscv_cmodel == CM_MEDLOW ? SYMBOL_ABSOLUTE : SYMBOL_PCREL;
+  switch (riscv_cmodel)
+    {
+    case CM_MEDLOW:
+      return SYMBOL_ABSOLUTE;
+    case CM_LARGE:
+      if (SYMBOL_REF_P (x))
+	return CONSTANT_POOL_ADDRESS_P (x) ? SYMBOL_PCREL : SYMBOL_FORCE_TO_MEM;
+      return SYMBOL_PCREL;
+    default:
+      return SYMBOL_PCREL;
+    }
 }
 
 /* Classify the base of symbolic expression X.  */
@@ -896,6 +909,7 @@ static int riscv_symbol_insns (enum riscv_symbol_type type)
     case SYMBOL_PCREL: return 2; /* AUIPC + the reference.  */
     case SYMBOL_TLS_LE: return 3; /* LUI + ADD TP + the reference.  */
     case SYMBOL_GOT_DISP: return 3; /* AUIPC + LD GOT + the reference.  */
+    case SYMBOL_FORCE_TO_MEM: return 3; /* AUIPC + LD + the reference.  */
     default: gcc_unreachable ();
     }
 }
@@ -1065,6 +1079,9 @@ riscv_cannot_force_const_mem (machine_mode mode ATTRIBUTE_UNUSED, rtx x)
   split_const (x, &base, &offset);
   if (riscv_symbolic_constant_p (base, &type))
     {
+      if (type == SYMBOL_FORCE_TO_MEM)
+	return false;
+
       /* As an optimization, don't spill symbolic constants that are as
 	 cheap to rematerialize as to access in the constant pool.  */
       if (SMALL_OPERAND (INTVAL (offset)) && riscv_symbol_insns (type) > 0)
@@ -1892,6 +1909,9 @@ riscv_split_symbol (rtx temp, rtx addr, machine_mode mode, rtx *low_out)
   if (low_out)
     switch (symbol_type)
       {
+      case SYMBOL_FORCE_TO_MEM:
+	return false;
+
       case SYMBOL_ABSOLUTE:
 	{
 	  rtx high = gen_rtx_HIGH (Pmode, copy_rtx (addr));
@@ -2049,7 +2069,20 @@ static rtx
 riscv_force_address (rtx x, machine_mode mode)
 {
   if (!riscv_legitimate_address_p (mode, x, false))
-    x = force_reg (Pmode, x);
+    {
+      if (can_create_pseudo_p ())
+	return force_reg (Pmode, x);
+      else
+	{
+	  /* It's only safe for the thunk function.
+	     Use ra as the temp regiater.  */
+	  gcc_assert (riscv_in_thunk_func);
+	  rtx reg = RISCV_PROLOGUE_TEMP2 (Pmode);
+	  riscv_emit_move (reg, x);
+	  return reg;
+	}
+    }
+
   return x;
 }
 
@@ -5868,6 +5901,12 @@ riscv_size_ok_for_small_data_p (int size)
 static bool
 riscv_in_small_data_p (const_tree x)
 {
+  /* Because default_use_anchors_for_symbol_p doesn't gather small data to use
+     the anchor symbol to address nearby objects.  In large model, it can get
+     the better result using the anchor optiomization.  */
+  if (riscv_cmodel == CM_LARGE)
+    return false;
+
   if (TREE_CODE (x) == STRING_CST || TREE_CODE (x) == FUNCTION_DECL)
     return false;
 
@@ -5933,12 +5972,32 @@ riscv_unique_section (tree decl, int reloc)
   default_unique_section (decl, reloc);
 }
 
+/* Constant pools are per-function when in large code model.  */
+
+static inline bool
+riscv_can_use_per_function_literal_pools_p (void)
+{
+  return riscv_cmodel == CM_LARGE;
+}
+
+static bool
+riscv_use_blocks_for_constant_p (machine_mode, const_rtx)
+{
+  /* We can't use blocks for constants when we're using a per-function
+     constant pool.  */
+  return !riscv_can_use_per_function_literal_pools_p ();
+}
+
 /* Return a section for X, handling small data. */
 
 static section *
 riscv_elf_select_rtx_section (machine_mode mode, rtx x,
 			      unsigned HOST_WIDE_INT align)
 {
+  /* The literal pool stays with the function.  */
+  if (riscv_can_use_per_function_literal_pools_p ())
+    return function_section (current_function_decl);
+
   section *s = default_elf_select_rtx_section (mode, x, align);
 
   if (riscv_size_ok_for_small_data_p (GET_MODE_SIZE (mode).to_constant ()))
@@ -8442,6 +8501,8 @@ riscv_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
   rtx this_rtx, temp1, temp2, fnaddr;
   rtx_insn *insn;
 
+  riscv_in_thunk_func = true;
+
   /* Pretend to be a post-reload pass while generating rtl.  */
   reload_completed = 1;
 
@@ -8508,6 +8569,7 @@ riscv_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
   /* Clean up the vars set above.  Note that final_end_function resets
      the global pointer for us.  */
   reload_completed = 0;
+  riscv_in_thunk_func = false;
 }
 
 /* Allocate a chunk of memory for per-function machine-dependent data.  */
@@ -8650,6 +8712,18 @@ riscv_option_override (void)
   if (flag_pic)
     g_switch_value = 0;
 
+  /* Always prefer medlow than medany for RV32 since medlow can access
+     full address space. */
+  if (riscv_cmodel == CM_LARGE && !TARGET_64BIT)
+    riscv_cmodel = CM_MEDLOW;
+
+  if (riscv_cmodel == CM_LARGE && TARGET_EXPLICIT_RELOCS)
+    sorry ("code model %qs with %qs", "large", "-mexplicit-relocs");
+
+  if (riscv_cmodel == CM_LARGE && flag_pic)
+    sorry ("code model %qs with %qs", "large",
+	   global_options.x_flag_pic > 1 ? "-fPIC" : "-fpic");
+
   if (flag_pic)
     riscv_cmodel = CM_PIC;
 
@@ -9017,6 +9091,12 @@ riscv_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
   if (cfun->machine->interrupt_handler_p)
     return false;
 
+  /* Don't use sibcalls in the large model, because a sibcall instruction
+     expanding and a epilogue expanding both use RISCV_PROLOGUE_TEMP
+     register.  */
+  if (riscv_cmodel == CM_LARGE)
+    return false;
+
   return true;
 }
 
@@ -10411,7 +10491,7 @@ extract_base_offset_in_addr (rtx mem, rtx *base, rtx *offset)
 #define TARGET_LEGITIMATE_CONSTANT_P riscv_legitimate_constant_p
 
 #undef TARGET_USE_BLOCKS_FOR_CONSTANT_P
-#define TARGET_USE_BLOCKS_FOR_CONSTANT_P hook_bool_mode_const_rtx_true
+#define TARGET_USE_BLOCKS_FOR_CONSTANT_P riscv_use_blocks_for_constant_p
 
 #undef TARGET_LEGITIMATE_ADDRESS_P
 #define TARGET_LEGITIMATE_ADDRESS_P	riscv_legitimate_address_p
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index 935eeb7fd8e..c9a3c7ae078 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -41,6 +41,7 @@
   ;; Symbolic accesses.  The order of this list must match that of
   ;; enum riscv_symbol_type in riscv-protos.h.
   UNSPEC_ADDRESS_FIRST
+  UNSPEC_FORCE_FOR_MEM
   UNSPEC_PCREL
   UNSPEC_LOAD_GOT
   UNSPEC_TLS
@@ -3735,6 +3736,14 @@
     FAIL;
 })
 
+(define_insn "*large_load_address"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+        (mem:DI (match_operand 1 "pcrel_symbol_operand" "")))]
+  "TARGET_64BIT && riscv_cmodel == CM_LARGE"
+  "ld\t%0,%1"
+  [(set_attr "type" "load")
+   (set (attr "length") (const_int 8))])
+
 (include "bitmanip.md")
 (include "crypto.md")
 (include "sync.md")
diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt
index 11526f9cc2a..85b5408bf32 100644
--- a/gcc/config/riscv/riscv.opt
+++ b/gcc/config/riscv/riscv.opt
@@ -123,6 +123,9 @@ Enum(code_model) String(medlow) Value(CM_MEDLOW)
 EnumValue
 Enum(code_model) String(medany) Value(CM_MEDANY)
 
+EnumValue
+Enum(code_model) String(large) Value(CM_LARGE)
+
 mexplicit-relocs
 Target Mask(EXPLICIT_RELOCS)
 Use %reloc() operators, rather than assembly macros, to load addresses.
diff --git a/gcc/testsuite/gcc.target/riscv/large-model.c b/gcc/testsuite/gcc.target/riscv/large-model.c
new file mode 100644
index 00000000000..244d14e1878
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/large-model.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64 -fno-section-anchors -mcmodel=large" } */
+/* { dg-skip-if "" { *-*-* } {"-O0"} } */
+int a, b;
+int foo1()
+{
+  return a*b;
+}
+
+/* { dg-final { scan-assembler-times "ld.*LC0" 1 } } */
+/* { dg-final { scan-assembler-times "ld.*LC1" 1 } } */
-- 
2.30.1


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

* Re: [RFC][V2] RISC-V: Support -mcmodel=large.
  2023-12-18  7:46     ` KuanLin Chen
@ 2023-12-20 17:55       ` Jeff Law
  2023-12-20 18:05         ` Palmer Dabbelt
  0 siblings, 1 reply; 11+ messages in thread
From: Jeff Law @ 2023-12-20 17:55 UTC (permalink / raw)
  To: KuanLin Chen; +Cc: gcc-patches, Kito Cheng



On 12/18/23 00:46, KuanLin Chen wrote:
> Hi Jeff,
> 
> Sorry for this missing.
> I've removed riscv_asm_output_pool_epilogue because the pool 
> beginning is always aligned from FUNCTION_BOUNDARY.
> Please find attached. Thank you.
Thanks. I regression tested this on rv64gc without any issues and fixed 
up the ChangeLog a bit.  Pushed to the trunk.  Thanks for your patience.

jeff

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

* Re: [RFC][V2] RISC-V: Support -mcmodel=large.
  2023-12-20 17:55       ` Jeff Law
@ 2023-12-20 18:05         ` Palmer Dabbelt
  2023-12-20 18:12           ` Jeff Law
  0 siblings, 1 reply; 11+ messages in thread
From: Palmer Dabbelt @ 2023-12-20 18:05 UTC (permalink / raw)
  To: jeffreyalaw; +Cc: best124612, gcc-patches, Kito Cheng

On Wed, 20 Dec 2023 09:55:48 PST (-0800), jeffreyalaw@gmail.com wrote:
>
>
> On 12/18/23 00:46, KuanLin Chen wrote:
>> Hi Jeff,
>>
>> Sorry for this missing.
>> I've removed riscv_asm_output_pool_epilogue because the pool
>> beginning is always aligned from FUNCTION_BOUNDARY.
>> Please find attached. Thank you.
> Thanks. I regression tested this on rv64gc without any issues and fixed
> up the ChangeLog a bit.  Pushed to the trunk.  Thanks for your patience.

Looks like the psABI PR is still open 
<https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/388>?

I guess there's no hard psABI dependency here, we're just doing constant 
pools so there's no new assembler/linker stuff that's strictly 
necessary.  I'm fine just ignoring the psABI as it's a pretty miserable 
place to try and get things done, we're started doing that where we can 
elsewhere as well.

So maybe we should just close that PR?

> jeff

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

* Re: [RFC][V2] RISC-V: Support -mcmodel=large.
  2023-12-20 18:05         ` Palmer Dabbelt
@ 2023-12-20 18:12           ` Jeff Law
  2023-12-20 18:21             ` Palmer Dabbelt
  0 siblings, 1 reply; 11+ messages in thread
From: Jeff Law @ 2023-12-20 18:12 UTC (permalink / raw)
  To: Palmer Dabbelt; +Cc: best124612, gcc-patches, Kito Cheng



On 12/20/23 11:05, Palmer Dabbelt wrote:
> On Wed, 20 Dec 2023 09:55:48 PST (-0800), jeffreyalaw@gmail.com wrote:
>>
>>
>> On 12/18/23 00:46, KuanLin Chen wrote:
>>> Hi Jeff,
>>>
>>> Sorry for this missing.
>>> I've removed riscv_asm_output_pool_epilogue because the pool
>>> beginning is always aligned from FUNCTION_BOUNDARY.
>>> Please find attached. Thank you.
>> Thanks. I regression tested this on rv64gc without any issues and fixed
>> up the ChangeLog a bit.  Pushed to the trunk.  Thanks for your patience.
> 
> Looks like the psABI PR is still open 
> <https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/388>?
> 
> I guess there's no hard psABI dependency here, we're just doing constant 
> pools so there's no new assembler/linker stuff that's strictly 
> necessary.  I'm fine just ignoring the psABI as it's a pretty miserable 
> place to try and get things done, we're started doing that where we can 
> elsewhere as well.
Yea, the implementation relies largely on just pushing stuff into the 
constant pool, so we're largely independent ABI stuff with the likely 
exception being relocations.

In theory (and I did not test this), it should be possible to use large 
code model codegen in a smaller mode and it should interoperate.  I 
seriously pondered doing that as an additional test, then figured I had 
other higher priority items on my list.



> 
> So maybe we should just close that PR?
I'll let Kito chime in on that.

jeff

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

* Re: [RFC][V2] RISC-V: Support -mcmodel=large.
  2023-12-20 18:12           ` Jeff Law
@ 2023-12-20 18:21             ` Palmer Dabbelt
  2023-12-20 18:25               ` Jeff Law
  0 siblings, 1 reply; 11+ messages in thread
From: Palmer Dabbelt @ 2023-12-20 18:21 UTC (permalink / raw)
  To: jeffreyalaw, Patrick O'Neill; +Cc: best124612, gcc-patches, Kito Cheng

On Wed, 20 Dec 2023 10:12:04 PST (-0800), jeffreyalaw@gmail.com wrote:
>
>
> On 12/20/23 11:05, Palmer Dabbelt wrote:
>> On Wed, 20 Dec 2023 09:55:48 PST (-0800), jeffreyalaw@gmail.com wrote:
>>>
>>>
>>> On 12/18/23 00:46, KuanLin Chen wrote:
>>>> Hi Jeff,
>>>>
>>>> Sorry for this missing.
>>>> I've removed riscv_asm_output_pool_epilogue because the pool
>>>> beginning is always aligned from FUNCTION_BOUNDARY.
>>>> Please find attached. Thank you.
>>> Thanks. I regression tested this on rv64gc without any issues and fixed
>>> up the ChangeLog a bit.  Pushed to the trunk.  Thanks for your patience.
>>
>> Looks like the psABI PR is still open
>> <https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/388>?
>>
>> I guess there's no hard psABI dependency here, we're just doing constant
>> pools so there's no new assembler/linker stuff that's strictly
>> necessary.  I'm fine just ignoring the psABI as it's a pretty miserable
>> place to try and get things done, we're started doing that where we can
>> elsewhere as well.
> Yea, the implementation relies largely on just pushing stuff into the
> constant pool, so we're largely independent ABI stuff with the likely
> exception being relocations.

Ya, but I think we'd only need the relocations if we were going to try 
relaxing stuff.  We'd kicked around some ideas there: we could 
de-duplicate constant pools or inline smaller constants.  That's all way 
to complex to try and get into this upcoming binutils release, though 
(doubly so with this LEB128 ABI break we're still trying to deal with).

So I think we can just punt on all that for a bit.  We've got bigger 
fish to fry.

> In theory (and I did not test this), it should be possible to use large
> code model codegen in a smaller mode and it should interoperate.  I
> seriously pondered doing that as an additional test, then figured I had
> other higher priority items on my list.

IMO we should test that.  At least the common case of a medlow libc 
linked into medany programs should be easy.

+Patrick: let's add some configs to the CI for this?

>> So maybe we should just close that PR?
> I'll let Kito chime in on that.

WFM, I try to stay as far away from that as possible ;)

>
> jeff

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

* Re: [RFC][V2] RISC-V: Support -mcmodel=large.
  2023-12-20 18:21             ` Palmer Dabbelt
@ 2023-12-20 18:25               ` Jeff Law
  2023-12-20 18:41                 ` Palmer Dabbelt
  0 siblings, 1 reply; 11+ messages in thread
From: Jeff Law @ 2023-12-20 18:25 UTC (permalink / raw)
  To: Palmer Dabbelt, Patrick O'Neill; +Cc: best124612, gcc-patches, Kito Cheng



On 12/20/23 11:21, Palmer Dabbelt wrote:

>> Yea, the implementation relies largely on just pushing stuff into the
>> constant pool, so we're largely independent ABI stuff with the likely
>> exception being relocations.
> 
> Ya, but I think we'd only need the relocations if we were going to try 
> relaxing stuff.  We'd kicked around some ideas there: we could 
> de-duplicate constant pools or inline smaller constants.  That's all way 
> to complex to try and get into this upcoming binutils release, though 
> (doubly so with this LEB128 ABI break we're still trying to deal with).
Agreed.  And note that de-duplication is mostly implemented without need 
for the target to do anything.  I was kindof amazed to see some of the 
places it kicked in on other ports I've worked with.


>> In theory (and I did not test this), it should be possible to use large
>> code model codegen in a smaller mode and it should interoperate.  I
>> seriously pondered doing that as an additional test, then figured I had
>> other higher priority items on my list.
> 
> IMO we should test that.  At least the common case of a medlow libc 
> linked into medany programs should be easy.
> 
> +Patrick: let's add some configs to the CI for this?
I was pondering a one-off by turning on the large code model by default, 
then doing a bootstrap & regression test in QEMU.  But integrated into 
CI is even better.

Jeff

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

* Re: [RFC][V2] RISC-V: Support -mcmodel=large.
  2023-12-20 18:25               ` Jeff Law
@ 2023-12-20 18:41                 ` Palmer Dabbelt
  2023-12-20 21:13                   ` Patrick O'Neill
  0 siblings, 1 reply; 11+ messages in thread
From: Palmer Dabbelt @ 2023-12-20 18:41 UTC (permalink / raw)
  To: jeffreyalaw; +Cc: Patrick O'Neill, best124612, gcc-patches, Kito Cheng

On Wed, 20 Dec 2023 10:25:00 PST (-0800), jeffreyalaw@gmail.com wrote:
>
>
> On 12/20/23 11:21, Palmer Dabbelt wrote:
>
>>> Yea, the implementation relies largely on just pushing stuff into the
>>> constant pool, so we're largely independent ABI stuff with the likely
>>> exception being relocations.
>>
>> Ya, but I think we'd only need the relocations if we were going to try
>> relaxing stuff.  We'd kicked around some ideas there: we could
>> de-duplicate constant pools or inline smaller constants.  That's all way
>> to complex to try and get into this upcoming binutils release, though
>> (doubly so with this LEB128 ABI break we're still trying to deal with).
> Agreed.  And note that de-duplication is mostly implemented without need
> for the target to do anything.  I was kindof amazed to see some of the
> places it kicked in on other ports I've worked with.

I think all we'd need from GCC is some way to get the "this load is a 
constant pool address that can be messed with" relocation in there, the 
linker would do all the heavy lifting.  That's probably just a new 
assembler pseudo, so pretty much nothing on the compiler side of things.

>>> In theory (and I did not test this), it should be possible to use large
>>> code model codegen in a smaller mode and it should interoperate.  I
>>> seriously pondered doing that as an additional test, then figured I had
>>> other higher priority items on my list.
>>
>> IMO we should test that.  At least the common case of a medlow libc
>> linked into medany programs should be easy.
>>
>> +Patrick: let's add some configs to the CI for this?
> I was pondering a one-off by turning on the large code model by default,
> then doing a bootstrap & regression test in QEMU.  But integrated into
> CI is even better.

OK, let's just add it to CI -- it'd be essentially the same testing, 
just it'll stick around.

>
> Jeff

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

* Re: [RFC][V2] RISC-V: Support -mcmodel=large.
  2023-12-20 18:41                 ` Palmer Dabbelt
@ 2023-12-20 21:13                   ` Patrick O'Neill
  0 siblings, 0 replies; 11+ messages in thread
From: Patrick O'Neill @ 2023-12-20 21:13 UTC (permalink / raw)
  To: Palmer Dabbelt, jeffreyalaw; +Cc: best124612, gcc-patches, Kito Cheng


On 12/20/23 10:41, Palmer Dabbelt wrote:
> On Wed, 20 Dec 2023 10:25:00 PST (-0800), jeffreyalaw@gmail.com wrote:
>>
>>
>> On 12/20/23 11:21, Palmer Dabbelt wrote:
>>
>>>> Yea, the implementation relies largely on just pushing stuff into the
>>>> constant pool, so we're largely independent ABI stuff with the likely
>>>> exception being relocations.
>>>
>>> Ya, but I think we'd only need the relocations if we were going to try
>>> relaxing stuff.  We'd kicked around some ideas there: we could
>>> de-duplicate constant pools or inline smaller constants. That's all way
>>> to complex to try and get into this upcoming binutils release, though
>>> (doubly so with this LEB128 ABI break we're still trying to deal with).
>> Agreed.  And note that de-duplication is mostly implemented without need
>> for the target to do anything.  I was kindof amazed to see some of the
>> places it kicked in on other ports I've worked with.
>
> I think all we'd need from GCC is some way to get the "this load is a 
> constant pool address that can be messed with" relocation in there, 
> the linker would do all the heavy lifting.  That's probably just a new 
> assembler pseudo, so pretty much nothing on the compiler side of things.
>
>>>> In theory (and I did not test this), it should be possible to use 
>>>> large
>>>> code model codegen in a smaller mode and it should interoperate.  I
>>>> seriously pondered doing that as an additional test, then figured I 
>>>> had
>>>> other higher priority items on my list.
>>>
>>> IMO we should test that.  At least the common case of a medlow libc
>>> linked into medany programs should be easy.
>>>
>>> +Patrick: let's add some configs to the CI for this?
>> I was pondering a one-off by turning on the large code model by default,
>> then doing a bootstrap & regression test in QEMU.  But integrated into
>> CI is even better.
>
> OK, let's just add it to CI -- it'd be essentially the same testing, 
> just it'll stick around.
ACK :)

Patrick
>
>>
>> Jeff

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

end of thread, other threads:[~2023-12-20 21:13 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-11-10  9:00 [RFC][V2] RISC-V: Support -mcmodel=large KuanLin Chen
2023-11-10  9:10 ` KuanLin Chen
2023-12-17 19:15   ` Jeff Law
2023-12-18  7:46     ` KuanLin Chen
2023-12-20 17:55       ` Jeff Law
2023-12-20 18:05         ` Palmer Dabbelt
2023-12-20 18:12           ` Jeff Law
2023-12-20 18:21             ` Palmer Dabbelt
2023-12-20 18:25               ` Jeff Law
2023-12-20 18:41                 ` Palmer Dabbelt
2023-12-20 21:13                   ` Patrick O'Neill

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).