Skip to content

Commit 08b3411

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 5dc1c6e commit 08b3411

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
@@ -11088,6 +11088,97 @@ arcv_fused_addr_p (rtx addr0, rtx addr1)
1108811088
return false;
1108911089
}
1109011090

11091+
/* Return true if PREV and CURR constitute an ordered load/store + op/opimm
11092+
pair, for the purposes of ARCV-specific macro-op fusion. */
11093+
static bool
11094+
arcv_memop_arith_pair_p (rtx_insn *prev, rtx_insn *curr)
11095+
{
11096+
rtx prev_set = single_set (prev);
11097+
rtx curr_set = single_set (curr);
11098+
11099+
gcc_assert (prev_set);
11100+
gcc_assert (curr_set);
11101+
11102+
/* Fuse load/store + register post-{inc,dec}rement:
11103+
* prev (ld) == (set (reg:X rd1) (mem:X (plus:X (reg:X rs1) (const_int))))
11104+
* or
11105+
* prev (st) == (set (mem:X (plus:X (reg:X rs1) (const_int))) (reg:X rs2))
11106+
* ...
11107+
*/
11108+
if ((get_attr_type (curr) == TYPE_ARITH
11109+
|| get_attr_type (curr) == TYPE_LOGICAL
11110+
|| get_attr_type (curr) == TYPE_SHIFT
11111+
|| get_attr_type (curr) == TYPE_SLT
11112+
|| get_attr_type (curr) == TYPE_BITMANIP
11113+
|| get_attr_type (curr) == TYPE_MIN
11114+
|| get_attr_type (curr) == TYPE_MAX
11115+
|| get_attr_type (curr) == TYPE_MINU
11116+
|| get_attr_type (curr) == TYPE_MAXU
11117+
|| get_attr_type (curr) == TYPE_CLZ
11118+
|| get_attr_type (curr) == TYPE_CTZ)
11119+
&& (CONST_INT_P (SET_SRC (curr_set))
11120+
|| REG_P (XEXP (SET_SRC (curr_set), 0)))
11121+
&& ((get_attr_type (prev) == TYPE_LOAD
11122+
&& REG_P (XEXP (SET_SRC (prev_set), 0))
11123+
&& REGNO (XEXP (SET_SRC (prev_set), 0))
11124+
== REGNO (XEXP (SET_SRC (curr_set), 0))
11125+
&& REGNO (XEXP (SET_SRC (prev_set), 0))
11126+
!= REGNO (SET_DEST (prev_set))
11127+
&& REGNO (SET_DEST (prev_set)) != REGNO (SET_DEST (curr_set))
11128+
&& (/* (set (reg:X rd1) (not (reg:X rs1))) */
11129+
GET_RTX_LENGTH (GET_CODE (SET_SRC (curr_set))) == 1
11130+
/* (op-imm) == (set (reg:X rd2) (plus/minus (reg:X rs1) (const_int))) */
11131+
|| CONST_INT_P (XEXP (SET_SRC (curr_set), 1))
11132+
/* (op) == (set (reg:X rd2) (plus/minus (reg:X rs1) (reg:X rs2))) */
11133+
|| REGNO (SET_DEST (prev_set))
11134+
!= REGNO (XEXP (SET_SRC (curr_set), 1))))
11135+
|| (get_attr_type (prev) == TYPE_STORE
11136+
&& REG_P (XEXP (SET_DEST (prev_set), 0))
11137+
&& REGNO (XEXP (SET_DEST (prev_set), 0))
11138+
== REGNO (XEXP (SET_SRC (curr_set), 0))
11139+
&& (/* (set (reg:X rd1) (not (reg:X rs1))) */
11140+
GET_RTX_LENGTH (GET_CODE (SET_SRC (curr_set))) == 1
11141+
/* (op-imm) == (set (reg:X rd2) (plus/minus (reg:X rs1) (const_int))) */
11142+
|| CONST_INT_P (XEXP (SET_SRC (curr_set), 1))
11143+
/* (op) == (set (reg:X rd2) (plus/minus (reg:X rs1) (reg:X rs2))) */
11144+
|| REGNO (XEXP (SET_DEST (prev_set), 0))
11145+
== REGNO (XEXP (SET_SRC (curr_set), 1))))))
11146+
return true;
11147+
11148+
return false;
11149+
}
11150+
11151+
/* Return true if PREV and CURR constitute an ordered load/store + lui pair, for
11152+
the purposes of ARCV-specific macro-op fusion. */
11153+
static bool
11154+
arcv_memop_lui_pair_p (rtx_insn *prev, rtx_insn *curr)
11155+
{
11156+
rtx prev_set = single_set (prev);
11157+
rtx curr_set = single_set (curr);
11158+
11159+
gcc_assert (prev_set);
11160+
gcc_assert (curr_set);
11161+
11162+
/* Fuse load/store with lui:
11163+
* prev (ld) == (set (reg:X rd1) (mem:X (plus:X (reg:X) (const_int))))
11164+
* or
11165+
* prev (st) == (set (mem:X (plus:X (reg:X) (const_int))) (reg:X rD))
11166+
*
11167+
* curr (lui) == (set (reg:X rd2) (const_int UPPER_IMM_20))
11168+
*/
11169+
if (REG_P (curr)
11170+
&& ((get_attr_type (curr) == TYPE_MOVE
11171+
&& GET_CODE (SET_SRC (curr_set)) == HIGH)
11172+
|| (CONST_INT_P (SET_SRC (curr_set))
11173+
&& LUI_OPERAND (INTVAL (SET_SRC (curr_set)))))
11174+
&& ((get_attr_type (prev) == TYPE_LOAD
11175+
&& REGNO (SET_DEST (prev_set)) != REGNO (SET_DEST (curr_set)))
11176+
|| get_attr_type (prev) == TYPE_STORE))
11177+
return true;
11178+
11179+
return false;
11180+
}
11181+
1109111182
/* Return true if PREV and CURR should be kept together during scheduling. */
1109211183

1109311184
static bool
@@ -11134,52 +11225,14 @@ arcv_macro_fusion_pair_p (rtx_insn *prev, rtx_insn *curr)
1113411225
return true;
1113511226
}
1113611227

11137-
/* Fuse load/store + register post-{inc,dec}rement:
11138-
* prev (ld) == (set (reg:X rd1) (mem:X (plus:X (reg:X rs1) (const_int))))
11139-
* or
11140-
* prev (st) == (set (mem:X (plus:X (reg:X rs1) (const_int))) (reg:X rs2))
11141-
* ...
11142-
*/
11143-
if ((GET_CODE (SET_SRC (curr_set)) == PLUS
11144-
|| GET_CODE (SET_SRC (curr_set)) == MINUS)
11145-
&& REG_P (XEXP (SET_SRC (curr_set), 0))
11146-
&& ((get_attr_type (prev) == TYPE_LOAD
11147-
&& REG_P (XEXP (SET_SRC (prev_set), 0))
11148-
&& REGNO (XEXP (SET_SRC (prev_set), 0))
11149-
== REGNO (XEXP (SET_SRC (curr_set), 0))
11150-
&& REGNO (XEXP (SET_SRC (prev_set), 0))
11151-
!= REGNO (SET_DEST (prev_set))
11152-
&& REGNO (SET_DEST (prev_set)) != REGNO (SET_DEST (curr_set))
11153-
/* curr (op-imm) == (set (reg:X rd2) (plus/minus (reg:X rs1) (const_int))) */
11154-
&& (CONST_INT_P (XEXP (SET_SRC (curr_set), 1))
11155-
/* or curr (op) == (set (reg:X rd2) (plus/minus (reg:X rs1) (reg:X rs2))) */
11156-
|| REGNO (SET_DEST (prev_set))
11157-
!= REGNO (XEXP (SET_SRC (curr_set), 1))))
11158-
|| (get_attr_type (prev) == TYPE_STORE
11159-
&& REG_P (XEXP (SET_DEST (prev_set), 0))
11160-
&& REGNO (XEXP (SET_DEST (prev_set), 0))
11161-
== REGNO (XEXP (SET_SRC (curr_set), 0))
11162-
/* curr (op-imm) == (set (reg:X rd2) (plus/minus (reg:X rs1) (const_int))) */
11163-
&& (CONST_INT_P (XEXP (SET_SRC (curr_set), 1))
11164-
/* or curr (op) == (set (reg:X rd2) (plus/minus (reg:X rs1) (reg:X rs2))) */
11165-
|| REGNO (XEXP (SET_DEST (prev_set), 0))
11166-
== REGNO (XEXP (SET_SRC (curr_set), 1))))))
11228+
/* Fuse a pre- or post-update memory operation. */
11229+
if (arcv_memop_arith_pair_p (prev, curr)
11230+
|| arcv_memop_arith_pair_p (curr, prev))
1116711231
return true;
1116811232

11169-
/* Fuse load/store with lui:
11170-
* prev (ld) == (set (reg:X rd1) (mem:X (plus:X (reg:X) (const_int))))
11171-
* or
11172-
* prev (st) == (set (mem:X (plus:X (reg:X) (const_int))) (reg:X rD))
11173-
*
11174-
* curr (lui) == (set (reg:X rd2) (const_int UPPER_IMM_20))
11175-
*/
11176-
if (((get_attr_type (curr) == TYPE_MOVE
11177-
&& GET_CODE (SET_SRC (curr_set)) == HIGH)
11178-
|| (CONST_INT_P (SET_SRC (curr_set))
11179-
&& LUI_OPERAND (INTVAL (SET_SRC (curr_set)))))
11180-
&& ((get_attr_type (prev) == TYPE_LOAD
11181-
&& REGNO (SET_DEST (prev_set)) != REGNO (SET_DEST (curr_set)))
11182-
|| get_attr_type (prev) == TYPE_STORE))
11233+
/* Fuse a memory operation preceded or followed by a lui. */
11234+
if (arcv_memop_lui_pair_p (prev, curr)
11235+
|| arcv_memop_lui_pair_p (curr, prev))
1118311236
return true;
1118411237

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

0 commit comments

Comments
 (0)