mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-25 10:30:43 +08:00
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.
This commit is contained in:
parent
54947e4db0
commit
e5cc04a73a
gcc
@ -1,3 +1,16 @@
|
||||
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
|
||||
@ -5745,69 +5523,6 @@
|
||||
(match_dup 0))]
|
||||
"")
|
||||
|
||||
;; 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
|
||||
|
Loading…
x
Reference in New Issue
Block a user