Commit 37119410 by Bernd Schmidt Committed by Bernd Schmidt

re PR target/40457 (use stm and ldm to access consecutive memory words)

	PR target/40457
	* config/arm/arm.h (arm_regs_in_sequence): Declare.
	* config/arm/arm-protos.h (emit_ldm_seq, emit_stm_seq,
	load_multiple_sequence, store_multiple_sequence): Delete
	declarations.
	(arm_gen_load_multiple, arm_gen_store_multiple): Adjust
	declarations.
	* config/arm/ldmstm.md: New file.
	* config/arm/arm.c (arm_regs_in_sequence): New array.
	(load_multiple_sequence): Now static.  New args SAVED_ORDER,
	CHECK_REGS.  All callers changed.
	If SAVED_ORDER is nonnull, copy the computed order into it.
	If CHECK_REGS is false, don't sort REGS.  Handle Thumb mode.
	(store_multiple_sequence): Now static.  New args NOPS_TOTAL,
	SAVED_ORDER, REG_RTXS and CHECK_REGS.  All callers changed.
	If SAVED_ORDER is nonnull, copy the computed order into it.
	If CHECK_REGS is false, don't sort REGS.  Set up REG_RTXS just
	like REGS.  Handle Thumb mode.
	(arm_gen_load_multiple_1): New function, broken out of
	arm_gen_load_multiple.
	(arm_gen_store_multiple_1): New function, broken out of
	arm_gen_store_multiple.
	(arm_gen_multiple_op): New function, with code from
	arm_gen_load_multiple and arm_gen_store_multiple moved here.
	(arm_gen_load_multiple, arm_gen_store_multiple): Now just
	wrappers around arm_gen_multiple_op.  Remove argument UP, all callers
	changed.
	(gen_ldm_seq, gen_stm_seq, gen_const_stm_seq): New functions.
	* config/arm/predicates.md (commutative_binary_operator): New.
	(load_multiple_operation, store_multiple_operation): Handle more
	variants of these patterns with different starting offsets.  Handle
	Thumb-1.
	* config/arm/arm.md: Include "ldmstm.md".
	(ldmsi_postinc4, ldmsi_postinc4_thumb1, ldmsi_postinc3, ldmsi_postinc2,
	ldmsi4, ldmsi3, ldmsi2, stmsi_postinc4, stmsi_postinc4_thumb1,
	stmsi_postinc3, stmsi_postinc2, stmsi4, stmsi3, stmsi2 and related
	peepholes): Delete.
	* config/arm/ldmstm.md: New file.
	* config/arm/arm-ldmstm.ml: New file.

testsuite/
	PR target/40457
	* gcc.target/arm/pr40457-1.c: New test.
	* gcc.target/arm/pr40457-2.c: New test.

From-SVN: r162815
parent 0bd44ba2
...@@ -45,6 +45,46 @@ ...@@ -45,6 +45,46 @@
(movdi, arm_movsf_soft_insn, arm_movdf_soft_insn): Define them (movdi, arm_movsf_soft_insn, arm_movdf_soft_insn): Define them
and allow for TARGET_32BIT. and allow for TARGET_32BIT.
PR target/40457
* config/arm/arm.h (arm_regs_in_sequence): Declare.
* config/arm/arm-protos.h (emit_ldm_seq, emit_stm_seq,
load_multiple_sequence, store_multiple_sequence): Delete
declarations.
(arm_gen_load_multiple, arm_gen_store_multiple): Adjust
declarations.
* config/arm/ldmstm.md: New file.
* config/arm/arm.c (arm_regs_in_sequence): New array.
(load_multiple_sequence): Now static. New args SAVED_ORDER,
CHECK_REGS. All callers changed.
If SAVED_ORDER is nonnull, copy the computed order into it.
If CHECK_REGS is false, don't sort REGS. Handle Thumb mode.
(store_multiple_sequence): Now static. New args NOPS_TOTAL,
SAVED_ORDER, REG_RTXS and CHECK_REGS. All callers changed.
If SAVED_ORDER is nonnull, copy the computed order into it.
If CHECK_REGS is false, don't sort REGS. Set up REG_RTXS just
like REGS. Handle Thumb mode.
(arm_gen_load_multiple_1): New function, broken out of
arm_gen_load_multiple.
(arm_gen_store_multiple_1): New function, broken out of
arm_gen_store_multiple.
(arm_gen_multiple_op): New function, with code from
arm_gen_load_multiple and arm_gen_store_multiple moved here.
(arm_gen_load_multiple, arm_gen_store_multiple): Now just
wrappers around arm_gen_multiple_op. Remove argument UP, all callers
changed.
(gen_ldm_seq, gen_stm_seq, gen_const_stm_seq): New functions.
* config/arm/predicates.md (commutative_binary_operator): New.
(load_multiple_operation, store_multiple_operation): Handle more
variants of these patterns with different starting offsets. Handle
Thumb-1.
* config/arm/arm.md: Include "ldmstm.md".
(ldmsi_postinc4, ldmsi_postinc4_thumb1, ldmsi_postinc3, ldmsi_postinc2,
ldmsi4, ldmsi3, ldmsi2, stmsi_postinc4, stmsi_postinc4_thumb1,
stmsi_postinc3, stmsi_postinc2, stmsi4, stmsi3, stmsi2 and related
peepholes): Delete.
* config/arm/ldmstm.md: New file.
* config/arm/arm-ldmstm.ml: New file.
2010-08-02 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com> 2010-08-02 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
* config/arm/arm.c (COSTS_N_INSNS): Remove definition. * config/arm/arm.c (COSTS_N_INSNS): Remove definition.
......
...@@ -98,14 +98,11 @@ extern int symbol_mentioned_p (rtx); ...@@ -98,14 +98,11 @@ extern int symbol_mentioned_p (rtx);
extern int label_mentioned_p (rtx); extern int label_mentioned_p (rtx);
extern RTX_CODE minmax_code (rtx); extern RTX_CODE minmax_code (rtx);
extern int adjacent_mem_locations (rtx, rtx); extern int adjacent_mem_locations (rtx, rtx);
extern int load_multiple_sequence (rtx *, int, int *, int *, HOST_WIDE_INT *); extern bool gen_ldm_seq (rtx *, int, bool);
extern const char *emit_ldm_seq (rtx *, int); extern bool gen_stm_seq (rtx *, int);
extern int store_multiple_sequence (rtx *, int, int *, int *, HOST_WIDE_INT *); extern bool gen_const_stm_seq (rtx *, int);
extern const char * emit_stm_seq (rtx *, int); extern rtx arm_gen_load_multiple (int *, int, rtx, int, rtx, HOST_WIDE_INT *);
extern rtx arm_gen_load_multiple (int, int, rtx, int, int, extern rtx arm_gen_store_multiple (int *, int, rtx, int, rtx, HOST_WIDE_INT *);
rtx, HOST_WIDE_INT *);
extern rtx arm_gen_store_multiple (int, int, rtx, int, int,
rtx, HOST_WIDE_INT *);
extern int arm_gen_movmemqi (rtx *); extern int arm_gen_movmemqi (rtx *);
extern enum machine_mode arm_select_cc_mode (RTX_CODE, rtx, rtx); extern enum machine_mode arm_select_cc_mode (RTX_CODE, rtx, rtx);
extern enum machine_mode arm_select_dominance_cc_mode (rtx, rtx, extern enum machine_mode arm_select_dominance_cc_mode (rtx, rtx,
......
...@@ -1096,6 +1096,9 @@ extern int arm_structure_size_boundary; ...@@ -1096,6 +1096,9 @@ extern int arm_structure_size_boundary;
((MODE) == TImode || (MODE) == EImode || (MODE) == OImode \ ((MODE) == TImode || (MODE) == EImode || (MODE) == OImode \
|| (MODE) == CImode || (MODE) == XImode) || (MODE) == CImode || (MODE) == XImode)
/* The register numbers in sequence, for passing to arm_gen_load_multiple. */
extern int arm_regs_in_sequence[];
/* The order in which register should be allocated. It is good to use ip /* The order in which register should be allocated. It is good to use ip
since no saving is required (though calls clobber it) and it never contains since no saving is required (though calls clobber it) and it never contains
function parameters. It is quite good to use lr since other calls may function parameters. It is quite good to use lr since other calls may
......
...@@ -206,6 +206,11 @@ ...@@ -206,6 +206,11 @@
(and (match_code "ior,xor,and") (and (match_code "ior,xor,and")
(match_test "mode == GET_MODE (op)"))) (match_test "mode == GET_MODE (op)")))
;; True for commutative operators
(define_special_predicate "commutative_binary_operator"
(and (match_code "ior,xor,and,plus")
(match_test "mode == GET_MODE (op)")))
;; True for shift operators. ;; True for shift operators.
(define_special_predicate "shift_operator" (define_special_predicate "shift_operator"
(and (ior (ior (and (match_code "mult") (and (ior (ior (and (match_code "mult")
...@@ -333,13 +338,17 @@ ...@@ -333,13 +338,17 @@
(match_code "parallel") (match_code "parallel")
{ {
HOST_WIDE_INT count = XVECLEN (op, 0); HOST_WIDE_INT count = XVECLEN (op, 0);
int dest_regno; unsigned dest_regno;
rtx src_addr; rtx src_addr;
HOST_WIDE_INT i = 1, base = 0; HOST_WIDE_INT i = 1, base = 0;
HOST_WIDE_INT offset = 0;
rtx elt; rtx elt;
bool addr_reg_loaded = false;
bool update = false;
if (count <= 1 if (count <= 1
|| GET_CODE (XVECEXP (op, 0, 0)) != SET) || GET_CODE (XVECEXP (op, 0, 0)) != SET
|| !REG_P (SET_DEST (XVECEXP (op, 0, 0))))
return false; return false;
/* Check to see if this might be a write-back. */ /* Check to see if this might be a write-back. */
...@@ -347,6 +356,7 @@ ...@@ -347,6 +356,7 @@
{ {
i++; i++;
base = 1; base = 1;
update = true;
/* Now check it more carefully. */ /* Now check it more carefully. */
if (GET_CODE (SET_DEST (elt)) != REG if (GET_CODE (SET_DEST (elt)) != REG
...@@ -365,6 +375,15 @@ ...@@ -365,6 +375,15 @@
dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, i - 1))); dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, i - 1)));
src_addr = XEXP (SET_SRC (XVECEXP (op, 0, i - 1)), 0); src_addr = XEXP (SET_SRC (XVECEXP (op, 0, i - 1)), 0);
if (GET_CODE (src_addr) == PLUS)
{
if (GET_CODE (XEXP (src_addr, 1)) != CONST_INT)
return false;
offset = INTVAL (XEXP (src_addr, 1));
src_addr = XEXP (src_addr, 0);
}
if (!REG_P (src_addr))
return false;
for (; i < count; i++) for (; i < count; i++)
{ {
...@@ -373,16 +392,28 @@ ...@@ -373,16 +392,28 @@
if (GET_CODE (elt) != SET if (GET_CODE (elt) != SET
|| GET_CODE (SET_DEST (elt)) != REG || GET_CODE (SET_DEST (elt)) != REG
|| GET_MODE (SET_DEST (elt)) != SImode || GET_MODE (SET_DEST (elt)) != SImode
|| REGNO (SET_DEST (elt)) != (unsigned int)(dest_regno + i - base) || REGNO (SET_DEST (elt)) <= dest_regno
|| GET_CODE (SET_SRC (elt)) != MEM || GET_CODE (SET_SRC (elt)) != MEM
|| GET_MODE (SET_SRC (elt)) != SImode || GET_MODE (SET_SRC (elt)) != SImode
|| GET_CODE (XEXP (SET_SRC (elt), 0)) != PLUS || ((GET_CODE (XEXP (SET_SRC (elt), 0)) != PLUS
|| !rtx_equal_p (XEXP (XEXP (SET_SRC (elt), 0), 0), src_addr) || !rtx_equal_p (XEXP (XEXP (SET_SRC (elt), 0), 0), src_addr)
|| GET_CODE (XEXP (XEXP (SET_SRC (elt), 0), 1)) != CONST_INT || GET_CODE (XEXP (XEXP (SET_SRC (elt), 0), 1)) != CONST_INT
|| INTVAL (XEXP (XEXP (SET_SRC (elt), 0), 1)) != (i - base) * 4) || INTVAL (XEXP (XEXP (SET_SRC (elt), 0), 1)) != offset + (i - base) * 4)
&& (!REG_P (XEXP (SET_SRC (elt), 0))
|| offset + (i - base) * 4 != 0)))
return false; return false;
dest_regno = REGNO (SET_DEST (elt));
if (dest_regno == REGNO (src_addr))
addr_reg_loaded = true;
} }
/* For Thumb, we only have updating instructions. If the pattern does
not describe an update, it must be because the address register is
in the list of loaded registers - on the hardware, this has the effect
of overriding the update. */
if (update && addr_reg_loaded)
return false;
if (TARGET_THUMB1)
return update || addr_reg_loaded;
return true; return true;
}) })
...@@ -390,9 +421,9 @@ ...@@ -390,9 +421,9 @@
(match_code "parallel") (match_code "parallel")
{ {
HOST_WIDE_INT count = XVECLEN (op, 0); HOST_WIDE_INT count = XVECLEN (op, 0);
int src_regno; unsigned src_regno;
rtx dest_addr; rtx dest_addr;
HOST_WIDE_INT i = 1, base = 0; HOST_WIDE_INT i = 1, base = 0, offset = 0;
rtx elt; rtx elt;
if (count <= 1 if (count <= 1
...@@ -423,6 +454,16 @@ ...@@ -423,6 +454,16 @@
src_regno = REGNO (SET_SRC (XVECEXP (op, 0, i - 1))); src_regno = REGNO (SET_SRC (XVECEXP (op, 0, i - 1)));
dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, i - 1)), 0); dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, i - 1)), 0);
if (GET_CODE (dest_addr) == PLUS)
{
if (GET_CODE (XEXP (dest_addr, 1)) != CONST_INT)
return false;
offset = INTVAL (XEXP (dest_addr, 1));
dest_addr = XEXP (dest_addr, 0);
}
if (!REG_P (dest_addr))
return false;
for (; i < count; i++) for (; i < count; i++)
{ {
elt = XVECEXP (op, 0, i); elt = XVECEXP (op, 0, i);
...@@ -430,14 +471,17 @@ ...@@ -430,14 +471,17 @@
if (GET_CODE (elt) != SET if (GET_CODE (elt) != SET
|| GET_CODE (SET_SRC (elt)) != REG || GET_CODE (SET_SRC (elt)) != REG
|| GET_MODE (SET_SRC (elt)) != SImode || GET_MODE (SET_SRC (elt)) != SImode
|| REGNO (SET_SRC (elt)) != (unsigned int)(src_regno + i - base) || REGNO (SET_SRC (elt)) <= src_regno
|| GET_CODE (SET_DEST (elt)) != MEM || GET_CODE (SET_DEST (elt)) != MEM
|| GET_MODE (SET_DEST (elt)) != SImode || GET_MODE (SET_DEST (elt)) != SImode
|| GET_CODE (XEXP (SET_DEST (elt), 0)) != PLUS || ((GET_CODE (XEXP (SET_DEST (elt), 0)) != PLUS
|| !rtx_equal_p (XEXP (XEXP (SET_DEST (elt), 0), 0), dest_addr) || !rtx_equal_p (XEXP (XEXP (SET_DEST (elt), 0), 0), dest_addr)
|| GET_CODE (XEXP (XEXP (SET_DEST (elt), 0), 1)) != CONST_INT || GET_CODE (XEXP (XEXP (SET_DEST (elt), 0), 1)) != CONST_INT
|| INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1)) != (i - base) * 4) || INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1)) != offset + (i - base) * 4)
&& (!REG_P (XEXP (SET_DEST (elt), 0))
|| offset + (i - base) * 4 != 0)))
return false; return false;
src_regno = REGNO (SET_SRC (elt));
} }
return true; return true;
......
2010-08-02 Bernd Schmidt <bernds@codesourcery.com>
PR target/40457
* gcc.target/arm/pr40457-1.c: New test.
* gcc.target/arm/pr40457-2.c: New test.
2010-08-01 Janus Weil <janus@gcc.gnu.org> 2010-08-01 Janus Weil <janus@gcc.gnu.org>
PR fortran/44912 PR fortran/44912
......
/* { dg-options "-Os" } */
/* { dg-do compile } */
int bar(int* p)
{
int x = p[0] + p[1];
return x;
}
/* { dg-final { scan-assembler "ldm" } } */
/* { dg-options "-O2" } */
/* { dg-do compile } */
void foo(int* p)
{
p[0] = 1;
p[1] = 0;
}
/* { dg-final { scan-assembler "stm" } } */
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