Skip to main content

CostTable

Struct CostTable 

Source
pub struct CostTable {
Show 26 fields pub add: Cycles, pub lea: Cycles, pub shift_const: Cycles, pub shift_var: Cycles, pub mult: [Cycles; 4], pub mult_bit: Cycles, pub divide: [Cycles; 4], pub movsx: Cycles, pub movzx: Cycles, pub reg_move: Cycles, pub move_int_load: [Cycles; 4], pub move_int_store: [Cycles; 4], pub move_int_reg: Cycles, pub move_fp_load: [Cycles; 2], pub move_fp_store: [Cycles; 2], pub move_fp_reg: Cycles, pub move_fp_to_int: Cycles, pub move_int_to_fp: Cycles, pub addr: [Cycles; 5], pub branch_cost: Cycles, pub mispredict_penalty: Cycles, pub move_ratio: u32, pub clear_ratio: u32, pub cheapest_store: Bytes, pub reassoc_int: u32, pub reassoc_fp: u32,
}
Expand description

What an operation costs on one target at one optimization goal.

Built through Builder and no other way, per the module documentation. Every field is public to read and none of them can be written after the table exists, because a target’s costs are data and a pass that adjusts them is a pass keeping a policy somewhere nobody can find it.

Fields§

§add: Cycles

A register to register add, which is the operation Cycles::ONE is defined as.

It is in the table anyway rather than assumed to be one, because a target where the unit operation is not an add should say so instead of having its whole table shifted.

§lea: Cycles

An address computation that does not touch flags, x86-64’s lea.

Section 40.3 keeps this separate from add because whether it is cheaper is exactly the kind of microarchitectural fact that varies between cores of the same target.

§shift_const: Cycles

A shift by an amount known at compile time.

§shift_var: Cycles

A shift by an amount in a register, which on x86-64 is the expensive one because of the flags dependency and the fixed count register.

§mult: [Cycles; 4]

A multiply, indexed by Width.

§mult_bit: Cycles

What each set bit in a constant multiplier adds, for deciding when to expand a multiply by a constant into shifts and adds.

§divide: [Cycles; 4]

A divide, indexed by Width. The most expensive integer operation on every target and the reason strength reduction of division is worth doing at all.

§movsx: Cycles

A sign extension.

§movzx: Cycles

A zero extension, which on x86-64 is free for the 32 to 64 case and is not for the others, so this is the cost of the ones that are not free.

§reg_move: Cycles

A register to register move, as the expression evaluator sees it.

§move_int_load: [Cycles; 4]

An integer load, indexed by Width, as the register allocator sees it.

§move_int_store: [Cycles; 4]

An integer store, indexed by Width, as the register allocator sees it.

§move_int_reg: Cycles

A move between two integer registers, as the register allocator sees it.

Separate from reg_move on purpose, per section 40.3. The allocator asks what a move it is about to insert costs, and the evaluator asks what a move already in the program costs, and gcc/config/i386/i386.h:114 says plainly that the two answers can differ.

§move_fp_load: [Cycles; 2]

A floating point load, for the two widths that exist, single then double.

§move_fp_store: [Cycles; 2]

A floating point store, single then double.

§move_fp_reg: Cycles

A move between two floating point registers.

§move_fp_to_int: Cycles

A move from a floating point register to an integer one, which goes through memory or a dedicated instruction and is never free.

§move_int_to_fp: Cycles

A move from an integer register to a floating point one.

§addr: [Cycles; 5]

An address of each shape, indexed by AddrMode, per section 40.9.

A mode the target does not have is Cycles::INFINITE, which is what the check that the speed and size tables agree about capability reads.

§branch_cost: Cycles

What an unpredictable branch costs when optimizing for speed, per section 40.5.

Only the unpredictable case is a target number. BRANCH_COST at gcc/config/i386/i386.h:2023 makes a predictable branch free and a branch costed for size worth 2 on every target, and those two are in crate::heuristics rather than here because they are not facts about the machine.

§mispredict_penalty: Cycles

What a mispredicted branch costs, per section 40.10.

The number that decides whether a switch becomes a jump table, because an indirect branch with many targets has to be priced as a mispredict and not as a branch.

§move_ratio: u32

How many scalar moves a block copy may expand to before it becomes a call, per section 40.7.

GCC’s move_ratio. A count of moves rather than of bytes, because how many moves a copy takes depends on the alignment the compiler can prove.

§clear_ratio: u32

The same for a block fill. GCC’s clear_ratio.

§cheapest_store: Bytes

The narrowest store worth using, per section 40.7’s trimming rule.

A partially dead store is trimmed only to a width at least this wide. Narrowing an 8-byte store to a 1-byte store because seven bytes are dead is legal and is usually a store forwarding stall, which is the thing this number stops.

§reassoc_int: u32

How many integer operations the machine issues in parallel, per section 40.8.

The reassociation width. A chain of eight adds becomes a tree only on a machine that can execute the tree’s independent operations at once, so this is a hardware fact rather than a tuning constant, and it defaults to 1 on a new target, meaning no reassociation.

§reassoc_fp: u32

The same for floating point.

Reassociating floating point needs -ffast-math whatever this says, because the transformation is not value preserving. This is only how wide the tree may be once that question has been answered somewhere else.

Implementations§

Source§

impl CostTable

Source

pub const FIELDS: &'static [&'static str]

Every field name, in declaration order.

Source

pub fn capabilities(&self) -> Vec<(&'static str, Vec<bool>)>

Which entries of which fields are impossible, per Capability.

Source§

impl CostTable

Source

pub fn builder() -> Builder

A fresh builder, which is the only way to a table.

Source

pub fn mult_of(&self, width: Width) -> Cycles

What a multiply of this width costs.

Source

pub fn divide_of(&self, width: Width) -> Cycles

What a divide of this width costs.

Source

pub fn int_load(&self, width: Width) -> Cycles

What an integer load of this width costs the allocator.

Source

pub fn int_store(&self, width: Width) -> Cycles

What an integer store of this width costs the allocator.

Source

pub fn has_addr(&self, mode: AddrMode) -> bool

Whether the target has this addressing mode at all.

Source

pub fn addr_cost(&self, mode: AddrMode) -> Cost

What an address of this shape costs, with the complexity counted relative to the target.

Section 40.9’s refinement, and the comment it comes from at gcc/tree-ssa-loop-ivopts.cc:4799: “Don’t increase the complexity of adding a scaled index if it’s the only kind of index that the target allows”. A feature the target offers no alternative to is not a complication, and counting it as one makes every address on that target look complicated, which is the same as the tiebreak not working.

Trait Implementations§

Source§

impl Clone for CostTable

Source§

fn clone(&self) -> CostTable

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for CostTable

Source§

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

Formats the value using the given formatter. Read more
Source§

impl Eq for CostTable

Source§

impl PartialEq for CostTable

Source§

fn eq(&self, other: &CostTable) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for CostTable

Auto Trait Implementations§

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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. 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> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
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.