[llvm] [LoopPeel] Add new option to peeling loops to convert PHI into IV (PR #121104)
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 22 13:29:50 PDT 2025
================
@@ -155,45 +159,170 @@ namespace {
// corresponding calls to g are determined and the code for computing
// x, y, and a can be removed.
//
+// Similarly, there are cases where peeling makes Phi nodes loop-inductions
+// (i.e., the value is increased or decreased by a fixed amount on every
+// iteration). For example, consider the following function.
+//
+// #define N 100
+// void f(int a[], int b[]) {
+// int im = N - 1;
+// for (int i = 0; i < N; i++) {
+// a[i] = b[i] + b[im];
+// im = i;
+// }
+// }
+//
+// The IR of the loop will look something like the following.
+//
+// %i = phi i32 [ 0, %entry ], [ %i.next, %for.body ]
+// %im = phi i32 [ 99, %entry ], [ %i, %for.body ]
+// ...
+// %i.next = add nuw nsw i32 %i, 1
+// ...
+//
+// In this case, %im becomes a loop-induction variable by peeling 1 iteration,
+// because %i is a loop-induction one. The peeling count can be determined by
+// the same algorithm with loop-invariant case. Such peeling is profitable for
+// loop-vectorization.
+//
// The PhiAnalyzer class calculates how many times a loop should be
// peeled based on the above analysis of the phi nodes in the loop while
// respecting the maximum specified.
class PhiAnalyzer {
public:
- PhiAnalyzer(const Loop &L, unsigned MaxIterations);
+ PhiAnalyzer(const Loop &L, unsigned MaxIterations, bool PeelForIV);
// Calculate the sufficient minimum number of iterations of the loop to peel
// such that phi instructions become determined (subject to allowable limits)
std::optional<unsigned> calculateIterationsToPeel();
protected:
- using PeelCounter = std::optional<unsigned>;
+ enum class PeelCounterType {
+ Invariant,
+ Induction,
+ };
+
+ using PeelCounterValue = std::pair<unsigned, PeelCounterType>;
+ using PeelCounter = std::optional<PeelCounterValue>;
const PeelCounter Unknown = std::nullopt;
// Add 1 respecting Unknown and return Unknown if result over MaxIterations
PeelCounter addOne(PeelCounter PC) const {
if (PC == Unknown)
return Unknown;
- return (*PC + 1 <= MaxIterations) ? PeelCounter{*PC + 1} : Unknown;
+ auto [Val, Ty] = *PC;
+ return (Val + 1 <= MaxIterations) ? PeelCounter({Val + 1, Ty}) : Unknown;
}
- // Calculate the number of iterations after which the given value
- // becomes an invariant.
+ // Return a value representing zero for the given counter type.
+ PeelCounter makeZero(PeelCounterType Ty) const {
+ return PeelCounter({0, Ty});
+ }
+
+ // Calculate the number of iterations after which the given value becomes an
+ // invariant or an induction.
PeelCounter calculate(const Value &);
+ // Auxiliary function to calculate the number of iterations for a comparison
+ // instruction or a binary operator.
+ PeelCounter mergeTwoCounter(const Instruction &CmpOrBinaryOp,
----------------
nikic wrote:
nit: mergeTwoCounters?
https://github.com/llvm/llvm-project/pull/121104
More information about the llvm-commits
mailing list