There is a conflict between aarch64_tbzltdi1 and aarch64_cbltdi with respect to pnum_clobbers, resulting in a recog failure:
0xa1fffe fancy_abort(char const*, int, char const*) ../../gcc/diagnostics/context.cc:1640 0x81340e patch_jump_insn ../../gcc/cfgrtl.cc:1303 0xc0eafe redirect_branch_edge ../../gcc/cfgrtl.cc:1330 0xc0f372 cfg_layout_redirect_edge_and_branch ../../gcc/cfgrtl.cc:4736 0xbfb6b9 redirect_edge_and_branch(edge_def*, basic_block_def*) ../../gcc/cfghooks.cc:391 0x1fa9310 try_forward_edges ../../gcc/cfgcleanup.cc:561 0x1fa9310 try_optimize_cfg ../../gcc/cfgcleanup.cc:2931 0x1fa9310 cleanup_cfg(int) ../../gcc/cfgcleanup.cc:3143 0x1fe11e8 rest_of_handle_cse ../../gcc/cse.cc:7591 0x1fe11e8 execute ../../gcc/cse.cc:7622 The simplest solution is to remove the clobber from aarch64_tbz. This removes the possibility of expansion via TST+B.cond, which will merely fall back to TBNZ+B on shorter branches. gcc: PR target/121385 * config/aarch64/aarch64.cc (*aarch64_tbz<LTGE><ALLI>1): Remove cc clobber and expansion via TST+Bcond. gcc/testsuite: * gcc.target/aarch64/cmpbr-1.c New. --- gcc/config/aarch64/aarch64.md | 26 +++++----------------- gcc/testsuite/gcc.target/aarch64/cmpbr-1.c | 25 +++++++++++++++++++++ 2 files changed, 31 insertions(+), 20 deletions(-) create mode 100644 gcc/testsuite/gcc.target/aarch64/cmpbr-1.c diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index ec7dea8de31..74a8912c7a9 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -838,27 +838,13 @@ [(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))] + (pc)))] "!aarch64_track_speculation" { - if (get_attr_length (insn) == 8) - { - if (get_attr_far_branch (insn) == FAR_BRANCH_YES) - 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 + if (get_attr_length (insn) == 4) return "<tbz>\t%<w>0, <sizem1>, %l1"; + return aarch64_gen_far_branch (operands, 1, "Ltb", + "<inv_tb>\\t%<w>0, <sizem1>, "); } [(set_attr "type" "branch") (set (attr "length") @@ -870,9 +856,9 @@ (const_int 8))) (set (attr "far_branch") (if_then_else (and (ge (minus (match_dup 1) (pc)) - (const_int BRANCH_LEN_N_1MiB)) + (const_int BRANCH_LEN_N_32KiB)) (lt (minus (match_dup 1) (pc)) - (const_int BRANCH_LEN_P_1MiB))) + (const_int BRANCH_LEN_P_32KiB))) (const_string "no") (const_string "yes")))] ) diff --git a/gcc/testsuite/gcc.target/aarch64/cmpbr-1.c b/gcc/testsuite/gcc.target/aarch64/cmpbr-1.c new file mode 100644 index 00000000000..39f1549edd5 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/cmpbr-1.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ +/* PR target/121385 */ + +#pragma GCC target "+cmpbr" + +struct DWstruct { + long low, high; +}; +typedef union { + struct DWstruct s; + __int128 ll; +} DWunion; +__int128 f(__int128 u) { + if (u >> 64 == 0) + { + __int128 t = (__int128)(unsigned long )u * 2; + DWunion ww; + ww.ll = t; + ww.s.high -= 1; + if (ww.s.high >= 0) + return ww.ll; + } + return 0; +} -- 2.34.1