OK juzhe.zhong@rivai.ai From: Lehua Ding Date: 2023-10-17 19:34 To: gcc-patches CC: juzhe.zhong; kito.cheng; rdapp.gcc; palmer; jeffreyalaw; lehua.ding Subject: [PATCH V2 13/14] RISC-V: P13: Reorganize functions used to modify RTL This sub-patch reoriganize the functions that used to modify RTL. gcc/ChangeLog: * config/riscv/riscv-vsetvl.cc (has_no_uses): Moved. (validate_change_or_fail): Moved. (gen_vsetvl_pat): Removed. (emit_vsetvl_insn): Removed. (eliminate_insn): Removed. (change_insn): Removed. (change_vsetvl_insn): New. (pre_vsetvl::emit_vsetvl): New. (pre_vsetvl::remove_avl_operand): Adjust. (pre_vsetvl::remove_unused_dest_operand): Adjust. (pass_vsetvl::simple_vsetvl): Adjust. --- gcc/config/riscv/riscv-vsetvl.cc | 443 ++++++++++++------------------- 1 file changed, 176 insertions(+), 267 deletions(-) diff --git a/gcc/config/riscv/riscv-vsetvl.cc b/gcc/config/riscv/riscv-vsetvl.cc index d91b0272d9f..78816cbee15 100644 --- a/gcc/config/riscv/riscv-vsetvl.cc +++ b/gcc/config/riscv/riscv-vsetvl.cc @@ -680,6 +680,30 @@ get_bb_index (unsigned expr_id, unsigned num_bb) return expr_id % num_bb; } +/* Return true if the SET result is not used by any instructions. */ +static bool +has_no_uses (basic_block cfg_bb, rtx_insn *rinsn, int regno) +{ + if (bitmap_bit_p (df_get_live_out (cfg_bb), regno)) + return false; + + rtx_insn *iter; + for (iter = NEXT_INSN (rinsn); iter && iter != NEXT_INSN (BB_END (cfg_bb)); + iter = NEXT_INSN (iter)) + if (df_find_use (iter, regno_reg_rtx[regno])) + return false; + + return true; +} + +/* Change insn and Assert the change always happens. */ +static void +validate_change_or_fail (rtx object, rtx *loc, rtx new_rtx, bool in_group) +{ + bool change_p = validate_change (object, loc, new_rtx, in_group); + gcc_assert (change_p); +} + /* This flags indicates the minimum demand of the vl and vtype values by the RVV instruction. For example, DEMAND_RATIO_P indicates that this RVV instruction only needs the SEW/LMUL ratio to remain the same, and does not @@ -1126,6 +1150,28 @@ public: } } + /* Returns the corresponding vsetvl rtx pat. */ + rtx get_vsetvl_pat (bool ignore_vl = false) const + { + rtx avl = get_avl (); + /* if optimization == 0 and the instruction is vmv.x.s/vfmv.f.s, + set the value of avl to (const_int 0) so that VSETVL PASS will + insert vsetvl correctly.*/ + if (!get_avl ()) + avl = GEN_INT (0); + rtx sew = gen_int_mode (get_sew (), Pmode); + rtx vlmul = gen_int_mode (get_vlmul (), Pmode); + rtx ta = gen_int_mode (get_ta (), Pmode); + rtx ma = gen_int_mode (get_ma (), Pmode); + + if (change_vtype_only_p ()) + return gen_vsetvl_vtype_change_only (sew, vlmul, ta, ma); + else if (has_reg_vl () && !ignore_vl) + return gen_vsetvl (Pmode, get_vl (), avl, sew, vlmul, ta, ma); + else + return gen_vsetvl_discard_result (Pmode, avl, sew, vlmul, ta, ma); + } + bool operator== (const vsetvl_info &other) const { gcc_assert (!uninit_p () && !other.uninit_p () @@ -1938,199 +1984,6 @@ public: } }; -/* Emit vsetvl instruction. */ -static rtx -gen_vsetvl_pat (enum vsetvl_type insn_type, const vsetvl_info &info, rtx vl) -{ - rtx avl = info.get_avl (); - /* if optimization == 0 and the instruction is vmv.x.s/vfmv.f.s, - set the value of avl to (const_int 0) so that VSETVL PASS will - insert vsetvl correctly.*/ - if (!info.get_avl ()) - avl = GEN_INT (0); - rtx sew = gen_int_mode (info.get_sew (), Pmode); - rtx vlmul = gen_int_mode (info.get_vlmul (), Pmode); - rtx ta = gen_int_mode (info.get_ta (), Pmode); - rtx ma = gen_int_mode (info.get_ma (), Pmode); - - if (insn_type == VSETVL_NORMAL) - { - gcc_assert (vl != NULL_RTX); - return gen_vsetvl (Pmode, vl, avl, sew, vlmul, ta, ma); - } - else if (insn_type == VSETVL_VTYPE_CHANGE_ONLY) - return gen_vsetvl_vtype_change_only (sew, vlmul, ta, ma); - else - return gen_vsetvl_discard_result (Pmode, avl, sew, vlmul, ta, ma); -} - -static rtx -gen_vsetvl_pat (rtx_insn *rinsn, const vsetvl_info &info, rtx vl = NULL_RTX) -{ - rtx new_pat; - vsetvl_info new_info = info; - /* For vmv.x.s, use 0 for avl. */ - if (!info.get_avl ()) - { - new_info.set_avl (const0_rtx); - new_info.set_avl_def (nullptr); - } - - if (vl) - new_pat = gen_vsetvl_pat (VSETVL_NORMAL, new_info, vl); - else - { - if (vsetvl_insn_p (rinsn) && !info.change_vtype_only_p ()) - new_pat = gen_vsetvl_pat (VSETVL_NORMAL, new_info, get_vl (rinsn)); - else if (info.change_vtype_only_p () - || INSN_CODE (rinsn) == CODE_FOR_vsetvl_vtype_change_only) - new_pat = gen_vsetvl_pat (VSETVL_VTYPE_CHANGE_ONLY, new_info, NULL_RTX); - else - new_pat = gen_vsetvl_pat (VSETVL_DISCARD_RESULT, new_info, NULL_RTX); - } - return new_pat; -} - -static void -emit_vsetvl_insn (enum vsetvl_type insn_type, enum emit_type emit_type, - const vsetvl_info &info, rtx vl, rtx_insn *rinsn) -{ - rtx pat = gen_vsetvl_pat (insn_type, info, vl); - - if (emit_type == EMIT_DIRECT) - { - emit_insn (pat); - if (dump_file) - { - fprintf (dump_file, " Insert vsetvl insn %d:\n", - INSN_UID (get_last_insn ())); - print_rtl_single (dump_file, get_last_insn ()); - } - } - else if (emit_type == EMIT_BEFORE) - { - emit_insn_before (pat, rinsn); - if (dump_file) - { - fprintf (dump_file, " Insert vsetvl insn before insn %d:\n", - INSN_UID (rinsn)); - print_rtl_single (dump_file, PREV_INSN (rinsn)); - } - } - else - { - emit_insn_after (pat, rinsn); - if (dump_file) - { - fprintf (dump_file, " Insert vsetvl insn after insn %d:\n", - INSN_UID (rinsn)); - print_rtl_single (dump_file, NEXT_INSN (rinsn)); - } - } -} - -static void -eliminate_insn (rtx_insn *rinsn) -{ - if (dump_file) - { - fprintf (dump_file, " Eliminate insn %d:\n", INSN_UID (rinsn)); - print_rtl_single (dump_file, rinsn); - } - if (in_sequence_p ()) - remove_insn (rinsn); - else - delete_insn (rinsn); -} - -/* Change insn and Assert the change always happens. */ -static void -validate_change_or_fail (rtx object, rtx *loc, rtx new_rtx, bool in_group) -{ - bool change_p = validate_change (object, loc, new_rtx, in_group); - gcc_assert (change_p); -} - -static void -change_insn (rtx_insn *rinsn, rtx new_pat) -{ - /* We don't apply change on RTL_SSA here since it's possible a - new INSN we add in the PASS before which doesn't have RTL_SSA - info yet.*/ - if (dump_file) - { - fprintf (dump_file, " Change insn %d from:\n", INSN_UID (rinsn)); - print_rtl_single (dump_file, rinsn); - } - - validate_change_or_fail (rinsn, &PATTERN (rinsn), new_pat, false); - - if (dump_file) - { - fprintf (dump_file, "\n to:\n"); - print_rtl_single (dump_file, rinsn); - } -} - -static bool -change_insn (function_info *ssa, insn_change change, insn_info *insn, - rtx new_pat) -{ - rtx_insn *rinsn = insn->rtl (); - auto attempt = ssa->new_change_attempt (); - if (!restrict_movement (change)) - return false; - - if (dump_file) - { - fprintf (dump_file, " Change insn %d from:\n", INSN_UID (rinsn)); - print_rtl_single (dump_file, rinsn); - } - - insn_change_watermark watermark; - validate_change_or_fail (rinsn, &PATTERN (rinsn), new_pat, true); - - /* These routines report failures themselves. */ - if (!recog (attempt, change) || !change_is_worthwhile (change, false)) - return false; - - remove_reg_equal_equiv_notes (rinsn); - confirm_change_group (); - ssa->change_insn (change); - - if (dump_file) - { - fprintf (dump_file, "\n to:\n"); - print_rtl_single (dump_file, rinsn); - } - - return true; -} - -static void -change_vsetvl_insn (const insn_info *insn, const vsetvl_info &info) -{ - rtx_insn *rinsn = insn->rtl (); - rtx new_pat = gen_vsetvl_pat (rinsn, info); - change_insn (rinsn, new_pat); -} - -/* Return true if the SET result is not used by any instructions. */ -static bool -has_no_uses (basic_block cfg_bb, rtx_insn *rinsn, int regno) -{ - if (bitmap_bit_p (df_get_live_out (cfg_bb), regno)) - return false; - - rtx_insn *iter; - for (iter = NEXT_INSN (rinsn); iter && iter != NEXT_INSN (BB_END (cfg_bb)); - iter = NEXT_INSN (iter)) - if (df_find_use (iter, regno_reg_rtx[regno])) - return false; - - return true; -} - class pre_vsetvl { private: @@ -2257,18 +2110,75 @@ private: } } - void insert_vsetvl (enum emit_type emit_type, rtx_insn *rinsn, - const vsetvl_info &info) + void insert_vsetvl_insn (enum emit_type emit_type, const vsetvl_info &info) { - if (info.change_vtype_only_p ()) - emit_vsetvl_insn (VSETVL_VTYPE_CHANGE_ONLY, emit_type, info, NULL_RTX, - rinsn); + rtx pat = info.get_vsetvl_pat (); + rtx_insn *rinsn = info.get_insn ()->rtl (); - else if (info.has_reg_vl ()) - emit_vsetvl_insn (VSETVL_NORMAL, emit_type, info, info.get_vl (), rinsn); + if (emit_type == EMIT_DIRECT) + { + emit_insn (pat); + if (dump_file) + { + fprintf (dump_file, " Insert vsetvl insn %d:\n", + INSN_UID (get_last_insn ())); + print_rtl_single (dump_file, get_last_insn ()); + } + } + else if (emit_type == EMIT_BEFORE) + { + emit_insn_before (pat, rinsn); + if (dump_file) + { + fprintf (dump_file, " Insert vsetvl insn before insn %d:\n", + INSN_UID (rinsn)); + print_rtl_single (dump_file, PREV_INSN (rinsn)); + } + } else - emit_vsetvl_insn (VSETVL_DISCARD_RESULT, emit_type, info, NULL_RTX, - rinsn); + { + emit_insn_after (pat, rinsn); + if (dump_file) + { + fprintf (dump_file, " Insert vsetvl insn after insn %d:\n", + INSN_UID (rinsn)); + print_rtl_single (dump_file, NEXT_INSN (rinsn)); + } + } + } + + void change_vsetvl_insn (const vsetvl_info &info) + { + rtx_insn *rinsn = info.get_insn ()->rtl (); + rtx new_pat = info.get_vsetvl_pat (); + + if (dump_file) + { + fprintf (dump_file, " Change insn %d from:\n", INSN_UID (rinsn)); + print_rtl_single (dump_file, rinsn); + } + + validate_change_or_fail (rinsn, &PATTERN (rinsn), new_pat, false); + + if (dump_file) + { + fprintf (dump_file, "\n to:\n"); + print_rtl_single (dump_file, rinsn); + } + } + + void remove_vsetvl_insn (const vsetvl_info &info) + { + rtx_insn *rinsn = info.get_insn ()->rtl (); + if (dump_file) + { + fprintf (dump_file, " Eliminate insn %d:\n", INSN_UID (rinsn)); + print_rtl_single (dump_file, rinsn); + } + if (in_sequence_p ()) + remove_insn (rinsn); + else + delete_insn (rinsn); } bool earliest_fusion_worthwhile_p (const basic_block cfg_bb) const @@ -3297,7 +3207,7 @@ pre_vsetvl::emit_vsetvl () if (curr_info.ignore_p ()) { if (vsetvl_insn_p (insn->rtl ())) - eliminate_insn (insn->rtl ()); + remove_vsetvl_insn (curr_info); continue; } else if (curr_info.valid_p ()) @@ -3314,7 +3224,7 @@ pre_vsetvl::emit_vsetvl () fprintf (dump_file, " to: "); curr_info.dump (dump_file, " "); } - change_vsetvl_insn (insn, curr_info); + change_vsetvl_insn (curr_info); } } else @@ -3326,7 +3236,7 @@ pre_vsetvl::emit_vsetvl () insn->uid ()); curr_info.dump (dump_file, " "); } - insert_vsetvl (EMIT_BEFORE, insn->rtl (), curr_info); + insert_vsetvl_insn (EMIT_BEFORE, curr_info); } } } @@ -3335,7 +3245,7 @@ pre_vsetvl::emit_vsetvl () for (const vsetvl_info &item : delete_list) { gcc_assert (vsetvl_insn_p (item.get_insn ()->rtl ())); - eliminate_insn (item.get_insn ()->rtl ()); + remove_vsetvl_insn (item); } /* Insert vsetvl as LCM suggest. */ @@ -3365,8 +3275,7 @@ pre_vsetvl::emit_vsetvl () rtl_profile_for_edge (eg); start_sequence (); - insn_info *insn = info.get_insn (); - insert_vsetvl (EMIT_DIRECT, insn->rtl (), info); + insert_vsetvl_insn (EMIT_DIRECT, info); rtx_insn *rinsn = get_insns (); end_sequence (); default_rtl_profile (); @@ -3385,7 +3294,6 @@ pre_vsetvl::emit_vsetvl () continue; const vsetvl_info &footer_info = block_info.get_footer_info (); - insn_info *insn = footer_info.get_insn (); if (footer_info.ignore_p ()) continue; @@ -3404,7 +3312,7 @@ pre_vsetvl::emit_vsetvl () footer_info.dump (dump_file, " "); } start_sequence (); - insert_vsetvl (EMIT_DIRECT, insn->rtl (), footer_info); + insert_vsetvl_insn (EMIT_DIRECT, footer_info); rtx_insn *rinsn = get_insns (); end_sequence (); default_rtl_profile (); @@ -3427,71 +3335,66 @@ pre_vsetvl::cleaup () void pre_vsetvl::remove_avl_operand () { - for (const bb_info *bb : crtl->ssa->bbs ()) - for (insn_info *insn : bb->real_nondebug_insns ()) - { - rtx_insn *rinsn = insn->rtl (); - /* Erase the AVL operand from the instruction. */ - if (!has_vl_op (rinsn) || !REG_P (get_vl (rinsn))) - continue; - rtx avl = get_vl (rinsn); - if (count_regno_occurrences (rinsn, REGNO (avl)) == 1) - { - /* Get the list of uses for the new instruction. */ - auto attempt = crtl->ssa->new_change_attempt (); - insn_change change (insn); - /* Remove the use of the substituted value. */ - access_array_builder uses_builder (attempt); - uses_builder.reserve (insn->num_uses () - 1); - for (use_info *use : insn->uses ()) - if (use != find_access (insn->uses (), REGNO (avl))) - uses_builder.quick_push (use); - use_array new_uses = use_array (uses_builder.finish ()); - change.new_uses = new_uses; - change.move_range = insn->ebb ()->insn_range (); - rtx pat; - if (fault_first_load_p (rinsn)) - pat = simplify_replace_rtx (PATTERN (rinsn), avl, const0_rtx); - else - { - rtx set = single_set (rinsn); - rtx src = simplify_replace_rtx (SET_SRC (set), avl, const0_rtx); - pat = gen_rtx_SET (SET_DEST (set), src); - } - bool ok = change_insn (crtl->ssa, change, insn, pat); - gcc_assert (ok); - } - } + basic_block cfg_bb; + rtx_insn *rinsn; + FOR_ALL_BB_FN (cfg_bb, cfun) + FOR_BB_INSNS (cfg_bb, rinsn) + if (NONDEBUG_INSN_P (rinsn) && has_vl_op (rinsn) + && REG_P (get_vl (rinsn))) + { + rtx avl = get_vl (rinsn); + if (count_regno_occurrences (rinsn, REGNO (avl)) == 1) + { + rtx new_pat; + if (fault_first_load_p (rinsn)) + new_pat + = simplify_replace_rtx (PATTERN (rinsn), avl, const0_rtx); + else + { + rtx set = single_set (rinsn); + rtx src + = simplify_replace_rtx (SET_SRC (set), avl, const0_rtx); + new_pat = gen_rtx_SET (SET_DEST (set), src); + } + if (dump_file) + { + fprintf (dump_file, " Cleanup insn %u's avl operand:\n", + INSN_UID (rinsn)); + print_rtl_single (dump_file, rinsn); + } + validate_change_or_fail (rinsn, &PATTERN (rinsn), new_pat, false); + } + } } void pre_vsetvl::remove_unused_dest_operand () { df_analyze (); - hash_set to_delete; basic_block cfg_bb; rtx_insn *rinsn; FOR_ALL_BB_FN (cfg_bb, cfun) - { - FOR_BB_INSNS (cfg_bb, rinsn) + FOR_BB_INSNS (cfg_bb, rinsn) + if (NONDEBUG_INSN_P (rinsn) && vsetvl_insn_p (rinsn)) { - if (NONDEBUG_INSN_P (rinsn) && vsetvl_insn_p (rinsn)) - { - rtx vl = get_vl (rinsn); - vsetvl_info info = vsetvl_info (rinsn); - if (has_no_uses (cfg_bb, rinsn, REGNO (vl))) - { - if (!info.has_vlmax_avl ()) - { - rtx new_pat = gen_vsetvl_pat (VSETVL_DISCARD_RESULT, info, - NULL_RTX); - validate_change_or_fail (rinsn, &PATTERN (rinsn), new_pat, - false); - } - } - } + rtx vl = get_vl (rinsn); + vsetvl_info info = vsetvl_info (rinsn); + if (has_no_uses (cfg_bb, rinsn, REGNO (vl))) + if (!info.has_vlmax_avl ()) + { + rtx new_pat = info.get_vsetvl_pat (true); + if (dump_file) + { + fprintf (dump_file, + " Remove vsetvl insn %u's dest(vl) operand since " + "it unused:\n", + INSN_UID (rinsn)); + print_rtl_single (dump_file, rinsn); + } + validate_change_or_fail (rinsn, &PATTERN (rinsn), new_pat, + false); + } } - } } const pass_data pass_data_vsetvl = { @@ -3536,9 +3439,15 @@ pass_vsetvl::simple_vsetvl () continue; if (has_vtype_op (rinsn)) { - const auto info = vsetvl_info (rinsn); - emit_vsetvl_insn (VSETVL_DISCARD_RESULT, EMIT_BEFORE, info, - NULL_RTX, rinsn); + const auto &info = vsetvl_info (rinsn); + rtx pat = info.get_vsetvl_pat (); + emit_insn_before (pat, rinsn); + if (dump_file) + { + fprintf (dump_file, " Insert vsetvl insn before insn %d:\n", + INSN_UID (rinsn)); + print_rtl_single (dump_file, PREV_INSN (rinsn)); + } } } } -- 2.36.3