mirror of
https://gcc.gnu.org/git/gcc.git
synced 2026-02-22 12:00:03 -05:00
Compare commits
7 Commits
master
...
devel/sh-l
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
09210f9272 | ||
|
|
eee3b80ab6 | ||
|
|
4d28c5b1eb | ||
|
|
c5a639c84c | ||
|
|
dbd192caf1 | ||
|
|
b924a79f5d | ||
|
|
8ee643e509 |
@@ -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;
|
||||
})
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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%#
|
||||
|
||||
@@ -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).
|
||||
|
||||
@@ -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);
|
||||
|
||||
31
gcc/testsuite/gcc.target/sh/pr55212-c248.c
Normal file
31
gcc/testsuite/gcc.target/sh/pr55212-c248.c
Normal 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);
|
||||
}
|
||||
Reference in New Issue
Block a user