Middle distance branches between 1KiB and 1MiB may be implemented with cmp+branch instead of branch+branch.
gcc: * config/aarch64/aarch64.cc (*aarch64_cb<INT_CMP><GPI>): Fall back to cmp/cmn + bcond if !far_branch. Adjust far_branch to 1MiB. (*aarch64_cb<INT_CMP><SHORT): Fall back to tst+bcond for EQ/NE if !far_branch. Adjust far_branch to 1MiB. --- gcc/config/aarch64/aarch64.md | 37 +++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index b947da977c3..4c9c1f43af2 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -876,10 +876,16 @@ (clobber (reg:CC CC_REGNUM))] "TARGET_CMPBR && aarch64_cb_rhs (<INT_CMP:CODE>, operands[1])" { - return (get_attr_far_branch (insn) == FAR_BRANCH_NO) - ? "cb<INT_CMP:cmp_op>\\t%<w>0, %<w>1, %l2" - : aarch64_gen_far_branch (operands, 2, - "cb<INT_CMP:inv_cmp_op>\\t%<w>0, %<w>1, "); + if (get_attr_length (insn) == 4) + return "cb<INT_CMP:cmp_op>\t%<w>0, %<w>1, %l2"; + if (get_attr_far_branch (insn) == FAR_BRANCH_YES) + return aarch64_gen_far_branch (operands, 2, + "cb<INT_CMP:inv_cmp_op>\t%<w>0, %<w>1, "); + if (REG_P (operands[1]) || INTVAL (operands[1]) >= 0) + output_asm_insn ("cmp\t%<w>0, %<w>1", operands); + else + output_asm_insn ("cmn\t%<w>0, %<w>1", operands); + return "b<INT_CMP:cmp_op>\t%l2"; } [(set_attr "type" "branch") (set (attr "length") @@ -891,9 +897,9 @@ (const_int 8))) (set (attr "far_branch") (if_then_else (and (ge (minus (match_dup 2) (pc)) - (const_int BRANCH_LEN_N_1KiB)) + (const_int BRANCH_LEN_N_1MiB)) (lt (minus (match_dup 2) (pc)) - (const_int BRANCH_LEN_P_1KiB))) + (const_int BRANCH_LEN_P_1MiB))) (const_string "no") (const_string "yes")))] ) @@ -908,10 +914,17 @@ (clobber (reg:CC CC_REGNUM))] "TARGET_CMPBR" { - return (get_attr_far_branch (insn) == FAR_BRANCH_NO) - ? "cb<SHORT:cmpbr_suffix><INT_CMP:cmp_op>\\t%<w>0, %<w>1, %l2" - : aarch64_gen_far_branch (operands, 2, - "cb<SHORT:cmpbr_suffix><INT_CMP:inv_cmp_op>\\t%<w>0, %<w>1, "); + if (get_attr_length (insn) == 4) + return "cb<SHORT:cmpbr_suffix><INT_CMP:cmp_op>\t%<w>0, %<w>1, %l2"; + if ((<INT_CMP:CODE> == EQ || <INT_CMP:CODE> == NE) + && operands[1] == const0_rtx + && get_attr_far_branch (insn) == FAR_BRANCH_NO) + { + operands[1] = GEN_INT (GET_MODE_MASK (<SHORT:MODE>mode)); + return "tst\t%w0, %1\;b<INT_CMP:cmp_op>\t%l2"; + } + return aarch64_gen_far_branch (operands, 2, + "cb<SHORT:cmpbr_suffix><INT_CMP:inv_cmp_op>\t%<w>0, %<w>1, "); } [(set_attr "type" "branch") (set (attr "length") @@ -923,9 +936,9 @@ (const_int 8))) (set (attr "far_branch") (if_then_else (and (ge (minus (match_dup 2) (pc)) - (const_int BRANCH_LEN_N_1KiB)) + (const_int BRANCH_LEN_N_1MiB)) (lt (minus (match_dup 2) (pc)) - (const_int BRANCH_LEN_P_1KiB))) + (const_int BRANCH_LEN_P_1MiB))) (const_string "no") (const_string "yes")))] ) -- 2.43.0