From 635c99aaf7250ef13dbd7a6f02141cb735bdcc2f Mon Sep 17 00:00:00 2001 From: Martin Jambor Date: Mon, 11 Sep 2017 11:09:26 +0200 Subject: [PATCH] Make HSA resilient to side-effects of split_edge 2017-09-11 Martin Jambor PR hsa/82119 * hsa-gen.c (gen_hsa_phi_from_gimple_phi): Process ADDR_EXPRs in arguments in advance. * hsa-regalloc.c (naive_process_phi): New parameter predecessors, use it to find predecessor edges. (naive_outof_ssa): Collect vector of predecessors. From-SVN: r251964 --- gcc/ChangeLog | 9 ++++++++ gcc/hsa-gen.c | 51 ++++++++++++++++++++++++++++++++++------------ gcc/hsa-regalloc.c | 14 ++++++++++--- 3 files changed, 58 insertions(+), 16 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b9b04565d28..9388cabc870 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2017-09-11 Martin Jambor + + PR hsa/82119 + * hsa-gen.c (gen_hsa_phi_from_gimple_phi): Process ADDR_EXPRs in + arguments in advance. + * hsa-regalloc.c (naive_process_phi): New parameter predecessors, + use it to find predecessor edges. + (naive_outof_ssa): Collect vector of predecessors. + 2017-09-08 Jason Merrill PR c++/70029 - ICE with ref-qualifier and -flto diff --git a/gcc/hsa-gen.c b/gcc/hsa-gen.c index bd227626e83..6e054c0ce82 100644 --- a/gcc/hsa-gen.c +++ b/gcc/hsa-gen.c @@ -5657,8 +5657,37 @@ gen_hsa_phi_from_gimple_phi (gimple *phi_stmt, hsa_bb *hbb) hphi = new hsa_insn_phi (count, dest); hphi->m_bb = hbb->m_bb; - tree lhs = gimple_phi_result (phi_stmt); + auto_vec aexprs; + auto_vec aregs; + + /* Calling split_edge when processing a PHI node messes up with the order of + gimple phi node arguments (it moves the one associated with the edge to + the end). We need to keep the order of edges and arguments of HSA phi + node arguments consistent, so we do all required splitting as the first + step, and in reverse order as to not be affected by the re-orderings. */ + for (unsigned j = count; j != 0; j--) + { + unsigned i = j - 1; + tree op = gimple_phi_arg_def (phi_stmt, i); + if (TREE_CODE (op) != ADDR_EXPR) + continue; + edge e = gimple_phi_arg_edge (as_a (phi_stmt), i); + hsa_bb *hbb_src = hsa_init_new_bb (split_edge (e)); + hsa_op_address *addr = gen_hsa_addr (TREE_OPERAND (op, 0), + hbb_src); + + hsa_op_reg *dest + = new hsa_op_reg (hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT)); + hsa_insn_basic *insn + = new hsa_insn_basic (2, BRIG_OPCODE_LDA, BRIG_TYPE_U64, + dest, addr); + hbb_src->append_insn (insn); + aexprs.safe_push (op); + aregs.safe_push (dest); + } + + tree lhs = gimple_phi_result (phi_stmt); for (unsigned i = 0; i < count; i++) { tree op = gimple_phi_arg_def (phi_stmt, i); @@ -5684,18 +5713,14 @@ gen_hsa_phi_from_gimple_phi (gimple *phi_stmt, hsa_bb *hbb) } else if (TREE_CODE (op) == ADDR_EXPR) { - edge e = gimple_phi_arg_edge (as_a (phi_stmt), i); - hsa_bb *hbb_src = hsa_init_new_bb (split_edge (e)); - hsa_op_address *addr = gen_hsa_addr (TREE_OPERAND (op, 0), - hbb_src); - - hsa_op_reg *dest - = new hsa_op_reg (hsa_get_segment_addr_type (BRIG_SEGMENT_FLAT)); - hsa_insn_basic *insn - = new hsa_insn_basic (2, BRIG_OPCODE_LDA, BRIG_TYPE_U64, - dest, addr); - hbb_src->append_insn (insn); - + hsa_op_reg *dest = NULL; + for (unsigned a_idx = 0; a_idx < aexprs.length (); a_idx++) + if (aexprs[a_idx] == op) + { + dest = aregs[a_idx]; + break; + } + gcc_assert (dest); hphi->set_op (i, dest); } else diff --git a/gcc/hsa-regalloc.c b/gcc/hsa-regalloc.c index 2a17254c3b2..7fc3a8afa3d 100644 --- a/gcc/hsa-regalloc.c +++ b/gcc/hsa-regalloc.c @@ -42,7 +42,7 @@ along with GCC; see the file COPYING3. If not see /* Process a PHI node PHI of basic block BB as a part of naive out-f-ssa. */ static void -naive_process_phi (hsa_insn_phi *phi) +naive_process_phi (hsa_insn_phi *phi, const vec &predecessors) { unsigned count = phi->operand_count (); for (unsigned i = 0; i < count; i++) @@ -55,7 +55,7 @@ naive_process_phi (hsa_insn_phi *phi) if (!op) break; - e = EDGE_PRED (phi->m_bb, i); + e = predecessors[i]; if (single_succ_p (e->src)) hbb = hsa_bb_for_bb (e->src); else @@ -89,10 +89,18 @@ naive_outof_ssa (void) hsa_bb *hbb = hsa_bb_for_bb (bb); hsa_insn_phi *phi; + /* naive_process_phi can call split_edge on an incoming edge which order if + the incoming edges to the basic block and thus make it inconsistent with + the ordering of PHI arguments, so we collect them in advance. */ + auto_vec predecessors; + unsigned pred_count = EDGE_COUNT (bb->preds); + for (unsigned i = 0; i < pred_count; i++) + predecessors.safe_push (EDGE_PRED (bb, i)); + for (phi = hbb->m_first_phi; phi; phi = phi->m_next ? as_a (phi->m_next) : NULL) - naive_process_phi (phi); + naive_process_phi (phi, predecessors); /* Zap PHI nodes, they will be deallocated when everything else will. */ hbb->m_first_phi = NULL; -- 2.30.2