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