public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/users/pheeck/heads/sccp)] added coments; will test with testsuite
@ 2023-02-15 10:15 Filip Kastl
0 siblings, 0 replies; 2+ messages in thread
From: Filip Kastl @ 2023-02-15 10:15 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:05964a2701e07670eb72a5a2c2cdcdc5e33d6532
commit 05964a2701e07670eb72a5a2c2cdcdc5e33d6532
Author: Filip Kastl <filip.kastl@gmail.com>
Date: Wed Sep 7 20:25:13 2022 +0200
added coments; will test with testsuite
Diff:
---
gcc/sccp.cc | 206 ++++++++++++++++++++++++++++++------------------------------
1 file changed, 103 insertions(+), 103 deletions(-)
diff --git a/gcc/sccp.cc b/gcc/sccp.cc
index fe2d20cb8fa..0fe4aee41c6 100644
--- a/gcc/sccp.cc
+++ b/gcc/sccp.cc
@@ -1,5 +1,4 @@
-/* TODO Pass description
- Strongly connected copy propagation pass
+/* Strongly connected copy propagation pass for the GNU compiler.
Copyright (C) 2022 Free Software Foundation, Inc.
Contributed by Filip Kastl <filip.kastl@gmail.com>
@@ -19,6 +18,25 @@ You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
+/* Strongly connected copy propagation (SCCP)
+
+ References:
+
+ Simple and Efficient Construction of Static Single Assignment Form,
+ Matthias Braun, et al., 2013, Section 3.2.
+
+ SCCP uses algorithm presented by Braun et al. to seek out redundant sets of
+ PHI functions and remove them. Redundant set of PHIs is defined as a set
+ where for some value v each PHI in the set references either another PHI
+ from the set or v.
+
+ Braun et al. prove that each redundant set contains a strongly connected
+ component (SCC) that is also redundant. The algorithm is based around
+ computing SCCs and then replacing all uses of variables from an SCC by
+ the appropriate value v.
+
+ For computing SCCs, local implementation of Tarjan's algorithm is used. */
+
#include "config.h"
#include "system.h"
#include "coretypes.h"
@@ -28,24 +46,32 @@ along with GCC; see the file COPYING3. If not see
#include "tree-pass.h"
#include "ssa.h"
#include "gimple-iterator.h"
-
#include "vec.h"
#include "hash-set.h"
+#include <algorithm>
-// DEBUG includes
+// DEBUG
#include <iostream>
-#include "gimple-pretty-print.h"
-#include "print-tree.h"
-#include "dumpfile.h"
+
+/* State of vertex during tarjan computation.
+
+ unvisited Vertex hasn't yet been popped from worklist.
+ vopen DFS has visited vertex for the first time. Vertex has been put on
+ Tarjan stack.
+ closed DFS has backtracked through vertex. At this point, vertex doesn't
+ have any unvisited neighbors.
+ in_scc Vertex has been popped from tarjan stack. */
enum vstate
{
unvisited,
- vopen, /* Open and closed vertices are on stack. */
+ vopen,
closed,
in_scc
};
+/* Information about a vertex used by tarjan. */
+
struct vertex
{
vstate state;
@@ -54,6 +80,9 @@ struct vertex
gphi* stmt;
};
+/* Set 'using' flag of gimple statement to true.
+ If the flag isn't set, tarjan will ignore the statement. */
+
static void
tarjan_set_using (gimple* stmt)
{
@@ -72,6 +101,9 @@ tarjan_is_using (gimple* stmt)
return gimple_plf (stmt, GF_PLF_1);
}
+/* Set 'phinum' of gimple PHI. Before computing SCCs, tarjan assigns PHIs
+ unique ids - phinums. */
+
static void
tarjan_set_phinum (gphi* phi, unsigned num)
{
@@ -84,64 +116,7 @@ tarjan_phinum (gphi* phi)
return gimple_uid (phi);
}
-static void
-init_sccp (void)
-{
- // Clear 'tarjan using' flag on all statements
- basic_block bb;
- FOR_EACH_BB_FN (bb, cfun)
- {
- gimple_stmt_iterator gsi;
- for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
- {
- gimple* stmt = gsi_stmt (gsi);
- tarjan_clear_using (stmt);
- }
- }
-}
-
-static void
-finalize_sccp (void)
-{
-}
-
-static void
-debug_phis (void) // DEBUG
-{
- std::cerr << "List of PHIs" << std::endl;
- basic_block bb;
- FOR_EACH_BB_FN (bb, cfun)
- {
- gphi_iterator pi;
- for (pi = gsi_start_phis (bb); !gsi_end_p (pi); gsi_next (&pi))
- {
- gphi *phi = pi.phi ();
- debug_gimple_stmt (phi);
- }
- }
- std::cerr << std::endl;
-}
-
-/* Return vector of all PHI functions from all basic blocks. */
-
-static auto_vec<gphi *>
-get_all_phis (void)
-{
- auto_vec<gphi *> result;
-
- basic_block bb;
- FOR_EACH_BB_FN (bb, cfun)
- {
- gphi_iterator pi;
- for (pi = gsi_start_phis (bb); !gsi_end_p (pi); gsi_next (&pi))
- {
- gphi *phi = pi.phi ();
- result.safe_push (phi);
- }
- }
-
- return result;
-}
+/* Create and initialize vertex struct for each given PHI. */
static auto_vec<vertex>
tarjan_phis_to_vertices (auto_vec<gphi *> &phis)
@@ -160,12 +135,18 @@ tarjan_phis_to_vertices (auto_vec<gphi *> &phis)
return result;
}
+/* Nonrecursive implementation of Tarjan's algorithm for computing strongly
+ connected components in a graph. PHIs are vertices. Edges lead from a PHI p
+ using another PHI q to the PHI being used (p -> q when q is operand of p).
+
+ Considers only the given PHIs. Ignores other PHIs. */
+
static auto_vec<vec<gphi *>>
tarjan_compute_sccs (auto_vec<gphi *> &phis)
{
auto_vec<vec<gphi *>> sccs;
- auto_vec<unsigned> worklist;
- auto_vec<unsigned> stack;
+ auto_vec<unsigned> worklist; /* DFS stack. */
+ auto_vec<unsigned> stack; /* Tarjan stack. */
unsigned curr_index = 0;
auto_vec<vertex> vs = tarjan_phis_to_vertices (phis);
@@ -278,7 +259,6 @@ tarjan_compute_sccs (auto_vec<gphi *> &phis)
}
}
- // DEBUG
if (!stack.is_empty ())
{
gcc_unreachable();
@@ -294,35 +274,22 @@ tarjan_compute_sccs (auto_vec<gphi *> &phis)
return sccs;
}
+/* Modify all usages of PHIs in a given SCC to instead reference a given
+ variable. */
+
static void
replace_scc_by_value (vec<gphi *> scc, tree replace_by)
{
// DEBUG
if (scc.length () >= 5)
{
- std::cerr << "Replacing scc of size " << scc.length () << std::endl;
+ std::cerr << "Replacing SCC of length " << scc.length () << std::endl;
}
for (gphi *phi : scc)
{
tree get_replaced = gimple_get_lhs (phi);
- // DEBUG
- /*
- unsigned vnum_get_replaced = SSA_NAME_VERSION (get_replaced);
- if (TREE_CODE (replace_by) == SSA_NAME)
- {
- unsigned vnum_replaced_by = SSA_NAME_VERSION (replace_by);
- std::cerr << "Replacing " << vnum_get_replaced << " by " <<
- vnum_replaced_by << std::endl;
- }
- else
- {
- std::cerr << "Replacing " << vnum_get_replaced << " by something"
- << " that isn't an SSA name" << std::endl;
- }
- */
-
if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (get_replaced)
&& TREE_CODE (replace_by) == SSA_NAME)
SSA_NAME_OCCURS_IN_ABNORMAL_PHI (replace_by) = 1;
@@ -357,12 +324,6 @@ remove_zero_uses_phis ()
{
/* Note that remove_phi_node() also frees SSA name. */
remove_phi_node (&pi, true);
-
- // DEBUG
- /*
- unsigned version = SSA_NAME_VERSION (ssa_name);
- std::cerr << "Removed " << version << std::endl;
- */
}
else
gsi_next (&pi);
@@ -370,6 +331,9 @@ remove_zero_uses_phis ()
}
}
+/* Apply Braun et al.'s algorithm on a given set of PHIs.
+ Main function of this pass. */
+
static void
remove_redundant_phis (auto_vec<gphi *> &phis)
{
@@ -424,7 +388,7 @@ remove_redundant_phis (auto_vec<gphi *> &phis)
if (outer_ops.elements () == 1)
{
/* Get the only operand in outer_ops. */
- tree outer_op;
+ tree outer_op = NULL_TREE;
for (tree foo : outer_ops)
{
outer_op = foo;
@@ -447,7 +411,7 @@ remove_redundant_phis (auto_vec<gphi *> &phis)
}
else
{
- gcc_unreachable (); // DEBUG
+ gcc_unreachable ();
}
scc.release ();
@@ -456,7 +420,51 @@ remove_redundant_phis (auto_vec<gphi *> &phis)
remove_zero_uses_phis ();
}
-/* TODO Pass description. */
+/* Return vector of all PHI functions from all basic blocks. */
+
+static auto_vec<gphi *>
+get_all_phis (void)
+{
+ auto_vec<gphi *> result;
+
+ basic_block bb;
+ FOR_EACH_BB_FN (bb, cfun)
+ {
+ gphi_iterator pi;
+ for (pi = gsi_start_phis (bb); !gsi_end_p (pi); gsi_next (&pi))
+ {
+ gphi *phi = pi.phi ();
+ result.safe_push (phi);
+ }
+ }
+
+ return result;
+}
+
+/* Called when pass execution starts. */
+
+static void
+init_sccp (void)
+{
+ // Clear 'tarjan using' flag on all statements
+ basic_block bb;
+ FOR_EACH_BB_FN (bb, cfun)
+ {
+ gimple_stmt_iterator gsi;
+ for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ gimple* stmt = gsi_stmt (gsi);
+ tarjan_clear_using (stmt);
+ }
+ }
+}
+
+/* Called before pass execution ends. */
+
+static void
+finalize_sccp (void)
+{
+}
namespace {
@@ -488,19 +496,11 @@ public:
unsigned
pass_sccp::execute (function *)
{
- //debug_phis (); // DEBUG
-
init_sccp ();
auto_vec<gphi *> phis = get_all_phis ();
remove_redundant_phis (phis);
finalize_sccp ();
- /*
- // DEBUG
- std::cerr << std::endl;
- debug_phis ();
- */
-
return 0;
}
^ permalink raw reply [flat|nested] 2+ messages in thread
* [gcc(refs/users/pheeck/heads/sccp)] added coments; will test with testsuite
@ 2022-09-07 18:25 Filip Kastl
0 siblings, 0 replies; 2+ messages in thread
From: Filip Kastl @ 2022-09-07 18:25 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:55d28b73b1b8568ac250c8b4702239f61c4da26f
commit 55d28b73b1b8568ac250c8b4702239f61c4da26f
Author: Filip Kastl <filip.kastl@gmail.com>
Date: Wed Sep 7 20:25:13 2022 +0200
added coments; will test with testsuite
Diff:
---
gcc/sccp.cc | 206 ++++++++++++++++++++++++++++++------------------------------
1 file changed, 103 insertions(+), 103 deletions(-)
diff --git a/gcc/sccp.cc b/gcc/sccp.cc
index fe2d20cb8fa..0fe4aee41c6 100644
--- a/gcc/sccp.cc
+++ b/gcc/sccp.cc
@@ -1,5 +1,4 @@
-/* TODO Pass description
- Strongly connected copy propagation pass
+/* Strongly connected copy propagation pass for the GNU compiler.
Copyright (C) 2022 Free Software Foundation, Inc.
Contributed by Filip Kastl <filip.kastl@gmail.com>
@@ -19,6 +18,25 @@ You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
+/* Strongly connected copy propagation (SCCP)
+
+ References:
+
+ Simple and Efficient Construction of Static Single Assignment Form,
+ Matthias Braun, et al., 2013, Section 3.2.
+
+ SCCP uses algorithm presented by Braun et al. to seek out redundant sets of
+ PHI functions and remove them. Redundant set of PHIs is defined as a set
+ where for some value v each PHI in the set references either another PHI
+ from the set or v.
+
+ Braun et al. prove that each redundant set contains a strongly connected
+ component (SCC) that is also redundant. The algorithm is based around
+ computing SCCs and then replacing all uses of variables from an SCC by
+ the appropriate value v.
+
+ For computing SCCs, local implementation of Tarjan's algorithm is used. */
+
#include "config.h"
#include "system.h"
#include "coretypes.h"
@@ -28,24 +46,32 @@ along with GCC; see the file COPYING3. If not see
#include "tree-pass.h"
#include "ssa.h"
#include "gimple-iterator.h"
-
#include "vec.h"
#include "hash-set.h"
+#include <algorithm>
-// DEBUG includes
+// DEBUG
#include <iostream>
-#include "gimple-pretty-print.h"
-#include "print-tree.h"
-#include "dumpfile.h"
+
+/* State of vertex during tarjan computation.
+
+ unvisited Vertex hasn't yet been popped from worklist.
+ vopen DFS has visited vertex for the first time. Vertex has been put on
+ Tarjan stack.
+ closed DFS has backtracked through vertex. At this point, vertex doesn't
+ have any unvisited neighbors.
+ in_scc Vertex has been popped from tarjan stack. */
enum vstate
{
unvisited,
- vopen, /* Open and closed vertices are on stack. */
+ vopen,
closed,
in_scc
};
+/* Information about a vertex used by tarjan. */
+
struct vertex
{
vstate state;
@@ -54,6 +80,9 @@ struct vertex
gphi* stmt;
};
+/* Set 'using' flag of gimple statement to true.
+ If the flag isn't set, tarjan will ignore the statement. */
+
static void
tarjan_set_using (gimple* stmt)
{
@@ -72,6 +101,9 @@ tarjan_is_using (gimple* stmt)
return gimple_plf (stmt, GF_PLF_1);
}
+/* Set 'phinum' of gimple PHI. Before computing SCCs, tarjan assigns PHIs
+ unique ids - phinums. */
+
static void
tarjan_set_phinum (gphi* phi, unsigned num)
{
@@ -84,64 +116,7 @@ tarjan_phinum (gphi* phi)
return gimple_uid (phi);
}
-static void
-init_sccp (void)
-{
- // Clear 'tarjan using' flag on all statements
- basic_block bb;
- FOR_EACH_BB_FN (bb, cfun)
- {
- gimple_stmt_iterator gsi;
- for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
- {
- gimple* stmt = gsi_stmt (gsi);
- tarjan_clear_using (stmt);
- }
- }
-}
-
-static void
-finalize_sccp (void)
-{
-}
-
-static void
-debug_phis (void) // DEBUG
-{
- std::cerr << "List of PHIs" << std::endl;
- basic_block bb;
- FOR_EACH_BB_FN (bb, cfun)
- {
- gphi_iterator pi;
- for (pi = gsi_start_phis (bb); !gsi_end_p (pi); gsi_next (&pi))
- {
- gphi *phi = pi.phi ();
- debug_gimple_stmt (phi);
- }
- }
- std::cerr << std::endl;
-}
-
-/* Return vector of all PHI functions from all basic blocks. */
-
-static auto_vec<gphi *>
-get_all_phis (void)
-{
- auto_vec<gphi *> result;
-
- basic_block bb;
- FOR_EACH_BB_FN (bb, cfun)
- {
- gphi_iterator pi;
- for (pi = gsi_start_phis (bb); !gsi_end_p (pi); gsi_next (&pi))
- {
- gphi *phi = pi.phi ();
- result.safe_push (phi);
- }
- }
-
- return result;
-}
+/* Create and initialize vertex struct for each given PHI. */
static auto_vec<vertex>
tarjan_phis_to_vertices (auto_vec<gphi *> &phis)
@@ -160,12 +135,18 @@ tarjan_phis_to_vertices (auto_vec<gphi *> &phis)
return result;
}
+/* Nonrecursive implementation of Tarjan's algorithm for computing strongly
+ connected components in a graph. PHIs are vertices. Edges lead from a PHI p
+ using another PHI q to the PHI being used (p -> q when q is operand of p).
+
+ Considers only the given PHIs. Ignores other PHIs. */
+
static auto_vec<vec<gphi *>>
tarjan_compute_sccs (auto_vec<gphi *> &phis)
{
auto_vec<vec<gphi *>> sccs;
- auto_vec<unsigned> worklist;
- auto_vec<unsigned> stack;
+ auto_vec<unsigned> worklist; /* DFS stack. */
+ auto_vec<unsigned> stack; /* Tarjan stack. */
unsigned curr_index = 0;
auto_vec<vertex> vs = tarjan_phis_to_vertices (phis);
@@ -278,7 +259,6 @@ tarjan_compute_sccs (auto_vec<gphi *> &phis)
}
}
- // DEBUG
if (!stack.is_empty ())
{
gcc_unreachable();
@@ -294,35 +274,22 @@ tarjan_compute_sccs (auto_vec<gphi *> &phis)
return sccs;
}
+/* Modify all usages of PHIs in a given SCC to instead reference a given
+ variable. */
+
static void
replace_scc_by_value (vec<gphi *> scc, tree replace_by)
{
// DEBUG
if (scc.length () >= 5)
{
- std::cerr << "Replacing scc of size " << scc.length () << std::endl;
+ std::cerr << "Replacing SCC of length " << scc.length () << std::endl;
}
for (gphi *phi : scc)
{
tree get_replaced = gimple_get_lhs (phi);
- // DEBUG
- /*
- unsigned vnum_get_replaced = SSA_NAME_VERSION (get_replaced);
- if (TREE_CODE (replace_by) == SSA_NAME)
- {
- unsigned vnum_replaced_by = SSA_NAME_VERSION (replace_by);
- std::cerr << "Replacing " << vnum_get_replaced << " by " <<
- vnum_replaced_by << std::endl;
- }
- else
- {
- std::cerr << "Replacing " << vnum_get_replaced << " by something"
- << " that isn't an SSA name" << std::endl;
- }
- */
-
if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (get_replaced)
&& TREE_CODE (replace_by) == SSA_NAME)
SSA_NAME_OCCURS_IN_ABNORMAL_PHI (replace_by) = 1;
@@ -357,12 +324,6 @@ remove_zero_uses_phis ()
{
/* Note that remove_phi_node() also frees SSA name. */
remove_phi_node (&pi, true);
-
- // DEBUG
- /*
- unsigned version = SSA_NAME_VERSION (ssa_name);
- std::cerr << "Removed " << version << std::endl;
- */
}
else
gsi_next (&pi);
@@ -370,6 +331,9 @@ remove_zero_uses_phis ()
}
}
+/* Apply Braun et al.'s algorithm on a given set of PHIs.
+ Main function of this pass. */
+
static void
remove_redundant_phis (auto_vec<gphi *> &phis)
{
@@ -424,7 +388,7 @@ remove_redundant_phis (auto_vec<gphi *> &phis)
if (outer_ops.elements () == 1)
{
/* Get the only operand in outer_ops. */
- tree outer_op;
+ tree outer_op = NULL_TREE;
for (tree foo : outer_ops)
{
outer_op = foo;
@@ -447,7 +411,7 @@ remove_redundant_phis (auto_vec<gphi *> &phis)
}
else
{
- gcc_unreachable (); // DEBUG
+ gcc_unreachable ();
}
scc.release ();
@@ -456,7 +420,51 @@ remove_redundant_phis (auto_vec<gphi *> &phis)
remove_zero_uses_phis ();
}
-/* TODO Pass description. */
+/* Return vector of all PHI functions from all basic blocks. */
+
+static auto_vec<gphi *>
+get_all_phis (void)
+{
+ auto_vec<gphi *> result;
+
+ basic_block bb;
+ FOR_EACH_BB_FN (bb, cfun)
+ {
+ gphi_iterator pi;
+ for (pi = gsi_start_phis (bb); !gsi_end_p (pi); gsi_next (&pi))
+ {
+ gphi *phi = pi.phi ();
+ result.safe_push (phi);
+ }
+ }
+
+ return result;
+}
+
+/* Called when pass execution starts. */
+
+static void
+init_sccp (void)
+{
+ // Clear 'tarjan using' flag on all statements
+ basic_block bb;
+ FOR_EACH_BB_FN (bb, cfun)
+ {
+ gimple_stmt_iterator gsi;
+ for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ gimple* stmt = gsi_stmt (gsi);
+ tarjan_clear_using (stmt);
+ }
+ }
+}
+
+/* Called before pass execution ends. */
+
+static void
+finalize_sccp (void)
+{
+}
namespace {
@@ -488,19 +496,11 @@ public:
unsigned
pass_sccp::execute (function *)
{
- //debug_phis (); // DEBUG
-
init_sccp ();
auto_vec<gphi *> phis = get_all_phis ();
remove_redundant_phis (phis);
finalize_sccp ();
- /*
- // DEBUG
- std::cerr << std::endl;
- debug_phis ();
- */
-
return 0;
}
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2023-02-15 10:15 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-02-15 10:15 [gcc(refs/users/pheeck/heads/sccp)] added coments; will test with testsuite Filip Kastl
-- strict thread matches above, loose matches on Subject: below --
2022-09-07 18:25 Filip Kastl
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).