rustc_codegen_spirv: use FxHash{Map,Set} instead of the std ones.

This commit is contained in:
Eduard-Mihai Burtescu 2021-04-08 14:23:57 +03:00 committed by Eduard-Mihai Burtescu
parent 98d7dec503
commit 8c89b49b66
19 changed files with 165 additions and 159 deletions

View File

@ -5,6 +5,7 @@ use crate::attr::{AggregatedSpirvAttributes, IntrinsicType};
use crate::codegen_cx::CodegenCx;
use crate::spirv_type::SpirvType;
use rspirv::spirv::{Capability, StorageClass, Word};
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::ErrorReported;
use rustc_middle::bug;
use rustc_middle::ty::layout::{FnAbiExt, TyAndLayout};
@ -18,7 +19,6 @@ use rustc_target::abi::{
};
use std::cell::RefCell;
use std::collections::hash_map::Entry;
use std::collections::HashMap;
use std::fmt;
/// If a struct contains a pointer to itself, even indirectly, then doing a naiive recursive walk
@ -28,7 +28,7 @@ use std::fmt;
/// tracking.
#[derive(Default)]
pub struct RecursivePointeeCache<'tcx> {
map: RefCell<HashMap<PointeeTy<'tcx>, PointeeDefState>>,
map: RefCell<FxHashMap<PointeeTy<'tcx>, PointeeDefState>>,
}
impl<'tcx> RecursivePointeeCache<'tcx> {

View File

@ -12,14 +12,14 @@ use rspirv::spirv::{
use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece};
use rustc_codegen_ssa::mir::place::PlaceRef;
use rustc_codegen_ssa::traits::{AsmBuilderMethods, InlineAsmOperandRef};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_hir::LlvmInlineAsmInner;
use rustc_middle::bug;
use rustc_span::source_map::Span;
use rustc_target::asm::{InlineAsmRegClass, InlineAsmRegOrRegClass, SpirVInlineAsmRegClass};
use std::collections::{HashMap, HashSet};
pub struct InstructionTable {
table: HashMap<&'static str, &'static rspirv::grammar::Instruction<'static>>,
table: FxHashMap<&'static str, &'static rspirv::grammar::Instruction<'static>>,
}
impl InstructionTable {
@ -133,9 +133,9 @@ impl<'a, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'tcx> {
}
}
let mut id_map = HashMap::new();
let mut defined_ids = HashSet::new();
let mut id_to_type_map = HashMap::new();
let mut id_map = FxHashMap::default();
let mut defined_ids = FxHashSet::default();
let mut id_to_type_map = FxHashMap::default();
for operand in operands {
if let InlineAsmOperandRef::In { reg: _, value } = operand {
let value = value.immediate();
@ -241,8 +241,8 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> {
fn insert_inst(
&mut self,
id_map: &mut HashMap<&str, Word>,
defined_ids: &mut HashSet<Word>,
id_map: &mut FxHashMap<&str, Word>,
defined_ids: &mut FxHashSet<Word>,
inst: dr::Instruction,
) {
// Types declared must be registered in our type system.
@ -339,9 +339,9 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> {
fn codegen_asm<'a>(
&mut self,
id_map: &mut HashMap<&'a str, Word>,
defined_ids: &mut HashSet<Word>,
id_to_type_map: &mut HashMap<Word, Word>,
id_map: &mut FxHashMap<&'a str, Word>,
defined_ids: &mut FxHashSet<Word>,
id_to_type_map: &mut FxHashMap<Word, Word>,
mut tokens: impl Iterator<Item = Token<'a, 'cx, 'tcx>>,
) where
'cx: 'a,
@ -433,8 +433,8 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> {
fn parse_operands<'a>(
&mut self,
id_map: &mut HashMap<&'a str, Word>,
id_to_type_map: &HashMap<Word, Word>,
id_map: &mut FxHashMap<&'a str, Word>,
id_to_type_map: &FxHashMap<Word, Word>,
mut tokens: impl Iterator<Item = Token<'a, 'cx, 'tcx>>,
instruction: &mut dr::Instruction,
) where
@ -537,7 +537,7 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> {
fn infer_result_type(
&self,
id_to_type_map: &HashMap<Word, Word>,
id_to_type_map: &FxHashMap<Word, Word>,
instruction: &dr::Instruction,
) -> Option<Word> {
use crate::spirv_type_constraints::{instruction_signatures, InstSig, TyListPat, TyPat};
@ -673,8 +673,8 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> {
fn parse_id_out<'a>(
&mut self,
id_map: &mut HashMap<&'a str, Word>,
defined_ids: &mut HashSet<Word>,
id_map: &mut FxHashMap<&'a str, Word>,
defined_ids: &mut FxHashSet<Word>,
token: Token<'a, 'cx, 'tcx>,
) -> Option<OutRegister<'a>> {
match token {
@ -762,7 +762,7 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> {
fn parse_id_in<'a>(
&mut self,
id_map: &mut HashMap<&'a str, Word>,
id_map: &mut FxHashMap<&'a str, Word>,
token: Token<'a, 'cx, 'tcx>,
) -> Option<Word> {
match token {
@ -904,7 +904,7 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> {
fn parse_one_operand<'a>(
&mut self,
id_map: &mut HashMap<&'a str, Word>,
id_map: &mut FxHashMap<&'a str, Word>,
inst: &mut dr::Instruction,
kind: OperandKind,
tokens: &mut impl Iterator<Item = Token<'a, 'cx, 'tcx>>,

View File

@ -7,6 +7,7 @@ use crate::spirv_type::SpirvType;
use rspirv::dr::Operand;
use rspirv::spirv::{Decoration, ExecutionModel, FunctionControl, StorageClass, Word};
use rustc_codegen_ssa::traits::{BaseTypeMethods, BuilderMethods};
use rustc_data_structures::fx::FxHashMap;
use rustc_hir as hir;
use rustc_middle::ty::layout::TyAndLayout;
use rustc_middle::ty::{Instance, Ty, TyKind};
@ -15,7 +16,6 @@ use rustc_target::abi::{
call::{ArgAbi, ArgAttribute, ArgAttributes, FnAbi, PassMode},
LayoutOf, Size,
};
use std::collections::HashMap;
impl<'tcx> CodegenCx<'tcx> {
// Entry points declare their "interface" (all uniforms, inputs, outputs, etc.) as parameters.
@ -132,7 +132,7 @@ impl<'tcx> CodegenCx<'tcx> {
let mut bx = Builder::new_block(self, stub_fn, "");
let mut call_args = vec![];
let mut decoration_locations = HashMap::new();
let mut decoration_locations = FxHashMap::default();
for (entry_arg_abi, hir_param) in arg_abis.iter().zip(hir_params) {
bx.set_span(hir_param.span);
self.declare_shader_interface_for_param(
@ -262,7 +262,7 @@ impl<'tcx> CodegenCx<'tcx> {
op_entry_point_interface_operands: &mut Vec<Word>,
bx: &mut Builder<'_, 'tcx>,
call_args: &mut Vec<SpirvValue>,
decoration_locations: &mut HashMap<StorageClass, u32>,
decoration_locations: &mut FxHashMap<StorageClass, u32>,
) {
let attrs = AggregatedSpirvAttributes::parse(self, self.tcx.hir().attrs(hir_param.hir_id));

View File

@ -30,7 +30,6 @@ use rustc_target::abi::call::FnAbi;
use rustc_target::abi::{HasDataLayout, TargetDataLayout};
use rustc_target::spec::{HasTargetSpec, Target};
use std::cell::{Cell, RefCell};
use std::collections::HashMap;
use std::iter::once;
use std::rc::Rc;
use std::str::FromStr;
@ -41,9 +40,9 @@ pub struct CodegenCx<'tcx> {
/// Spir-v module builder
pub builder: BuilderSpirv,
/// Map from MIR function to spir-v function ID
pub instances: RefCell<HashMap<Instance<'tcx>, SpirvValue>>,
pub instances: RefCell<FxHashMap<Instance<'tcx>, SpirvValue>>,
/// Map from function ID to parameter list
pub function_parameter_values: RefCell<HashMap<Word, Vec<SpirvValue>>>,
pub function_parameter_values: RefCell<FxHashMap<Word, Vec<SpirvValue>>>,
pub type_cache: TypeCache<'tcx>,
/// Cache generated vtables
pub vtables: RefCell<FxHashMap<(Ty<'tcx>, Option<PolyExistentialTraitRef<'tcx>>), SpirvValue>>,
@ -51,17 +50,17 @@ pub struct CodegenCx<'tcx> {
/// Invalid spir-v IDs that should be stripped from the final binary,
/// each with its own reason and span that should be used for reporting
/// (in the event that the value is actually needed)
zombie_decorations: RefCell<HashMap<Word, ZombieDecoration>>,
zombie_decorations: RefCell<FxHashMap<Word, ZombieDecoration>>,
/// Functions that have `#[spirv(unroll_loops)]`, and therefore should
/// get `LoopControl::UNROLL` applied to all of their loops' `OpLoopMerge`
/// instructions, during structuralization.
unroll_loops_decorations: RefCell<HashMap<Word, UnrollLoopsDecoration>>,
unroll_loops_decorations: RefCell<FxHashMap<Word, UnrollLoopsDecoration>>,
pub kernel_mode: bool,
/// Cache of all the builtin symbols we need
pub sym: Rc<Symbols>,
pub instruction_table: InstructionTable,
pub zombie_undefs_for_system_fn_addrs: RefCell<HashMap<Word, Word>>,
pub libm_intrinsics: RefCell<HashMap<Word, super::builder::libm_intrinsics::LibmIntrinsic>>,
pub zombie_undefs_for_system_fn_addrs: RefCell<FxHashMap<Word, Word>>,
pub libm_intrinsics: RefCell<FxHashMap<Word, super::builder::libm_intrinsics::LibmIntrinsic>>,
/// Simple `panic!("...")` and builtin panics (from MIR `Assert`s) call `#[lang = "panic"]`.
pub panic_fn_id: Cell<Option<Word>>,

View File

@ -2,6 +2,7 @@ use crate::{linker, SpirvCodegenBackend, SpirvModuleBuffer, SpirvThinBuffer};
use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule, ThinShared};
use rustc_codegen_ssa::back::write::CodegenContext;
use rustc_codegen_ssa::{CodegenResults, NativeLib};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::owning_ref::OwningRef;
use rustc_data_structures::rustc_erase_owner;
use rustc_data_structures::sync::MetadataRef;
@ -13,7 +14,6 @@ use rustc_session::config::{CrateType, DebugInfo, Lto, OptLevel, OutputFilenames
use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename};
use rustc_session::utils::NativeLibKind;
use rustc_session::Session;
use std::collections::{HashMap, HashSet};
use std::env;
use std::ffi::{CString, OsStr};
use std::fs::File;
@ -143,7 +143,7 @@ fn link_exe(
if !out_dir.is_dir() {
std::fs::create_dir_all(&out_dir).unwrap();
}
let mut hashmap = HashMap::new();
let mut hashmap = FxHashMap::default();
for (name, spv_binary) in map {
let mut module_filename = out_dir.clone();
module_filename.push(sanitize_filename::sanitize(&name));
@ -374,7 +374,7 @@ fn create_archive(files: &[&Path], metadata: &[u8], out_filename: &Path) {
header.set_cksum();
builder.append(&header, metadata).unwrap();
}
let mut filenames = HashSet::new();
let mut filenames = FxHashSet::default();
filenames.insert(OsStr::new(".metadata"));
for file in files {
assert!(

View File

@ -1,10 +1,10 @@
use rspirv::dr::{Instruction, Module};
use rspirv::spirv::{Capability, Op};
use std::collections::HashSet;
use rustc_data_structures::fx::FxHashSet;
pub fn remove_extra_capabilities(module: &mut Module) {
let used_capabilities = used_capabilities(module);
let removable_capabilities: HashSet<Capability> = [
let removable_capabilities: FxHashSet<Capability> = [
Capability::Int8,
Capability::Int16,
Capability::Int64,
@ -24,8 +24,8 @@ pub fn remove_extra_capabilities(module: &mut Module) {
remove_capabilities(module, &to_remove);
}
fn used_capabilities(module: &Module) -> HashSet<Capability> {
let mut set = HashSet::new();
fn used_capabilities(module: &Module) -> FxHashSet<Capability> {
let mut set = FxHashSet::default();
for inst in module.all_inst_iter() {
set.extend(inst.class.capabilities);
match inst.class.opcode {
@ -56,7 +56,7 @@ fn used_capabilities(module: &Module) -> HashSet<Capability> {
set
}
fn remove_capabilities(module: &mut Module, set: &HashSet<Capability>) {
fn remove_capabilities(module: &mut Module, set: &FxHashSet<Capability>) {
module.capabilities.retain(|inst| {
inst.class.opcode != Op::Capability || !set.contains(&inst.operands[0].unwrap_capability())
});
@ -87,7 +87,7 @@ fn additional_extensions(module: &Module, inst: &Instruction) -> &'static [&'sta
}
pub fn remove_extra_extensions(module: &mut Module) {
let set: HashSet<&str> = module
let set: FxHashSet<&str> = module
.all_inst_iter()
.flat_map(|inst| {
let extensions = inst.class.extensions.iter().copied();

View File

@ -9,7 +9,7 @@
use rspirv::dr::{Function, Instruction, Module};
use rspirv::spirv::{Op, Word};
use std::collections::HashSet;
use rustc_data_structures::fx::FxHashSet;
pub fn dce(module: &mut Module) {
let mut rooted = collect_roots(module);
@ -17,15 +17,15 @@ pub fn dce(module: &mut Module) {
kill_unrooted(module, &rooted);
}
pub fn collect_roots(module: &Module) -> HashSet<Word> {
let mut rooted = HashSet::new();
pub fn collect_roots(module: &Module) -> FxHashSet<Word> {
let mut rooted = FxHashSet::default();
for inst in &module.entry_points {
root(inst, &mut rooted);
}
rooted
}
fn spread_roots(module: &Module, rooted: &mut HashSet<Word>) -> bool {
fn spread_roots(module: &Module, rooted: &mut FxHashSet<Word>) -> bool {
let mut any = false;
for inst in module.global_inst_iter() {
if let Some(id) = inst.result_id {
@ -44,7 +44,7 @@ fn spread_roots(module: &Module, rooted: &mut HashSet<Word>) -> bool {
any
}
fn root(inst: &Instruction, rooted: &mut HashSet<Word>) -> bool {
fn root(inst: &Instruction, rooted: &mut FxHashSet<Word>) -> bool {
let mut any = false;
if let Some(id) = inst.result_type {
any |= rooted.insert(id);
@ -57,7 +57,7 @@ fn root(inst: &Instruction, rooted: &mut HashSet<Word>) -> bool {
any
}
fn is_rooted(inst: &Instruction, rooted: &HashSet<Word>) -> bool {
fn is_rooted(inst: &Instruction, rooted: &FxHashSet<Word>) -> bool {
if let Some(result_id) = inst.result_id {
rooted.contains(&result_id)
} else {
@ -69,7 +69,7 @@ fn is_rooted(inst: &Instruction, rooted: &HashSet<Word>) -> bool {
}
}
fn kill_unrooted(module: &mut Module, rooted: &HashSet<Word>) {
fn kill_unrooted(module: &mut Module, rooted: &FxHashSet<Word>) {
module
.ext_inst_imports
.retain(|inst| is_rooted(inst, rooted));
@ -87,7 +87,7 @@ fn kill_unrooted(module: &mut Module, rooted: &HashSet<Word>) {
}
pub fn dce_phi(func: &mut Function) {
let mut used = HashSet::new();
let mut used = FxHashSet::default();
loop {
let mut changed = false;
for inst in func.all_inst_iter() {

View File

@ -2,11 +2,12 @@ use crate::decorations::{CustomDecoration, ZombieDecoration};
use rspirv::binary::Assemble;
use rspirv::dr::{Instruction, Module, Operand};
use rspirv::spirv::{Op, Word};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_middle::bug;
use std::collections::{hash_map, HashMap, HashSet};
use std::collections::hash_map;
pub fn remove_duplicate_extensions(module: &mut Module) {
let mut set = HashSet::new();
let mut set = FxHashSet::default();
module.extensions.retain(|inst| {
inst.class.opcode != Op::Extension
@ -15,7 +16,7 @@ pub fn remove_duplicate_extensions(module: &mut Module) {
}
pub fn remove_duplicate_capablities(module: &mut Module) {
let mut set = HashSet::new();
let mut set = FxHashSet::default();
module.capabilities.retain(|inst| {
inst.class.opcode != Op::Capability || set.insert(inst.operands[0].unwrap_capability())
});
@ -23,8 +24,8 @@ pub fn remove_duplicate_capablities(module: &mut Module) {
pub fn remove_duplicate_ext_inst_imports(module: &mut Module) {
// This is a simpler version of remove_duplicate_types, see that for comments
let mut ext_to_id = HashMap::new();
let mut rewrite_rules = HashMap::new();
let mut ext_to_id = FxHashMap::default();
let mut rewrite_rules = FxHashMap::default();
// First deduplicate the imports
for inst in &mut module.ext_inst_imports {
@ -69,8 +70,8 @@ fn make_annotation_key(inst: &Instruction) -> Vec<u32> {
data
}
fn gather_annotations(annotations: &[Instruction]) -> HashMap<Word, Vec<u32>> {
let mut map = HashMap::new();
fn gather_annotations(annotations: &[Instruction]) -> FxHashMap<Word, Vec<u32>> {
let mut map = FxHashMap::default();
for inst in annotations {
if inst.class.opcode == Op::Decorate || inst.class.opcode == Op::MemberDecorate {
match map.entry(inst.operands[0].id_ref_any().unwrap()) {
@ -93,7 +94,7 @@ fn gather_annotations(annotations: &[Instruction]) -> HashMap<Word, Vec<u32>> {
.collect()
}
fn gather_names(debugs: &[Instruction]) -> HashMap<Word, String> {
fn gather_names(debugs: &[Instruction]) -> FxHashMap<Word, String> {
debugs
.iter()
.filter(|inst| inst.class.opcode == Op::Name)
@ -108,10 +109,10 @@ fn gather_names(debugs: &[Instruction]) -> HashMap<Word, String> {
fn make_dedupe_key(
inst: &Instruction,
unresolved_forward_pointers: &HashSet<Word>,
zombies: &HashSet<Word>,
annotations: &HashMap<Word, Vec<u32>>,
names: &HashMap<Word, String>,
unresolved_forward_pointers: &FxHashSet<Word>,
zombies: &FxHashSet<Word>,
annotations: &FxHashMap<Word, Vec<u32>>,
names: &FxHashMap<Word, String>,
) -> Vec<u32> {
let mut data = vec![inst.class.opcode as u32];
@ -168,7 +169,7 @@ fn make_dedupe_key(
data
}
fn rewrite_inst_with_rules(inst: &mut Instruction, rules: &HashMap<u32, u32>) {
fn rewrite_inst_with_rules(inst: &mut Instruction, rules: &FxHashMap<u32, u32>) {
if let Some(ref mut id) = inst.result_type {
// If the rewrite rules contain this ID, replace with the mapped value, otherwise don't touch it.
*id = rules.get(id).copied().unwrap_or(*id);
@ -184,18 +185,18 @@ pub fn remove_duplicate_types(module: &mut Module) {
// Keep in mind, this algorithm requires forward type references to not exist - i.e. it's a valid spir-v module.
// Include zombies in the key to not merge zombies with non-zombies
let zombies: HashSet<Word> = ZombieDecoration::decode_all(module)
let zombies: FxHashSet<Word> = ZombieDecoration::decode_all(module)
.map(|(z, _)| z)
.collect();
// When a duplicate type is encountered, then this is a map from the deleted ID, to the new, deduplicated ID.
let mut rewrite_rules = HashMap::new();
let mut rewrite_rules = FxHashMap::default();
// Instructions are encoded into "keys": their opcode, followed by arguments, then annotations.
// Importantly, result_id is left out. This means that any instruction that declares the same
// type, but with different result_id, will result in the same key.
let mut key_to_result_id = HashMap::new();
let mut key_to_result_id = FxHashMap::default();
// TODO: This is implementing forward pointers incorrectly.
let mut unresolved_forward_pointers = HashSet::new();
let mut unresolved_forward_pointers = FxHashSet::default();
// Collect a map from type ID to an annotation "key blob" (to append to the type key)
let annotations = gather_annotations(&module.annotations);
@ -262,12 +263,12 @@ pub fn remove_duplicate_types(module: &mut Module) {
// The same decorations for duplicated types will cause those different types to merge
// together. So, we need to deduplicate the annotations as well. (Note we *do* care about the
// ID of the type being applied to here, unlike `gather_annotations`)
let mut anno_set = HashSet::new();
let mut anno_set = FxHashSet::default();
module
.annotations
.retain(|inst| anno_set.insert(inst.assemble()));
// Same thing with OpName
let mut name_ids = HashSet::new();
let mut name_ids = FxHashSet::default();
module.debugs.retain(|inst| {
inst.class.opcode != Op::Name || name_ids.insert(inst.operands[0].unwrap_id_ref())
});

View File

@ -1,9 +1,9 @@
use super::Result;
use rspirv::dr::{Instruction, Module};
use rspirv::spirv::{Capability, Decoration, LinkageType, Op, Word};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::ErrorReported;
use rustc_session::Session;
use std::collections::{HashMap, HashSet};
pub fn run(sess: &Session, module: &mut Module) -> Result<()> {
let (rewrite_rules, killed_parameters) =
@ -17,15 +17,15 @@ pub fn run(sess: &Session, module: &mut Module) -> Result<()> {
fn find_import_export_pairs_and_killed_params(
sess: &Session,
module: &Module,
) -> Result<(HashMap<u32, u32>, HashSet<u32>)> {
) -> Result<(FxHashMap<u32, u32>, FxHashSet<u32>)> {
let type_map = get_type_map(module);
let fn_parameters = fn_parameters(module);
// Map from name -> (definition, type)
let mut exports = HashMap::new();
let mut exports = FxHashMap::default();
// Rules to rewrite the module with
let mut rewrite_rules = HashMap::new();
let mut killed_parameters = HashSet::new();
let mut rewrite_rules = FxHashMap::default();
let mut killed_parameters = FxHashSet::default();
// First, collect all the exports.
for annotation in &module.annotations {
@ -84,7 +84,7 @@ fn get_linkage_inst(inst: &Instruction) -> Option<(Word, &str, LinkageType)> {
}
}
fn get_type_map(module: &Module) -> HashMap<Word, Word> {
fn get_type_map(module: &Module) -> FxHashMap<Word, Word> {
let vars = module
.types_global_values
.iter()
@ -97,7 +97,7 @@ fn get_type_map(module: &Module) -> HashMap<Word, Word> {
vars.chain(fns).collect()
}
fn fn_parameters(module: &Module) -> HashMap<Word, Vec<Word>> {
fn fn_parameters(module: &Module) -> FxHashMap<Word, Vec<Word>> {
module
.functions
.iter()
@ -117,7 +117,7 @@ fn check_tys_equal(sess: &Session, name: &str, import_type: Word, export_type: W
}
}
fn replace_all_uses_with(module: &mut Module, rules: &HashMap<u32, u32>) {
fn replace_all_uses_with(module: &mut Module, rules: &FxHashMap<u32, u32>) {
module.all_inst_iter_mut().for_each(|inst| {
if let Some(ref mut result_type) = &mut inst.result_type {
if let Some(&rewrite) = rules.get(result_type) {
@ -135,7 +135,7 @@ fn replace_all_uses_with(module: &mut Module, rules: &HashMap<u32, u32>) {
});
}
fn kill_linkage_instructions(module: &mut Module, rewrite_rules: &HashMap<u32, u32>) {
fn kill_linkage_instructions(module: &mut Module, rewrite_rules: &FxHashMap<u32, u32>) {
// drop imported functions
module
.functions
@ -161,8 +161,8 @@ fn kill_linkage_instructions(module: &mut Module, rewrite_rules: &HashMap<u32, u
fn import_kill_annotations_and_debug(
module: &mut Module,
rewrite_rules: &HashMap<u32, u32>,
killed_parameters: &HashSet<u32>,
rewrite_rules: &FxHashMap<u32, u32>,
killed_parameters: &FxHashSet<u32>,
) {
module.annotations.retain(|inst| {
inst.operands.is_empty()

View File

@ -8,10 +8,10 @@ use super::apply_rewrite_rules;
use super::simple_passes::outgoing_edges;
use rspirv::dr::{Block, Function, Instruction, Module, ModuleHeader, Operand};
use rspirv::spirv::{FunctionControl, Op, StorageClass, Word};
use std::collections::{HashMap, HashSet};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use std::mem::replace;
type FunctionMap = HashMap<Word, Function>;
type FunctionMap = FxHashMap<Word, Function>;
pub fn inline(module: &mut Module) {
let functions = module
@ -28,7 +28,7 @@ pub fn inline(module: &mut Module) {
.unwrap_or(0);
// Drop all the functions we'll be inlining. (This also means we won't waste time processing
// inlines in functions that will get inlined)
let mut dropped_ids = HashSet::new();
let mut dropped_ids = FxHashSet::default();
module.functions.retain(|f| {
if should_inline(&disallowed_argument_types, f) {
// TODO: We should insert all defined IDs in this function.
@ -58,7 +58,7 @@ pub fn inline(module: &mut Module) {
}
}
fn compute_disallowed_argument_types(module: &Module) -> HashSet<Word> {
fn compute_disallowed_argument_types(module: &Module) -> FxHashSet<Word> {
let allowed_argument_storage_classes = &[
StorageClass::UniformConstant,
StorageClass::Function,
@ -67,8 +67,8 @@ fn compute_disallowed_argument_types(module: &Module) -> HashSet<Word> {
StorageClass::AtomicCounter,
// TODO: StorageBuffer is allowed if VariablePointers is enabled
];
let mut disallowed_argument_types = HashSet::new();
let mut disallowed_pointees = HashSet::new();
let mut disallowed_argument_types = FxHashSet::default();
let mut disallowed_pointees = FxHashSet::default();
for inst in &module.types_global_values {
match inst.class.opcode {
Op::TypePointer => {
@ -115,7 +115,7 @@ fn compute_disallowed_argument_types(module: &Module) -> HashSet<Word> {
disallowed_argument_types
}
fn should_inline(disallowed_argument_types: &HashSet<Word>, function: &Function) -> bool {
fn should_inline(disallowed_argument_types: &FxHashSet<Word>, function: &Function) -> bool {
let def = function.def.as_ref().unwrap();
let control = def.operands[0].unwrap_function_control();
control.contains(FunctionControl::INLINE)
@ -136,8 +136,8 @@ struct Inliner<'m, 'map> {
types_global_values: &'m mut Vec<Instruction>,
void: Word,
functions: &'map FunctionMap,
disallowed_argument_types: &'map HashSet<Word>,
// rewrite_rules: HashMap<Word, Word>,
disallowed_argument_types: &'map FxHashSet<Word>,
// rewrite_rules: FxHashMap<Word, Word>,
}
impl Inliner<'_, '_> {
@ -298,7 +298,7 @@ impl Inliner<'_, '_> {
true
}
fn add_clone_id_rules(&mut self, rewrite_rules: &mut HashMap<Word, Word>, blocks: &[Block]) {
fn add_clone_id_rules(&mut self, rewrite_rules: &mut FxHashMap<Word, Word>, blocks: &[Block]) {
for block in blocks {
for inst in block.label.iter().chain(&block.instructions) {
if let Some(result_id) = inst.result_id {

View File

@ -13,13 +13,14 @@ use super::simple_passes::outgoing_edges;
use super::{apply_rewrite_rules, id};
use rspirv::dr::{Block, Function, Instruction, ModuleHeader, Operand};
use rspirv::spirv::{Op, Word};
use std::collections::{hash_map, HashMap, HashSet};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use std::collections::hash_map;
pub fn mem2reg(
header: &mut ModuleHeader,
types_global_values: &mut Vec<Instruction>,
pointer_to_pointee: &HashMap<Word, Word>,
constants: &HashMap<Word, u32>,
pointer_to_pointee: &FxHashMap<Word, Word>,
constants: &FxHashMap<Word, u32>,
func: &mut Function,
) {
let reachable = compute_reachable(&func.blocks);
@ -124,9 +125,12 @@ fn compute_idom(preds: &[Vec<usize>], reachable_blocks: &[bool]) -> Vec<Option<u
}
// Same paper as above
fn compute_dominance_frontier(preds: &[Vec<usize>], idom: &[Option<usize>]) -> Vec<HashSet<usize>> {
fn compute_dominance_frontier(
preds: &[Vec<usize>],
idom: &[Option<usize>],
) -> Vec<FxHashSet<usize>> {
assert_eq!(preds.len(), idom.len());
let mut dominance_frontier = vec![HashSet::new(); preds.len()];
let mut dominance_frontier = vec![FxHashSet::default(); preds.len()];
for node in 0..preds.len() {
if preds[node].len() >= 2 {
let node_idom = idom[node].unwrap();
@ -145,10 +149,10 @@ fn compute_dominance_frontier(preds: &[Vec<usize>], idom: &[Option<usize>]) -> V
fn insert_phis_all(
header: &mut ModuleHeader,
types_global_values: &mut Vec<Instruction>,
pointer_to_pointee: &HashMap<Word, Word>,
constants: &HashMap<Word, u32>,
pointer_to_pointee: &FxHashMap<Word, Word>,
constants: &FxHashMap<Word, u32>,
blocks: &mut [Block],
dominance_frontier: Vec<HashSet<usize>>,
dominance_frontier: Vec<FxHashSet<usize>>,
) {
let thing = blocks[0]
.instructions
@ -172,10 +176,10 @@ fn insert_phis_all(
blocks_with_phi,
base_var_type,
var_map,
phi_defs: HashSet::new(),
visited: HashSet::new(),
phi_defs: FxHashSet::default(),
visited: FxHashSet::default(),
stack: Vec::new(),
rewrite_rules: HashMap::new(),
rewrite_rules: FxHashMap::default(),
};
renamer.rename(0, None);
apply_rewrite_rules(&renamer.rewrite_rules, blocks);
@ -193,15 +197,15 @@ struct VarInfo {
}
fn collect_access_chains(
pointer_to_pointee: &HashMap<Word, Word>,
constants: &HashMap<Word, u32>,
pointer_to_pointee: &FxHashMap<Word, Word>,
constants: &FxHashMap<Word, u32>,
blocks: &[Block],
base_var: Word,
base_var_ty: Word,
) -> Option<HashMap<Word, VarInfo>> {
) -> Option<FxHashMap<Word, VarInfo>> {
fn construct_access_chain_info(
pointer_to_pointee: &HashMap<Word, Word>,
constants: &HashMap<Word, u32>,
pointer_to_pointee: &FxHashMap<Word, Word>,
constants: &FxHashMap<Word, u32>,
inst: &Instruction,
base: &VarInfo,
) -> Option<VarInfo> {
@ -217,7 +221,7 @@ fn collect_access_chains(
})
}
let mut variables = HashMap::new();
let mut variables = FxHashMap::default();
variables.insert(
base_var,
VarInfo {
@ -262,7 +266,7 @@ fn collect_access_chains(
Some(variables)
}
fn has_store(block: &Block, var_map: &HashMap<Word, VarInfo>) -> bool {
fn has_store(block: &Block, var_map: &FxHashMap<Word, VarInfo>) -> bool {
block.instructions.iter().any(|inst| {
let ptr = match inst.class.opcode {
Op::Store => inst.operands[0].id_ref_any().unwrap(),
@ -276,14 +280,14 @@ fn has_store(block: &Block, var_map: &HashMap<Word, VarInfo>) -> bool {
fn insert_phis(
blocks: &[Block],
dominance_frontier: &[HashSet<usize>],
var_map: &HashMap<Word, VarInfo>,
) -> HashSet<usize> {
dominance_frontier: &[FxHashSet<usize>],
var_map: &FxHashMap<Word, VarInfo>,
) -> FxHashSet<usize> {
// TODO: Some algorithms check if the var is trivial in some way, e.g. all loads and stores are
// in a single block. We should probably do that too.
let mut ever_on_work_list = HashSet::new();
let mut ever_on_work_list = FxHashSet::default();
let mut work_list = Vec::new();
let mut blocks_with_phi = HashSet::new();
let mut blocks_with_phi = FxHashSet::default();
for (block_idx, block) in blocks.iter().enumerate() {
if has_store(block, var_map) {
ever_on_work_list.insert(block_idx);
@ -333,13 +337,13 @@ struct Renamer<'a> {
header: &'a mut ModuleHeader,
types_global_values: &'a mut Vec<Instruction>,
blocks: &'a mut [Block],
blocks_with_phi: HashSet<usize>,
blocks_with_phi: FxHashSet<usize>,
base_var_type: Word,
var_map: &'a HashMap<Word, VarInfo>,
phi_defs: HashSet<Word>,
visited: HashSet<usize>,
var_map: &'a FxHashMap<Word, VarInfo>,
phi_defs: FxHashSet<Word>,
visited: FxHashSet<usize>,
stack: Vec<Word>,
rewrite_rules: HashMap<Word, Word>,
rewrite_rules: FxHashMap<Word, Word>,
}
impl Renamer<'_> {
@ -484,7 +488,7 @@ fn remove_nops(blocks: &mut [Block]) {
}
}
fn remove_old_variables(blocks: &mut [Block], thing: &[(HashMap<u32, VarInfo>, u32)]) {
fn remove_old_variables(blocks: &mut [Block], thing: &[(FxHashMap<u32, VarInfo>, u32)]) {
blocks[0].instructions.retain(|inst| {
inst.class.opcode != Op::Variable || {
let result_id = inst.result_id.unwrap();

View File

@ -17,9 +17,9 @@ use crate::decorations::{CustomDecoration, UnrollLoopsDecoration};
use rspirv::binary::Consumer;
use rspirv::dr::{Block, Instruction, Loader, Module, ModuleHeader, Operand};
use rspirv::spirv::{Op, StorageClass, Word};
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::ErrorReported;
use rustc_session::Session;
use std::collections::HashMap;
pub type Result<T> = std::result::Result<T, ErrorReported>;
@ -35,7 +35,7 @@ pub struct Options {
pub enum LinkResult {
SingleModule(Module),
MultipleModules(HashMap<String, Module>),
MultipleModules(FxHashMap<String, Module>),
}
fn id(header: &mut ModuleHeader) -> Word {
@ -44,7 +44,7 @@ fn id(header: &mut ModuleHeader) -> Word {
result
}
fn apply_rewrite_rules(rewrite_rules: &HashMap<Word, Word>, blocks: &mut [Block]) {
fn apply_rewrite_rules(rewrite_rules: &FxHashMap<Word, Word>, blocks: &mut [Block]) {
let apply = |inst: &mut Instruction| {
if let Some(ref mut id) = &mut inst.result_id {
if let Some(&rewrite) = rewrite_rules.get(id) {
@ -185,7 +185,7 @@ pub fn link(sess: &Session, mut inputs: Vec<Module>, opts: &Options) -> Result<L
let unroll_loops_decorations = UnrollLoopsDecoration::decode_all(&output)
.map(|(id, unroll_loops)| (id, unroll_loops.deserialize()))
.collect::<HashMap<_, _>>();
.collect::<FxHashMap<_, _>>();
UnrollLoopsDecoration::remove_all(&mut output);
let mut output = if opts.structurize {
@ -201,8 +201,8 @@ pub fn link(sess: &Session, mut inputs: Vec<Module>, opts: &Options) -> Result<L
{
let _timer = sess.timer("link_block_ordering_pass_and_mem2reg");
let mut pointer_to_pointee = HashMap::new();
let mut constants = HashMap::new();
let mut pointer_to_pointee = FxHashMap::default();
let mut constants = FxHashMap::default();
if opts.mem2reg {
let mut u32 = None;
for inst in &output.types_global_values {

View File

@ -2,7 +2,7 @@ use crate::decorations::UnrollLoopsDecoration;
use indexmap::{indexmap, IndexMap};
use rspirv::dr::{Block, Builder, Function, InsertPoint, Module, Operand};
use rspirv::spirv::{LoopControl, Op, SelectionControl, Word};
use std::collections::HashMap;
use rustc_data_structures::fx::FxHashMap;
use std::{iter, mem};
/// Cached IDs of `OpTypeBool`, `OpConstantFalse`, and `OpConstantTrue`.
@ -40,7 +40,7 @@ impl FuncBuilder<'_> {
pub fn structurize(
module: Module,
unroll_loops_decorations: HashMap<Word, UnrollLoopsDecoration>,
unroll_loops_decorations: FxHashMap<Word, UnrollLoopsDecoration>,
) -> Module {
let mut builder = Builder::new_from_module(module);
@ -100,7 +100,7 @@ pub fn structurize(
block_id_to_idx,
loop_control,
incoming_edge_count: vec![],
regions: HashMap::new(),
regions: FxHashMap::default(),
}
.structurize_func();
}
@ -140,7 +140,7 @@ struct Structurizer<'a> {
globals: Globals,
func: FuncBuilder<'a>,
block_id_to_idx: HashMap<BlockId, BlockIdx>,
block_id_to_idx: FxHashMap<BlockId, BlockIdx>,
/// `LoopControl` to use in all loops' `OpLoopMerge` instruction.
/// Currently only affected by function-scoped `#[spirv(unroll_loops)]`.
@ -151,7 +151,7 @@ struct Structurizer<'a> {
/// (backedge count is subtracted to hide them from outer regions).
incoming_edge_count: Vec<usize>,
regions: HashMap<BlockIdx, Region>,
regions: FxHashMap<BlockIdx, Region>,
}
impl Structurizer<'_> {

View File

@ -1,6 +1,6 @@
use rspirv::dr::{Block, Function, Module};
use rspirv::spirv::{Op, Word};
use std::collections::{HashMap, HashSet};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use std::mem::replace;
pub fn shift_ids(module: &mut Module, add: u32) {
@ -31,7 +31,7 @@ pub fn block_ordering_pass(func: &mut Function) {
}
fn visit_postorder(
func: &Function,
visited: &mut HashSet<Word>,
visited: &mut FxHashSet<Word>,
postorder: &mut Vec<Word>,
current: Word,
) {
@ -60,7 +60,7 @@ pub fn block_ordering_pass(func: &mut Function) {
postorder.push(current);
}
let mut visited = HashSet::new();
let mut visited = FxHashSet::default();
let mut postorder = Vec::new();
let entry_label = func.blocks[0].label_id().unwrap();
@ -93,7 +93,7 @@ pub fn outgoing_edges(block: &Block) -> impl Iterator<Item = Word> + '_ {
}
pub fn compact_ids(module: &mut Module) -> u32 {
let mut remap = HashMap::new();
let mut remap = FxHashMap::default();
let mut insert = |current_id: u32| -> u32 {
let len = remap.len();

View File

@ -54,8 +54,9 @@ use indexmap::{IndexMap, IndexSet};
use rspirv::dr::{Builder, Function, Instruction, Module, Operand};
use rspirv::spirv::{Op, StorageClass, Word};
use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use smallvec::SmallVec;
use std::collections::{BTreeMap, HashMap, HashSet, VecDeque};
use std::collections::{BTreeMap, VecDeque};
use std::convert::{TryFrom, TryInto};
use std::ops::{Range, RangeTo};
use std::{fmt, io, iter, mem, slice};
@ -109,7 +110,7 @@ pub fn specialize(module: Module, specialization: impl Specialization) -> Module
let debug = std::env::var("SPECIALIZER_DEBUG").is_ok();
let dump_instances = std::env::var("SPECIALIZER_DUMP_INSTANCES").ok();
let mut debug_names = HashMap::new();
let mut debug_names = FxHashMap::default();
if debug || dump_instances.is_some() {
debug_names = module
.debugs
@ -131,7 +132,7 @@ pub fn specialize(module: Module, specialization: impl Specialization) -> Module
debug_names,
generics: IndexMap::new(),
int_consts: HashMap::new(),
int_consts: FxHashMap::default(),
};
specializer.collect_generics(&module);
@ -197,7 +198,7 @@ struct CallGraph {
impl CallGraph {
fn collect(module: &Module) -> Self {
let func_id_to_idx: HashMap<_, _> = module
let func_id_to_idx: FxHashMap<_, _> = module
.functions
.iter()
.enumerate()
@ -579,14 +580,14 @@ struct Specializer<S: Specialization> {
debug: bool,
// HACK(eddyb) if debugging is requested, this is used to quickly get `OpName`s.
debug_names: HashMap<Word, String>,
debug_names: FxHashMap<Word, String>,
// FIXME(eddyb) compact SPIR-V IDs to allow flatter maps.
generics: IndexMap<Word, Generic>,
/// Integer `OpConstant`s (i.e. containing a `LiteralInt32`), to be used
/// for interpreting `TyPat::IndexComposite` (such as for `OpAccessChain`).
int_consts: HashMap<Word, u32>,
int_consts: FxHashMap<Word, u32>,
}
impl<S: Specialization> Specializer<S> {
@ -616,7 +617,7 @@ impl<S: Specialization> Specializer<S> {
.iter()
.chain(module.functions.iter().filter_map(|f| f.def.as_ref()));
let mut forward_declared_pointers = HashSet::new();
let mut forward_declared_pointers = FxHashSet::default();
for inst in types_global_values_and_functions {
let result_id = inst.result_id.unwrap_or_else(|| {
unreachable!(
@ -2478,7 +2479,7 @@ impl<'a, S: Specialization> Expander<'a, S> {
if newly_expanded_functions.len() > 1 {
// NOTE(eddyb) this is defined outside the loop to avoid
// allocating it for every expanded copy of the function.
let mut rewrite_rules = HashMap::new();
let mut rewrite_rules = FxHashMap::default();
for func in newly_expanded_functions {
rewrite_rules.extend(func.parameters.iter_mut().map(|param| {

View File

@ -7,8 +7,9 @@ use rspirv::{
dr::{Block, Builder, InsertPoint, Module, Operand},
spirv::LoopControl,
};
use rustc_data_structures::fx::FxHashMap;
use rustc_session::Session;
use std::collections::{HashMap, VecDeque};
use std::collections::VecDeque;
pub struct LoopInfo {
merge_id: Word,
@ -127,7 +128,7 @@ impl ControlFlowInfo {
pub fn structurize(
sess: &Session,
module: Module,
unroll_loops_decorations: HashMap<Word, UnrollLoopsDecoration>,
unroll_loops_decorations: FxHashMap<Word, UnrollLoopsDecoration>,
) -> Module {
let mut builder = Builder::new_from_module(module);
@ -686,7 +687,7 @@ pub fn insert_selection_merge_on_conditional_branch(
}
}
let mut modified_ids = HashMap::new();
let mut modified_ids = FxHashMap::default();
// Find convergence point.
for id in branch_conditional_ops.iter() {
@ -798,7 +799,7 @@ pub fn insert_loop_merge_on_conditional_branch(
}
}
}
let mut modified_ids = HashMap::new();
let mut modified_ids = FxHashMap::default();
// Figure out which branch loops and which branch should merge, also find any potential break ops.
for (id, looping_branch_idx) in branch_conditional_ops.iter() {

View File

@ -3,9 +3,9 @@
use crate::decorations::{CustomDecoration, ZombieDecoration};
use rspirv::dr::{Instruction, Module};
use rspirv::spirv::{Op, Word};
use rustc_data_structures::fx::FxHashMap;
use rustc_session::Session;
use rustc_span::{Span, DUMMY_SP};
use std::collections::HashMap;
use std::env;
use std::iter::once;
@ -35,7 +35,7 @@ impl<'a> ZombieInfo<'a> {
fn contains_zombie<'h, 'a>(
inst: &Instruction,
zombie: &'h HashMap<Word, ZombieInfo<'a>>,
zombie: &'h FxHashMap<Word, ZombieInfo<'a>>,
) -> Option<&'h ZombieInfo<'a>> {
if let Some(result_type) = inst.result_type {
if let Some(reason) = zombie.get(&result_type) {
@ -49,7 +49,7 @@ fn contains_zombie<'h, 'a>(
fn is_zombie<'h, 'a>(
inst: &Instruction,
zombie: &'h HashMap<Word, ZombieInfo<'a>>,
zombie: &'h FxHashMap<Word, ZombieInfo<'a>>,
) -> Option<&'h ZombieInfo<'a>> {
if let Some(result_id) = inst.result_id {
zombie.get(&result_id)
@ -60,13 +60,13 @@ fn is_zombie<'h, 'a>(
fn is_or_contains_zombie<'h, 'a>(
inst: &Instruction,
zombie: &'h HashMap<Word, ZombieInfo<'a>>,
zombie: &'h FxHashMap<Word, ZombieInfo<'a>>,
) -> Option<&'h ZombieInfo<'a>> {
let result_zombie = inst.result_id.and_then(|result_id| zombie.get(&result_id));
result_zombie.or_else(|| contains_zombie(inst, zombie))
}
fn spread_zombie(module: &mut Module, zombie: &mut HashMap<Word, ZombieInfo<'_>>) -> bool {
fn spread_zombie(module: &mut Module, zombie: &mut FxHashMap<Word, ZombieInfo<'_>>) -> bool {
let mut any = false;
// globals are easy
for inst in module.global_inst_iter() {
@ -103,7 +103,7 @@ fn spread_zombie(module: &mut Module, zombie: &mut HashMap<Word, ZombieInfo<'_>>
any
}
fn get_names(module: &Module) -> HashMap<Word, &str> {
fn get_names(module: &Module) -> FxHashMap<Word, &str> {
module
.debugs
.iter()
@ -120,7 +120,7 @@ fn get_names(module: &Module) -> HashMap<Word, &str> {
// If an entry point references a zombie'd value, then the entry point would normally get removed.
// That's an absolutely horrible experience to debug, though, so instead, create a nice error
// message containing the stack trace of how the entry point got to the zombie value.
fn report_error_zombies(sess: &Session, module: &Module, zombie: &HashMap<Word, ZombieInfo<'_>>) {
fn report_error_zombies(sess: &Session, module: &Module, zombie: &FxHashMap<Word, ZombieInfo<'_>>) {
let mut names = None;
for root in super::dce::collect_roots(module) {
if let Some(reason) = zombie.get(&root) {

View File

@ -7,11 +7,11 @@ use rspirv::dr::Operand;
use rspirv::spirv::{
AccessQualifier, Capability, Decoration, Dim, ImageFormat, StorageClass, Word,
};
use rustc_data_structures::fx::FxHashMap;
use rustc_span::def_id::DefId;
use rustc_span::Span;
use rustc_target::abi::{Align, Size};
use std::cell::RefCell;
use std::collections::HashMap;
use std::fmt;
use std::iter;
use std::lazy::SyncLazy;
@ -690,7 +690,7 @@ pub struct TypeCache<'tcx> {
/// Set of names for a type (only `SpirvType::Adt` currently).
/// The same `OpType*` may have multiple names if it's e.g. a generic
/// `struct` where the generic parameters result in the same field types.
type_names: RefCell<HashMap<Word, IndexSet<TyLayoutNameKey<'tcx>>>>,
type_names: RefCell<FxHashMap<Word, IndexSet<TyLayoutNameKey<'tcx>>>>,
}
impl TypeCache<'_> {

View File

@ -2,9 +2,9 @@ use crate::attr::{Entry, ExecutionModeExtra, IntrinsicType, SpirvAttribute};
use crate::builder::libm_intrinsics;
use rspirv::spirv::{BuiltIn, ExecutionMode, ExecutionModel, StorageClass};
use rustc_ast::ast::{AttrKind, Attribute, Lit, LitIntType, LitKind, NestedMetaItem};
use rustc_data_structures::fx::FxHashMap;
use rustc_span::symbol::{Ident, Symbol};
use rustc_span::Span;
use std::collections::HashMap;
use std::rc::Rc;
/// Various places in the codebase (mostly attribute parsing) need to compare rustc Symbols to particular keywords.
@ -41,9 +41,9 @@ pub struct Symbols {
sampled: Symbol,
image_format: Symbol,
access_qualifier: Symbol,
attributes: HashMap<Symbol, SpirvAttribute>,
execution_modes: HashMap<Symbol, (ExecutionMode, ExecutionModeExtraDim)>,
pub libm_intrinsics: HashMap<Symbol, libm_intrinsics::LibmIntrinsic>,
attributes: FxHashMap<Symbol, SpirvAttribute>,
execution_modes: FxHashMap<Symbol, (ExecutionMode, ExecutionModeExtraDim)>,
pub libm_intrinsics: FxHashMap<Symbol, libm_intrinsics::LibmIntrinsic>,
}
const BUILTINS: &[(&str, BuiltIn)] = {
@ -350,20 +350,20 @@ impl Symbols {
.chain(execution_models)
.chain(custom_attributes)
.map(|(a, b)| (Symbol::intern(a), b));
let mut attributes = HashMap::new();
let mut attributes = FxHashMap::default();
for (a, b) in attributes_iter {
let old = attributes.insert(a, b);
// `.collect()` into a HashMap does not error on duplicates, so manually write out the
// `.collect()` into a FxHashMap does not error on duplicates, so manually write out the
// loop here to error on duplicates.
assert!(old.is_none());
}
let mut execution_modes = HashMap::new();
let mut execution_modes = FxHashMap::default();
for &(key, mode, dim) in EXECUTION_MODES {
let old = execution_modes.insert(Symbol::intern(key), (mode, dim));
assert!(old.is_none());
}
let mut libm_intrinsics = HashMap::new();
let mut libm_intrinsics = FxHashMap::default();
for &(a, b) in libm_intrinsics::TABLE {
let old = libm_intrinsics.insert(Symbol::intern(a), b);
assert!(old.is_none());