Commit e5cc04a7 by Jeff Law

Clean up dead patterns, splitters, expanders and peepholes on the H8 port.

	* config/h8300/h8300.md (cpymemsi, movmd): Remove dead patterns,
	expanders, splits, etc.
	(movmd_internal_<mode>, movmd splitter, movstr, movsd): Likewise.
	(stpcpy_internal_<mode>, stpcpy splitter): Likewise.
	(peepholes to convert QI/HI mode pushes to SI mode pushes): Likewise.
	* config/h8300/h8300.c (h8300_swap_into_er6): Remove unused function.
	(h8300_swap_out_of_er6, h8sx_emit_movmd): Likewise
	* config/h8300/h8300-protos.h (h8300_swap_into_er6): Remove unused
	function prototype.
	(h8300_swap_out_of_er6, h8sx_emit_movmd): Likewise.
parent 54947e4d
2020-02-12 Jeff Law <law@redhat.com>
* config/h8300/h8300.md (cpymemsi, movmd): Remove dead patterns,
expanders, splits, etc.
(movmd_internal_<mode>, movmd splitter, movstr, movsd): Likewise.
(stpcpy_internal_<mode>, stpcpy splitter): Likewise.
(peepholes to convert QI/HI mode pushes to SI mode pushes): Likewise.
* config/h8300/h8300.c (h8300_swap_into_er6): Remove unused function.
(h8300_swap_out_of_er6, h8sx_emit_movmd): Likewise
* config/h8300/h8300-protos.h (h8300_swap_into_er6): Remove unused
function prototype.
(h8300_swap_out_of_er6, h8sx_emit_movmd): Likewise.
2020-02-12 Jakub Jelinek <jakub@redhat.com>
PR target/93670
......
......@@ -109,9 +109,6 @@ extern unsigned int h8300_insn_length_from_table (rtx_insn *, rtx *);
extern const char * output_h8sx_shift (rtx *, int, int);
extern bool h8300_operands_match_p (rtx *);
extern bool h8sx_mergeable_memrefs_p (rtx, rtx);
extern bool h8sx_emit_movmd (rtx, rtx, rtx, HOST_WIDE_INT);
extern void h8300_swap_into_er6 (rtx);
extern void h8300_swap_out_of_er6 (rtx);
extern poly_int64 h8300_push_rounding (poly_int64);
#endif /* ! GCC_H8300_PROTOS_H */
......@@ -2647,145 +2647,6 @@ h8300_operands_match_p (rtx *operands)
return false;
}
/* Try using movmd to move LENGTH bytes from memory region SRC to memory
region DEST. The two regions do not overlap and have the common
alignment given by ALIGNMENT. Return true on success.
Using movmd for variable-length moves seems to involve some
complex trade-offs. For instance:
- Preparing for a movmd instruction is similar to preparing
for a memcpy. The main difference is that the arguments
are moved into er4, er5 and er6 rather than er0, er1 and er2.
- Since movmd clobbers the frame pointer, we need to save
and restore it somehow when frame_pointer_needed. This can
sometimes make movmd sequences longer than calls to memcpy().
- The counter register is 16 bits, so the instruction is only
suitable for variable-length moves when sizeof (size_t) == 2.
That's only true in normal mode.
- We will often lack static alignment information. Falling back
on movmd.b would likely be slower than calling memcpy(), at least
for big moves.
This function therefore only uses movmd when the length is a
known constant, and only then if -fomit-frame-pointer is in
effect or if we're not optimizing for size.
At the moment the function uses movmd for all in-range constants,
but it might be better to fall back on memcpy() for large moves
if ALIGNMENT == 1. */
bool
h8sx_emit_movmd (rtx dest, rtx src, rtx length,
HOST_WIDE_INT alignment)
{
if (!flag_omit_frame_pointer && optimize_size)
return false;
if (GET_CODE (length) == CONST_INT)
{
rtx dest_reg, src_reg, first_dest, first_src;
HOST_WIDE_INT n;
int factor;
/* Use movmd.l if the alignment allows it, otherwise fall back
on movmd.b. */
factor = (alignment >= 2 ? 4 : 1);
/* Make sure the length is within range. We can handle counter
values up to 65536, although HImode truncation will make
the count appear negative in rtl dumps. */
n = INTVAL (length);
if (n <= 0 || n / factor > 65536)
return false;
/* Create temporary registers for the source and destination
pointers. Initialize them to the start of each region. */
dest_reg = copy_addr_to_reg (XEXP (dest, 0));
src_reg = copy_addr_to_reg (XEXP (src, 0));
/* Create references to the movmd source and destination blocks. */
first_dest = replace_equiv_address (dest, dest_reg);
first_src = replace_equiv_address (src, src_reg);
set_mem_size (first_dest, n & -factor);
set_mem_size (first_src, n & -factor);
length = copy_to_mode_reg (HImode, gen_int_mode (n / factor, HImode));
emit_insn (gen_movmd (first_dest, first_src, length, GEN_INT (factor)));
if ((n & -factor) != n)
{
/* Move SRC and DEST past the region we just copied.
This is done to update the memory attributes. */
dest = adjust_address (dest, BLKmode, n & -factor);
src = adjust_address (src, BLKmode, n & -factor);
/* Replace the addresses with the source and destination
registers, which movmd has left with the right values. */
dest = replace_equiv_address (dest, dest_reg);
src = replace_equiv_address (src, src_reg);
/* Mop up the left-over bytes. */
if (n & 2)
emit_move_insn (adjust_address (dest, HImode, 0),
adjust_address (src, HImode, 0));
if (n & 1)
emit_move_insn (adjust_address (dest, QImode, n & 2),
adjust_address (src, QImode, n & 2));
}
return true;
}
return false;
}
/* Move ADDR into er6 after pushing its old value onto the stack. */
void
h8300_swap_into_er6 (rtx addr)
{
rtx insn = push (HARD_FRAME_POINTER_REGNUM, false);
if (frame_pointer_needed)
add_reg_note (insn, REG_CFA_DEF_CFA,
plus_constant (Pmode, gen_rtx_MEM (Pmode, stack_pointer_rtx),
2 * UNITS_PER_WORD));
else
add_reg_note (insn, REG_CFA_ADJUST_CFA,
gen_rtx_SET (stack_pointer_rtx,
plus_constant (Pmode, stack_pointer_rtx, 4)));
emit_move_insn (hard_frame_pointer_rtx, addr);
if (REGNO (addr) == SP_REG)
emit_move_insn (hard_frame_pointer_rtx,
plus_constant (Pmode, hard_frame_pointer_rtx,
GET_MODE_SIZE (word_mode)));
}
/* Move the current value of er6 into ADDR and pop its old value
from the stack. */
void
h8300_swap_out_of_er6 (rtx addr)
{
rtx insn;
if (REGNO (addr) != SP_REG)
emit_move_insn (addr, hard_frame_pointer_rtx);
insn = pop (HARD_FRAME_POINTER_REGNUM);
if (frame_pointer_needed)
add_reg_note (insn, REG_CFA_DEF_CFA,
plus_constant (Pmode, hard_frame_pointer_rtx,
2 * UNITS_PER_WORD));
else
add_reg_note (insn, REG_CFA_ADJUST_CFA,
gen_rtx_SET (stack_pointer_rtx,
plus_constant (Pmode, stack_pointer_rtx, -4)));
}
/* Return the length of mov instruction. */
unsigned int
......
......@@ -474,174 +474,6 @@
(set_attr "length_table" "*,movl")
(set_attr "cc" "set_zn,set_znv")])
;; Implement block copies using movmd. Defining cpymemsi allows the full
;; range of constant lengths (up to 0x40000 bytes when using movmd.l).
;; See h8sx_emit_movmd for details.
(define_expand "cpymemsi"
[(use (match_operand:BLK 0 "memory_operand" ""))
(use (match_operand:BLK 1 "memory_operand" ""))
(use (match_operand:SI 2 "" ""))
(use (match_operand:SI 3 "const_int_operand" ""))]
"TARGET_H8300SX && 0"
{
if (h8sx_emit_movmd (operands[0], operands[1], operands[2], INTVAL (operands[3])))
DONE;
else
FAIL;
})
;; Expander for generating movmd insns. Operand 0 is the destination
;; memory region, operand 1 is the source, operand 2 is the counter
;; register and operand 3 is the chunk size (1, 2 or 4).
(define_expand "movmd"
[(parallel
[(set (match_operand:BLK 0 "memory_operand" "")
(match_operand:BLK 1 "memory_operand" ""))
(unspec [(match_operand:HI 2 "register_operand" "")
(match_operand:HI 3 "const_int_operand" "")] UNSPEC_MOVMD)
(clobber (match_dup 4))
(clobber (match_dup 5))
(set (match_dup 2)
(const_int 0))])]
"TARGET_H8300SX && 0"
{
operands[4] = copy_rtx (XEXP (operands[0], 0));
operands[5] = copy_rtx (XEXP (operands[1], 0));
})
;; This is a difficult instruction to reload since operand 0 must be the
;; frame pointer. See h8300_reg_class_from_letter for an explanation.
(define_insn "movmd_internal_<mode>"
[(set (mem:BLK (match_operand:P 3 "register_operand" "0,r"))
(mem:BLK (match_operand:P 4 "register_operand" "1,1")))
(unspec [(match_operand:HI 5 "register_operand" "2,2")
(match_operand:HI 6 "const_int_operand" "n,n")] UNSPEC_MOVMD)
(clobber (match_operand:P 0 "register_operand" "=d,??D"))
(clobber (match_operand:P 1 "register_operand" "=f,f"))
(set (match_operand:HI 2 "register_operand" "=c,c")
(const_int 0))]
"TARGET_H8300SX && 0"
"@
movmd%m6
#"
[(set_attr "length" "2,14")
(set_attr "can_delay" "no")
(set_attr "cc" "none,clobber")])
;; Split the above instruction if the destination register isn't er6.
;; We need a sequence like:
;;
;; mov.l er6,@-er7
;; mov.l <dest>,er6
;; movmd.sz
;; mov.l er6,<dest>
;; mov.l @er7+,er6
;;
;; where <dest> is the current destination register (operand 4).
;; The fourth instruction will be deleted if <dest> dies here.
(define_split
[(set (match_operand:BLK 0 "memory_operand" "")
(match_operand:BLK 1 "memory_operand" ""))
(unspec [(match_operand:HI 2 "register_operand" "")
(match_operand:HI 3 "const_int_operand" "")] UNSPEC_MOVMD)
(clobber (match_operand:P 4 "register_operand" ""))
(clobber (match_operand:P 5 "register_operand" ""))
(set (match_dup 2)
(const_int 0))]
"TARGET_H8300SX && reload_completed
&& 0
&& REGNO (operands[4]) != DESTINATION_REG"
[(const_int 0)]
{
rtx dest;
h8300_swap_into_er6 (XEXP (operands[0], 0));
dest = replace_equiv_address (operands[0], hard_frame_pointer_rtx);
emit_insn (gen_movmd (dest, operands[1], operands[2], operands[3]));
h8300_swap_out_of_er6 (operands[4]);
DONE;
})
;; Expand a call to stpcpy() using movsd. Operand 0 should point to
;; the final character, but movsd leaves it pointing to the character
;; after that.
(define_expand "movstr"
[(use (match_operand 0 "register_operand" ""))
(use (match_operand:BLK 1 "memory_operand" ""))
(use (match_operand:BLK 2 "memory_operand" ""))]
"TARGET_H8300SX && 0"
{
operands[1] = replace_equiv_address
(operands[1], copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
operands[2] = replace_equiv_address
(operands[2], copy_to_mode_reg (Pmode, XEXP (operands[2], 0)));
emit_insn (gen_movsd (operands[1], operands[2], gen_reg_rtx (Pmode)));
emit_insn (gen_add3_insn (operands[0], XEXP (operands[1], 0), constm1_rtx));
DONE;
})
;; Expander for generating a movsd instruction. Operand 0 is the
;; destination string, operand 1 is the source string and operand 2
;; is a scratch register.
(define_expand "movsd"
[(parallel
[(set (match_operand:BLK 0 "memory_operand" "")
(unspec:BLK [(match_operand:BLK 1 "memory_operand" "")]
UNSPEC_STPCPY))
(clobber (match_dup 3))
(clobber (match_dup 4))
(clobber (match_operand 2 "register_operand" ""))])]
"TARGET_H8300SX && 0"
{
operands[3] = copy_rtx (XEXP (operands[0], 0));
operands[4] = copy_rtx (XEXP (operands[1], 0));
})
;; See comments above memcpy_internal().
(define_insn "stpcpy_internal_<mode>"
[(set (mem:BLK (match_operand:P 3 "register_operand" "0,r"))
(unspec:BLK [(mem:BLK (match_operand:P 4 "register_operand" "1,1"))]
UNSPEC_STPCPY))
(clobber (match_operand:P 0 "register_operand" "=d,??D"))
(clobber (match_operand:P 1 "register_operand" "=f,f"))
(clobber (match_operand:P 2 "register_operand" "=c,c"))]
"TARGET_H8300SX && 0"
"@
\n1:\tmovsd\t2f\;bra\t1b\n2:
#"
[(set_attr "length" "6,18")
(set_attr "cc" "none,clobber")])
;; Split the above instruction if the destination isn't er6. This works
;; in the same way as the movmd splitter.
(define_split
[(set (match_operand:BLK 0 "memory_operand" "")
(unspec:BLK [(match_operand:BLK 1 "memory_operand" "")] UNSPEC_STPCPY))
(clobber (match_operand:P 2 "register_operand" ""))
(clobber (match_operand:P 3 "register_operand" ""))
(clobber (match_operand:P 4 "register_operand" ""))]
"TARGET_H8300SX && reload_completed
&& 0
&& REGNO (operands[2]) != DESTINATION_REG"
[(const_int 0)]
{
rtx dest;
h8300_swap_into_er6 (XEXP (operands[0], 0));
dest = replace_equiv_address (operands[0], hard_frame_pointer_rtx);
emit_insn (gen_movsd (dest, operands[1], operands[4]));
h8300_swap_out_of_er6 (operands[2]);
DONE;
})
(include "mova.md")
(define_insn "*movsf_h8300"
......@@ -4248,60 +4080,6 @@
(clobber (match_dup 2))])]
"")
;; Convert a QImode push into an SImode push so that the
;; define_peephole2 below can cram multiple pushes into one stm.l.
(define_peephole2
[(parallel [(set (reg:SI SP_REG)
(plus:SI (reg:SI SP_REG) (const_int -4)))
(set (mem:QI (plus:SI (reg:SI SP_REG) (const_int -3)))
(match_operand:QI 0 "register_operand" ""))])]
"TARGET_H8300S && !TARGET_NORMAL_MODE && REGNO (operands[0]) != SP_REG"
[(set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
(match_dup 0))]
{
operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]));
})
(define_peephole2
[(parallel [(set (reg:HI SP_REG)
(plus:HI (reg:HI SP_REG) (const_int -4)))
(set (mem:QI (plus:HI (reg:HI SP_REG) (const_int -3)))
(match_operand:QI 0 "register_operand" ""))])]
"TARGET_H8300S && TARGET_NORMAL_MODE && REGNO (operands[0]) != SP_REG"
[(set (mem:SI (pre_dec:HI (reg:HI SP_REG)))
(match_dup 0))]
{
operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]));
})
;; Convert a HImode push into an SImode push so that the
;; define_peephole2 below can cram multiple pushes into one stm.l.
(define_peephole2
[(parallel [(set (reg:SI SP_REG)
(plus:SI (reg:SI SP_REG) (const_int -4)))
(set (mem:HI (plus:SI (reg:SI SP_REG) (const_int -2)))
(match_operand:HI 0 "register_operand" ""))])]
"TARGET_H8300S && !TARGET_NORMAL_MODE && REGNO (operands[0]) != SP_REG"
[(set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
(match_dup 0))]
{
operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]));
})
(define_peephole2
[(parallel [(set (reg:HI SP_REG)
(plus:HI (reg:HI SP_REG) (const_int -4)))
(set (mem:HI (plus:HI (reg:HI SP_REG) (const_int -2)))
(match_operand:HI 0 "register_operand" ""))])]
"TARGET_H8300S && TARGET_NORMAL_MODE && REGNO (operands[0]) != SP_REG"
[(set (mem:SI (pre_dec:HI (reg:HI SP_REG)))
(match_dup 0))]
{
operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]));
})
;; Cram four pushes into stm.l.
(define_peephole2
......@@ -5748,69 +5526,6 @@
;; Transform
;;
;; mov dst,reg
;; op src,reg
;; mov reg,dst
;;
;; into
;;
;; op src,dst
;;
;; if "reg" dies at the end of the sequence.
(define_peephole2
[(set (match_operand 0 "register_operand" "")
(match_operand 1 "memory_operand" ""))
(set (match_dup 0)
(match_operator 2 "h8sx_binary_memory_operator"
[(match_dup 0)
(match_operand 3 "h8300_src_operand" "")]))
(set (match_operand 4 "memory_operand" "")
(match_dup 0))]
"0 /* Disable because it breaks compiling fp-bit.c. */
&& TARGET_H8300SX
&& peep2_reg_dead_p (3, operands[0])
&& !reg_overlap_mentioned_p (operands[0], operands[3])
&& !reg_overlap_mentioned_p (operands[0], operands[4])
&& h8sx_mergeable_memrefs_p (operands[4], operands[1])"
[(set (match_dup 4)
(match_dup 5))]
{
operands[5] = shallow_copy_rtx (operands[2]);
XEXP (operands[5], 0) = operands[1];
})
;; Transform
;;
;; mov src,reg
;; op reg,dst
;;
;; into
;;
;; op src,dst
;;
;; if "reg" dies in the second insn.
(define_peephole2
[(set (match_operand 0 "register_operand" "")
(match_operand 1 "h8300_src_operand" ""))
(set (match_operand 2 "h8300_dst_operand" "")
(match_operator 3 "h8sx_binary_memory_operator"
[(match_operand 4 "h8300_dst_operand" "")
(match_dup 0)]))]
"0 /* Disable because it breaks compiling fp-bit.c. */
&& TARGET_H8300SX
&& peep2_reg_dead_p (2, operands[0])
&& !reg_overlap_mentioned_p (operands[0], operands[4])"
[(set (match_dup 2)
(match_dup 5))]
{
operands[5] = shallow_copy_rtx (operands[3]);
XEXP (operands[5], 1) = operands[1];
})
;; Transform
;;
;; mov dst,reg
;; op reg
;; mov reg,dst
;;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment