pub struct Builder { /* private fields */ }Expand description
The one way to build a CostTable.
Every field starts unset, and Builder::build refuses to produce a table while any
of them still is. That is section 40.13’s completeness check, moved from a test into
the constructor so that a target added next year cannot skip it.
Implementations§
Source§impl Builder
impl Builder
Sourcepub fn add(self, value: Cycles) -> Self
pub fn add(self, value: Cycles) -> Self
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.
Sourcepub fn lea(self, value: Cycles) -> Self
pub fn lea(self, value: Cycles) -> Self
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.
Sourcepub fn shift_const(self, value: Cycles) -> Self
pub fn shift_const(self, value: Cycles) -> Self
A shift by an amount known at compile time.
Sourcepub fn shift_var(self, value: Cycles) -> Self
pub fn shift_var(self, value: Cycles) -> Self
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.
Sourcepub fn mult_bit(self, value: Cycles) -> Self
pub fn mult_bit(self, value: Cycles) -> Self
What each set bit in a constant multiplier adds, for deciding when to expand a multiply by a constant into shifts and adds.
Sourcepub fn divide(self, value: [Cycles; 4]) -> Self
pub fn divide(self, value: [Cycles; 4]) -> Self
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.
Sourcepub fn movzx(self, value: Cycles) -> Self
pub fn movzx(self, value: Cycles) -> Self
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.
Sourcepub fn reg_move(self, value: Cycles) -> Self
pub fn reg_move(self, value: Cycles) -> Self
A register to register move, as the expression evaluator sees it.
Sourcepub fn move_int_load(self, value: [Cycles; 4]) -> Self
pub fn move_int_load(self, value: [Cycles; 4]) -> Self
An integer load, indexed by Width, as the register allocator sees it.
Sourcepub fn move_int_store(self, value: [Cycles; 4]) -> Self
pub fn move_int_store(self, value: [Cycles; 4]) -> Self
An integer store, indexed by Width, as the register allocator sees it.
Sourcepub fn move_int_reg(self, value: Cycles) -> Self
pub fn move_int_reg(self, value: Cycles) -> Self
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.
Sourcepub fn move_fp_load(self, value: [Cycles; 2]) -> Self
pub fn move_fp_load(self, value: [Cycles; 2]) -> Self
A floating point load, for the two widths that exist, single then double.
Sourcepub fn move_fp_store(self, value: [Cycles; 2]) -> Self
pub fn move_fp_store(self, value: [Cycles; 2]) -> Self
A floating point store, single then double.
Sourcepub fn move_fp_reg(self, value: Cycles) -> Self
pub fn move_fp_reg(self, value: Cycles) -> Self
A move between two floating point registers.
Sourcepub fn move_fp_to_int(self, value: Cycles) -> Self
pub fn move_fp_to_int(self, value: Cycles) -> Self
A move from a floating point register to an integer one, which goes through memory or a dedicated instruction and is never free.
Sourcepub fn move_int_to_fp(self, value: Cycles) -> Self
pub fn move_int_to_fp(self, value: Cycles) -> Self
A move from an integer register to a floating point one.
Sourcepub fn addr(self, value: [Cycles; 5]) -> Self
pub fn addr(self, value: [Cycles; 5]) -> Self
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.
Sourcepub fn branch_cost(self, value: Cycles) -> Self
pub fn branch_cost(self, value: Cycles) -> Self
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.
Sourcepub fn mispredict_penalty(self, value: Cycles) -> Self
pub fn mispredict_penalty(self, value: Cycles) -> Self
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.
Sourcepub fn move_ratio(self, value: u32) -> Self
pub fn move_ratio(self, value: u32) -> Self
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.
Sourcepub fn clear_ratio(self, value: u32) -> Self
pub fn clear_ratio(self, value: u32) -> Self
The same for a block fill. GCC’s clear_ratio.
Sourcepub fn cheapest_store(self, value: Bytes) -> Self
pub fn cheapest_store(self, value: Bytes) -> Self
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.
Sourcepub fn reassoc_int(self, value: u32) -> Self
pub fn reassoc_int(self, value: u32) -> Self
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.
Sourcepub fn reassoc_fp(self, value: u32) -> Self
pub fn reassoc_fp(self, value: u32) -> Self
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.
Sourcepub fn missing(&self) -> Vec<&'static str>
pub fn missing(&self) -> Vec<&'static str>
The fields nobody has set, in declaration order.
Public so that a test can name them, which turns “the table is incomplete” into
“the table is missing branch_cost” without anybody reading a panic message.
Sourcepub fn build(self) -> CostTable
pub fn build(self) -> CostTable
The finished table.
§Panics
If any field was left unset, naming them. A target’s cost table is written once and is a compile time constant of the compiler in every sense that matters, so this fires during the tests of whoever added the target and never in front of a user.