diff --git a/lib/cretonne/src/cfg.rs b/lib/cretonne/src/cfg.rs index f68d8bcbf4..5466355812 100644 --- a/lib/cretonne/src/cfg.rs +++ b/lib/cretonne/src/cfg.rs @@ -1,8 +1,9 @@ //! A control flow graph represented as mappings of extended basic blocks to their predecessors -//! and successors. Successors are represented as extended basic blocks while predecessors are -//! represented by basic blocks. -//! BasicBlocks are denoted by tuples of EBB and branch/jump instructions. Each predecessor -//! tuple corresponds to the end of a basic block. +//! and successors. +//! +//! Successors are represented as extended basic blocks while predecessors are represented by basic +//! blocks. Basic blocks are denoted by tuples of EBB and branch/jump instructions. Each +//! predecessor tuple corresponds to the end of a basic block. //! //! ```c //! Ebb0: @@ -19,8 +20,8 @@ //! jmp Ebb2 ; end of basic block //! ``` //! -//! Here Ebb1 and Ebb2 would each have a single predecessor denoted as (Ebb0, `brz vx, Ebb1`) -//! and (Ebb0, `jmp Ebb2`) respectively. +//! Here `Ebb1` and `Ebb2` would each have a single predecessor denoted as `(Ebb0, brz)` +//! and `(Ebb0, jmp Ebb2)` respectively. use ir::{Function, Inst, Ebb}; use ir::instructions::BranchInfo; @@ -91,7 +92,7 @@ impl ControlFlowGraph { &self.data[ebb].successors } - /// Return [reachable] ebbs in postorder. + /// Return [reachable] ebbs in post-order. pub fn postorder_ebbs(&self) -> Vec { let entry_block = match self.entry_block { None => { @@ -111,7 +112,7 @@ impl ControlFlowGraph { // This is a white node. Mark it as gray. grey.insert(node); stack.push(node); - // Get any children we’ve never seen before. + // Get any children we've never seen before. for child in self.get_successors(node) { if !grey.contains(child) { stack.push(child.clone()); @@ -125,7 +126,7 @@ impl ControlFlowGraph { postorder } - /// An iterator across all of the ebbs stored in the cfg. + /// An iterator across all of the ebbs stored in the CFG. pub fn ebbs(&self) -> Keys { self.data.keys() } diff --git a/lib/cretonne/src/constant_hash.rs b/lib/cretonne/src/constant_hash.rs index f76fde7fb7..08cc2944c8 100644 --- a/lib/cretonne/src/constant_hash.rs +++ b/lib/cretonne/src/constant_hash.rs @@ -67,7 +67,7 @@ mod tests { #[test] fn basic() { - // c.f. meta/constant_hash.py tests. + // c.f. `meta/constant_hash.py` tests. assert_eq!(simple_hash("Hello"), 0x2fa70c01); assert_eq!(simple_hash("world"), 0x5b0c31d5); } diff --git a/lib/cretonne/src/dominator_tree.rs b/lib/cretonne/src/dominator_tree.rs index f940d3c910..eaec78f367 100644 --- a/lib/cretonne/src/dominator_tree.rs +++ b/lib/cretonne/src/dominator_tree.rs @@ -52,7 +52,7 @@ impl DominatorTree { self.nodes[ebb].idom.into() } - /// Compare two EBBs relative to a reverse pst-order traversal of the control-flow graph. + /// Compare two EBBs relative to a reverse post-order traversal of the control-flow graph. /// /// Return `Ordering::Less` if `a` comes before `b` in the RPO. pub fn rpo_cmp(&self, a: Ebb, b: Ebb) -> Ordering { @@ -124,7 +124,7 @@ impl DominatorTree { pub fn new(func: &Function, cfg: &ControlFlowGraph) -> DominatorTree { let mut domtree = DominatorTree { nodes: EntityMap::with_capacity(func.dfg.num_ebbs()) }; - // We'll be iterating over a reverse postorder of the CFG. + // We'll be iterating over a reverse post-order of the CFG. // This vector only contains reachable EBBs. let mut postorder = cfg.postorder_ebbs(); @@ -154,8 +154,8 @@ impl DominatorTree { } } - // Now that we have RPO numbers for everything and initial idom estimates, iterate until - // convergence. + // Now that we have RPO numbers for everything and initial immediate dominator estimates, + // iterate until convergence. // // If the function is free of irreducible control flow, this will exit after one iteration. let mut changed = true; @@ -173,7 +173,8 @@ impl DominatorTree { domtree } - // Compute the idom for `ebb` using the current `idom` states for the reachable nodes. + // Compute the immediate dominator for `ebb` using the current `idom` states for the reachable + // nodes. fn compute_idom(&self, ebb: Ebb, cfg: &ControlFlowGraph, layout: &Layout) -> Inst { // Get an iterator with just the reachable predecessors to `ebb`. // Note that during the first pass, `is_reachable` returns false for blocks that haven't diff --git a/lib/cretonne/src/entity_list.rs b/lib/cretonne/src/entity_list.rs index 6ec23e39e2..d94795c902 100644 --- a/lib/cretonne/src/entity_list.rs +++ b/lib/cretonne/src/entity_list.rs @@ -178,7 +178,7 @@ impl ListPool { /// Returns two mutable slices representing the two requested blocks. /// /// The two returned slices can be longer than the blocks. Each block is located at the front - /// the the respective slice. + /// of the respective slice. fn mut_slices(&mut self, block0: usize, block1: usize) -> (&mut [T], &mut [T]) { if block0 < block1 { let (s0, s1) = self.data.split_at_mut(block1); diff --git a/lib/cretonne/src/entity_map.rs b/lib/cretonne/src/entity_map.rs index 33d355e9f1..f9ac258f92 100644 --- a/lib/cretonne/src/entity_map.rs +++ b/lib/cretonne/src/entity_map.rs @@ -139,7 +139,7 @@ impl EntityMap self.elems.resize(n, V::default()); } - /// Ensure that `k` is a valid key but adding default entries if necesssary. + /// Ensure that `k` is a valid key but adding default entries if necessary. /// /// Return a mutable reference to the corresponding entry. pub fn ensure(&mut self, k: K) -> &mut V { @@ -202,7 +202,7 @@ impl Iterator for Keys mod tests { use super::*; - // EntityRef impl for testing. + // `EntityRef` impl for testing. #[derive(Clone, Copy, Debug, PartialEq, Eq)] struct E(u32); diff --git a/lib/cretonne/src/ir/builder.rs b/lib/cretonne/src/ir/builder.rs index ad3f8e22fe..639b640c20 100644 --- a/lib/cretonne/src/ir/builder.rs +++ b/lib/cretonne/src/ir/builder.rs @@ -13,7 +13,7 @@ use ir::condcodes::{IntCC, FloatCC}; /// /// The `InstBuilderBase` trait provides the basic functionality required by the methods of the /// generated `InstBuilder` trait. These methods should not normally be used directly. Use the -/// methods in the `InstBuilder trait instead. +/// methods in the `InstBuilder` trait instead. /// /// Any data type that implements `InstBuilderBase` also gets all the methods of the `InstBuilder` /// trait. @@ -104,7 +104,7 @@ impl<'c, 'fc, 'fd> InstBuilderBase<'fd> for InsertBuilder<'c, 'fc, 'fd> { /// /// If the old instruction still has secondary result values attached, it is assumed that the new /// instruction produces the same number and types of results. The old secondary values are -/// preserved. If the replacemant instruction format does not support multiple results, the builder +/// preserved. If the replacement instruction format does not support multiple results, the builder /// panics. It is a bug to leave result values dangling. /// /// If the old instruction was capable of producing secondary results, but the values have been diff --git a/lib/cretonne/src/ir/dfg.rs b/lib/cretonne/src/ir/dfg.rs index a01a4dd654..94117095a7 100644 --- a/lib/cretonne/src/ir/dfg.rs +++ b/lib/cretonne/src/ir/dfg.rs @@ -12,7 +12,7 @@ use packed_option::PackedOption; use std::ops::{Index, IndexMut}; use std::u16; -/// A data flow graph defines all instuctions and extended basic blocks in a function as well as +/// A data flow graph defines all instructions and extended basic blocks in a function as well as /// the data flow dependencies between them. The DFG also tracks values which can be either /// instruction results or EBB arguments. /// @@ -213,7 +213,7 @@ impl DataFlowGraph { original: original, }; } else { - panic!("Cannot change dirrect value {} into an alias", dest); + panic!("Cannot change direct value {} into an alias", dest); } } } @@ -328,7 +328,7 @@ impl DataFlowGraph { // Additional values form a linked list starting from the second result value. Generate // the list backwards so we don't have to modify value table entries in place. (This - // causes additional result values to be numbered backwards which is not the aestetic + // causes additional result values to be numbered backwards which is not the aesthetic // choice, but since it is only visible in extremely rare instructions with 3+ results, // we don't care). let mut head = None; @@ -498,7 +498,7 @@ impl DataFlowGraph { return num as usize + 1; } } - panic!("inconsistent value table entry for EBB arg"); + panic!("inconsistent value table entry for EBB argument"); } } } @@ -514,7 +514,7 @@ impl DataFlowGraph { next: None.into(), }); match self.ebbs[ebb].last_arg.expand() { - // If last_arg is `None`, we're adding the first EBB argument. + // If last_argument is `None`, we're adding the first EBB argument. None => { self.ebbs[ebb].first_arg = val.into(); } @@ -525,11 +525,11 @@ impl DataFlowGraph { if let ValueData::Arg { ref mut next, .. } = self.extended_values[idx] { *next = val.into(); } else { - panic!("inconsistent value table entry for EBB arg"); + panic!("inconsistent value table entry for EBB argument"); } } ExpandedValue::Direct(_) => { - panic!("inconsistent value table entry for EBB arg") + panic!("inconsistent value table entry for EBB argument") } } } @@ -556,7 +556,7 @@ impl DataFlowGraph { struct EbbData { // First argument to this EBB, or `None` if the block has no arguments. // - // The arguments are all ValueData::Argument entries that form a linked list from `first_arg` + // The arguments are all `ValueData::Argument` entries that form a linked list from `first_arg` // to `last_arg`. first_arg: PackedOption, @@ -680,14 +680,14 @@ mod tests { _ => panic!(), }; - // Detach the 'c' value from iadd. + // Detach the 'c' value from `iadd`. { let mut vals = dfg.detach_secondary_results(iadd); assert_eq!(vals.next(), Some(c)); assert_eq!(vals.next(), None); } - // Replace iadd_cout with a normal iadd and an icmp. + // Replace `iadd_cout` with a normal `iadd` and an `icmp`. dfg.replace(iadd).iadd(v1, arg0); let c2 = dfg.ins(pos).icmp(IntCC::UnsignedLessThan, s, v1); dfg.change_to_alias(c, c2); diff --git a/lib/cretonne/src/ir/entities.rs b/lib/cretonne/src/ir/entities.rs index 69a9902151..51ca70ad7a 100644 --- a/lib/cretonne/src/ir/entities.rs +++ b/lib/cretonne/src/ir/entities.rs @@ -65,7 +65,7 @@ pub struct Ebb(u32); entity_impl!(Ebb, "ebb"); impl Ebb { - /// Create a new EBB reference from its number. This corresponds to the ebbNN representation. + /// Create a new EBB reference from its number. This corresponds to the `ebbNN` representation. /// /// This method is for use by the parser. pub fn with_number(n: u32) -> Option { @@ -90,7 +90,7 @@ pub enum ExpandedValue { impl Value { /// Create a `Direct` value from its number representation. - /// This is the number in the vNN notation. + /// This is the number in the `vNN` notation. /// /// This method is for use by the parser. pub fn direct_with_number(n: u32) -> Option { @@ -104,7 +104,7 @@ impl Value { } /// Create a `Table` value from its number representation. - /// This is the number in the vxNN notation. + /// This is the number in the `vxNN` notation. /// /// This method is for use by the parser. pub fn table_with_number(n: u32) -> Option { diff --git a/lib/cretonne/src/ir/function.rs b/lib/cretonne/src/ir/function.rs index db6c811b5a..2828104daa 100644 --- a/lib/cretonne/src/ir/function.rs +++ b/lib/cretonne/src/ir/function.rs @@ -60,7 +60,7 @@ impl Function { } } - /// Create a new empty, anomymous function. + /// Create a new empty, anonymous function. pub fn new() -> Function { Self::with_name_signature(FunctionName::default(), Signature::new()) } diff --git a/lib/cretonne/src/ir/immediates.rs b/lib/cretonne/src/ir/immediates.rs index e2fc0c446d..bc44e6c022 100644 --- a/lib/cretonne/src/ir/immediates.rs +++ b/lib/cretonne/src/ir/immediates.rs @@ -62,7 +62,7 @@ impl Display for Imm64 { impl FromStr for Imm64 { type Err = &'static str; - // Parse a decimal or hexadecimal Imm64, formatted as above. + // Parse a decimal or hexadecimal `Imm64`, formatted as above. fn from_str(s: &str) -> Result { let mut value: u64 = 0; let mut digits = 0; @@ -149,7 +149,7 @@ pub struct Ieee64(f64); // Format a floating point number in a way that is reasonably human-readable, and that can be // converted back to binary without any rounding issues. The hexadecimal formatting of normal and -// subnormal numbers is compatible with C99 and the printf "%a" format specifier. The NaN and Inf +// subnormal numbers is compatible with C99 and the `printf "%a"` format specifier. The NaN and Inf // formats are not supported by C99. // // The encoding parameters are: @@ -380,7 +380,7 @@ impl Ieee32 { Ieee32(x) } - /// Construct Ieee32 immediate from raw bits. + /// Construct `Ieee32` immediate from raw bits. pub fn from_bits(x: u32) -> Ieee32 { Ieee32(unsafe { mem::transmute(x) }) } @@ -410,7 +410,7 @@ impl Ieee64 { Ieee64(x) } - /// Construct Ieee64 immediate from raw bits. + /// Construct `Ieee64` immediate from raw bits. pub fn from_bits(x: u64) -> Ieee64 { Ieee64(unsafe { mem::transmute(x) }) } @@ -496,7 +496,7 @@ mod tests { "Negative number too small for Imm64"); parse_ok::("18446744073709551615", "-1"); parse_ok::("-9223372036854775808", "0x8000_0000_0000_0000"); - // Overflow both the checked_add and checked_mul. + // Overflow both the `checked_add` and `checked_mul`. parse_err::("18446744073709551616", "Too large decimal Imm64"); parse_err::("184467440737095516100", "Too large decimal Imm64"); parse_err::("-9223372036854775809", diff --git a/lib/cretonne/src/ir/instructions.rs b/lib/cretonne/src/ir/instructions.rs index f25c58d197..17a0ef2c27 100644 --- a/lib/cretonne/src/ir/instructions.rs +++ b/lib/cretonne/src/ir/instructions.rs @@ -57,9 +57,9 @@ impl Opcode { } } -// This trait really belongs in lib/reader where it is used by the .cton file parser, but since it -// critically depends on the `opcode_name()` function which is needed here anyway, it lives in this -// module. This also saves us from running the build script twice to generate code for the two +// This trait really belongs in lib/reader where it is used by the `.cton` file parser, but since +// it critically depends on the `opcode_name()` function which is needed here anyway, it lives in +// this module. This also saves us from running the build script twice to generate code for the two // separate crates. impl FromStr for Opcode { type Err = &'static str; @@ -141,7 +141,7 @@ pub enum InstructionData { arg: Value, imm: Imm64, }, - // Same as BinaryImm, but the immediate is the lhs operand. + // Same as `BinaryImm`, but the immediate is the left-hand-side operand. BinaryImmRev { opcode: Opcode, ty: Type, @@ -246,7 +246,7 @@ impl VariableArgs { } } -// Coerce VariableArgs into a &[Value] slice. +// Coerce `VariableArgs` into a `&[Value]` slice. impl Deref for VariableArgs { type Target = [Value]; @@ -311,7 +311,7 @@ impl Display for TernaryOverflowData { } /// Payload data for jump instructions. These need to carry lists of EBB arguments that won't fit -/// in the allowed InstructionData size. +/// in the allowed `InstructionData` size. #[derive(Clone, Debug)] pub struct JumpData { /// Jump destination EBB. @@ -331,7 +331,7 @@ impl Display for JumpData { } /// Payload data for branch instructions. These need to carry lists of EBB arguments that won't fit -/// in the allowed InstructionData size. +/// in the allowed `InstructionData` size. #[derive(Clone, Debug)] pub struct BranchData { /// Value argument controlling the branch. @@ -702,11 +702,10 @@ mod tests { #[test] fn instruction_data() { use std::mem; - // The size of the InstructionData enum is important for performance. It should not exceed - // 16 bytes. Use `Box` out-of-line payloads for instruction formats that require - // more space than that. - // It would be fine with a data structure smaller than 16 bytes, but what are the odds of - // that? + // The size of the `InstructionData` enum is important for performance. It should not + // exceed 16 bytes. Use `Box` out-of-line payloads for instruction formats that + // require more space than that. It would be fine with a data structure smaller than 16 + // bytes, but what are the odds of that? assert_eq!(mem::size_of::(), 16); } diff --git a/lib/cretonne/src/ir/jumptable.rs b/lib/cretonne/src/ir/jumptable.rs index 824e2dcf23..7103485094 100644 --- a/lib/cretonne/src/ir/jumptable.rs +++ b/lib/cretonne/src/ir/jumptable.rs @@ -33,7 +33,7 @@ impl JumpTableData { /// Set a table entry. /// - /// The table will grow as needed to fit 'idx'. + /// The table will grow as needed to fit `idx`. pub fn set_entry(&mut self, idx: usize, dest: Ebb) { // Resize table to fit `idx`. if idx >= self.table.len() { diff --git a/lib/cretonne/src/ir/layout.rs b/lib/cretonne/src/ir/layout.rs index 2a8d1ba4ac..f914142c7e 100644 --- a/lib/cretonne/src/ir/layout.rs +++ b/lib/cretonne/src/ir/layout.rs @@ -573,10 +573,10 @@ impl<'f> DoubleEndedIterator for Insts<'f> { /// /// A `Cursor` represents a position in a function layout where instructions can be inserted and /// removed. It can be used to iterate through the instructions of a function while editing them at -/// the same time. A normal instruction iterator can't do this since it holds an immutable refernce -/// to the Layout. +/// the same time. A normal instruction iterator can't do this since it holds an immutable +/// reference to the Layout. /// -/// When new instructions are added, the cursor can either apend them to an EBB or insert them +/// When new instructions are added, the cursor can either append them to an EBB or insert them /// before the current instruction. pub struct Cursor<'f> { layout: &'f mut Layout, @@ -592,7 +592,7 @@ pub enum CursorPosition { /// New instructions will be inserted *before* the current instruction. At(Inst), /// Cursor is before the beginning of an EBB. No instructions can be inserted. Calling - /// `next_inst()` wil move to the first instruction in the EBB. + /// `next_inst()` will move to the first instruction in the EBB. Before(Ebb), /// Cursor is pointing after the end of an EBB. /// New instructions will be appended to the EBB. @@ -851,7 +851,7 @@ impl<'f> Cursor<'f> { /// - If pointing at the bottom of an EBB, the new instruction is appended to the EBB. /// - Otherwise panic. /// - /// In either case, the cursor is not moved, such that repeates calls to `insert_inst()` causes + /// In either case, the cursor is not moved, such that repeated calls to `insert_inst()` causes /// instructions to appear in insertion order in the EBB. pub fn insert_inst(&mut self, inst: Inst) { use self::CursorPosition::*; @@ -1263,7 +1263,7 @@ mod tests { assert_eq!(cur.prev_ebb(), None); } - // Check ProgramOrder. + // Check `ProgramOrder`. assert_eq!(layout.cmp(e2, e2), Ordering::Equal); assert_eq!(layout.cmp(e2, i2), Ordering::Less); assert_eq!(layout.cmp(i3, i2), Ordering::Greater); diff --git a/lib/cretonne/src/ir/types.rs b/lib/cretonne/src/ir/types.rs index c001c9f3c7..cdd2207aad 100644 --- a/lib/cretonne/src/ir/types.rs +++ b/lib/cretonne/src/ir/types.rs @@ -43,7 +43,7 @@ impl Type { Type(self.0 & 0x0f) } - /// Get log2 of the number of bits in a lane. + /// Get log_2 of the number of bits in a lane. pub fn log2_lane_bits(self) -> u8 { match self.lane_type() { B1 => 0, @@ -157,7 +157,7 @@ impl Type { } } - /// Get log2 of the number of lanes in this SIMD vector type. + /// Get log_2 of the number of lanes in this SIMD vector type. /// /// All SIMD types have a lane count that is a power of two and no larger than 256, so this /// will be a number in the range 0-8. diff --git a/lib/cretonne/src/legalizer.rs b/lib/cretonne/src/legalizer.rs index a83485b5e2..015bfb9b30 100644 --- a/lib/cretonne/src/legalizer.rs +++ b/lib/cretonne/src/legalizer.rs @@ -69,8 +69,8 @@ pub fn legalize_function(func: &mut Function, isa: &TargetIsa) { } } -// Include legalization patterns that were generated by gen_legalizer.py from the XForms in -// meta/cretonne/legalize.py. +// Include legalization patterns that were generated by `gen_legalizer.py` from the `XForms` in +// `meta/cretonne/legalize.py`. // // Concretely, this defines private functions `narrow()`, and `expand()`. include!(concat!(env!("OUT_DIR"), "/legalizer.rs")); diff --git a/lib/cretonne/src/predicates.rs b/lib/cretonne/src/predicates.rs index a0e50402bf..748a75e23a 100644 --- a/lib/cretonne/src/predicates.rs +++ b/lib/cretonne/src/predicates.rs @@ -20,7 +20,7 @@ pub fn is_signed_int>(x: T, wd: u8, sc: u8) -> bool { #[allow(dead_code)] pub fn is_unsigned_int>(x: T, wd: u8, sc: u8) -> bool { let u = x.into() as u64; - // Bitmask of the permitted bits. + // Bit-mask of the permitted bits. let m = (1 << wd) - (1 << sc); u == (u & m) } @@ -40,7 +40,7 @@ mod tests { assert!(is_signed_int(x2, 2, 0)); assert!(!is_signed_int(x2, 2, 1)); - // u32 doesn't sign-extend when converted to i64. + // `u32` doesn't sign-extend when converted to `i64`. assert!(!is_signed_int(x3, 8, 0)); assert!(is_unsigned_int(x1, 1, 0)); diff --git a/lib/cretonne/src/regalloc/allocatable_set.rs b/lib/cretonne/src/regalloc/allocatable_set.rs index f2ef0102d4..2c608b0a16 100644 --- a/lib/cretonne/src/regalloc/allocatable_set.rs +++ b/lib/cretonne/src/regalloc/allocatable_set.rs @@ -38,7 +38,7 @@ impl AllocatableSet { AllocatableSet { avail: [!0; 3] } } - /// Returns `true` if the spoecified register is available. + /// Returns `true` if the specified register is available. pub fn is_avail(&self, rc: RegClass, reg: RegUnit) -> bool { let (idx, bits) = bitmask(rc, reg); (self.avail[idx] & bits) == bits @@ -71,7 +71,7 @@ impl AllocatableSet { for idx in 0..self.avail.len() { // If a single unit in a register is unavailable, the whole register can't be used. // If a register straddles a word boundary, it will be marked as unavailable. - // There's an assertion in cdsl/registers.py to check for that. + // There's an assertion in `cdsl/registers.py` to check for that. for i in 0..rc.width { rsi.regs[idx] &= self.avail[idx] >> i; } @@ -102,7 +102,7 @@ impl Iterator for RegSetIter { return Some(unit); } - // How many register units was there in the word? This is a constant 32 for u32 etc. + // How many register units was there in the word? This is a constant 32 for `u32` etc. unit_offset += 8 * size_of_val(word) as RegUnit; } @@ -134,7 +134,7 @@ mod tests { fn put_and_take() { let mut regs = AllocatableSet::new(); - // GPR has units 28-36. + // `GPR` has units 28-36. assert_eq!(regs.iter(GPR).count(), 8); assert_eq!(regs.iter(DPR).collect::>(), [28, 30, 33, 35]); diff --git a/lib/cretonne/src/regalloc/liveness.rs b/lib/cretonne/src/regalloc/liveness.rs index c7646ed701..2e6cb78db4 100644 --- a/lib/cretonne/src/regalloc/liveness.rs +++ b/lib/cretonne/src/regalloc/liveness.rs @@ -8,8 +8,8 @@ //! //! The primary consumer of the liveness analysis is the SSA coloring pass which goes through each //! EBB and assigns a register to the defined values. This algorithm needs to maintain a set of the -//! curently live values as it is iterating down the instructions in the EBB. It asks the following -//! questions: +//! currently live values as it is iterating down the instructions in the EBB. It asks the +//! following questions: //! //! - What is the set of live values at the entry to the EBB? //! - When moving past a use of a value, is that value still alive in the EBB, or was that the last @@ -18,7 +18,7 @@ //! //! The set of `LiveRange` instances can answer these questions through their `def_local_end` and //! `livein_local_end` queries. The coloring algorithm visits EBBs in a topological order of the -//! dominator tree, so it can compute the set of live values at the begining of an EBB by starting +//! dominator tree, so it can compute the set of live values at the beginning of an EBB by starting //! from the set of live values at the dominating branch instruction and filtering it with //! `livein_local_end`. These sets do not need to be stored in the liveness analysis. //! @@ -32,11 +32,11 @@ //! A number of different liveness analysis algorithms exist, so it is worthwhile to look at a few //! alternatives. //! -//! ## Dataflow equations +//! ## Data-flow equations //! //! The classic *live variables analysis* that you will find in all compiler books from the //! previous century does not depend on SSA form. It is typically implemented by iteratively -//! solving dataflow equations on bitvectors of variables. The result is a live-out bitvector of +//! solving data-flow equations on bit-vectors of variables. The result is a live-out bit-vector of //! variables for every basic block in the program. //! //! This algorithm has some disadvantages that makes us look elsewhere: @@ -44,18 +44,18 @@ //! - Quadratic memory use. We need a bit per variable per basic block in the function. //! - Sparse representation. In practice, the majority of SSA values never leave their basic block, //! and those that do span basic blocks rarely span a large number of basic blocks. This makes -//! the bitvectors quite sparse. -//! - Traditionally, the dataflow equations were solved for real program *variables* which does not -//! include temporaries used in evaluating expressions. We have an SSA form program which blurs -//! the distinction between temporaries and variables. This makes the quadratic memory problem -//! worse because there are many more SSA values than there was variables in the original +//! the bit-vectors quite sparse. +//! - Traditionally, the data-flow equations were solved for real program *variables* which does +//! not include temporaries used in evaluating expressions. We have an SSA form program which +//! blurs the distinction between temporaries and variables. This makes the quadratic memory +//! problem worse because there are many more SSA values than there was variables in the original //! program, and we don't know a priori which SSA values leave their basic block. //! - Missing last-use information. For values that are not live-out of a basic block, we would //! need to store information about the last use in the block somewhere. LLVM stores this //! information as a 'kill bit' on the last use in the IR. Maintaining these kill bits has been a //! source of problems for LLVM's register allocator. //! -//! Dataflow equations can detect when a variable is used uninitialized, and they can handle +//! Data-flow equations can detect when a variable is used uninitialized, and they can handle //! multiple definitions of the same variable. We don't need this generality since we already have //! a program in SSA form. //! @@ -83,7 +83,7 @@ //! The iterative SSA form reconstruction can be skipped if the depth-first search only encountered //! one SSA value. //! -//! This algorithm has some advantages compared to the dataflow equations: +//! This algorithm has some advantages compared to the data-flow equations: //! //! - The live ranges of local virtual registers are computed very quickly without ever traversing //! the CFG. The memory needed to store these live ranges is independent of the number of basic @@ -106,11 +106,11 @@ //! was presented at CGO 2008: //! //! > Boissinot, B., Hack, S., Grund, D., de Dinechin, B. D., & Rastello, F. (2008). *Fast Liveness -//! Checking for SSA-Form Programs.* CGO. +//! Checking for SSA-Form Programs.* CGO. //! -//! This analysis uses a global precomputation that only depends on the CFG of the function. It +//! This analysis uses a global pre-computation that only depends on the CFG of the function. It //! then allows liveness queries for any (value, program point) pair. Each query traverses the use -//! chain of the value and performs lookups in the precomputed bitvectors. +//! chain of the value and performs lookups in the precomputed bit-vectors. //! //! I did not seriously consider this analysis for Cretonne because: //! @@ -118,8 +118,8 @@ //! - Popular variables like the `this` pointer in a C++ method can have very large use chains. //! Traversing such a long use chain on every liveness lookup has the potential for some nasty //! quadratic behavior in unfortunate cases. -//! - It says "fast" in the title, but the paper only claims to be 16% faster than a dataflow based -//! approach, which isn't that impressive. +//! - It says "fast" in the title, but the paper only claims to be 16% faster than a data-flow +//! based approach, which isn't that impressive. //! //! Nevertheless, the property of only depending in the CFG structure is very useful. If Cretonne //! gains use chains, this approach would be worth a proper evaluation. @@ -171,7 +171,7 @@ //! - Related values should be stored on the same cache line. The current sparse set implementation //! does a decent job of that. //! - For global values, the list of live-in intervals is very likely to fit on a single cache -//! line. These lists are very likely ot be found in L2 cache at least. +//! line. These lists are very likely to be found in L2 cache at least. //! //! There is some room for improvement. @@ -271,10 +271,10 @@ impl Liveness { self.worklist.push(ebb); } - // The worklist contains those EBBs where we have learned that the value needs to be + // The work list contains those EBBs where we have learned that the value needs to be // live-in. // - // This algorithm bcomes a depth-first traversal up the CFG, enumerating all paths through + // This algorithm becomes a depth-first traversal up the CFG, enumerating all paths through // the CFG from the existing live range to `ebb`. // // Extend the live range as we go. The live range itself also serves as a visited set since diff --git a/lib/cretonne/src/regalloc/liverange.rs b/lib/cretonne/src/regalloc/liverange.rs index 67667a3a47..c132a82478 100644 --- a/lib/cretonne/src/regalloc/liverange.rs +++ b/lib/cretonne/src/regalloc/liverange.rs @@ -45,13 +45,13 @@ //! handle *early clobbers* which are output registers that are not allowed to alias any input //! registers. //! -//! If i1 < i2 < i3 are program points, we have: +//! If `i1 < i2 < i3` are program points, we have: //! -//! - i1-i2 and i1-i3 interfere because the intervals overlap. -//! - i1-i2 and i2-i3 don't interfere. -//! - i1-i3 and i2-i2 do interfere because the dead def would clobber the register. -//! - i1-i2 and i2-i2 don't interfere. -//! - i2-i3 and i2-i2 do interfere. +//! - `i1-i2` and `i1-i3` interfere because the intervals overlap. +//! - `i1-i2` and `i2-i3` don't interfere. +//! - `i1-i3` and `i2-i2` do interfere because the dead def would clobber the register. +//! - `i1-i2` and `i2-i2` don't interfere. +//! - `i2-i3` and `i2-i2` do interfere. //! //! Because of this behavior around interval end points, live range interference is not completely //! equivalent to mathematical intersection of open or half-open intervals. @@ -415,7 +415,7 @@ mod tests { } } - // Singleton ProgramOrder for tests below. + // Singleton `ProgramOrder` for tests below. const PO: &'static ProgOrder = &ProgOrder {}; #[test] @@ -441,7 +441,7 @@ mod tests { assert!(lr.is_local()); assert_eq!(lr.def(), e2.into()); assert_eq!(lr.def_local_end(), e2.into()); - // The def interval of an EBB arg does not count as live-in. + // The def interval of an EBB argument does not count as live-in. assert_eq!(lr.livein_local_end(e2, PO), None); PO.validate(&lr); } @@ -478,8 +478,8 @@ mod tests { let i13 = Inst::new(13); let mut lr = LiveRange::new(v0, e10); - // Extending a dead EBB arg in its own block should not indicate that a live-in interval - // was created. + // Extending a dead EBB argument in its own block should not indicate that a live-in + // interval was created. assert_eq!(lr.extend_in_ebb(e10, i12, PO), false); PO.validate(&lr); assert!(!lr.is_dead()); diff --git a/lib/cretonne/src/sparse_map.rs b/lib/cretonne/src/sparse_map.rs index 48844c026a..3a1b4dbdb6 100644 --- a/lib/cretonne/src/sparse_map.rs +++ b/lib/cretonne/src/sparse_map.rs @@ -27,7 +27,7 @@ //! about creating new mappings to the default value. It doesn't distinguish clearly between an //! unmapped key and one that maps to the default value. `SparseMap` does not require `Default` //! values, and it tracks accurately if a key has been mapped or not. -//! - Iterating over the contants of an `EntityMap` is linear in the size of the *key space*, while +//! - Iterating over the contents of an `EntityMap` is linear in the size of the *key space*, while //! iterating over a `SparseMap` is linear in the number of elements in the mapping. This is an //! advantage precisely when the mapping is sparse. //! - `SparseMap::clear()` is constant time and super-fast. `EntityMap::clear()` is linear in the @@ -45,7 +45,7 @@ use std::u32; /// All values stored in a `SparseMap` must keep track of their own key in the map and implement /// this trait to provide access to the key. pub trait SparseMapValue { - /// Get the key of this sparse map value. This key is not alowed to change while the value + /// Get the key of this sparse map value. This key is not allowed to change while the value /// is a member of the map. fn key(&self) -> K; } diff --git a/lib/cretonne/src/verifier.rs b/lib/cretonne/src/verifier.rs index f0a4b66b32..0076933934 100644 --- a/lib/cretonne/src/verifier.rs +++ b/lib/cretonne/src/verifier.rs @@ -3,18 +3,18 @@ //! //! EBB integrity //! -//! - All instructions reached from the ebb_insts iterator must belong to -//! the EBB as reported by inst_ebb(). +//! - All instructions reached from the `ebb_insts` iterator must belong to +//! the EBB as reported by `inst_ebb()`. //! - Every EBB must end in a terminator instruction, and no other instruction //! can be a terminator. -//! - Every value in the ebb_args iterator belongs to the EBB as reported by value_ebb. +//! - Every value in the `ebb_args` iterator belongs to the EBB as reported by `value_ebb`. //! //! Instruction integrity //! //! - The instruction format must match the opcode. //! TODO: //! - All result values must be created for multi-valued instructions. -//! - Instructions with no results must have a VOID first_type(). +//! - Instructions with no results must have a VOID `first_type()`. //! - All referenced entities must exist. (Values, EBBs, stack slots, ...) //! //! SSA form @@ -33,7 +33,7 @@ //! - Compare input and output values against the opcode's type constraints. //! For polymorphic opcodes, determine the controlling type variable first. //! - Branches and jumps must pass arguments to destination EBBs that match the -//! expected types excatly. The number of arguments must match. +//! expected types exactly. The number of arguments must match. //! - All EBBs in a jump_table must take no arguments. //! - Function calls are type checked against their signature. //! - The entry block must take arguments that match the signature of the current @@ -44,10 +44,10 @@ //! Ad hoc checking //! //! - Stack slot loads and stores must be in-bounds. -//! - Immediate constraints for certain opcodes, like udiv_imm v3, 0. +//! - Immediate constraints for certain opcodes, like `udiv_imm v3, 0`. //! - Extend / truncate instructions have more type constraints: Source type can't be //! larger / smaller than result type. -//! - Insertlane and extractlane instructions have immediate lane numbers that must be in +//! - `Insertlane` and `extractlane` instructions have immediate lane numbers that must be in //! range for their polymorphic type. //! - Swizzle and shuffle instructions take a variable number of lane arguments. The number //! of arguments must match the destination type, and the lane indexes must be in range. @@ -76,7 +76,7 @@ impl Display for Error { /// Verifier result. pub type Result = result::Result; -// Create an `Err` variant of `Result` from a location and `format!` args. +// Create an `Err` variant of `Result` from a location and `format!` arguments. macro_rules! err { ( $loc:expr, $msg:expr ) => { Err(Error { diff --git a/lib/cretonne/src/write.rs b/lib/cretonne/src/write.rs index d8db064cd6..8dfe955e42 100644 --- a/lib/cretonne/src/write.rs +++ b/lib/cretonne/src/write.rs @@ -43,7 +43,8 @@ fn write_preamble(w: &mut Write, func: &Function) -> result::Result try!(writeln!(w, " {} = {}", ss, func.stack_slots[ss])); } - // Write out all signatures before functions since function decls can refer to signatures. + // Write out all signatures before functions since function declarations can refer to + // signatures. for sig in func.dfg.signatures.keys() { any = true; try!(writeln!(w, " {} = signature{}", sig, func.dfg.signatures[sig])); @@ -93,7 +94,7 @@ pub fn write_ebb_header(w: &mut Write, func: &Function, ebb: Ebb) -> Result { try!(write_arg(w, func, arg)); } } - // Remaining args. + // Remaining arguments. for arg in args { try!(write!(w, ", ")); try!(write_arg(w, func, arg));