Move generate_table from cranelift-codegen-shared to cranelift-codegen-meta
This commit is contained in:
64
cranelift/codegen/meta/src/constant_hash.rs
Normal file
64
cranelift/codegen/meta/src/constant_hash.rs
Normal file
@@ -0,0 +1,64 @@
|
||||
//! Build support for precomputed constant hash tables.
|
||||
//!
|
||||
//! This module can generate constant hash tables using open addressing and quadratic probing.
|
||||
//!
|
||||
//! The hash tables are arrays that are guaranteed to:
|
||||
//!
|
||||
//! - Have a power-of-two size.
|
||||
//! - Contain at least one empty slot.
|
||||
|
||||
use std::iter;
|
||||
|
||||
/// Compute an open addressed, quadratically probed hash table containing
|
||||
/// `items`. The returned table is a list containing the elements of the
|
||||
/// iterable `items` and `None` in unused slots.
|
||||
#[allow(clippy::float_arithmetic)]
|
||||
pub fn generate_table<'cont, T, I: iter::Iterator<Item = &'cont T>, H: Fn(&T) -> usize>(
|
||||
items: I,
|
||||
num_items: usize,
|
||||
hash_function: H,
|
||||
) -> Vec<Option<&'cont T>> {
|
||||
let size = (1.20 * num_items as f64) as usize;
|
||||
|
||||
// Probing code's stop condition relies on the table having one vacant entry at least.
|
||||
let size = if size.is_power_of_two() {
|
||||
size * 2
|
||||
} else {
|
||||
size.next_power_of_two()
|
||||
};
|
||||
|
||||
let mut table = vec![None; size];
|
||||
|
||||
for i in items {
|
||||
let mut h = hash_function(&i) % size;
|
||||
let mut s = 0;
|
||||
while table[h].is_some() {
|
||||
s += 1;
|
||||
h = (h + s) % size;
|
||||
}
|
||||
table[h] = Some(i);
|
||||
}
|
||||
|
||||
table
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::generate_table;
|
||||
use cranelift_codegen_shared::constant_hash::simple_hash;
|
||||
|
||||
#[test]
|
||||
fn test_generate_table() {
|
||||
let v = vec!["Hello".to_string(), "world".to_string()];
|
||||
let table = generate_table(v.iter(), v.len(), |s| simple_hash(&s));
|
||||
assert_eq!(
|
||||
table,
|
||||
vec![
|
||||
None,
|
||||
Some(&"Hello".to_string()),
|
||||
Some(&"world".to_string()),
|
||||
None
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -553,7 +553,8 @@ fn gen_opcodes(all_inst: &AllInstructions, fmt: &mut Formatter) {
|
||||
fmt.empty_line();
|
||||
|
||||
// Generate an opcode hash table for looking up opcodes by name.
|
||||
let hash_table = constant_hash::generate_table(all_inst.iter(), all_inst.len(), |inst| {
|
||||
let hash_table =
|
||||
crate::constant_hash::generate_table(all_inst.iter(), all_inst.len(), |inst| {
|
||||
constant_hash::simple_hash(&inst.name)
|
||||
});
|
||||
fmtln!(
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
//! Generate the ISA-specific settings.
|
||||
use std::collections::HashMap;
|
||||
|
||||
use cranelift_codegen_shared::constant_hash::{generate_table, simple_hash};
|
||||
use crate::constant_hash::generate_table;
|
||||
use cranelift_codegen_shared::constant_hash::simple_hash;
|
||||
|
||||
use crate::cdsl::camel_case;
|
||||
use crate::cdsl::settings::{
|
||||
|
||||
@@ -11,6 +11,7 @@ mod gen_inst;
|
||||
mod gen_settings;
|
||||
mod gen_types;
|
||||
|
||||
mod constant_hash;
|
||||
mod shared;
|
||||
mod unique_table;
|
||||
|
||||
|
||||
@@ -1,16 +1,4 @@
|
||||
//! Build support for precomputed constant hash tables.
|
||||
//!
|
||||
//! This module can generate constant hash tables using open addressing and quadratic probing.
|
||||
//!
|
||||
//! The hash tables are arrays that are guaranteed to:
|
||||
//!
|
||||
//! - Have a power-of-two size.
|
||||
//! - Contain at least one empty slot.
|
||||
//!
|
||||
//! This module provides build meta support for lookups in these tables, as well as the shared hash
|
||||
//! function used for probing.
|
||||
|
||||
use std::iter;
|
||||
//! This module provides a primitive hash function.
|
||||
|
||||
/// A primitive hash function for matching opcodes.
|
||||
pub fn simple_hash(s: &str) -> usize {
|
||||
@@ -21,61 +9,13 @@ pub fn simple_hash(s: &str) -> usize {
|
||||
h as usize
|
||||
}
|
||||
|
||||
/// Compute an open addressed, quadratically probed hash table containing
|
||||
/// `items`. The returned table is a list containing the elements of the
|
||||
/// iterable `items` and `None` in unused slots.
|
||||
#[allow(clippy::float_arithmetic)]
|
||||
pub fn generate_table<'cont, T, I: iter::Iterator<Item = &'cont T>, H: Fn(&T) -> usize>(
|
||||
items: I,
|
||||
num_items: usize,
|
||||
hash_function: H,
|
||||
) -> Vec<Option<&'cont T>> {
|
||||
let size = (1.20 * num_items as f64) as usize;
|
||||
|
||||
// Probing code's stop condition relies on the table having one vacant entry at least.
|
||||
let size = if size.is_power_of_two() {
|
||||
size * 2
|
||||
} else {
|
||||
size.next_power_of_two()
|
||||
};
|
||||
|
||||
let mut table = vec![None; size];
|
||||
|
||||
for i in items {
|
||||
let mut h = hash_function(&i) % size;
|
||||
let mut s = 0;
|
||||
while table[h].is_some() {
|
||||
s += 1;
|
||||
h = (h + s) % size;
|
||||
}
|
||||
table[h] = Some(i);
|
||||
}
|
||||
|
||||
table
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{generate_table, simple_hash};
|
||||
use super::simple_hash;
|
||||
|
||||
#[test]
|
||||
fn basic() {
|
||||
assert_eq!(simple_hash("Hello"), 0x2fa70c01);
|
||||
assert_eq!(simple_hash("world"), 0x5b0c31d5);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_generate_table() {
|
||||
let v = vec!["Hello".to_string(), "world".to_string()];
|
||||
let table = generate_table(v.iter(), v.len(), |s| simple_hash(&s));
|
||||
assert_eq!(
|
||||
table,
|
||||
vec![
|
||||
None,
|
||||
Some(&"Hello".to_string()),
|
||||
Some(&"world".to_string()),
|
||||
None
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user