===================================================================
@@ -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);
===================================================================
@@ -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")