Implement `-mgprel', forcing `-mexplicit-relocs' whenever the option is active due to the lack of GAS macro support for GP-relative addressing.
gcc/ * riscv/riscv-protos.h (riscv_symbol_type): Add SYMBOL_GPREL enumeration constant. * config/riscv/riscv.c (riscv_classify_symbol) (riscv_symbolic_constant_p, riscv_symbol_insns) (riscv_split_symbol_type, riscv_split_symbol, riscv_output_move) (riscv_print_operand_reloc, riscv_option_override): Handle GP-relative addressing. * config/riscv/riscv.md (unspec): Add UNSPEC_GPREL enumeration constant. * config/riscv/riscv.opt (mgprel): New option. --- Hi, This is very early stage really, just implementing basic GP-relative relocation support, in preparation for FDPIC support discussed here: <https://groups.google.com/a/groups.riscv.org/g/sw-dev/c/ZjYUJswknQ4> I planned adding support to GAS macros such as LA next so that we don't have to force explicit relocations with `-mgprel' for this option to work, but I won't be able to continue with this effort now as I am leaving Western Digital today, so I am posting this in case someone finds it useful or wishes to continue the effort. No regressions in `riscv64-linux-gnu' testing, RV32/ilp32d ABI with QEMU in the Linux user emulation mode across all GCC frontends and libraries, except for an odd ICE with one of the Fortran test cases and a couple timeouts with GNAT test cases, which I put all on the version difference between the test runs (10.0.1 20200426 vs 11.0.0 20200827). Unfortunately I lost several hours, because 11.0.0 20200829 has regressed enough compared to 11.0.0 20200827 for testing not to progress well enough in 15 hours where it usually completes in ~10 hours. So I had to restart with an older snapshot and wouldn't get reference results in time (I only had libgo results with 11.0.0 20200827). I think my assumption as to the nature of the regressions is right though. A corresponding binutils change has also been posted. Maciej --- gcc/config/riscv/riscv-protos.h | 1 + gcc/config/riscv/riscv.c | 32 +++++++++++++++++++++++++++++--- gcc/config/riscv/riscv.md | 1 + gcc/config/riscv/riscv.opt | 4 ++++ 4 files changed, 35 insertions(+), 3 deletions(-) gcc-riscv-gprel.diff Index: gcc/gcc/config/riscv/riscv-protos.h =================================================================== --- gcc.orig/gcc/config/riscv/riscv-protos.h +++ gcc/gcc/config/riscv/riscv-protos.h @@ -28,6 +28,7 @@ enum riscv_symbol_type { SYMBOL_ABSOLUTE, SYMBOL_PCREL, SYMBOL_GOT_DISP, + SYMBOL_GPREL, SYMBOL_TLS, SYMBOL_TLS_LE, SYMBOL_TLS_IE, Index: gcc/gcc/config/riscv/riscv.c =================================================================== --- gcc.orig/gcc/config/riscv/riscv.c +++ gcc/gcc/config/riscv/riscv.c @@ -559,7 +559,13 @@ 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; + if (riscv_cmodel == CM_MEDLOW) + return SYMBOL_ABSOLUTE; + + if (LABEL_REF_P (x) || (SYMBOL_REF_P (x) && SYMBOL_REF_FUNCTION_P (x))) + return SYMBOL_PCREL; + + return TARGET_GPREL ? SYMBOL_GPREL : SYMBOL_PCREL; } /* Classify the base of symbolic expression X. */ @@ -604,6 +610,7 @@ riscv_symbolic_constant_p (rtx x, enum r case SYMBOL_ABSOLUTE: case SYMBOL_PCREL: case SYMBOL_TLS_LE: + case SYMBOL_GPREL: /* GAS rejects offsets outside the range [-2^31, 2^31-1]. */ return sext_hwi (INTVAL (offset), 32) == INTVAL (offset); @@ -622,6 +629,7 @@ static int riscv_symbol_insns (enum risc case SYMBOL_ABSOLUTE: return 2; /* LUI + the reference. */ case SYMBOL_PCREL: return 2; /* AUIPC + the reference. */ case SYMBOL_TLS_LE: return 3; /* LUI + ADD TP + the reference. */ + case SYMBOL_GPREL: return 3; /* LUI + ADD GP + the reference. */ case SYMBOL_GOT_DISP: return 3; /* AUIPC + LD GOT + the reference. */ default: gcc_unreachable (); } @@ -735,7 +743,9 @@ riscv_split_symbol_type (enum riscv_symb if (!TARGET_EXPLICIT_RELOCS) return false; - return symbol_type == SYMBOL_ABSOLUTE || symbol_type == SYMBOL_PCREL; + return (symbol_type == SYMBOL_ABSOLUTE + || symbol_type == SYMBOL_PCREL + || symbol_type == SYMBOL_GPREL); } /* Return true if a LO_SUM can address a value of mode MODE when the @@ -1241,6 +1251,17 @@ riscv_split_symbol (rtx temp, rtx addr, } break; + case SYMBOL_GPREL: + { + rtx high = gen_rtx_HIGH (Pmode, copy_rtx (addr)); + rtx gp = gen_rtx_REG (Pmode, GP_REGNUM); + high = riscv_force_temporary (temp, high, in_splitter); + rtx reg = gen_rtx_PLUS (Pmode, high, gp); + reg = riscv_force_temporary (temp, reg, in_splitter); + *low_out = gen_rtx_LO_SUM (Pmode, reg, addr); + } + break; + default: gcc_unreachable (); } @@ -2030,6 +2051,7 @@ riscv_output_move (rtx dest, rtx src) case SYMBOL_GOT_DISP: return "la\t%0,%1"; case SYMBOL_ABSOLUTE: return "lla\t%0,%1"; case SYMBOL_PCREL: return "lla\t%0,%1"; + case SYMBOL_GPREL: return "la\t%0,%1"; default: gcc_unreachable (); } } @@ -3290,6 +3312,10 @@ riscv_print_operand_reloc (FILE *file, r reloc = hi_reloc ? "%tprel_hi" : "%tprel_lo"; break; + case SYMBOL_GPREL: + reloc = hi_reloc ? "%gprel_hi" : "%gprel_lo"; + break; + default: output_operand_lossage ("invalid use of '%%%c'", hi_reloc ? 'h' : 'R'); return; @@ -4735,7 +4761,7 @@ riscv_option_override (void) /* We get better code with explicit relocs for CM_MEDLOW, but worse code for the others (for now). Pick the best default. */ if ((target_flags_explicit & MASK_EXPLICIT_RELOCS) == 0) - if (riscv_cmodel == CM_MEDLOW) + if (riscv_cmodel == CM_MEDLOW || TARGET_GPREL) target_flags |= MASK_EXPLICIT_RELOCS; /* Require that the ISA supports the requested floating-point ABI. */ Index: gcc/gcc/config/riscv/riscv.md =================================================================== --- gcc.orig/gcc/config/riscv/riscv.md +++ gcc/gcc/config/riscv/riscv.md @@ -28,6 +28,7 @@ UNSPEC_ADDRESS_FIRST UNSPEC_PCREL UNSPEC_LOAD_GOT + UNSPEC_GPREL UNSPEC_TLS UNSPEC_TLS_LE UNSPEC_TLS_IE Index: gcc/gcc/config/riscv/riscv.opt =================================================================== --- gcc.orig/gcc/config/riscv/riscv.opt +++ gcc/gcc/config/riscv/riscv.opt @@ -179,3 +179,7 @@ Use the given offset for addressing the TargetVariable long riscv_stack_protector_guard_offset = 0 + +mgprel +Target Report Mask(GPREL) +Use GP-relative sequences for data accesses.