Skip to main content

Ranges

Struct Ranges 

Source
pub struct Ranges<'a> { /* private fields */ }
Expand description

The range analysis of one function.

Queries take &mut self because a query fills the cache and moves the counters, which is the design and not an accident: an analysis that answered without recording what it was asked could not report the losses in section 10.7.

Implementations§

Source§

impl<'a> Ranges<'a>

Source

pub fn new(func: &'a Func, cfg: &'a Cfg, dom: &'a Dominators) -> Self

The analysis of this function, with the limits at their defaults.

Source

pub fn with( func: &'a Func, cfg: &'a Cfg, dom: &'a Dominators, options: Options, ) -> Self

The same, with the limits the command line asked for.

Source

pub const fn counts(&self) -> &Counts

What the queries have done so far.

Source

pub fn of(&mut self, value: Value) -> Range

What this value can be where it is defined.

Source

pub fn at(&mut self, value: Value, block: Block) -> Range

What this value can be on entry to this block.

The block has to be one the definition reaches, which for a use is the block the use is in. Asking about a block the definition does not dominate is not wrong, it just gets an answer that ignored the branches it could not see.

Source

pub fn at_inst(&mut self, value: Value, inst: Inst) -> Range

What this value can be at this instruction.

The same as Ranges::at on the block holding it. Ranges within a block do not change in rucc’s IR, because there is nothing between two instructions that could narrow one: the branches are all at the ends of blocks.

Source

pub fn compare( &mut self, pred: IntPred, a: Value, b: Value, block: Block, ) -> Truth

Whether this comparison is settled where it stands.

The ranges answer first, because they answer more often. The oracle answers the cases they cannot, which are the ones where the two values are related without either being pinned down, and section 10.3 says that is most of what removes a repeated bounds check.

Source

pub fn relation(&mut self, a: Value, b: Value, block: Block) -> Option<IntPred>

What is known to hold between these two values in this block, if anything.

What was recorded on a dominating edge, read in the order asked, plus one step through an intermediate value. Not the transitive closure: section 10.3 says computing that is where the cost of a relational oracle goes and that one step pays for most of it.

Trait Implementations§

Source§

impl<'a> Debug for Ranges<'a>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<'a> Freeze for Ranges<'a>

§

impl<'a> RefUnwindSafe for Ranges<'a>

§

impl<'a> Send for Ranges<'a>

§

impl<'a> Sync for Ranges<'a>

§

impl<'a> Unpin for Ranges<'a>

§

impl<'a> UnsafeUnpin for Ranges<'a>

§

impl<'a> UnwindSafe for Ranges<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.