mirror of
https://github.com/EmbarkStudios/rust-gpu.git
synced 2024-11-21 22:34:34 +00:00
rustc_codegen_spirv: use FxHash{Map,Set}
instead of the std ones.
This commit is contained in:
parent
98d7dec503
commit
8c89b49b66
@ -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> {
|
||||
|
@ -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>>,
|
||||
|
@ -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));
|
||||
|
||||
|
@ -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>>,
|
||||
|
@ -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!(
|
||||
|
@ -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();
|
||||
|
@ -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() {
|
||||
|
@ -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())
|
||||
});
|
||||
|
@ -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()
|
||||
|
@ -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 {
|
||||
|
@ -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();
|
||||
|
@ -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 {
|
||||
|
@ -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<'_> {
|
||||
|
@ -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();
|
||||
|
@ -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| {
|
||||
|
@ -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() {
|
||||
|
@ -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) {
|
||||
|
@ -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<'_> {
|
||||
|
@ -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());
|
||||
|
Loading…
Reference in New Issue
Block a user