Commit 32a6f4f4 by Kito Cheng Committed by Chung-Ju Wu

[NDS32] Refine load_multiple and store_multiple.

gcc/
	* config/nds32/nds32-protos.h
	(nds32_expand_load_multiple): New arguments.
	(nds32_expand_store_multiple): Ditto.
	(nds32_valid_multiple_load_store): Rename ...
	(nds32_valid_multiple_load_store_p): ... to this.
	* config/nds32/nds32-memory-manipulation.c
	(nds32_expand_load_multiple): Refine implementation.
	(nds32_expand_store_multiple): Ditto.
	* config/nds32/nds32-multiple.md
	(load_multiple): Update nds32_expand_load_multiple interface.
	(store_multiple): Update nds32_expand_store_multiple interface.
	* config/nds32/nds32-predicates.c
	(nds32_valid_multiple_load_store): Rename ...
	(nds32_valid_multiple_load_store_p): ... to this and refine
	implementation.
	* config/nds32/predicates.md
	(nds32_load_multiple_and_update_address_operation): New predicate.
	(nds32_store_multiple_and_update_address_operation): New predicate.

Co-Authored-By: Chung-Ju Wu <jasonwucj@gmail.com>
Co-Authored-By: Monk Chiang <sh.chiang04@gmail.com>

From-SVN: r258234
parent 264159d2
2018-03-04 Kito Cheng <kito.cheng@gmail.com> 2018-03-04 Kito Cheng <kito.cheng@gmail.com>
Monk Chiang <sh.chiang04@gmail.com>
Chung-Ju Wu <jasonwucj@gmail.com>
* config/nds32/nds32-protos.h
(nds32_expand_load_multiple): New arguments.
(nds32_expand_store_multiple): Ditto.
(nds32_valid_multiple_load_store): Rename ...
(nds32_valid_multiple_load_store_p): ... to this.
* config/nds32/nds32-memory-manipulation.c
(nds32_expand_load_multiple): Refine implementation.
(nds32_expand_store_multiple): Ditto.
* config/nds32/nds32-multiple.md
(load_multiple): Update nds32_expand_load_multiple interface.
(store_multiple): Update nds32_expand_store_multiple interface.
* config/nds32/nds32-predicates.c
(nds32_valid_multiple_load_store): Rename ...
(nds32_valid_multiple_load_store_p): ... to this and refine
implementation.
* config/nds32/predicates.md
(nds32_load_multiple_and_update_address_operation): New predicate.
(nds32_store_multiple_and_update_address_operation): New predicate.
2018-03-04 Kito Cheng <kito.cheng@gmail.com>
Chung-Ju Wu <jasonwucj@gmail.com> Chung-Ju Wu <jasonwucj@gmail.com>
* config/nds32/nds32.md (type): Add load_multiple and store_multiple. * config/nds32/nds32.md (type): Add load_multiple and store_multiple.
......
...@@ -40,16 +40,50 @@ ...@@ -40,16 +40,50 @@
Check nds32-multiple.md file for the patterns. */ Check nds32-multiple.md file for the patterns. */
rtx rtx
nds32_expand_load_multiple (int base_regno, int count, nds32_expand_load_multiple (int base_regno, int count,
rtx base_addr, rtx basemem) rtx base_addr, rtx basemem,
bool update_base_reg_p,
rtx *update_base_reg)
{ {
int par_index; int par_index;
int offset; int offset;
int start_idx;
rtx result; rtx result;
rtx new_addr, mem, reg; rtx new_addr, mem, reg;
/* Create the pattern that is presented in nds32-multiple.md. */ /* Generate a unaligned load to prevent load instruction pull out from
parallel, and then it will generate lwi, and lose unaligned acces */
if (count == 1)
{
reg = gen_rtx_REG (SImode, base_regno);
if (update_base_reg_p)
{
*update_base_reg = gen_reg_rtx (SImode);
return gen_unaligned_load_update_base_w (*update_base_reg, reg, base_addr);
}
else
return gen_unaligned_load_w (reg, gen_rtx_MEM (SImode, base_addr));
}
/* Create the pattern that is presented in nds32-multiple.md. */
if (update_base_reg_p)
{
result = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count + 1));
start_idx = 1;
}
else
{
result = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count)); result = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
start_idx = 0;
}
if (update_base_reg_p)
{
offset = count * 4;
new_addr = plus_constant (Pmode, base_addr, offset);
*update_base_reg = gen_reg_rtx (SImode);
XVECEXP (result, 0, 0) = gen_rtx_SET (*update_base_reg, new_addr);
}
for (par_index = 0; par_index < count; par_index++) for (par_index = 0; par_index < count; par_index++)
{ {
...@@ -60,7 +94,7 @@ nds32_expand_load_multiple (int base_regno, int count, ...@@ -60,7 +94,7 @@ nds32_expand_load_multiple (int base_regno, int count,
new_addr, offset); new_addr, offset);
reg = gen_rtx_REG (SImode, base_regno + par_index); reg = gen_rtx_REG (SImode, base_regno + par_index);
XVECEXP (result, 0, par_index) = gen_rtx_SET (reg, mem); XVECEXP (result, 0, (par_index + start_idx)) = gen_rtx_SET (reg, mem);
} }
return result; return result;
...@@ -68,16 +102,49 @@ nds32_expand_load_multiple (int base_regno, int count, ...@@ -68,16 +102,49 @@ nds32_expand_load_multiple (int base_regno, int count,
rtx rtx
nds32_expand_store_multiple (int base_regno, int count, nds32_expand_store_multiple (int base_regno, int count,
rtx base_addr, rtx basemem) rtx base_addr, rtx basemem,
bool update_base_reg_p,
rtx *update_base_reg)
{ {
int par_index; int par_index;
int offset; int offset;
int start_idx;
rtx result; rtx result;
rtx new_addr, mem, reg; rtx new_addr, mem, reg;
if (count == 1)
{
reg = gen_rtx_REG (SImode, base_regno);
if (update_base_reg_p)
{
*update_base_reg = gen_reg_rtx (SImode);
return gen_unaligned_store_update_base_w (*update_base_reg, base_addr, reg);
}
else
return gen_unaligned_store_w (gen_rtx_MEM (SImode, base_addr), reg);
}
/* Create the pattern that is presented in nds32-multiple.md. */ /* Create the pattern that is presented in nds32-multiple.md. */
if (update_base_reg_p)
{
result = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count + 1));
start_idx = 1;
}
else
{
result = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count)); result = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
start_idx = 0;
}
if (update_base_reg_p)
{
offset = count * 4;
new_addr = plus_constant (Pmode, base_addr, offset);
*update_base_reg = gen_reg_rtx (SImode);
XVECEXP (result, 0, 0) = gen_rtx_SET (*update_base_reg, new_addr);
}
for (par_index = 0; par_index < count; par_index++) for (par_index = 0; par_index < count; par_index++)
{ {
...@@ -88,7 +155,7 @@ nds32_expand_store_multiple (int base_regno, int count, ...@@ -88,7 +155,7 @@ nds32_expand_store_multiple (int base_regno, int count,
new_addr, offset); new_addr, offset);
reg = gen_rtx_REG (SImode, base_regno + par_index); reg = gen_rtx_REG (SImode, base_regno + par_index);
XVECEXP (result, 0, par_index) = gen_rtx_SET (mem, reg); XVECEXP (result, 0, par_index + start_idx) = gen_rtx_SET (mem, reg);
} }
return result; return result;
...@@ -135,8 +202,12 @@ nds32_expand_movmemqi (rtx dstmem, rtx srcmem, rtx total_bytes, rtx alignment) ...@@ -135,8 +202,12 @@ nds32_expand_movmemqi (rtx dstmem, rtx srcmem, rtx total_bytes, rtx alignment)
out_words = in_words = INTVAL (total_bytes) / UNITS_PER_WORD; out_words = in_words = INTVAL (total_bytes) / UNITS_PER_WORD;
emit_insn (nds32_expand_load_multiple (0, in_words, src_base_reg, srcmem)); emit_insn (
emit_insn (nds32_expand_store_multiple (0, out_words, dst_base_reg, dstmem)); nds32_expand_load_multiple (0, in_words, src_base_reg,
srcmem, false, NULL));
emit_insn (
nds32_expand_store_multiple (0, out_words, dst_base_reg,
dstmem, false, NULL));
/* Successfully create patterns, return 1. */ /* Successfully create patterns, return 1. */
return 1; return 1;
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -101,21 +101,33 @@ nds32_consecutive_registers_load_store_p (rtx op, ...@@ -101,21 +101,33 @@ nds32_consecutive_registers_load_store_p (rtx op,
We have to extract reg and mem of every element and We have to extract reg and mem of every element and
check if the information is valid for multiple load/store operation. */ check if the information is valid for multiple load/store operation. */
bool bool
nds32_valid_multiple_load_store (rtx op, bool load_p) nds32_valid_multiple_load_store_p (rtx op, bool load_p, bool bim_p)
{ {
int count; int count;
int first_elt_regno; int first_elt_regno;
int update_base_elt_idx;
int offset;
rtx elt; rtx elt;
rtx update_base;
/* Get the counts of elements in the parallel rtx. */ /* Get the counts of elements in the parallel rtx.
Last one is update base register if bim_p.
and pick up the first element. */
if (bim_p)
{
count = XVECLEN (op, 0) - 1;
elt = XVECEXP (op, 0, 1);
}
else
{
count = XVECLEN (op, 0); count = XVECLEN (op, 0);
/* Pick up the first element. */
elt = XVECEXP (op, 0, 0); elt = XVECEXP (op, 0, 0);
}
/* Perform some quick check for the first element in the parallel rtx. */ /* Perform some quick check for the first element in the parallel rtx. */
if (GET_CODE (elt) != SET if (GET_CODE (elt) != SET
|| count <= 1 || count <= 1
|| count > 8) || count > 25)
return false; return false;
/* Pick up regno of first element for further detail checking. /* Pick up regno of first element for further detail checking.
...@@ -141,11 +153,29 @@ nds32_valid_multiple_load_store (rtx op, bool load_p) ...@@ -141,11 +153,29 @@ nds32_valid_multiple_load_store (rtx op, bool load_p)
Refer to nds32-multiple.md for more information Refer to nds32-multiple.md for more information
about following checking. about following checking.
The starting element of parallel rtx is index 0. */ The starting element of parallel rtx is index 0. */
if (!nds32_consecutive_registers_load_store_p (op, load_p, 0, if (!nds32_consecutive_registers_load_store_p (op, load_p, bim_p ? 1 : 0,
first_elt_regno, first_elt_regno,
count)) count))
return false; return false;
if (bim_p)
{
update_base_elt_idx = 0;
update_base = XVECEXP (op, 0, update_base_elt_idx);
if (!REG_P (SET_DEST (update_base)))
return false;
if (GET_CODE (SET_SRC (update_base)) != PLUS)
return false;
else
{
offset = count * UNITS_PER_WORD;
elt = XEXP (SET_SRC (update_base), 1);
if (GET_CODE (elt) != CONST_INT
|| (INTVAL (elt) != offset))
return false;
}
}
/* Pass all test, this is a valid rtx. */ /* Pass all test, this is a valid rtx. */
return true; return true;
} }
......
...@@ -66,8 +66,8 @@ extern bool nds32_valid_smw_lwm_base_p (rtx); ...@@ -66,8 +66,8 @@ extern bool nds32_valid_smw_lwm_base_p (rtx);
/* Auxiliary functions for expanding rtl used in nds32-multiple.md. */ /* Auxiliary functions for expanding rtl used in nds32-multiple.md. */
extern rtx nds32_expand_load_multiple (int, int, rtx, rtx); extern rtx nds32_expand_load_multiple (int, int, rtx, rtx, bool, rtx *);
extern rtx nds32_expand_store_multiple (int, int, rtx, rtx); extern rtx nds32_expand_store_multiple (int, int, rtx, rtx, bool, rtx *);
extern int nds32_expand_movmemqi (rtx, rtx, rtx, rtx); extern int nds32_expand_movmemqi (rtx, rtx, rtx, rtx);
/* Auxiliary functions for expand unalign load instruction. */ /* Auxiliary functions for expand unalign load instruction. */
...@@ -80,7 +80,7 @@ extern void nds32_expand_unaligned_store (rtx *, enum machine_mode); ...@@ -80,7 +80,7 @@ extern void nds32_expand_unaligned_store (rtx *, enum machine_mode);
/* Auxiliary functions for multiple load/store predicate checking. */ /* Auxiliary functions for multiple load/store predicate checking. */
extern bool nds32_valid_multiple_load_store (rtx, bool); extern bool nds32_valid_multiple_load_store_p (rtx, bool, bool);
/* Auxiliary functions for stack operation predicate checking. */ /* Auxiliary functions for stack operation predicate checking. */
......
...@@ -66,7 +66,16 @@ ...@@ -66,7 +66,16 @@
{ {
/* To verify 'load' operation, pass 'true' for the second argument. /* To verify 'load' operation, pass 'true' for the second argument.
See the implementation in nds32.c for details. */ See the implementation in nds32.c for details. */
return nds32_valid_multiple_load_store (op, true); return nds32_valid_multiple_load_store_p (op, true, false);
})
(define_special_predicate "nds32_load_multiple_and_update_address_operation"
(match_code "parallel")
{
/* To verify 'load' operation, pass 'true' for the second argument.
to verify 'update address' operation, pass 'true' for the third argument
See the implementation in nds32.c for details. */
return nds32_valid_multiple_load_store_p (op, true, true);
}) })
(define_special_predicate "nds32_store_multiple_operation" (define_special_predicate "nds32_store_multiple_operation"
...@@ -74,7 +83,16 @@ ...@@ -74,7 +83,16 @@
{ {
/* To verify 'store' operation, pass 'false' for the second argument. /* To verify 'store' operation, pass 'false' for the second argument.
See the implementation in nds32.c for details. */ See the implementation in nds32.c for details. */
return nds32_valid_multiple_load_store (op, false); return nds32_valid_multiple_load_store_p (op, false, false);
})
(define_special_predicate "nds32_store_multiple_and_update_address_operation"
(match_code "parallel")
{
/* To verify 'store' operation, pass 'false' for the second argument,
to verify 'update address' operation, pass 'true' for the third argument
See the implementation in nds32.c for details. */
return nds32_valid_multiple_load_store_p (op, false, true);
}) })
(define_special_predicate "nds32_stack_push_operation" (define_special_predicate "nds32_stack_push_operation"
......
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