Skip to content

Commit 925d7fa

Browse files
artemiy-volkovMichielDerhaeg
authored andcommitted
arcv: allow inverted instruction order for some fusion types
Some fusion types (namely, LD/ST-OP/OPIMM and LD/ST-LUI) are available regardless of the order of instructions. To support this, extract the new arcv_memop_arith_pair_p () and arcv_memop_lui_pair_p () functions and call them twice. Signed-off-by: Artemiy Volkov <artemiy@synopsys.com>
1 parent 9fe2286 commit 925d7fa

File tree

1 file changed

+97
-44
lines changed

1 file changed

+97
-44
lines changed

gcc/config/riscv/riscv.cc

Lines changed: 97 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -10461,6 +10461,97 @@ arcv_fused_addr_p (rtx addr0, rtx addr1)
1046110461
return false;
1046210462
}
1046310463

10464+
/* Return true if PREV and CURR constitute an ordered load/store + op/opimm
10465+
pair, for the purposes of ARCV-specific macro-op fusion. */
10466+
static bool
10467+
arcv_memop_arith_pair_p (rtx_insn *prev, rtx_insn *curr)
10468+
{
10469+
rtx prev_set = single_set (prev);
10470+
rtx curr_set = single_set (curr);
10471+
10472+
gcc_assert (prev_set);
10473+
gcc_assert (curr_set);
10474+
10475+
/* Fuse load/store + register post-{inc,dec}rement:
10476+
* prev (ld) == (set (reg:X rd1) (mem:X (plus:X (reg:X rs1) (const_int))))
10477+
* or
10478+
* prev (st) == (set (mem:X (plus:X (reg:X rs1) (const_int))) (reg:X rs2))
10479+
* ...
10480+
*/
10481+
if ((get_attr_type (curr) == TYPE_ARITH
10482+
|| get_attr_type (curr) == TYPE_LOGICAL
10483+
|| get_attr_type (curr) == TYPE_SHIFT
10484+
|| get_attr_type (curr) == TYPE_SLT
10485+
|| get_attr_type (curr) == TYPE_BITMANIP
10486+
|| get_attr_type (curr) == TYPE_MIN
10487+
|| get_attr_type (curr) == TYPE_MAX
10488+
|| get_attr_type (curr) == TYPE_MINU
10489+
|| get_attr_type (curr) == TYPE_MAXU
10490+
|| get_attr_type (curr) == TYPE_CLZ
10491+
|| get_attr_type (curr) == TYPE_CTZ)
10492+
&& (CONST_INT_P (SET_SRC (curr_set))
10493+
|| REG_P (XEXP (SET_SRC (curr_set), 0)))
10494+
&& ((get_attr_type (prev) == TYPE_LOAD
10495+
&& REG_P (XEXP (SET_SRC (prev_set), 0))
10496+
&& REGNO (XEXP (SET_SRC (prev_set), 0))
10497+
== REGNO (XEXP (SET_SRC (curr_set), 0))
10498+
&& REGNO (XEXP (SET_SRC (prev_set), 0))
10499+
!= REGNO (SET_DEST (prev_set))
10500+
&& REGNO (SET_DEST (prev_set)) != REGNO (SET_DEST (curr_set))
10501+
&& (/* (set (reg:X rd1) (not (reg:X rs1))) */
10502+
GET_RTX_LENGTH (GET_CODE (SET_SRC (curr_set))) == 1
10503+
/* (op-imm) == (set (reg:X rd2) (plus/minus (reg:X rs1) (const_int))) */
10504+
|| CONST_INT_P (XEXP (SET_SRC (curr_set), 1))
10505+
/* (op) == (set (reg:X rd2) (plus/minus (reg:X rs1) (reg:X rs2))) */
10506+
|| REGNO (SET_DEST (prev_set))
10507+
!= REGNO (XEXP (SET_SRC (curr_set), 1))))
10508+
|| (get_attr_type (prev) == TYPE_STORE
10509+
&& REG_P (XEXP (SET_DEST (prev_set), 0))
10510+
&& REGNO (XEXP (SET_DEST (prev_set), 0))
10511+
== REGNO (XEXP (SET_SRC (curr_set), 0))
10512+
&& (/* (set (reg:X rd1) (not (reg:X rs1))) */
10513+
GET_RTX_LENGTH (GET_CODE (SET_SRC (curr_set))) == 1
10514+
/* (op-imm) == (set (reg:X rd2) (plus/minus (reg:X rs1) (const_int))) */
10515+
|| CONST_INT_P (XEXP (SET_SRC (curr_set), 1))
10516+
/* (op) == (set (reg:X rd2) (plus/minus (reg:X rs1) (reg:X rs2))) */
10517+
|| REGNO (XEXP (SET_DEST (prev_set), 0))
10518+
== REGNO (XEXP (SET_SRC (curr_set), 1))))))
10519+
return true;
10520+
10521+
return false;
10522+
}
10523+
10524+
/* Return true if PREV and CURR constitute an ordered load/store + lui pair, for
10525+
the purposes of ARCV-specific macro-op fusion. */
10526+
static bool
10527+
arcv_memop_lui_pair_p (rtx_insn *prev, rtx_insn *curr)
10528+
{
10529+
rtx prev_set = single_set (prev);
10530+
rtx curr_set = single_set (curr);
10531+
10532+
gcc_assert (prev_set);
10533+
gcc_assert (curr_set);
10534+
10535+
/* Fuse load/store with lui:
10536+
* prev (ld) == (set (reg:X rd1) (mem:X (plus:X (reg:X) (const_int))))
10537+
* or
10538+
* prev (st) == (set (mem:X (plus:X (reg:X) (const_int))) (reg:X rD))
10539+
*
10540+
* curr (lui) == (set (reg:X rd2) (const_int UPPER_IMM_20))
10541+
*/
10542+
if (REG_P (curr)
10543+
&& ((get_attr_type (curr) == TYPE_MOVE
10544+
&& GET_CODE (SET_SRC (curr_set)) == HIGH)
10545+
|| (CONST_INT_P (SET_SRC (curr_set))
10546+
&& LUI_OPERAND (INTVAL (SET_SRC (curr_set)))))
10547+
&& ((get_attr_type (prev) == TYPE_LOAD
10548+
&& REGNO (SET_DEST (prev_set)) != REGNO (SET_DEST (curr_set)))
10549+
|| get_attr_type (prev) == TYPE_STORE))
10550+
return true;
10551+
10552+
return false;
10553+
}
10554+
1046410555
/* Return true if PREV and CURR should be kept together during scheduling. */
1046510556

1046610557
static bool
@@ -10507,52 +10598,14 @@ arcv_macro_fusion_pair_p (rtx_insn *prev, rtx_insn *curr)
1050710598
return true;
1050810599
}
1050910600

10510-
/* Fuse load/store + register post-{inc,dec}rement:
10511-
* prev (ld) == (set (reg:X rd1) (mem:X (plus:X (reg:X rs1) (const_int))))
10512-
* or
10513-
* prev (st) == (set (mem:X (plus:X (reg:X rs1) (const_int))) (reg:X rs2))
10514-
* ...
10515-
*/
10516-
if ((GET_CODE (SET_SRC (curr_set)) == PLUS
10517-
|| GET_CODE (SET_SRC (curr_set)) == MINUS)
10518-
&& REG_P (XEXP (SET_SRC (curr_set), 0))
10519-
&& ((get_attr_type (prev) == TYPE_LOAD
10520-
&& REG_P (XEXP (SET_SRC (prev_set), 0))
10521-
&& REGNO (XEXP (SET_SRC (prev_set), 0))
10522-
== REGNO (XEXP (SET_SRC (curr_set), 0))
10523-
&& REGNO (XEXP (SET_SRC (prev_set), 0))
10524-
!= REGNO (SET_DEST (prev_set))
10525-
&& REGNO (SET_DEST (prev_set)) != REGNO (SET_DEST (curr_set))
10526-
/* curr (op-imm) == (set (reg:X rd2) (plus/minus (reg:X rs1) (const_int))) */
10527-
&& (CONST_INT_P (XEXP (SET_SRC (curr_set), 1))
10528-
/* or curr (op) == (set (reg:X rd2) (plus/minus (reg:X rs1) (reg:X rs2))) */
10529-
|| REGNO (SET_DEST (prev_set))
10530-
!= REGNO (XEXP (SET_SRC (curr_set), 1))))
10531-
|| (get_attr_type (prev) == TYPE_STORE
10532-
&& REG_P (XEXP (SET_DEST (prev_set), 0))
10533-
&& REGNO (XEXP (SET_DEST (prev_set), 0))
10534-
== REGNO (XEXP (SET_SRC (curr_set), 0))
10535-
/* curr (op-imm) == (set (reg:X rd2) (plus/minus (reg:X rs1) (const_int))) */
10536-
&& (CONST_INT_P (XEXP (SET_SRC (curr_set), 1))
10537-
/* or curr (op) == (set (reg:X rd2) (plus/minus (reg:X rs1) (reg:X rs2))) */
10538-
|| REGNO (XEXP (SET_DEST (prev_set), 0))
10539-
== REGNO (XEXP (SET_SRC (curr_set), 1))))))
10601+
/* Fuse a pre- or post-update memory operation. */
10602+
if (arcv_memop_arith_pair_p (prev, curr)
10603+
|| arcv_memop_arith_pair_p (curr, prev))
1054010604
return true;
1054110605

10542-
/* Fuse load/store with lui:
10543-
* prev (ld) == (set (reg:X rd1) (mem:X (plus:X (reg:X) (const_int))))
10544-
* or
10545-
* prev (st) == (set (mem:X (plus:X (reg:X) (const_int))) (reg:X rD))
10546-
*
10547-
* curr (lui) == (set (reg:X rd2) (const_int UPPER_IMM_20))
10548-
*/
10549-
if (((get_attr_type (curr) == TYPE_MOVE
10550-
&& GET_CODE (SET_SRC (curr_set)) == HIGH)
10551-
|| (CONST_INT_P (SET_SRC (curr_set))
10552-
&& LUI_OPERAND (INTVAL (SET_SRC (curr_set)))))
10553-
&& ((get_attr_type (prev) == TYPE_LOAD
10554-
&& REGNO (SET_DEST (prev_set)) != REGNO (SET_DEST (curr_set)))
10555-
|| get_attr_type (prev) == TYPE_STORE))
10606+
/* Fuse a memory operation preceded or followed by a lui. */
10607+
if (arcv_memop_lui_pair_p (prev, curr)
10608+
|| arcv_memop_lui_pair_p (curr, prev))
1055610609
return true;
1055710610

1055810611
/* Fuse load-immediate with a store of the destination register. */

0 commit comments

Comments
 (0)