Richard Henderson <richard.hender...@linaro.org> writes:
> 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);

It looks like this should be "cmn\t%<w>0, #%n1", since GAS "helpfully"
converts cmn w0, #-1 to cmp w0, #1.

Alternatively, we could use the cmp string unconditionally and rely on
the assembler alias for negative immediates.  I don't see anything in
the ISA documentation that mandates the negative immediate aliases though,
so keeping cmn is probably safer.

Richard

> +    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")))]
>  )

Reply via email to