summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMariam Arutunian <mariamarutunian@gmail.com>2023-02-03 17:57:29 +0400
committerJeff Law <jlaw@ventanamicro>2023-03-21 09:03:21 -0600
commit08b8bff52f8945d763ce3af879698633b034c62c (patch)
treed4b6ba23245108c37e3d1a0196c502952dd27c04
parent155ed5f338e4758618b27a82109dfe4ef671beb1 (diff)
downloadgcc-08b8bff52f8945d763ce3af879698633b034c62c.tar.gz
CRC code generation v1: - Added CRC_IFN, with not complete function body. - Removed basic blocks of the CRC function and added IFN call returning its value.
-rw-r--r--gcc/gimple-crc-optimization.cc252
-rw-r--r--gcc/internal-fn.cc11
-rw-r--r--gcc/internal-fn.def1
-rw-r--r--gcc/optabs.def1
4 files changed, 265 insertions, 0 deletions
diff --git a/gcc/gimple-crc-optimization.cc b/gcc/gimple-crc-optimization.cc
index 78400f06318..bfd9562ff84 100644
--- a/gcc/gimple-crc-optimization.cc
+++ b/gcc/gimple-crc-optimization.cc
@@ -35,6 +35,17 @@ along with GCC; see the file COPYING3. If not see
#include "tree-scalar-evolution.h"
#include "hwint.h"
#include "crc_verification.h"
+#include "internal-fn.h"
+#include "tree-into-ssa.h"
+#include "tree-ssa-loop-manip.h"
+#include "predict.h"
+#include "cfghooks.h"
+#include "tree-ssa.h"
+#include "tree-ssa-live.h"
+#include "tree-dfa.h"
+#include "dominance.h"
+#include "tree-ssa-dce.h"
+#include "tree-cfgcleanup.h"
class crc_optimization {
private:
@@ -192,6 +203,10 @@ class crc_optimization {
/* Prints extracted details of CRC calculation. */
void print_crc_information ();
+ /* Replaces function body with CRC_IFN call.
+ Returns true if replacement is succeeded, otherwise false. */
+ bool faster_crc_code_generation (function *);
+
public:
unsigned int execute (function *fun);
};
@@ -993,6 +1008,238 @@ crc_optimization::function_may_calculate_crc (function *fun)
return false;
}
+/* Remove all statements and basic blocks of the function
+ except for the return statement. */
+gimple *
+remove_stmts_besides_return (function *fun)
+{
+ gimple_stmt_iterator gsi;
+ basic_block bb, next_bb;
+ gimple *return_stmt = NULL;
+ for (bb = fun->cfg->x_entry_block_ptr->next_bb;
+ bb != fun->cfg->x_exit_block_ptr; bb = next_bb)
+ {
+
+ for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi);)
+ gsi_remove (&gsi, true);
+
+ for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
+ {
+ gimple *gs = gsi_stmt (gsi);
+ if (gimple_code (gs) == GIMPLE_RETURN)
+ {
+ return_stmt = gs;
+ gsi_next (&gsi);
+ }
+ else
+ {
+ gimple *stmt = gsi_stmt (gsi);
+ gsi_remove (&gsi, true);
+ release_defs (stmt);
+ }
+ }
+/*
+ edge e;
+ edge_iterator ei;
+ for (ei = ei_start (bb->preds); (e = ei_safe_edge (ei));)
+ {
+ e->dest = bb->next_bb;
+ remove_edge (e);
+ }
+
+ for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei));)
+ {
+ e->src = bb->prev_bb;
+ remove_edge (e);
+ }*/
+
+ if (!return_stmt)
+ {
+ next_bb = bb->next_bb;
+ delete_basic_block (bb);
+ }
+ else
+ next_bb = bb->next_bb;
+ }
+ set_immediate_dominator (CDI_DOMINATORS, fun->cfg->x_entry_block_ptr,
+ return_stmt->bb);
+ make_edge (fun->cfg->x_entry_block_ptr, return_stmt->bb,
+ EDGE_FALLTHRU);
+ return return_stmt;
+}
+
+void
+remove_statements_and_update_ssa (function *fn)
+{
+ basic_block bb, next_bb;
+ gimple_stmt_iterator gsi;
+
+ for (bb = fn->cfg->x_entry_block_ptr->next_bb;
+ bb != fn->cfg->x_exit_block_ptr; bb = next_bb)
+ {
+ gsi = gsi_last_bb (bb);
+
+ // Remove all statements from the basic block.
+ while (!gsi_end_p (gsi))
+ {
+ gimple *stmt = gsi_stmt (gsi);
+ gsi_remove (&gsi, true);
+
+ // Update the SSA form to remove the dead statement.
+ release_defs (stmt);
+ }
+
+ // Remove the basic block from the CFG.
+ next_bb = bb->next_bb;
+ delete_basic_block (bb);
+ }
+ remove_unused_locals ();
+ /*set_immediate_dominator (CDI_DOMINATORS, fn->cfg->x_entry_block_ptr,
+ fn->cfg->x_exit_block_ptr);
+make_edge (fn->cfg->x_entry_block_ptr, EXIT_BLOCK_PTR_FOR_FN (fn),
+ EDGE_FALLTHRU);*/
+ update_ssa (TODO_update_ssa);
+ free_dominance_info (fn, CDI_DOMINATORS);
+ calculate_dominance_info (CDI_DOMINATORS);
+}
+
+void
+add_return_statement (function *fn)
+{
+ basic_block bb = create_basic_block (NULL, 0, ENTRY_BLOCK_PTR_FOR_FN (fn));
+ gimple_stmt_iterator gsi = gsi_last_bb (bb);
+
+ tree return_value = build_int_cst (integer_type_node, 10);
+ gimple *stmt = gimple_build_return (return_value);
+
+ gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
+ calculate_dominance_info (CDI_DOMINATORS);
+ // Update the SSA form to reflect the new return statement.
+ update_ssa (TODO_update_ssa);
+
+}
+
+/* Will be removed from here, after writing a correct code. */
+void
+destroy_loop (class loop *loop)
+{
+ unsigned nbbs = loop->num_nodes;
+ edge exit = single_exit (loop);
+ basic_block src = loop_preheader_edge (loop)->src, dest = exit->dest;
+ basic_block *bbs;
+ unsigned i;
+
+ bbs = get_loop_body_in_dom_order (loop);
+
+ gimple_stmt_iterator dst_gsi = gsi_after_labels (exit->dest);
+ bool safe_p = single_pred_p (exit->dest);
+ for (unsigned i = 0; i < nbbs; ++i)
+ {
+ /* We have made sure to not leave any dangling uses of SSA
+ names defined in the loop. With the exception of virtuals.
+ Make sure we replace all uses of virtual defs that will remain
+ outside of the loop with the bare symbol as delete_basic_block
+ will release them. */
+ for (gphi_iterator gsi = gsi_start_phis (bbs[i]); !gsi_end_p (gsi);
+ gsi_next (&gsi))
+ {
+ gphi *phi = gsi.phi ();
+ if (virtual_operand_p (gimple_phi_result (phi)))
+ mark_virtual_phi_result_for_renaming (phi);
+ }
+ for (gimple_stmt_iterator gsi = gsi_start_bb (bbs[i]); !gsi_end_p (gsi);)
+ {
+ gimple *stmt = gsi_stmt (gsi);
+ tree vdef = gimple_vdef (stmt);
+ if (vdef && TREE_CODE (vdef) == SSA_NAME)
+ mark_virtual_operand_for_renaming (vdef);
+ /* Also move and eventually reset debug stmts. We can leave
+ constant values in place in case the stmt dominates the exit.
+ ??? Non-constant values from the last iteration can be
+ replaced with final values if we can compute them. */
+ if (gimple_debug_bind_p (stmt))
+ {
+ tree val = gimple_debug_bind_get_value (stmt);
+ gsi_move_before (&gsi, &dst_gsi);
+ if (val
+ && (!safe_p
+ || !is_gimple_min_invariant (val)
+ || !dominated_by_p (CDI_DOMINATORS, exit->src, bbs[i])))
+ {
+ gimple_debug_bind_reset_value (stmt);
+ update_stmt (stmt);
+ }
+ }
+ else
+ gsi_next (&gsi);
+ }
+ }
+
+ redirect_edge_pred (exit, src);
+ exit->flags &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE);
+ exit->flags |= EDGE_FALLTHRU;
+ cancel_loop_tree (loop);
+ rescan_loop_exit (exit, false, true);
+
+ i = nbbs;
+ do
+ {
+ --i;
+ delete_basic_block (bbs[i]);
+ }
+ while (i != 0);
+
+ free (bbs);
+
+ set_immediate_dominator (CDI_DOMINATORS, dest,
+ recompute_dominator (CDI_DOMINATORS, dest));
+}
+
+/* Replaces function body with CRC_IFN call.
+ Returns true if replacement is succeeded, otherwise false. */
+bool
+crc_optimization::faster_crc_code_generation (function *fun)
+{
+ if (!(data && first_phi_for_crc))
+ return false;
+ tree crc_arg = PHI_ARG_DEF (first_phi_for_crc, 1);
+ tree data_arg = PHI_ARG_DEF (data, 1);
+ destroy_loop (crc_loop);
+ //repair_loop_structures ();
+ gimple *return_stmt = remove_stmts_besides_return (fun);
+
+ /* Add IFN call and return the value. */
+ gcall *call
+ = gimple_build_call_internal (IFN_CRC, 3,
+ crc_arg,
+ data_arg,
+ data_arg);
+
+ tree result = make_ssa_name (TREE_TYPE (DECL_RESULT (fun->decl)));
+ gimple_call_set_lhs (call, result);
+ gimple_set_location (call, fun->function_start_locus);
+ gimple_stmt_iterator si = gsi_start_bb (return_stmt->bb);
+ gsi_insert_before (&si, call, GSI_SAME_STMT);
+ use_operand_p imm_use_p;
+ imm_use_iterator iterator;
+ gimple *stmt;
+ FOR_EACH_IMM_USE_STMT (stmt, iterator,
+ gimple_return_retval (as_a<greturn *> (return_stmt)))
+ {
+ FOR_EACH_IMM_USE_ON_STMT (imm_use_p, iterator)
+ SET_USE (imm_use_p, result);
+ update_stmt (stmt);
+ }
+
+ /* Fix up CFG. */
+ remove_unused_locals ();
+ scev_reset ();
+ mark_virtual_operands_for_renaming (fun);
+ free_dominance_info (fun, CDI_DOMINATORS);
+ calculate_dominance_info (CDI_DOMINATORS);
+ rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa);
+ return true;
+}
unsigned int
crc_optimization::execute (function *fun)
@@ -1033,6 +1280,11 @@ crc_optimization::execute (function *fun)
if (dump_file)
fprintf (dump_file, "%s function calculates CRC!\n",
function_name (fun));
+ if (!faster_crc_code_generation (fun))
+ {
+ if (dump_file)
+ fprintf (dump_file, "Couldn't generate faster CRC code.\n");
+ }
}
else
{
diff --git a/gcc/internal-fn.cc b/gcc/internal-fn.cc
index 6e81dc05e0e..140ac255289 100644
--- a/gcc/internal-fn.cc
+++ b/gcc/internal-fn.cc
@@ -131,6 +131,7 @@ init_internal_fns ()
#define fold_left_direct { 1, 1, false }
#define mask_fold_left_direct { 1, 1, false }
#define check_ptrs_direct { 0, 0, false }
+#define crc_direct { 1, -1, true }
const direct_internal_fn_info direct_internal_fn_array[IFN_LAST + 1] = {
#define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) not_direct,
@@ -3715,6 +3716,15 @@ expand_convert_optab_fn (internal_fn fn, gcall *stmt, convert_optab optab,
expand_fn_using_insn (stmt, icode, 1, nargs);
}
+static void
+expand_crc_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
+{
+ tree lhs = gimple_call_lhs (stmt);
+ tree rhs1 = gimple_call_arg (stmt, 0);
+ tree rhs2 = gimple_call_arg (stmt, 1);
+ tree rhs3 = gimple_call_arg (stmt, 2);
+}
+
/* Expanders for optabs that can use expand_direct_optab_fn. */
#define expand_unary_optab_fn(FN, STMT, OPTAB) \
@@ -3830,6 +3840,7 @@ multi_vector_optab_supported_p (convert_optab optab, tree_pair types,
#define direct_cond_unary_optab_supported_p direct_optab_supported_p
#define direct_cond_binary_optab_supported_p direct_optab_supported_p
#define direct_cond_ternary_optab_supported_p direct_optab_supported_p
+#define direct_crc_optab_supported_p convert_optab_supported_p
#define direct_mask_load_optab_supported_p convert_optab_supported_p
#define direct_load_lanes_optab_supported_p multi_vector_optab_supported_p
#define direct_mask_load_lanes_optab_supported_p multi_vector_optab_supported_p
diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def
index 7fe742c2ae7..741bffeb196 100644
--- a/gcc/internal-fn.def
+++ b/gcc/internal-fn.def
@@ -123,6 +123,7 @@ along with GCC; see the file COPYING3. If not see
DEF_INTERNAL_OPTAB_FN (NAME, FLAGS, OPTAB, TYPE)
#endif
+DEF_INTERNAL_OPTAB_FN (CRC, ECF_CONST | ECF_NOTHROW, crc, crc)
DEF_INTERNAL_OPTAB_FN (MASK_LOAD, ECF_PURE, maskload, mask_load)
DEF_INTERNAL_OPTAB_FN (LOAD_LANES, ECF_CONST, vec_load_lanes, load_lanes)
DEF_INTERNAL_OPTAB_FN (MASK_LOAD_LANES, ECF_PURE,
diff --git a/gcc/optabs.def b/gcc/optabs.def
index 695f5911b30..849607b6d11 100644
--- a/gcc/optabs.def
+++ b/gcc/optabs.def
@@ -78,6 +78,7 @@ OPTAB_CD(smsub_widen_optab, "msub$b$a4")
OPTAB_CD(umsub_widen_optab, "umsub$b$a4")
OPTAB_CD(ssmsub_widen_optab, "ssmsub$b$a4")
OPTAB_CD(usmsub_widen_optab, "usmsub$a$b4")
+OPTAB_CD(crc_optab, "crc$a$b4")
OPTAB_CD(vec_load_lanes_optab, "vec_load_lanes$a$b")
OPTAB_CD(vec_store_lanes_optab, "vec_store_lanes$a$b")
OPTAB_CD(vec_mask_load_lanes_optab, "vec_mask_load_lanes$a$b")