Skip to content

Commit c68fd52

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 6560513 commit c68fd52

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
@@ -11157,6 +11157,78 @@ riscv_macro_fusion_pair_p (rtx_insn *prev, rtx_insn *curr)
1115711157
return false;
1115811158
}
1115911159

11160+
/* If INSN is a load or store of address in the form of [base+offset],
11161+
extract the two parts and set to BASE and OFFSET. IS_LOAD is set
11162+
to TRUE if it's a load. Return TRUE if INSN is such an instruction,
11163+
otherwise return FALSE. */
11164+
11165+
static bool
11166+
fusion_load_store (rtx_insn *insn, rtx *base, rtx *offset, bool *is_load)
11167+
{
11168+
rtx x, dest, src;
11169+
11170+
gcc_assert (INSN_P (insn));
11171+
x = PATTERN (insn);
11172+
if (GET_CODE (x) != SET)
11173+
return false;
11174+
11175+
src = SET_SRC (x);
11176+
dest = SET_DEST (x);
11177+
if (REG_P (src) && MEM_P (dest))
11178+
{
11179+
*is_load = false;
11180+
extract_base_offset_in_addr (dest, base, offset);
11181+
}
11182+
else if (MEM_P (src) && REG_P (dest))
11183+
{
11184+
*is_load = true;
11185+
extract_base_offset_in_addr (src, base, offset);
11186+
}
11187+
else
11188+
return false;
11189+
11190+
return (*base != NULL_RTX && *offset != NULL_RTX);
11191+
}
11192+
11193+
static void
11194+
riscv_sched_fusion_priority (rtx_insn *insn, int max_pri, int *fusion_pri,
11195+
int *pri)
11196+
{
11197+
int tmp, off_val;
11198+
bool is_load;
11199+
rtx base, offset;
11200+
11201+
gcc_assert (INSN_P (insn));
11202+
11203+
tmp = max_pri - 1;
11204+
if (!fusion_load_store (insn, &base, &offset, &is_load))
11205+
{
11206+
*pri = tmp;
11207+
*fusion_pri = tmp;
11208+
return;
11209+
}
11210+
11211+
tmp /= 2;
11212+
11213+
/* INSN with smaller base register goes first. */
11214+
tmp -= ((REGNO (base) & 0xff) << 20);
11215+
11216+
/* INSN with smaller offset goes first. */
11217+
off_val = (int)(INTVAL (offset));
11218+
11219+
/* Put loads/stores operating on adjacent words into the same
11220+
* scheduling group. */
11221+
*fusion_pri = tmp - ((off_val / (UNITS_PER_WORD * 2)) << 1) + is_load;
11222+
11223+
if (off_val >= 0)
11224+
tmp -= (off_val & 0xfffff);
11225+
else
11226+
tmp += ((- off_val) & 0xfffff);
11227+
11228+
*pri = tmp;
11229+
return;
11230+
}
11231+
1116011232
/* Adjust the cost/latency of instructions for scheduling.
1116111233
For now this is just used to change the latency of vector instructions
1116211234
according to their LMUL. We assume that an insn with LMUL == 8 requires
@@ -15823,6 +15895,9 @@ riscv_prefetch_offset_address_p (rtx x, machine_mode mode)
1582315895
#undef TARGET_SCHED_MACRO_FUSION_PAIR_P
1582415896
#define TARGET_SCHED_MACRO_FUSION_PAIR_P riscv_macro_fusion_pair_p
1582515897

15898+
#undef TARGET_SCHED_FUSION_PRIORITY
15899+
#define TARGET_SCHED_FUSION_PRIORITY riscv_sched_fusion_priority
15900+
1582615901
#undef TARGET_SCHED_VARIABLE_ISSUE
1582715902
#define TARGET_SCHED_VARIABLE_ISSUE riscv_sched_variable_issue
1582815903

0 commit comments

Comments
 (0)