> On 7 May 2025, at 12:27, Karl Meakin <karl.mea...@arm.com> wrote:
> 
> The rules for conditional branches were spread throughout `aarch64.md`.
> Group them together so it is easier to understand how `cbranch<mode>4`
> is lowered to RTL.
> 
> gcc/ChangeLog:
> 
> * config/aarch64/aarch64.md (condjump): move.
> (*compare_condjump<GPI:mode>): likewise.
> (aarch64_cb<optab><mode>1): likewise.
> (*cb<optab><mode>1): likewise.
> (tbranch_<code><mode>3): likewise.
> (@aarch64_tb<optab><ALLI:mode><GPI:mode>): likewise.

Changelog entries should start with a capital letter.


> ---
> gcc/config/aarch64/aarch64.md | 387 ++++++++++++++++++----------------
> 1 file changed, 201 insertions(+), 186 deletions(-)
> 
> diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
> index c678f7afb1a..4d556d886bc 100644
> --- a/gcc/config/aarch64/aarch64.md
> +++ b/gcc/config/aarch64/aarch64.md
> @@ -674,6 +674,10 @@ (define_insn "aarch64_write_sysregti"
>  "msrr\t%x0, %x1, %H1"
> )
> 
> +;; -------------------------------------------------------------------
> +;; Unconditional jumps
> +;; -------------------------------------------------------------------
> +
> (define_insn "indirect_jump"
>   [(set (pc) (match_operand:DI 0 "register_operand" "r"))]
>   ""
> @@ -692,6 +696,12 @@ (define_insn "jump"
>   [(set_attr "type" "branch")]
> )
> 
> +
> +
> +;; -------------------------------------------------------------------
> +;; Conditional jumps
> +;; -------------------------------------------------------------------
> +
> (define_expand "cbranch<mode>4"
>   [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
>    [(match_operand:GPI 1 "register_operand")
> @@ -731,6 +741,197 @@ (define_expand "cbranchcc4"
>   ""
>   "")
> 
> +(define_insn "condjump"
> +  [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
> +    [(match_operand 1 "cc_register" "") (const_int 0)])
> +   (label_ref (match_operand 2 "" ""))
> +   (pc)))]
> +  ""
> +  {
> +    /* GCC's traditional style has been to use "beq" instead of "b.eq", etc.,
> +       but the "." is required for SVE conditions.  */
> +    bool use_dot_p = GET_MODE (operands[1]) == CC_NZCmode;
> +    if (get_attr_length (insn) == 8)
> +      return aarch64_gen_far_branch (operands, 2, "Lbcond",
> +     use_dot_p ? "b.%M0\\t" : "b%M0\\t");
> +    else
> +      return use_dot_p ? "b.%m0\\t%l2" : "b%m0\\t%l2";
> +  }
> +  [(set_attr "type" "branch")
> +   (set (attr "length")
> + (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
> +   (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
> +      (const_int 4)
> +      (const_int 8)))
> +   (set (attr "far_branch")
> + (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
> +   (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
> +      (const_int 0)
> +      (const_int 1)))]
> +)
> +
> +;; For a 24-bit immediate CST we can optimize the compare for equality
> +;; and branch sequence from:
> +;; mov x0, #imm1
> +;; movk x0, #imm2, lsl 16 /* x0 contains CST.  */
> +;; cmp x1, x0
> +;; b<ne,eq> .Label
> +;; into the shorter:
> +;; sub x0, x1, #(CST & 0xfff000)
> +;; subs x0, x0, #(CST & 0x000fff)
> +;; b<ne,eq> .Label
> +(define_insn_and_split "*compare_condjump<GPI:mode>"
> +  [(set (pc) (if_then_else (EQL
> +      (match_operand:GPI 0 "register_operand" "r")
> +      (match_operand:GPI 1 "aarch64_imm24" "n"))
> +   (label_ref:P (match_operand 2 "" ""))
> +   (pc)))]
> +  "!aarch64_move_imm (INTVAL (operands[1]), <GPI:MODE>mode)
> +   && !aarch64_plus_operand (operands[1], <GPI:MODE>mode)
> +   && !reload_completed"
> +  "#"
> +  "&& true"
> +  [(const_int 0)]
> +  {
> +    HOST_WIDE_INT lo_imm = UINTVAL (operands[1]) & 0xfff;
> +    HOST_WIDE_INT hi_imm = UINTVAL (operands[1]) & 0xfff000;
> +    rtx tmp = gen_reg_rtx (<GPI:MODE>mode);
> +    emit_insn (gen_add<GPI:mode>3 (tmp, operands[0], GEN_INT (-hi_imm)));
> +    emit_insn (gen_add<GPI:mode>3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
> +    rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
> +    rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <GPI:MODE>mode,
> +  cc_reg, const0_rtx);
> +    emit_jump_insn (gen_condjump (cmp_rtx, cc_reg, operands[2]));
> +    DONE;
> +  }
> +)

This pattern isn’t really related to lowering jumps, it’s a splitting 
optimization.
So I wouldn’t group it with other patterns moved here.
Ok otherwise.
Thanks,
Kyrill

> +
> +(define_insn "aarch64_cb<optab><mode>1"
> +  [(set (pc) (if_then_else (EQL (match_operand:GPI 0 "register_operand" "r")
> + (const_int 0))
> +   (label_ref (match_operand 1 "" ""))
> +   (pc)))]
> +  "!aarch64_track_speculation"
> +  {
> +    if (get_attr_length (insn) == 8)
> +      return aarch64_gen_far_branch (operands, 1, "Lcb", "<inv_cb>\\t%<w>0, 
> ");
> +    else
> +      return "<cbz>\\t%<w>0, %l1";
> +  }
> +  [(set_attr "type" "branch")
> +   (set (attr "length")
> + (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576))
> +   (lt (minus (match_dup 1) (pc)) (const_int 1048572)))
> +      (const_int 4)
> +      (const_int 8)))
> +   (set (attr "far_branch")
> + (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
> +   (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
> +      (const_int 0)
> +      (const_int 1)))]
> +)
> +
> +(define_insn "*cb<optab><mode>1"
> +  [(set (pc) (if_then_else (LTGE (match_operand:ALLI 0 "register_operand" 
> "r")
> + (const_int 0))
> +   (label_ref (match_operand 1 "" ""))
> +   (pc)))
> +   (clobber (reg:CC CC_REGNUM))]
> +  "!aarch64_track_speculation"
> +  {
> +    if (get_attr_length (insn) == 8)
> +      {
> + if (get_attr_far_branch (insn) == 1)
> +  return aarch64_gen_far_branch (operands, 1, "Ltb",
> + "<inv_tb>\\t%<w>0, <sizem1>, ");
> + else
> +  {
> +    char buf[64];
> +    uint64_t val = ((uint64_t) 1)
> + << (GET_MODE_SIZE (<MODE>mode) * BITS_PER_UNIT - 1);
> +    sprintf (buf, "tst\t%%<w>0, %" PRId64, val);
> +    output_asm_insn (buf, operands);
> +    return "<bcond>\t%l1";
> +  }
> +      }
> +    else
> +      return "<tbz>\t%<w>0, <sizem1>, %l1";
> +  }
> +  [(set_attr "type" "branch")
> +   (set (attr "length")
> + (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -32768))
> +   (lt (minus (match_dup 1) (pc)) (const_int 32764)))
> +      (const_int 4)
> +      (const_int 8)))
> +   (set (attr "far_branch")
> + (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576))
> +   (lt (minus (match_dup 1) (pc)) (const_int 1048572)))
> +      (const_int 0)
> +      (const_int 1)))]
> +)
> +
> +;; -------------------------------------------------------------------
> +;; Test bit and branch
> +;; -------------------------------------------------------------------
> +
> +(define_expand "tbranch_<code><mode>3"
> +  [(set (pc) (if_then_else
> +      (EQL (match_operand:SHORT 0 "register_operand")
> +   (match_operand 1 "const0_operand"))
> +      (label_ref (match_operand 2 ""))
> +      (pc)))]
> +  ""
> +{
> +  rtx bitvalue = gen_reg_rtx (<ZEROM>mode);
> +  rtx reg = gen_lowpart (<ZEROM>mode, operands[0]);
> +  rtx val = gen_int_mode (HOST_WIDE_INT_1U << UINTVAL (operands[1]),
> +  <MODE>mode);
> +  emit_insn (gen_and<zerom>3 (bitvalue, reg, val));
> +  operands[1] = const0_rtx;
> +  operands[0] = aarch64_gen_compare_reg (<CODE>, bitvalue,
> + operands[1]);
> +})
> +
> +(define_insn "@aarch64_tb<optab><ALLI:mode><GPI:mode>"
> +  [(set (pc) (if_then_else
> +      (EQL (zero_extract:GPI (match_operand:ALLI 0 "register_operand" "r")
> +     (const_int 1)
> +     (match_operand 1
> +       "aarch64_simd_shift_imm_<ALLI:mode>" "n"))
> +   (const_int 0))
> +     (label_ref (match_operand 2 "" ""))
> +     (pc)))
> +   (clobber (reg:CC CC_REGNUM))]
> +  "!aarch64_track_speculation"
> +  {
> +    if (get_attr_length (insn) == 8)
> +      {
> + if (get_attr_far_branch (insn) == 1)
> +  return aarch64_gen_far_branch (operands, 2, "Ltb",
> + "<inv_tb>\\t%<ALLI:w>0, %1, ");
> + else
> +  {
> +    operands[1] = GEN_INT (HOST_WIDE_INT_1U << UINTVAL (operands[1]));
> +    return "tst\t%<ALLI:w>0, %1\;<bcond>\t%l2";
> +  }
> +      }
> +    else
> +      return "<tbz>\t%<ALLI:w>0, %1, %l2";
> +  }
> +  [(set_attr "type" "branch")
> +   (set (attr "length")
> + (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -32768))
> +   (lt (minus (match_dup 2) (pc)) (const_int 32764)))
> +      (const_int 4)
> +      (const_int 8)))
> +   (set (attr "far_branch")
> + (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
> +   (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
> +      (const_int 0)
> +      (const_int 1)))]
> +
> +)
> +
> (define_insn "@ccmp<CC_ONLY:mode><GPI:mode>"
>   [(set (match_operand:CC_ONLY 1 "cc_register")
> (if_then_else:CC_ONLY
> @@ -861,71 +1062,6 @@ (define_expand "mod<mode>3"
>   }
> )
> 
> -(define_insn "condjump"
> -  [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
> -    [(match_operand 1 "cc_register" "") (const_int 0)])
> -   (label_ref (match_operand 2 "" ""))
> -   (pc)))]
> -  ""
> -  {
> -    /* GCC's traditional style has been to use "beq" instead of "b.eq", etc.,
> -       but the "." is required for SVE conditions.  */
> -    bool use_dot_p = GET_MODE (operands[1]) == CC_NZCmode;
> -    if (get_attr_length (insn) == 8)
> -      return aarch64_gen_far_branch (operands, 2, "Lbcond",
> -     use_dot_p ? "b.%M0\\t" : "b%M0\\t");
> -    else
> -      return use_dot_p ? "b.%m0\\t%l2" : "b%m0\\t%l2";
> -  }
> -  [(set_attr "type" "branch")
> -   (set (attr "length")
> - (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
> -   (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
> -      (const_int 4)
> -      (const_int 8)))
> -   (set (attr "far_branch")
> - (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
> -   (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
> -      (const_int 0)
> -      (const_int 1)))]
> -)
> -
> -;; For a 24-bit immediate CST we can optimize the compare for equality
> -;; and branch sequence from:
> -;; mov x0, #imm1
> -;; movk x0, #imm2, lsl 16 /* x0 contains CST.  */
> -;; cmp x1, x0
> -;; b<ne,eq> .Label
> -;; into the shorter:
> -;; sub x0, x1, #(CST & 0xfff000)
> -;; subs x0, x0, #(CST & 0x000fff)
> -;; b<ne,eq> .Label
> -(define_insn_and_split "*compare_condjump<GPI:mode>"
> -  [(set (pc) (if_then_else (EQL
> -      (match_operand:GPI 0 "register_operand" "r")
> -      (match_operand:GPI 1 "aarch64_imm24" "n"))
> -   (label_ref:P (match_operand 2 "" ""))
> -   (pc)))]
> -  "!aarch64_move_imm (INTVAL (operands[1]), <GPI:MODE>mode)
> -   && !aarch64_plus_operand (operands[1], <GPI:MODE>mode)
> -   && !reload_completed"
> -  "#"
> -  "&& true"
> -  [(const_int 0)]
> -  {
> -    HOST_WIDE_INT lo_imm = UINTVAL (operands[1]) & 0xfff;
> -    HOST_WIDE_INT hi_imm = UINTVAL (operands[1]) & 0xfff000;
> -    rtx tmp = gen_reg_rtx (<GPI:MODE>mode);
> -    emit_insn (gen_add<GPI:mode>3 (tmp, operands[0], GEN_INT (-hi_imm)));
> -    emit_insn (gen_add<GPI:mode>3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
> -    rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
> -    rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <GPI:MODE>mode,
> -  cc_reg, const0_rtx);
> -    emit_jump_insn (gen_condjump (cmp_rtx, cc_reg, operands[2]));
> -    DONE;
> -  }
> -)
> -
> (define_expand "casesi"
>   [(match_operand:SI 0 "register_operand") ; Index
>    (match_operand:SI 1 "const_int_operand") ; Lower bound
> @@ -1117,127 +1253,6 @@ (define_insn "simple_return"
>    (set_attr "sls_length" "retbr")]
> )
> 
> -(define_insn "aarch64_cb<optab><mode>1"
> -  [(set (pc) (if_then_else (EQL (match_operand:GPI 0 "register_operand" "r")
> - (const_int 0))
> -   (label_ref (match_operand 1 "" ""))
> -   (pc)))]
> -  "!aarch64_track_speculation"
> -  {
> -    if (get_attr_length (insn) == 8)
> -      return aarch64_gen_far_branch (operands, 1, "Lcb", "<inv_cb>\\t%<w>0, 
> ");
> -    else
> -      return "<cbz>\\t%<w>0, %l1";
> -  }
> -  [(set_attr "type" "branch")
> -   (set (attr "length")
> - (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576))
> -   (lt (minus (match_dup 1) (pc)) (const_int 1048572)))
> -      (const_int 4)
> -      (const_int 8)))
> -   (set (attr "far_branch")
> - (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
> -   (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
> -      (const_int 0)
> -      (const_int 1)))]
> -)
> -
> -(define_expand "tbranch_<code><mode>3"
> -  [(set (pc) (if_then_else
> -              (EQL (match_operand:SHORT 0 "register_operand")
> -                   (match_operand 1 "const0_operand"))
> -              (label_ref (match_operand 2 ""))
> -              (pc)))]
> -  ""
> -{
> -  rtx bitvalue = gen_reg_rtx (<ZEROM>mode);
> -  rtx reg = gen_lowpart (<ZEROM>mode, operands[0]);
> -  rtx val = gen_int_mode (HOST_WIDE_INT_1U << UINTVAL (operands[1]), 
> <MODE>mode);
> -  emit_insn (gen_and<zerom>3 (bitvalue, reg, val));
> -  operands[1] = const0_rtx;
> -  operands[0] = aarch64_gen_compare_reg (<CODE>, bitvalue,
> - operands[1]);
> -})
> -
> -(define_insn "@aarch64_tb<optab><ALLI:mode><GPI:mode>"
> -  [(set (pc) (if_then_else
> -      (EQL (zero_extract:GPI (match_operand:ALLI 0 "register_operand" "r")
> -     (const_int 1)
> -     (match_operand 1
> -       "aarch64_simd_shift_imm_<ALLI:mode>" "n"))
> -   (const_int 0))
> -     (label_ref (match_operand 2 "" ""))
> -     (pc)))
> -   (clobber (reg:CC CC_REGNUM))]
> -  "!aarch64_track_speculation"
> -  {
> -    if (get_attr_length (insn) == 8)
> -      {
> - if (get_attr_far_branch (insn) == 1)
> -  return aarch64_gen_far_branch (operands, 2, "Ltb",
> - "<inv_tb>\\t%<ALLI:w>0, %1, ");
> - else
> -  {
> -    operands[1] = GEN_INT (HOST_WIDE_INT_1U << UINTVAL (operands[1]));
> -    return "tst\t%<ALLI:w>0, %1\;<bcond>\t%l2";
> -  }
> -      }
> -    else
> -      return "<tbz>\t%<ALLI:w>0, %1, %l2";
> -  }
> -  [(set_attr "type" "branch")
> -   (set (attr "length")
> - (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -32768))
> -   (lt (minus (match_dup 2) (pc)) (const_int 32764)))
> -      (const_int 4)
> -      (const_int 8)))
> -   (set (attr "far_branch")
> - (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
> -   (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
> -      (const_int 0)
> -      (const_int 1)))]
> -
> -)
> -
> -(define_insn "*cb<optab><mode>1"
> -  [(set (pc) (if_then_else (LTGE (match_operand:ALLI 0 "register_operand" 
> "r")
> - (const_int 0))
> -   (label_ref (match_operand 1 "" ""))
> -   (pc)))
> -   (clobber (reg:CC CC_REGNUM))]
> -  "!aarch64_track_speculation"
> -  {
> -    if (get_attr_length (insn) == 8)
> -      {
> - if (get_attr_far_branch (insn) == 1)
> -  return aarch64_gen_far_branch (operands, 1, "Ltb",
> - "<inv_tb>\\t%<w>0, <sizem1>, ");
> - else
> -  {
> -    char buf[64];
> -    uint64_t val = ((uint64_t) 1)
> - << (GET_MODE_SIZE (<MODE>mode) * BITS_PER_UNIT - 1);
> -    sprintf (buf, "tst\t%%<w>0, %" PRId64, val);
> -    output_asm_insn (buf, operands);
> -    return "<bcond>\t%l1";
> -  }
> -      }
> -    else
> -      return "<tbz>\t%<w>0, <sizem1>, %l1";
> -  }
> -  [(set_attr "type" "branch")
> -   (set (attr "length")
> - (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -32768))
> -   (lt (minus (match_dup 1) (pc)) (const_int 32764)))
> -      (const_int 4)
> -      (const_int 8)))
> -   (set (attr "far_branch")
> - (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576))
> -   (lt (minus (match_dup 1) (pc)) (const_int 1048572)))
> -      (const_int 0)
> -      (const_int 1)))]
> -)
> -
> (define_expand "save_stack_nonlocal"
>   [(set (match_operand 0 "memory_operand")
>         (match_operand 1 "register_operand"))]
> -- 
> 2.45.2
> 

Reply via email to