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: 0001-RISC-V-Support-mcmodel-large.patch
Description: Binary data

Reply via email to