pub struct Scev<'a> { /* private fields */ }Expand description
The analysis, which works out an answer when asked and remembers it.
Demand driven and memoized, per section 7.8, because the cost of scalar evolution is a function of how many distinct values get asked about rather than of the size of the function. The cache holds one loop’s worth of answers per loop and the whole thing is thrown away when anything about the loops changes, which per document 04.4 is any pass that touches one.
Implementations§
Source§impl<'a> Scev<'a>
impl<'a> Scev<'a>
Sourcepub fn new(func: &'a Func, cfg: &'a Cfg, loops: &'a Loops) -> Self
pub fn new(func: &'a Func, cfg: &'a Cfg, loops: &'a Loops) -> Self
A fresh analysis over these loops, knowing nothing yet.
Sourcepub fn evolution(&mut self, id: LoopId, value: Value) -> Evolution
pub fn evolution(&mut self, id: LoopId, value: Value) -> Evolution
How this value changes across the iterations of this loop.
The way in, and what it does before answering is settle Scev::holds for the loop. That has
to happen out here rather than at the point Scev::extend wants it, because settling it
means asking about other values and Scev::at parks a marker on the value it is working on.
Asked from in there, the answer would depend on what was already in flight.
Sourcepub fn bound(&mut self, id: LoopId) -> Option<Bound>
pub fn bound(&mut self, id: LoopId) -> Option<Bound>
How many times this loop runs at most, and what that rests on.
Any one exit gives a valid upper bound, because a loop cannot run more times than the
first exit that fires, so this takes the first exit it can solve rather than the smallest.
That is max_loop_iterations and not estimate_numbers_of_iterations, which is why the
answer is a Bound.