Loop unswitching.
Copyright (C) 2004-2024 Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 3, or (at your option) any
later version.
GCC is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
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/>.
This file implements the loop unswitching, i.e. transformation of loops like
while (A)
{
if (inv)
B;
X;
if (!inv)
C;
}
where inv is the loop invariant, into
if (inv)
{
while (A)
{
B;
X;
}
}
else
{
while (A)
{
X;
C;
}
}
Inv is considered invariant iff the values it compares are both invariant;
tree-ssa-loop-im.cc ensures that all the suitable conditions are in this
shape.
Loop unswitching algorithm for innermost loops works in the following steps:
1) Number of instructions is estimated for each BB that belongs to a loop.
2) Unswitching candidates are found for gcond and gswitch statements
(note that an unswitching predicate for a gswitch actually corresponds
to a non-default edge so it can contain multiple cases).
3) The so called unswitch predicates are stored in a cache where the
gimple_uid of the last stmt in a basic-block is an index to the cache.
4) We consider one by one the unswitching candidates and calculate BBs that
will be reachable in the unswitch version.
5) A selected predicate is chosen and we simplify the CFG (dead edges) in
both versions of the loop. We utilize both Ranger for condition
simplification and also symbol equivalence. The folded if conditions
are replaced with true/false values, while for gswitch we mark the
corresponding edges with a pass-defined unreachable flag.
6) Every time we unswitch a loop, we save unswitch_predicate to a vector
together with information if true or false edge was taken. Doing that
we have a so called PREDICATE_PATH that is utilized for simplification
of the cloned loop.
7) The process is repeated until we reach a growth threshold or all
unswitching opportunities are taken.
A tuple that holds a GENERIC condition and value range for an unswitching
predicate.