@@ -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
1046610557static 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