Compare commits

...

7 Commits

Author SHA1 Message Date
Oleg Endo
09210f9272 SH: enable LRA by default
gcc/ChangeLog:

	PR target/55212
	* conifg/sh/sh.opt (sh_lra_flag): Init to 1.
2024-09-25 10:24:09 +09:00
Kaz Kojima
eee3b80ab6 SH: Fix the condition to use movsh_ie_y pattern.
gcc/ChangeLog:
	* config/sh/sh.cc (sh_movsf_ie_y_split_p): Take the subreg
	of DImode into account.
2024-09-25 10:22:10 +09:00
Kaz Kojima
4d28c5b1eb SH: pin input args to hard-regs via predicates for sfuncs
Some sfuncs uses hard reg as input and clobber its raw reg pattern. It
seems that LRA doesn't process this clobber pattern.  Rewrite these
patterns so as to work with LRA.

gcc/ChangeLog:
	* config/sh/predicates.md (hard_reg_r4, hard_reg_r5,
	hard_reg_r6): New predicates.
	* config/sh/sh.md (udivsi3_i4, udivsi3_i4_single,
	udivsi3_i1): Rewrite with match_operand and match_dup.
	(block_lump_real, block_lump_real_i4): Ditto.
	(udivsi3): Adjust for it.
	* config/sh/sh-mem.cc (expand_block_move): Ditto.
2024-09-25 10:20:31 +09:00
Kaz Kojima
c5a639c84c SH: A test case for the wrong-code with -mlra PR55212 c#248.
gcc/testsuite/ChangeLog:
	* gcc.target/sh/pr55212-c248.c: New test.
2024-09-25 10:02:28 +09:00
Alexandre Oliva
dbd192caf1 LRA: Take scratch as implicit unused output reloads
gcc/ChangeLog:
	* lra-constraints.cc (match_reload, process_alt_operands,
	curr_insn_transform): Take scratch as implicit unused
	output reloads.
2024-09-25 10:01:40 +09:00
Kaz Kojima
b924a79f5d SH: try to workaround fp-reg related move insns
LRA will try to satisfy the constraints in match_scratch for the memory
displacements and it will make issues on this target. To mitigate the
issue, split movsf_ie_ra into several new patterns to remove
match_scratch.  Also define a new sub-pattern of movdf for constant
loads.

gcc/ChangeLog:
	* gcc/config/sh/predicates.md (pc_relative_load_operand):
	New predicate.
	* gcc/config/sh/sh-protos.h (sh_movsf_ie_ra_split_p): Remove.
	(sh_movsf_ie_y_split_p): New proto.
	* gcc/config/sh/sh.cc: (sh_movsf_ie_ra_split_p): Remove.
	(sh_movsf_ie_y_split_p): New function.
	(broken_move): Take movsf_ie_ra into account for fldi cases.
	* gcc/config/sh/sh.md (movdf_i4_F_z): New insn pattern.
	(movdf): Use it.
	(movsf_ie_ra): Use define_insn instead of define_insn_and_split.
	(movsf_ie_F_z, movsf_ie_Q_z, movsf_ie_y): New insn pattern.
	(movsf): Use new patterns.
	(movsf-1):  Don't split when operands[0] or operands[1]
	is fpul.
	(movdf_i4_F_z+7): New splitter.
2024-09-25 10:01:01 +09:00
Kaz Kojima
8ee643e509 SH: Try to reduce R0 live ranges
Some move or extend patterns will make long R0 live ranges and could
confuse LRA.

gcc/ChangeLog:
	* config/sh/sh-protos.h
        (sh_satisfies_constraint_Sid_subreg_index): Declare.
	* config/sh/sh.cc (sh_satisfies_constraint_Sid_subreg_index):
	New function.
	* config/sh/sh.md (extend<mode>si2_short_mem_disp_z,
	*mov<mode>_store_mem_index, mov<mode>_store_mem_index):
	New insn and insn_and_split patterns.
	(extend<mode>si2, mov<mode>): Use them for LRA.
2024-09-25 09:51:15 +09:00
8 changed files with 327 additions and 97 deletions

View File

@@ -485,6 +485,17 @@
&& sh_legitimate_index_p (mode, XEXP (plus0_rtx, 1), TARGET_SH2A, true);
})
;; Returns true if OP is a pc relative load operand.
(define_predicate "pc_relative_load_operand"
(match_code "mem")
{
if (GET_MODE (op) != QImode
&& IS_PC_RELATIVE_LOAD_ADDR_P (XEXP (op, 0)))
return true;
return false;
})
;; Returns true if OP is a valid source operand for a logical operation.
(define_predicate "logical_operand"
(and (match_code "subreg,reg,const_int")
@@ -807,3 +818,22 @@
return false;
})
;; Predicats for the arguments of sfunc R4, R5 and R6.
(define_predicate "hard_reg_r4"
(match_code "reg")
{
return REGNO (op) == R4_REG;
})
(define_predicate "hard_reg_r5"
(match_code "reg")
{
return REGNO (op) == R5_REG;
})
(define_predicate "hard_reg_r6"
(match_code "reg")
{
return REGNO (op) == R6_REG;
})

View File

@@ -134,7 +134,7 @@ expand_block_move (rtx *operands)
int dwords = bytes >> 3;
emit_insn (gen_move_insn (r6, GEN_INT (dwords - 1)));
emit_insn (gen_block_lump_real_i4 (func_addr_rtx, lab));
emit_insn (gen_block_lump_real_i4 (func_addr_rtx, lab, r4, r5, r6));
return true;
}
else
@@ -178,7 +178,7 @@ expand_block_move (rtx *operands)
final_switch = 16 - ((bytes / 4) % 16);
while_loop = ((bytes / 4) / 16 - 1) * 16;
emit_insn (gen_move_insn (r6, GEN_INT (while_loop + final_switch)));
emit_insn (gen_block_lump_real (func_addr_rtx, lab));
emit_insn (gen_block_lump_real (func_addr_rtx, lab, r4, r5, r6));
return true;
}

View File

@@ -61,6 +61,7 @@ extern rtx legitimize_pic_address (rtx, machine_mode, rtx);
extern bool nonpic_symbol_mentioned_p (rtx);
extern void output_pic_addr_const (FILE *, rtx);
extern bool expand_block_move (rtx *);
extern bool sh_satisfies_constraint_Sid_subreg_index (rtx);
extern void prepare_move_operands (rtx[], machine_mode mode);
extern bool sh_expand_cmpstr (rtx *);
extern bool sh_expand_cmpnstr (rtx *);
@@ -102,7 +103,7 @@ extern rtx sh_find_equiv_gbr_addr (rtx_insn* cur_insn, rtx mem);
extern int sh_eval_treg_value (rtx op);
extern HOST_WIDE_INT sh_disp_addr_displacement (rtx mem_op);
extern int sh_max_mov_insn_displacement (machine_mode mode, bool consider_sh2a);
extern bool sh_movsf_ie_ra_split_p (rtx, rtx, rtx);
extern bool sh_movsf_ie_y_split_p (rtx, rtx);
extern void sh_expand_sym_label2reg (rtx, rtx, rtx, bool);
/* Result value of sh_find_set_of_reg. */

View File

@@ -1577,6 +1577,18 @@ sh_encode_section_info (tree decl, rtx rtl, int first)
SYMBOL_REF_FLAGS (XEXP (rtl, 0)) |= SYMBOL_FLAG_FUNCVEC_FUNCTION;
}
/* Test Sid constraint with subreg index. See also the comment in
prepare_move_operands. */
bool
sh_satisfies_constraint_Sid_subreg_index (rtx op)
{
return ((GET_CODE (op) == MEM)
&& ((GET_CODE (XEXP (op, 0)) == PLUS)
&& ((GET_CODE (XEXP (XEXP (op, 0), 0)) == REG)
&& ((GET_CODE (XEXP (XEXP (op, 0), 1)) == SUBREG)
&& (GET_CODE (XEXP (XEXP (XEXP (op, 0), 1), 0)) == REG)))));
}
/* Prepare operands for a move define_expand; specifically, one of the
operands must be in a register. */
void
@@ -4820,6 +4832,7 @@ broken_move (rtx_insn *insn)
we changed this to do a constant load. In that case
we don't have an r0 clobber, hence we must use fldi. */
&& (TARGET_FMOVD
|| sh_lra_p ()
|| (GET_CODE (XEXP (XVECEXP (PATTERN (insn), 0, 2), 0))
== SCRATCH))
&& REG_P (SET_DEST (pat))
@@ -11443,30 +11456,21 @@ sh_legitimize_address_displacement (rtx *offset1, rtx *offset2,
return false;
}
/* Return true if movsf insn should be splited with an additional
register. */
/* Return true if movsf insn should be splited with fpul register. */
bool
sh_movsf_ie_ra_split_p (rtx op0, rtx op1, rtx op2)
sh_movsf_ie_y_split_p (rtx op0, rtx op1)
{
/* op0 == op1 */
if (rtx_equal_p (op0, op1))
/* f, r */
if (REG_P (op0)
&& (SUBREG_P (op1)
&& (GET_MODE (SUBREG_REG (op1)) == SImode
|| GET_MODE (SUBREG_REG (op1)) == DImode)))
return true;
/* fy, FQ, reg */
if (GET_CODE (op1) == CONST_DOUBLE
&& ! satisfies_constraint_G (op1)
&& ! satisfies_constraint_H (op1)
&& REG_P (op0)
&& REG_P (op2))
return true;
/* f, r, y */
if (REG_P (op0) && FP_REGISTER_P (REGNO (op0))
&& REG_P (op1) && GENERAL_REGISTER_P (REGNO (op1))
&& REG_P (op2) && (REGNO (op2) == FPUL_REG))
return true;
/* r, f, y */
if (REG_P (op1) && FP_REGISTER_P (REGNO (op1))
&& REG_P (op0) && GENERAL_REGISTER_P (REGNO (op0))
&& REG_P (op2) && (REGNO (op2) == FPUL_REG))
/* r, f */
if (REG_P (op1)
&& (SUBREG_P (op0)
&& (GET_MODE (SUBREG_REG (op0)) == SImode
|| GET_MODE (SUBREG_REG (op0)) == DImode)))
return true;
return false;

View File

@@ -2194,13 +2194,24 @@
;; there is nothing to prevent reload from using r0 to reload the address.
;; This reload would clobber the value in r0 we are trying to store.
;; If we let reload allocate r0, then this problem can never happen.
;;
;; In addition to that, we also must pin the input regs to hard-regs via the
;; predicates. When these insns are instantiated it also emits the
;; accompanying mov insns to load the hard-regs. However, subsequent RTL
;; passes might move things around and reassign the operands to pseudo regs
;; which might get allocated to different (wrong) hard-regs eventually. To
;; avoid that, only allow matching these insns if the operands are the
;; expected hard-regs.
(define_insn "udivsi3_i1"
[(set (match_operand:SI 0 "register_operand" "=z,z")
(udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
(udiv:SI (match_operand:SI 3 "hard_reg_r4" "=r,r")
(match_operand:SI 4 "hard_reg_r5" "=r,r")))
(clobber (reg:SI T_REG))
(clobber (reg:SI PR_REG))
(clobber (reg:SI R1_REG))
(clobber (reg:SI R4_REG))
(clobber (match_dup 3))
(use (reg:SI R4_REG))
(use (reg:SI R5_REG))
(use (match_operand:SI 1 "arith_reg_operand" "r,r"))
(use (match_operand 2 "" "Z,Ccl"))]
"TARGET_SH1 && TARGET_DIVIDE_CALL_DIV1"
@@ -2212,7 +2223,8 @@
(define_insn "udivsi3_i4"
[(set (match_operand:SI 0 "register_operand" "=y,y")
(udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
(udiv:SI (match_operand:SI 3 "hard_reg_r4" "=r,r")
(match_operand:SI 4 "hard_reg_r5" "=r,r")))
(clobber (reg:SI T_REG))
(clobber (reg:SI PR_REG))
(clobber (reg:DF DR0_REG))
@@ -2220,9 +2232,11 @@
(clobber (reg:DF DR4_REG))
(clobber (reg:SI R0_REG))
(clobber (reg:SI R1_REG))
(clobber (reg:SI R4_REG))
(clobber (reg:SI R5_REG))
(clobber (match_dup 3))
(clobber (match_dup 4))
(clobber (reg:SI FPSCR_STAT_REG))
(use (reg:SI R4_REG))
(use (reg:SI R5_REG))
(use (match_operand:SI 1 "arith_reg_operand" "r,r"))
(use (match_operand 2 "" "Z,Ccl"))
(use (reg:SI FPSCR_MODES_REG))]
@@ -2236,7 +2250,8 @@
(define_insn "udivsi3_i4_single"
[(set (match_operand:SI 0 "register_operand" "=y,y")
(udiv:SI (reg:SI R4_REG) (reg:SI R5_REG)))
(udiv:SI (match_operand:SI 3 "hard_reg_r4" "=r,r")
(match_operand:SI 4 "hard_reg_r5" "=r,r")))
(clobber (reg:SI T_REG))
(clobber (reg:SI PR_REG))
(clobber (reg:DF DR0_REG))
@@ -2244,8 +2259,10 @@
(clobber (reg:DF DR4_REG))
(clobber (reg:SI R0_REG))
(clobber (reg:SI R1_REG))
(clobber (reg:SI R4_REG))
(clobber (reg:SI R5_REG))
(clobber (match_dup 3))
(clobber (match_dup 4))
(use (reg:SI R4_REG))
(use (reg:SI R5_REG))
(use (match_operand:SI 1 "arith_reg_operand" "r,r"))
(use (match_operand 2 "" "Z,Ccl"))]
"TARGET_FPU_ANY && TARGET_FPU_SINGLE"
@@ -2278,6 +2295,8 @@
{
rtx last;
rtx func_ptr = gen_reg_rtx (Pmode);
rtx r4 = gen_rtx_REG (SImode, R4_REG);
rtx r5 = gen_rtx_REG (SImode, R5_REG);
/* Emit the move of the address to a pseudo outside of the libcall. */
if (TARGET_DIVIDE_CALL_TABLE)
@@ -2305,9 +2324,9 @@
{
rtx lab = function_symbol (func_ptr, "__udivsi3_i4", SFUNC_STATIC).lab;
if (TARGET_FPU_SINGLE)
last = gen_udivsi3_i4_single (operands[0], func_ptr, lab);
last = gen_udivsi3_i4_single (operands[0], func_ptr, lab, r4, r5);
else
last = gen_udivsi3_i4 (operands[0], func_ptr, lab);
last = gen_udivsi3_i4 (operands[0], func_ptr, lab, r4, r5);
}
else if (TARGET_SH2A)
{
@@ -2319,10 +2338,10 @@
else
{
rtx lab = function_symbol (func_ptr, "__udivsi3", SFUNC_STATIC).lab;
last = gen_udivsi3_i1 (operands[0], func_ptr, lab);
last = gen_udivsi3_i1 (operands[0], func_ptr, lab, r4, r5);
}
emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
emit_move_insn (r4, operands[1]);
emit_move_insn (r5, operands[2]);
emit_insn (last);
DONE;
})
@@ -4801,7 +4820,38 @@
(define_expand "extend<mode>si2"
[(set (match_operand:SI 0 "arith_reg_dest")
(sign_extend:SI (match_operand:QIHI 1 "general_extend_operand")))])
(sign_extend:SI (match_operand:QIHI 1 "general_extend_operand")))]
""
{
/* When the displacement addressing is used, RA will assign r0 to
the pseudo register operand for the QI/HImode load. See
the comment in sh.cc:prepare_move_operand and PR target/55212. */
if (! lra_in_progress && ! reload_completed
&& sh_lra_p ()
&& ! TARGET_SH2A
&& arith_reg_dest (operands[0], <MODE>mode)
&& short_displacement_mem_operand (operands[1], <MODE>mode))
{
emit_insn (gen_extend<mode>si2_short_mem_disp_z (operands[0],
operands[1]));
DONE;
}
})
(define_insn_and_split "extend<mode>si2_short_mem_disp_z"
[(set (match_operand:SI 0 "arith_reg_dest" "=r")
(sign_extend:SI
(match_operand:QIHI 1 "short_displacement_mem_operand" "m")))
(clobber (reg:SI R0_REG))]
"TARGET_SH1 && ! TARGET_SH2A && sh_lra_p ()"
"#"
"&& 1"
[(set (match_dup 2) (sign_extend:SI (match_dup 1)))
(set (match_dup 0) (match_dup 2))]
{
operands[2] = gen_rtx_REG (SImode, R0_REG);
}
[(set_attr "type" "load")])
(define_insn_and_split "*extend<mode>si2_compact_reg"
[(set (match_operand:SI 0 "arith_reg_dest" "=r")
@@ -5343,9 +5393,50 @@
operands[1] = gen_lowpart (<MODE>mode, reg);
}
if (! lra_in_progress && ! reload_completed
&& sh_lra_p ()
&& ! TARGET_SH2A
&& arith_reg_operand (operands[1], <MODE>mode)
&& (satisfies_constraint_Sid (operands[0])
|| sh_satisfies_constraint_Sid_subreg_index (operands[0])))
{
rtx adr = XEXP (operands[0], 0);
rtx base = XEXP (adr, 0);
rtx idx = XEXP (adr, 1);
emit_insn (gen_mov<mode>_store_mem_index (base, idx,
operands[1]));
DONE;
}
prepare_move_operands (operands, <MODE>mode);
})
(define_insn "*mov<mode>_store_mem_index"
[(set (mem:QIHI
(plus:SI (match_operand:SI 0 "arith_reg_operand" "%r")
(match_operand:SI 1 "arith_reg_operand" "z")))
(match_operand:QIHI 2 "arith_reg_operand" "r"))]
"TARGET_SH1 && ! TARGET_SH2A && sh_lra_p ()
&& REG_P (operands[1]) && REGNO (operands[1]) == R0_REG"
"mov.<bw> %2,@(%1,%0)"
[(set_attr "type" "store")])
(define_insn_and_split "mov<mode>_store_mem_index"
[(set (mem:QIHI
(plus:SI (match_operand:SI 0 "arith_reg_operand" "%r")
(match_operand:SI 1 "arith_reg_operand" "^zr")))
(match_operand:QIHI 2 "arith_reg_operand" "r"))
(clobber (reg:SI R0_REG))]
"TARGET_SH1 && ! TARGET_SH2A && sh_lra_p ()"
"#"
"&& 1"
[(set (match_dup 3) (match_dup 1))
(set (mem:QIHI (plus:SI (match_dup 0) (match_dup 3))) (match_dup 2))]
{
operands[3] = gen_rtx_REG (SImode, R0_REG);
}
[(set_attr "type" "store")])
;; The pre-dec and post-inc mems must be captured by the '<' and '>'
;; constraints, otherwise wrong code might get generated.
(define_insn "*mov<mode>_load_predec"
@@ -5631,6 +5722,22 @@
(const_string "double")
(const_string "none")))])
;; LRA will try to satisfy the constraints in match_scratch for the memory
;; displacements and it will make issues on this target. Use R0 as a scratch
;; register for the constant load.
(define_insn "movdf_i4_F_z"
[(set (match_operand:DF 0 "fp_arith_reg_operand" "=d")
(match_operand:DF 1 "const_double_operand" "F"))
(use (reg:SI FPSCR_MODES_REG))
(clobber (reg:SI R0_REG))]
"TARGET_FPU_DOUBLE && sh_lra_p ()"
"#"
[(set_attr "type" "pcfload")
(set (attr "length") (if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 8)))
(set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
(const_string "double")
(const_string "none")))])
;; Moving DFmode between fp/general registers through memory
;; (the top of the stack) is faster than moving through fpul even for
;; little endian. Because the type of an instruction is important for its
@@ -5770,6 +5877,15 @@
[(set (match_dup 0) (match_dup 0))]
"")
(define_split
[(set (match_operand:SF 0 "register_operand" "")
(match_operand:SF 1 "register_operand" ""))
(use (reg:SI FPSCR_MODES_REG))]
"TARGET_SH2E && sh_lra_p () && reload_completed
&& true_regnum (operands[0]) == true_regnum (operands[1])"
[(set (match_dup 0) (match_dup 0))]
"")
;; fmovd substitute post-reload splits
(define_split
[(set (match_operand:DF 0 "register_operand" "")
@@ -6014,6 +6130,14 @@
prepare_move_operands (operands, DFmode);
if (TARGET_FPU_DOUBLE)
{
if (sh_lra_p ()
&& (GET_CODE (operands[1]) == CONST_DOUBLE
&& REG_P (operands[0])))
{
emit_insn (gen_movdf_i4_F_z (operands[0], operands[1]));
DONE;
}
emit_insn (gen_movdf_i4 (operands[0], operands[1]));
DONE;
}
@@ -6139,15 +6263,16 @@
(const_string "none")
(const_string "none")])])
(define_insn_and_split "movsf_ie_ra"
;; LRA will try to satisfy the constraints in match_scratch for the memory
;; displacements and it will make issues on this target. movsf_ie is splitted
;; into 4 patterns to avoid it when lra_in_progress is true.
(define_insn "movsf_ie_ra"
[(set (match_operand:SF 0 "general_movdst_operand"
"=f,r,f,f,fy,f,m, r,r,m,f,y,y,rf,r,y,<,y,y")
"=f,r,f,f,f,m, r,r,m,f,y,y,r,y,<,y,y")
(match_operand:SF 1 "general_movsrc_operand"
" f,r,G,H,FQ,m,f,FQ,m,r,y,f,>,fr,y,r,y,>,y"))
(use (reg:SI FPSCR_MODES_REG))
(clobber (match_scratch:SF 2 "=r,r,X,X,&z,r,r, X,r,r,r,r,r, y,r,r,r,r,r"))
(const_int 0)]
"TARGET_SH2E
" f,r,G,H,m,f,FQ,m,r,y,f,>,y,r,y,>,y"))
(use (reg:SI FPSCR_MODES_REG))]
"TARGET_SH2E && sh_lra_p ()
&& (arith_reg_operand (operands[0], SFmode)
|| fpul_operand (operands[0], SFmode)
|| arith_reg_operand (operands[1], SFmode)
@@ -6157,7 +6282,6 @@
mov %1,%0
fldi0 %0
fldi1 %0
#
fmov.s %1,%0
fmov.s %1,%0
mov.l %1,%0
@@ -6166,31 +6290,19 @@
fsts fpul,%0
flds %1,fpul
lds.l %1,%0
#
sts %1,%0
lds %1,%0
sts.l %1,%0
lds.l %1,%0
! move optimized away"
"reload_completed
&& sh_movsf_ie_ra_split_p (operands[0], operands[1], operands[2])"
[(const_int 0)]
{
if (! rtx_equal_p (operands[0], operands[1]))
{
emit_insn (gen_movsf_ie (operands[2], operands[1]));
emit_insn (gen_movsf_ie (operands[0], operands[2]));
}
}
[(set_attr "type" "fmove,move,fmove,fmove,pcfload,fload,fstore,pcload,load,
store,fmove,fmove,load,*,fpul_gp,gp_fpul,fstore,load,nil")
(set_attr "late_fp_use" "*,*,*,*,*,*,yes,*,*,*,*,*,*,*,yes,*,yes,*,*")
[(set_attr "type" "fmove,move,fmove,fmove,fload,fstore,pcload,load,
store,fmove,fmove,load,fpul_gp,gp_fpul,fstore,load,nil")
(set_attr "late_fp_use" "*,*,*,*,*,yes,*,*,*,*,*,*,yes,*,yes,*,*")
(set_attr_alternative "length"
[(const_int 2)
(const_int 2)
(const_int 2)
(const_int 2)
(const_int 4)
(if_then_else (match_operand 1 "displacement_mem_operand")
(const_int 4) (const_int 2))
(if_then_else (match_operand 0 "displacement_mem_operand")
@@ -6203,7 +6315,6 @@
(const_int 2)
(const_int 2)
(const_int 2)
(const_int 4)
(const_int 2)
(const_int 2)
(const_int 2)
@@ -6215,7 +6326,6 @@
(const_string "none")
(const_string "single")
(const_string "single")
(const_string "none")
(if_then_else (eq_attr "fmovd" "yes")
(const_string "single") (const_string "none"))
(if_then_else (eq_attr "fmovd" "yes")
@@ -6230,15 +6340,46 @@
(const_string "none")
(const_string "none")
(const_string "none")
(const_string "none")
(const_string "none")])])
(define_insn "movsf_ie_F_z"
[(set (match_operand:SF 0 "fp_arith_reg_operand" "=f")
(match_operand:SF 1 "const_double_operand" "F"))
(use (reg:SI FPSCR_MODES_REG))
(clobber (reg:SI R0_REG))]
"TARGET_SH2E && sh_lra_p ()"
"#"
[(set_attr "type" "pcfload")
(set_attr "length" "4")])
(define_insn "movsf_ie_Q_z"
[(set (match_operand:SF 0 "fpul_operand" "=y")
(match_operand:SF 1 "pc_relative_load_operand" "Q"))
(use (reg:SI FPSCR_MODES_REG))
(clobber (reg:SI R0_REG))]
"TARGET_SH2E && sh_lra_p ()"
"#"
[(set_attr "type" "pcfload")
(set_attr "length" "4")])
(define_insn "movsf_ie_y"
[(set (match_operand:SF 0 "arith_reg_dest" "=fr")
(match_operand:SF 1 "arith_reg_operand" "rf"))
(use (reg:SI FPSCR_MODES_REG))
(clobber (reg:SI FPUL_REG))]
"TARGET_SH2E && sh_lra_p ()"
"#"
[(set_attr "type" "*")
(set_attr "length" "4")])
(define_split
[(set (match_operand:SF 0 "register_operand" "")
(match_operand:SF 1 "register_operand" ""))
(use (reg:SI FPSCR_MODES_REG))
(clobber (reg:SI FPUL_REG))]
"TARGET_SH1"
"TARGET_SH1
&& ! fpul_operand (operands[0], SFmode)
&& ! fpul_operand (operands[1], SFmode)"
[(parallel [(set (reg:SF FPUL_REG) (match_dup 1))
(use (reg:SI FPSCR_MODES_REG))
(clobber (scratch:SI))])
@@ -6255,11 +6396,22 @@
prepare_move_operands (operands, SFmode);
if (TARGET_SH2E)
{
if (lra_in_progress)
if (sh_lra_p ())
{
if (GET_CODE (operands[0]) == SCRATCH)
DONE;
emit_insn (gen_movsf_ie_ra (operands[0], operands[1]));
if (GET_CODE (operands[1]) == CONST_DOUBLE
&& ! satisfies_constraint_G (operands[1])
&& ! satisfies_constraint_H (operands[1])
&& REG_P (operands[0]))
emit_insn (gen_movsf_ie_F_z (operands[0], operands[1]));
else if ((REG_P (operands[0]) && REGNO (operands[0]) == FPUL_REG)
&& satisfies_constraint_Q (operands[1]))
emit_insn (gen_movsf_ie_Q_z (operands[0], operands[1]));
else if (sh_movsf_ie_y_split_p (operands[0], operands[1]))
emit_insn (gen_movsf_ie_y (operands[0], operands[1]));
else
emit_insn (gen_movsf_ie_ra (operands[0], operands[1]));
DONE;
}
@@ -8951,17 +9103,20 @@
(set_attr "needs_delay_slot" "yes")])
(define_insn "block_lump_real"
[(parallel [(set (mem:BLK (reg:SI R4_REG))
(mem:BLK (reg:SI R5_REG)))
(use (match_operand:SI 0 "arith_reg_operand" "r,r"))
(use (match_operand 1 "" "Z,Ccl"))
(use (reg:SI R6_REG))
(clobber (reg:SI PR_REG))
(clobber (reg:SI T_REG))
(clobber (reg:SI R4_REG))
(clobber (reg:SI R5_REG))
(clobber (reg:SI R6_REG))
(clobber (reg:SI R0_REG))])]
[(set (mem:BLK (match_operand:SI 2 "hard_reg_r4" "=r,r"))
(mem:BLK (match_operand:SI 3 "hard_reg_r5" "=r,r")))
(use (match_operand:SI 0 "arith_reg_operand" "r,r"))
(use (match_operand 1 "" "Z,Ccl"))
(use (match_operand:SI 4 "hard_reg_r6" "=r,r"))
(use (reg:SI R4_REG))
(use (reg:SI R5_REG))
(use (reg:SI R6_REG))
(clobber (match_dup 2))
(clobber (match_dup 3))
(clobber (match_dup 4))
(clobber (reg:SI PR_REG))
(clobber (reg:SI T_REG))
(clobber (reg:SI R0_REG))]
"TARGET_SH1 && ! TARGET_HARD_SH4"
"@
jsr @%0%#
@@ -8986,20 +9141,23 @@
(set_attr "needs_delay_slot" "yes")])
(define_insn "block_lump_real_i4"
[(parallel [(set (mem:BLK (reg:SI R4_REG))
(mem:BLK (reg:SI R5_REG)))
(use (match_operand:SI 0 "arith_reg_operand" "r,r"))
(use (match_operand 1 "" "Z,Ccl"))
(use (reg:SI R6_REG))
(clobber (reg:SI PR_REG))
(clobber (reg:SI T_REG))
(clobber (reg:SI R4_REG))
(clobber (reg:SI R5_REG))
(clobber (reg:SI R6_REG))
(clobber (reg:SI R0_REG))
(clobber (reg:SI R1_REG))
(clobber (reg:SI R2_REG))
(clobber (reg:SI R3_REG))])]
[(set (mem:BLK (match_operand:SI 2 "hard_reg_r4" "=r,r"))
(mem:BLK (match_operand:SI 3 "hard_reg_r5" "=r,r")))
(use (match_operand:SI 0 "arith_reg_operand" "r,r"))
(use (match_operand 1 "" "Z,Ccl"))
(use (match_operand:SI 4 "hard_reg_r6" "=r,r"))
(use (reg:SI R4_REG))
(use (reg:SI R5_REG))
(use (reg:SI R6_REG))
(clobber (match_dup 2))
(clobber (match_dup 3))
(clobber (match_dup 4))
(clobber (reg:SI PR_REG))
(clobber (reg:SI T_REG))
(clobber (reg:SI R0_REG))
(clobber (reg:SI R1_REG))
(clobber (reg:SI R2_REG))
(clobber (reg:SI R3_REG))]
"TARGET_HARD_SH4"
"@
jsr @%0%#

View File

@@ -299,5 +299,5 @@ Target Var(TARGET_FSRRA)
Enable the use of the fsrra instruction.
mlra
Target Var(sh_lra_flag) Init(0) Save
Target Var(sh_lra_flag) Init(1) Save
Use LRA instead of reload (transitional).

View File

@@ -1213,7 +1213,9 @@ match_reload (signed char out, signed char *ins, signed char *outs,
return;
/* See a comment for the input operand above. */
narrow_reload_pseudo_class (out_rtx, goal_class);
if (find_reg_note (curr_insn, REG_UNUSED, out_rtx) == NULL_RTX)
if (find_reg_note (curr_insn, REG_UNUSED, out_rtx) == NULL_RTX
&& !ira_former_scratch_p (REGNO (SUBREG_P (out_rtx)
? SUBREG_REG (out_rtx) : out_rtx)))
{
reg = SUBREG_P (out_rtx) ? SUBREG_REG (out_rtx) : out_rtx;
start_sequence ();
@@ -2946,7 +2948,8 @@ process_alt_operands (int only_alternative)
objects with a REG_UNUSED note. */
if ((curr_static_id->operand[nop].type != OP_IN
&& no_output_reloads_p
&& ! find_reg_note (curr_insn, REG_UNUSED, op))
&& ! find_reg_note (curr_insn, REG_UNUSED, op)
&& ! ira_former_scratch_p (REGNO (operand_reg[nop])))
|| (curr_static_id->operand[nop].type != OP_OUT
&& no_input_reloads_p && ! const_to_mem)
|| (this_alternative_matches >= 0
@@ -2956,7 +2959,9 @@ process_alt_operands (int only_alternative)
[this_alternative_matches].type != OP_IN)
&& ! find_reg_note (curr_insn, REG_UNUSED,
no_subreg_reg_operand
[this_alternative_matches])))))
[this_alternative_matches])
&& ! (ira_former_scratch_p
(REGNO (operand_reg[nop])))))))
{
if (lra_dump_file != NULL)
fprintf
@@ -4744,7 +4749,8 @@ curr_insn_transform (bool check_only_p)
if (type != OP_IN
&& find_reg_note (curr_insn, REG_UNUSED, old) == NULL_RTX
/* OLD can be an equivalent constant here. */
&& !CONSTANT_P (old))
&& !CONSTANT_P (old)
&& !ira_former_scratch_p (REGNO (old)))
{
start_sequence ();
lra_emit_move (type == OP_INOUT ? copy_rtx (old) : old, new_reg);

View File

@@ -0,0 +1,31 @@
/* { dg-do run } */
/* { dg-options "-O2 -m4 -mlra -ffixed-r7 -ffixed-r8 -ffixed-r9 -ffixed-r10 -ffixed-r11 -ffixed-r12 -ffixed-r13" } */
#include <stdlib.h>
#include <string.h>
typedef struct { int c[64]; } obj;
obj obj0;
obj obj1;
void __attribute__ ((noinline))
bar (int a, int b, int c, int d, obj *q)
{
if (q->c[0] != 0x12345678 || q->c[1] != 0xdeadbeef)
abort ();
}
void foo (obj *p)
{
obj bobj;
bobj = *p;
bar (0, 0, 0, 0, &bobj);
}
int
main ()
{
obj0.c[0] = 0x12345678;
obj0.c[1] = 0xdeadbeef;
foo (&obj0);
exit (0);
}