Browse Source

Merge pull request #3480 from bjorn3/move_constant_hash_gen_table

Move generate_table from cranelift-codegen-shared to cranelift-codege…
pull/3491/head
Chris Fallin 3 years ago
committed by GitHub
parent
commit
e953c2dd4c
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 64
      cranelift/codegen/meta/src/constant_hash.rs
  2. 7
      cranelift/codegen/meta/src/gen_inst.rs
  3. 3
      cranelift/codegen/meta/src/gen_settings.rs
  4. 1
      cranelift/codegen/meta/src/lib.rs
  5. 64
      cranelift/codegen/shared/src/constant_hash.rs

64
cranelift/codegen/meta/src/constant_hash.rs

@ -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
]
);
}
}

7
cranelift/codegen/meta/src/gen_inst.rs

@ -553,9 +553,10 @@ 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| {
constant_hash::simple_hash(&inst.name)
});
let hash_table =
crate::constant_hash::generate_table(all_inst.iter(), all_inst.len(), |inst| {
constant_hash::simple_hash(&inst.name)
});
fmtln!(
fmt,
"const OPCODE_HASH_TABLE: [Option<Opcode>; {}] = [",

3
cranelift/codegen/meta/src/gen_settings.rs

@ -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::{

1
cranelift/codegen/meta/src/lib.rs

@ -11,6 +11,7 @@ mod gen_inst;
mod gen_settings;
mod gen_types;
mod constant_hash;
mod shared;
mod unique_table;

64
cranelift/codegen/shared/src/constant_hash.rs

@ -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
]
);
}
}

Loading…
Cancel
Save