Skip to content

Commit 0e5512b

Browse files
artemiy-volkovMichielDerhaeg
authored andcommitted
arcv: implement TARGET_SCHED_FUSION_PRIORITY
To take better advantage of double load/store fusion, make use of the sched_fusion pass that assigns unique "fusion priorities" to load/store instructions and schedules operations on adjacent addresses together. This maximizes the probability that loads/stores are fused between each other instead of with other instructions. Signed-off-by: Artemiy Volkov <artemiy@synopsys.com>
1 parent 1aa42c1 commit 0e5512b

File tree

1 file changed

+75
-0
lines changed

1 file changed

+75
-0
lines changed

gcc/config/riscv/riscv.cc

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11784,6 +11784,78 @@ riscv_macro_fusion_pair_p (rtx_insn *prev, rtx_insn *curr)
1178411784
return false;
1178511785
}
1178611786

11787+
/* If INSN is a load or store of address in the form of [base+offset],
11788+
extract the two parts and set to BASE and OFFSET. IS_LOAD is set
11789+
to TRUE if it's a load. Return TRUE if INSN is such an instruction,
11790+
otherwise return FALSE. */
11791+
11792+
static bool
11793+
fusion_load_store (rtx_insn *insn, rtx *base, rtx *offset, bool *is_load)
11794+
{
11795+
rtx x, dest, src;
11796+
11797+
gcc_assert (INSN_P (insn));
11798+
x = PATTERN (insn);
11799+
if (GET_CODE (x) != SET)
11800+
return false;
11801+
11802+
src = SET_SRC (x);
11803+
dest = SET_DEST (x);
11804+
if (REG_P (src) && MEM_P (dest))
11805+
{
11806+
*is_load = false;
11807+
extract_base_offset_in_addr (dest, base, offset);
11808+
}
11809+
else if (MEM_P (src) && REG_P (dest))
11810+
{
11811+
*is_load = true;
11812+
extract_base_offset_in_addr (src, base, offset);
11813+
}
11814+
else
11815+
return false;
11816+
11817+
return (*base != NULL_RTX && *offset != NULL_RTX);
11818+
}
11819+
11820+
static void
11821+
riscv_sched_fusion_priority (rtx_insn *insn, int max_pri, int *fusion_pri,
11822+
int *pri)
11823+
{
11824+
int tmp, off_val;
11825+
bool is_load;
11826+
rtx base, offset;
11827+
11828+
gcc_assert (INSN_P (insn));
11829+
11830+
tmp = max_pri - 1;
11831+
if (!fusion_load_store (insn, &base, &offset, &is_load))
11832+
{
11833+
*pri = tmp;
11834+
*fusion_pri = tmp;
11835+
return;
11836+
}
11837+
11838+
tmp /= 2;
11839+
11840+
/* INSN with smaller base register goes first. */
11841+
tmp -= ((REGNO (base) & 0xff) << 20);
11842+
11843+
/* INSN with smaller offset goes first. */
11844+
off_val = (int)(INTVAL (offset));
11845+
11846+
/* Put loads/stores operating on adjacent words into the same
11847+
* scheduling group. */
11848+
*fusion_pri = tmp - ((off_val / (UNITS_PER_WORD * 2)) << 1) + is_load;
11849+
11850+
if (off_val >= 0)
11851+
tmp -= (off_val & 0xfffff);
11852+
else
11853+
tmp += ((- off_val) & 0xfffff);
11854+
11855+
*pri = tmp;
11856+
return;
11857+
}
11858+
1178711859
/* Adjust the cost/latency of instructions for scheduling.
1178811860
For now this is just used to change the latency of vector instructions
1178911861
according to their LMUL. We assume that an insn with LMUL == 8 requires
@@ -16468,6 +16540,9 @@ riscv_prefetch_offset_address_p (rtx x, machine_mode mode)
1646816540
#undef TARGET_SCHED_INIT
1646916541
#define TARGET_SCHED_INIT riscv_sched_init
1647016542

16543+
#undef TARGET_SCHED_FUSION_PRIORITY
16544+
#define TARGET_SCHED_FUSION_PRIORITY riscv_sched_fusion_priority
16545+
1647116546
#undef TARGET_SCHED_VARIABLE_ISSUE
1647216547
#define TARGET_SCHED_VARIABLE_ISSUE riscv_sched_variable_issue
1647316548

0 commit comments

Comments
 (0)