Hi all, If we want to add more macro fusion cases in the arm backend we need to rework the aarch_macro_fusion_pair_p a bit to not return early during the MOVW/MOVT fusion checks. This simple patch does that by adding a helper function that can be called with the two sets to check if they satisfy the fusion logic. There is no change in codegen.
Bootstrapped and tested on arm-none-linux-gnueabihf. Ok for trunk? Thanks, Kyrill 2016-08-23 Kyrylo Tkachov <kyrylo.tkac...@arm.com> * config/arm/arm.c (arm_sets_movw_movt_fusible_p): New function. (aarch_macro_fusion_pair_p): Use above to avoid early return.
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 2deb62b2f724ef9c17f585046480e47abcd341b0..bb6ada9e0f62efae95fdeb11dfcee14dba3299b0 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -29903,11 +29903,57 @@ arm_macro_fusion_p (void) return current_tune->fusible_ops != tune_params::FUSE_NOTHING; } +/* Return true if the two back-to-back sets PREV_SET, CURR_SET are suitable + for MOVW / MOVT macro fusion. */ + +static bool +arm_sets_movw_movt_fusible_p (rtx prev_set, rtx curr_set) +{ + /* We are trying to fuse + movw imm / movt imm + instructions as a group that gets scheduled together. */ + + rtx set_dest = SET_DEST (curr_set); + + if (GET_MODE (set_dest) != SImode) + return false; + + /* We are trying to match: + prev (movw) == (set (reg r0) (const_int imm16)) + curr (movt) == (set (zero_extract (reg r0) + (const_int 16) + (const_int 16)) + (const_int imm16_1)) + or + prev (movw) == (set (reg r1) + (high (symbol_ref ("SYM")))) + curr (movt) == (set (reg r0) + (lo_sum (reg r1) + (symbol_ref ("SYM")))) */ + + if (GET_CODE (set_dest) == ZERO_EXTRACT) + { + if (CONST_INT_P (SET_SRC (curr_set)) + && CONST_INT_P (SET_SRC (prev_set)) + && REG_P (XEXP (set_dest, 0)) + && REG_P (SET_DEST (prev_set)) + && REGNO (XEXP (set_dest, 0)) == REGNO (SET_DEST (prev_set))) + return true; + + } + else if (GET_CODE (SET_SRC (curr_set)) == LO_SUM + && REG_P (SET_DEST (curr_set)) + && REG_P (SET_DEST (prev_set)) + && GET_CODE (SET_SRC (prev_set)) == HIGH + && REGNO (SET_DEST (curr_set)) == REGNO (SET_DEST (prev_set))) + return true; + + return false; +} static bool aarch_macro_fusion_pair_p (rtx_insn* prev, rtx_insn* curr) { - rtx set_dest; rtx prev_set = single_set (prev); rtx curr_set = single_set (curr); @@ -29925,45 +29971,10 @@ aarch_macro_fusion_pair_p (rtx_insn* prev, rtx_insn* curr) && aarch_crypto_can_dual_issue (prev, curr)) return true; - if (current_tune->fusible_ops & tune_params::FUSE_MOVW_MOVT) - { - /* We are trying to fuse - movw imm / movt imm - instructions as a group that gets scheduled together. */ - - set_dest = SET_DEST (curr_set); - - if (GET_MODE (set_dest) != SImode) - return false; + if (current_tune->fusible_ops & tune_params::FUSE_MOVW_MOVT + && arm_sets_movw_movt_fusible_p (prev_set, curr_set)) + return true; - /* We are trying to match: - prev (movw) == (set (reg r0) (const_int imm16)) - curr (movt) == (set (zero_extract (reg r0) - (const_int 16) - (const_int 16)) - (const_int imm16_1)) - or - prev (movw) == (set (reg r1) - (high (symbol_ref ("SYM")))) - curr (movt) == (set (reg r0) - (lo_sum (reg r1) - (symbol_ref ("SYM")))) */ - if (GET_CODE (set_dest) == ZERO_EXTRACT) - { - if (CONST_INT_P (SET_SRC (curr_set)) - && CONST_INT_P (SET_SRC (prev_set)) - && REG_P (XEXP (set_dest, 0)) - && REG_P (SET_DEST (prev_set)) - && REGNO (XEXP (set_dest, 0)) == REGNO (SET_DEST (prev_set))) - return true; - } - else if (GET_CODE (SET_SRC (curr_set)) == LO_SUM - && REG_P (SET_DEST (curr_set)) - && REG_P (SET_DEST (prev_set)) - && GET_CODE (SET_SRC (prev_set)) == HIGH - && REGNO (SET_DEST (curr_set)) == REGNO (SET_DEST (prev_set))) - return true; - } return false; }