This patch builds on the previous patch, and it adds the PCREL_OPT optimization for loads of external variables that involve sign extension, zero extension, or float extension as part of the load.
I have built a bootstrap compiler on a little endian power8 system and it caused no regressions in the test suite. Can I check this in once the previous patch has been checked in? 2019-11-15 Michael Meissner <meiss...@linux.ibm.com> * config/rs6000/pcrel-opt.c (pcrel_opt::do_pcrel_opt_load): Add support to do the PCREL_OPT optimization with sign, zero, and float extension. * config/rs6000/rs6000.md (pcrel_opt_ldsi_sext<mode>): New insns for applying the PCREL_OPT optimization to SImode sign extension. (pcrel_opt_ldhi_sext<mode>): New insns for applying the PCREL_OPT optimization to HImode sign extension. (pcrel_opt_ldsi_zext<mode>): New insns for applying the PCREL_OPT optimization to SImode zero extension. (pcrel_opt_ldhi_zext<mode>): New insns for applying the PCREL_OPT optimization to HImode zero extension. (pcrel_opt_ldqi_zext<mode>): New insns for applying the PCREL_OPT optimization to QImode zero extension. (pcrel_opt_ldsf_extend): New insns for applying the PCREL_OPT optimization to SFmode float extension. Index: gcc/config/rs6000/pcrel-opt.c =================================================================== --- gcc/config/rs6000/pcrel-opt.c (revision 278315) +++ gcc/config/rs6000/pcrel-opt.c (working copy) @@ -223,6 +223,27 @@ pcrel_opt::do_pcrel_opt_load (rtx_insn * rtx mem_inner = mem; unsigned int reg_regno = reg_or_subregno (reg); + // LWA is a DS format instruction, but LWZ is a D format instruction. We use + // DImode for the mode to force checking whether the bottom 2 bits are 0. + // However FPR and vector registers uses the LFIWAX instruction which is + // indexed only. + if (GET_CODE (mem) == SIGN_EXTEND && GET_MODE (XEXP (mem, 0)) == SImode) + { + if (!INT_REGNO_P (reg_regno)) + return false; + + mem_inner = XEXP (mem, 0); + mem_mode = DImode; + } + + else if (GET_CODE (mem) == SIGN_EXTEND + || GET_CODE (mem) == ZERO_EXTEND + || GET_CODE (mem) == FLOAT_EXTEND) + { + mem_inner = XEXP (mem, 0); + mem_mode = GET_MODE (mem_inner); + } + if (!MEM_P (mem_inner)) return false; @@ -275,8 +296,9 @@ pcrel_opt::do_pcrel_opt_load (rtx_insn * return false; } - // Update the load insn. Add an explicit clobber of the GOT register just in - // case something runs after this pass. + // Update the load insn. If the mem had a sign/zero/float extend, add that + // also after doing the UNSPEC. Add an explicit clobber of the GOT register + // just in case something runs after this pass. // // (parallel [(set (reg) // (unspec:<MODE> [(mem (got) @@ -288,6 +310,9 @@ pcrel_opt::do_pcrel_opt_load (rtx_insn * rtx new_load = gen_rtx_UNSPEC (GET_MODE (mem_inner), v_load, UNSPEC_PCREL_OPT_LD_RELOC); + if (GET_CODE (mem) != GET_CODE (mem_inner)) + new_load = gen_rtx_fmt_e (GET_CODE (mem), reg_mode, new_load); + rtx old_load_set = PATTERN (load_insn); rtx new_load_set = gen_rtx_SET (reg, new_load); rtx load_clobber = gen_rtx_CLOBBER (VOIDmode, @@ -484,11 +509,21 @@ pcrel_opt::do_pcrel_opt_got_addr (rtx_in { reg = SET_DEST (load_set); mem = SET_SRC (load_set); - if (!MEM_P (mem)) - return; + switch (GET_CODE (mem)) + { + case MEM: + break; - if (!REG_P (reg) && !SUBREG_P (reg)) - return; + case SIGN_EXTEND: + case ZERO_EXTEND: + case FLOAT_EXTEND: + if (!MEM_P (XEXP (mem, 0))) + return; + break; + + default: + return; + } // If there were any stores in the insns between loading the GOT address // and doing the load, turn off the optimization. @@ -499,6 +534,9 @@ pcrel_opt::do_pcrel_opt_got_addr (rtx_in else return; + if (!REG_P (reg) && !SUBREG_P (reg)) + return; + machine_mode mode = GET_MODE (reg); unsigned int regno = reg_or_subregno (reg); unsigned int size = GET_MODE_SIZE (mode); Index: gcc/config/rs6000/rs6000.md =================================================================== --- gcc/config/rs6000/rs6000.md (revision 278315) +++ gcc/config/rs6000/rs6000.md (working copy) @@ -14813,6 +14813,61 @@ (define_insn "*pcrel_opt_ld<mode>" "%r2l<wd>z %0,%1" [(set_attr "type" "load")]) +(define_insn "*pcrel_opt_ldsi_sext<mode>" + [(set (match_operand:EXTSI 0 "gpc_reg_operand" "=r") + (sign_extend:EXTSI + (unspec:SI [(match_operand:SI 1 "non_prefixed_memory" "o") + (match_operand 2 "const_int_operand" "n")] + UNSPEC_PCREL_OPT_LD_RELOC))) + (clobber (match_scratch:DI 3 "=bX"))] + "TARGET_PCREL_OPT" + "%r2lwa %0,%1" + [(set_attr "type" "load")]) + +(define_insn "*pcrel_opt_ldhi_sext<mode>" + [(set (match_operand:EXTHI 0 "gpc_reg_operand" "=r") + (sign_extend:EXTHI + (unspec:HI [(match_operand:HI 1 "non_prefixed_memory" "o") + (match_operand 2 "const_int_operand" "n")] + UNSPEC_PCREL_OPT_LD_RELOC))) + (clobber (match_scratch:DI 3 "=bX"))] + "TARGET_PCREL_OPT" + "%r2lha %0,%1" + [(set_attr "type" "load")]) + +(define_insn "*pcrel_opt_ldsi_zext<mode>" + [(set (match_operand:EXTSI 0 "gpc_reg_operand" "=r") + (zero_extend:EXTSI + (unspec:SI [(match_operand:SI 1 "non_prefixed_memory" "o") + (match_operand 2 "const_int_operand" "n")] + UNSPEC_PCREL_OPT_LD_RELOC))) + (clobber (match_scratch:DI 3 "=bX"))] + "TARGET_PCREL_OPT" + "%r2lwz %0,%1" + [(set_attr "type" "load")]) + +(define_insn "*pcrel_opt_ldhi_zext<mode>" + [(set (match_operand:EXTHI 0 "gpc_reg_operand" "=r") + (zero_extend:EXTHI + (unspec:HI [(match_operand:HI 1 "non_prefixed_memory" "o") + (match_operand 2 "const_int_operand" "n")] + UNSPEC_PCREL_OPT_LD_RELOC))) + (clobber (match_scratch:DI 3 "=bX"))] + "TARGET_PCREL_OPT" + "%r2lhz %0,%1" + [(set_attr "type" "load")]) + +(define_insn "*pcrel_opt_ldqi_zext<mode>" + [(set (match_operand:EXTQI 0 "gpc_reg_operand" "=r") + (zero_extend:EXTQI + (unspec:QI [(match_operand:QI 1 "non_prefixed_memory" "o") + (match_operand 2 "const_int_operand" "n")] + UNSPEC_PCREL_OPT_LD_RELOC))) + (clobber (match_scratch:DI 3 "=bX"))] + "TARGET_PCREL_OPT" + "%r2lbz %0,%1" + [(set_attr "type" "load")]) + (define_insn "*pcrel_opt_lddi" [(set (match_operand:DI 0 "gpc_reg_operand" "=r,d,v") (unspec:DI [(match_operand:DI 1 "non_prefixed_memory" "o,o,o") @@ -14839,6 +14894,19 @@ (define_insn "*pcrel_opt_ldsf" %r2lwz %0,%1" [(set_attr "type" "fpload,fpload,load")]) +(define_insn "*pcrel_opt_ldsf_extend" + [(set (match_operand:DF 0 "gpc_reg_operand" "=d,v") + (float_extend:DF + (unspec:SF [(match_operand:SF 1 "non_prefixed_memory" "o,o") + (match_operand 2 "const_int_operand" "n,n")] + UNSPEC_PCREL_OPT_LD_RELOC))) + (clobber (match_scratch:DI 3 "=bX,bX"))] + "TARGET_PCREL_OPT" + "@ + %r2lfs %0,%1 + %r2lxssp %0,%1" + [(set_attr "type" "fpload")]) + (define_insn "*pcrel_opt_lddf" [(set (match_operand:DF 0 "gpc_reg_operand" "=d,v,r") (unspec:DF [(match_operand:DF 1 "non_prefixed_memory" "o,o,o") -- Michael Meissner, IBM IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA email: meiss...@linux.ibm.com, phone: +1 (978) 899-4797