From 5c1cd7b026d56fb3469da6d48a6ad6a42e140252 Mon Sep 17 00:00:00 2001 From: liyancheng <412998149@qq.com> Date: Thu, 8 Jun 2023 16:08:32 +0800 Subject: [PATCH] [PGO] Bugfix for ICE with -freorder-blocks-and-partition and inline-asm goto If asm goto has a crossing_edge, redirect it to a new bb and insert an unconditional jump to orig dest from the new bb. Avoid optimizing indirect jumps across different partitions in pass ira. --- gcc/bb-reorder.c | 40 +++++++++++++++++++ gcc/ira.c | 20 ++++++++++ .../rtl/aarch64/bb-reorder-and-inline-asm.c | 17 ++++++++ 3 files changed, 77 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/rtl/aarch64/bb-reorder-and-inline-asm.c diff --git a/gcc/bb-reorder.c b/gcc/bb-reorder.c index c635010c69f..6fccadb7b47 100644 --- a/gcc/bb-reorder.c +++ b/gcc/bb-reorder.c @@ -2116,6 +2116,46 @@ fix_crossing_conditional_branches (void) { rtx_insn *old_jump = BB_END (cur_bb); + /* If asm goto has a crossing_edge, redirect it to a new bb and + insert an unconditional jump to orig dest from the new bb. + In some architecture that conditional branches can not span + all of memory, the unconditional jump will transfer into + indirect jump in fix_crossing_unconditional_branches (). */ + rtx asm_op = extract_asm_operands (PATTERN (old_jump)); + if (asm_op) + { + rtx_code_label *new_label = gen_label_rtx (); + basic_block old_dest = crossing_edge->dest; + + /* Put the new label and a jump in the new basic block. */ + rtx_insn *label = emit_label (new_label); + rtx_code_label *old_label = block_label (old_dest); + rtx_insn *jump = emit_jump_insn (targetm.gen_jump (old_label)); + JUMP_LABEL (jump) = old_label; + + /* Create the new basic block and put it in last position. */ + basic_block last_bb = EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb; + basic_block new_bb = create_basic_block (label, jump, last_bb); + new_bb->aux = last_bb->aux; + last_bb->aux = new_bb; + /* Make sure the new bb count is the same as crossing edge. */ + new_bb->count = crossing_edge->count (); + + emit_barrier_after_bb (new_bb); + + new_edge = make_single_succ_edge (new_bb, old_dest, 0); + new_edge->flags |= EDGE_CROSSING; + /* Make sure the new basic block is in the same partition. */ + BB_SET_PARTITION (new_bb, BB_PARTITION (old_dest)); + /* Make orignal edge jump to new dest. */ + redirect_edge_and_branch (crossing_edge, new_bb); + crossing_edge->flags &= ~EDGE_CROSSING; + if (dump_file) + fprintf (dump_file, "\nRedirect asm goto from bb %d" + " to bb %d.\n\n", + old_dest->index, new_bb->index); + } + /* Check to make sure the jump instruction is a conditional jump. */ diff --git a/gcc/ira.c b/gcc/ira.c index 681ec2f46f9..24afaf8dc41 100644 --- a/gcc/ira.c +++ b/gcc/ira.c @@ -3918,6 +3918,7 @@ static void indirect_jump_optimize (void) { basic_block bb; + basic_block dest_bb = NULL; bool rebuild_p = false; FOR_EACH_BB_REVERSE_FN (bb, cfun) @@ -3927,6 +3928,25 @@ indirect_jump_optimize (void) || find_reg_note (insn, REG_NON_LOCAL_GOTO, NULL_RTX)) continue; + /* In pass reorder_blocks_and_partition, if the architecture does + not have unconditional branches that can span all of memory, + convert crossing unconditional branches into indirect jumps. + We should avoid optimizing indirect jumps across different + partitions here. */ + if (flag_reorder_blocks_and_partition && !HAS_LONG_UNCOND_BRANCH) + { + if (JUMP_LABEL (insn) && BLOCK_FOR_INSN (JUMP_LABEL (insn))) + dest_bb = BLOCK_FOR_INSN (JUMP_LABEL (insn)); + + if (dest_bb && BB_PARTITION (bb) != BB_PARTITION (dest_bb)) + { + if (dump_file) + fprintf (dump_file, "\nSkip indirect_jump_optimize due to" + " edge crossing different partition.\n"); + continue; + } + } + rtx x = pc_set (insn); if (!x || !REG_P (SET_SRC (x))) continue; diff --git a/gcc/testsuite/gcc.dg/rtl/aarch64/bb-reorder-and-inline-asm.c b/gcc/testsuite/gcc.dg/rtl/aarch64/bb-reorder-and-inline-asm.c new file mode 100644 index 00000000000..fe960746d63 --- /dev/null +++ b/gcc/testsuite/gcc.dg/rtl/aarch64/bb-reorder-and-inline-asm.c @@ -0,0 +1,17 @@ +/* { dg-do compile { target aarch64-*-* } } */ +/* { dg-options "-O2 -freorder-blocks-and-partition -save-temps -fdump-rtl-bbpart" } */ + +int a; +__attribute__((__cold__)) int b(char *); +void d(void) { +e: + for (; a;) + ; + b(""); + asm goto("" : : : : c); + asm(""); +c: + goto e; +} + +/* { dg-final { scan-assembler-times {d.cold:} 1 } } */ \ No newline at end of file -- Gitee