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: CyclesA 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: CyclesAn 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: CyclesA shift by an amount known at compile time.
shift_var: CyclesA 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: CyclesWhat 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: CyclesA sign extension.
movzx: CyclesA 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: CyclesA 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: CyclesA 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: CyclesA move between two floating point registers.
move_fp_to_int: CyclesA 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: CyclesA 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: CyclesWhat 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: CyclesWhat 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: u32How 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: u32The same for a block fill. GCC’s clear_ratio.
cheapest_store: BytesThe 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: u32How 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: u32The 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
impl CostTable
Sourcepub fn capabilities(&self) -> Vec<(&'static str, Vec<bool>)>
pub fn capabilities(&self) -> Vec<(&'static str, Vec<bool>)>
Which entries of which fields are impossible, per Capability.
Source§impl CostTable
impl CostTable
Sourcepub fn int_load(&self, width: Width) -> Cycles
pub fn int_load(&self, width: Width) -> Cycles
What an integer load of this width costs the allocator.
Sourcepub fn int_store(&self, width: Width) -> Cycles
pub fn int_store(&self, width: Width) -> Cycles
What an integer store of this width costs the allocator.
Sourcepub fn has_addr(&self, mode: AddrMode) -> bool
pub fn has_addr(&self, mode: AddrMode) -> bool
Whether the target has this addressing mode at all.
Sourcepub fn addr_cost(&self, mode: AddrMode) -> Cost
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.