pub struct Cycles(/* private fields */);Expand description
Time, as multiples of one simple ALU operation.
Fixed point with two decimal places, per Cycles::SCALE. Integers are not enough: an lea
on x86-64 costs less than an add on some microarchitectures and more on others, and a table
that can only say one or two has to round the answer before any pass has seen it. Floating
point would do, and is not used, because two compilers built from the same source must make the
same decisions and a cost that is compared for equality is a cost that has to be exact.
§Infinity
Cycles::INFINITE means the thing is not possible, which is a different statement from very
expensive and is the same type so that the comparison operators work on both. Section 40.2
takes this from GCC’s infinite_cost in gcc/tree-ssa-loop-ivopts.cc, and the reason to have
it once rather than in each pass is that i64::MAX / 2 written in eight places is eight
chances to overflow it.
Arithmetic saturates at infinity rather than wrapping. Section 40.13 asks that the saturating
case be visible rather than silent, and crate::Cost is where that is recorded, because a
saturation matters when it decides something and a bare Cycles has not decided anything yet.
Implementations§
Source§impl Cycles
impl Cycles
Sourcepub const SCALE: i64 = 100
pub const SCALE: i64 = 100
How many units one simple ALU operation is worth, which fixes where the point sits.
A hundred, so that a table can be read and written in the units people quote latencies in.
GCC’s COSTS_N_INSNS uses four, which buys quarter granularity and makes every number in
every target file a multiple of four that has to be divided in your head.
Sourcepub const ZERO: Self
pub const ZERO: Self
Free. Not the same as Cycles::ONE on a machine that issues several operations a cycle,
and not the same as unknown either.
Sourcepub const fn hundredths(n: i64) -> Self
pub const fn hundredths(n: i64) -> Self
A number of hundredths, for a table entry that is not a whole number of operations.
Sourcepub const fn is_infinite(self) -> bool
pub const fn is_infinite(self) -> bool
Whether this is Cycles::INFINITE, meaning impossible rather than expensive.
Worth asking before printing a cost and before dividing by one, and worth not asking anywhere else, since the ordering already puts it above everything finite.
Trait Implementations§
Source§impl AddAssign for Cycles
impl AddAssign for Cycles
Source§fn add_assign(&mut self, other: Self)
fn add_assign(&mut self, other: Self)
+= operation. Read moreSource§impl Capability for Cycles
impl Capability for Cycles
Source§fn impossible(&self) -> Vec<bool>
fn impossible(&self) -> Vec<bool>
impl Copy for Cycles
Source§impl Div<i64> for Cycles
impl Div<i64> for Cycles
Source§fn div(self, by: i64) -> Self
fn div(self, by: i64) -> Self
Dividing infinity leaves infinity, and dividing by zero is a bug rather than an infinity.
A pass that divides a cost by a count it did not check is a pass with an empty set it thought was non-empty, and turning that into a very large number would hide it until the number came out of a heuristic somewhere else.
impl Eq for Cycles
Source§impl Ord for Cycles
impl Ord for Cycles
1.21.0 (const: unstable) · Source§fn max(self, other: Self) -> Selfwhere
Self: Sized,
fn max(self, other: Self) -> Selfwhere
Self: Sized,
1.21.0 (const: unstable) · Source§fn min(self, other: Self) -> Selfwhere
Self: Sized,
fn min(self, other: Self) -> Selfwhere
Self: Sized,
Source§impl PartialOrd for Cycles
impl PartialOrd for Cycles
impl StructuralPartialEq for Cycles
Source§impl Sub for Cycles
impl Sub for Cycles
Source§fn sub(self, other: Self) -> Self
fn sub(self, other: Self) -> Self
Saturating below at zero as well as above at infinity.
A negative cost is not a thing any pass here means. Every subtraction in the documents is a saving, of the form what it cost before minus what it costs now, and a saving that came out negative is a transformation that did not pay, which zero says as well as minus three does and without the risk that something later multiplies by it.