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.