https://gcc.gnu.org/bugzilla/show_bug.cgi?id=122755
Bug ID: 122755
Summary: Missed optimization opportunity for loop-split
Product: gcc
Version: 16.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: tree-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: dizhao at os dot amperecomputing.com
Target Milestone: ---
This tiny code is simplified from gcc/tree-ssa-sccvn.cc. After
inling dominated_by_p into can_track_predicate_on_edge, the
for-loop can be optimized by splitting it upon conditional
statement "if (dom_computed[dir_index] == 2)". Because once
the expression is TRUE, the loop won't change its value, so
it is (at least) a semi-invariant for the second kind of
transformation in pass lsplit. (Compile options is "-O3".)
#include <vector>
struct et_node
{
void *data;
int dfs_num_in, dfs_num_out;
};
struct basic_block {
struct et_node * dom[2];
int index;
};
class edge
{
public:
basic_block* src;
basic_block* dest;
int flags;
};
extern bool
et_below (struct et_node *down, struct et_node *up);
int dom_computed[2];
bool
dominated_by_p (unsigned int dir_index, basic_block* bb1, basic_block* bb2)
{
struct et_node *n1 = bb1->dom[dir_index], *n2 = bb2->dom[dir_index];
if (dom_computed[dir_index] == 2)
return (n1->dfs_num_in >= n2->dfs_num_in
&& n1->dfs_num_out <= n2->dfs_num_out);
return et_below (n1, n2);
}
bool
can_track_predicate_on_edge (std::vector<edge *> preds)
{
for (unsigned i = 0; i < preds.size (); ++i)
{
edge *e = preds[i];
if (!dominated_by_p (0, e->src, e->dest))
return false;
}
return true;
}
Currently the check in tree-ssa-loop-split.cc:control_dep_semi_invariant_p
fails around "i < preds.size ()", because it is not semi-invariant.
Since its false edge is loop-exit and won't change the value of
"(dom_computed[dir_index] == 2", I think we can refine the checks in
control_dep_semi_invariant_p to optimize such cases.