Skip to content

Commit

Permalink
Integrate SPIR-T (replacing structurizer and shuffling passes around).
Browse files Browse the repository at this point in the history
  • Loading branch information
eddyb committed Dec 2, 2022
1 parent f8af5d1 commit d14d58e
Show file tree
Hide file tree
Showing 30 changed files with 247 additions and 125 deletions.
78 changes: 62 additions & 16 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/rustc_codegen_spirv/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ serde_json = "1.0"
smallvec = { version = "1.6.1", features = ["union"] }
spirv-tools = { version = "0.9", default-features = false }
rustc_codegen_spirv-types.workspace = true
spirt = { git = "https://github.com/EmbarkStudios/spirt.git" }

[dev-dependencies]
pipe = "0.4"
Expand Down
102 changes: 96 additions & 6 deletions crates/rustc_codegen_spirv/src/linker/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,10 +129,10 @@ pub fn link(sess: &Session, mut inputs: Vec<Module>, opts: &Options) -> Result<L
bound += module.header.as_ref().unwrap().bound - 1;
let this_version = module.header.as_ref().unwrap().version();
if version != this_version {
sess.fatal(format!(
return Err(sess.err(format!(
"cannot link two modules with different SPIR-V versions: v{}.{} and v{}.{}",
version.0, version.1, this_version.0, this_version.1
))
)));
}
}

Expand Down Expand Up @@ -221,25 +221,27 @@ pub fn link(sess: &Session, mut inputs: Vec<Module>, opts: &Options) -> Result<L
);
}

{
if false {
let _timer = sess.timer("link_inline");
inline::inline(sess, &mut output)?;
}

if opts.dce {
let _timer = sess.timer("link_dce");
let _timer = sess.timer("link_dce-early");
dce::dce(&mut output);
}

let mut output = if opts.structurize {
// FIXME(eddyb) remove this in favor of SPIR-T's?
let use_legacy_structurizer = false;
let mut output = if opts.structurize && use_legacy_structurizer {
let _timer = sess.timer("link_structurize");
structurizer::structurize(output)
} else {
output
};

{
let _timer = sess.timer("link_block_ordering_pass_and_mem2reg");
let _timer = sess.timer("link_block_ordering_pass_and_mem2reg-early");
let mut pointer_to_pointee = FxHashMap::default();
let mut constants = FxHashMap::default();
let mut u32 = None;
Expand Down Expand Up @@ -277,6 +279,94 @@ pub fn link(sess: &Session, mut inputs: Vec<Module>, opts: &Options) -> Result<L
}
}

if true {
let _timer = sess.timer("link_inline");
inline::inline(sess, &mut output)?;
}

if opts.dce {
let _timer = sess.timer("link_dce-late");
dce::dce(&mut output);
}

{
let _timer = sess.timer("link_block_ordering_pass_and_mem2reg-late");
let mut pointer_to_pointee = FxHashMap::default();
let mut constants = FxHashMap::default();
let mut u32 = None;
for inst in &output.types_global_values {
match inst.class.opcode {
Op::TypePointer => {
pointer_to_pointee
.insert(inst.result_id.unwrap(), inst.operands[1].unwrap_id_ref());
}
Op::TypeInt
if inst.operands[0].unwrap_literal_int32() == 32
&& inst.operands[1].unwrap_literal_int32() == 0 =>
{
assert!(u32.is_none());
u32 = Some(inst.result_id.unwrap());
}
Op::Constant if u32.is_some() && inst.result_type == u32 => {
let value = inst.operands[0].unwrap_literal_int32();
constants.insert(inst.result_id.unwrap(), value);
}
_ => {}
}
}
for func in &mut output.functions {
simple_passes::block_ordering_pass(func);
// Note: mem2reg requires functions to be in RPO order (i.e. block_ordering_pass)
mem2reg::mem2reg(
output.header.as_mut().unwrap(),
&mut output.types_global_values,
&pointer_to_pointee,
&constants,
func,
);
destructure_composites::destructure_composites(func);
}
}

{
let spv_bytes = {
let _timer = sess.timer("assemble-to-spv_bytes-for-spirt");
spirv_tools::binary::from_binary(&output.assemble()).to_vec()
};
let cx = std::rc::Rc::new(spirt::Context::new());
let mut module = {
let _timer = sess.timer("spirt::Module::lower_from_spv_file");
match spirt::Module::lower_from_spv_bytes(cx, spv_bytes) {
Ok(module) => module,
Err(e) => {
use rspirv::binary::Disassemble;

return Err(sess
.struct_err(format!("{e}"))
.note(format!(
"while lowering this SPIR-V module to SPIR-T:\n{}",
output.disassemble()
))
.emit());
}
}
};
if opts.structurize {
let _timer = sess.timer("spirt::legalize::structurize_func_cfgs");
spirt::passes::legalize::structurize_func_cfgs(&mut module);
}
let spv_words = {
let _timer = sess.timer("spirt::Module::lift_to_spv_module_emitter");
module.lift_to_spv_module_emitter().unwrap().words
};
output = {
let _timer = sess.timer("parse-spv_words-from-spirt");
let mut loader = Loader::new();
rspirv::binary::parse_words(&spv_words, &mut loader).unwrap();
loader.module()
};
}

{
let _timer = sess.timer("peephole_opts");
let types = peephole_opts::collect_types(&output);
Expand Down
24 changes: 12 additions & 12 deletions crates/rustc_codegen_spirv/src/linker/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -474,26 +474,26 @@ fn use_exported_func_param_attr() {

let result = assemble_and_link(&[&a, &b]).unwrap();

let expect = r#"OpCapability Kernel
OpCapability Linkage
let expect = r#"OpCapability Linkage
OpCapability Kernel
OpMemoryModel Logical OpenCL
OpDecorate %1 FuncParamAttr Zext
OpDecorate %2 LinkageAttributes "HACK(eddyb) keep function alive" Export
OpDecorate %3 LinkageAttributes "foo" Export
OpDecorate %4 FuncParamAttr Sext
OpDecorate %2 FuncParamAttr Sext
OpDecorate %3 LinkageAttributes "HACK(eddyb) keep function alive" Export
OpDecorate %4 LinkageAttributes "foo" Export
%5 = OpTypeVoid
%6 = OpTypeInt 32 0
%7 = OpTypeFunction %5 %6
%2 = OpFunction %5 None %7
%3 = OpFunction %5 None %7
%1 = OpFunctionParameter %6
%8 = OpLabel
%9 = OpLoad %6 %1
OpReturn
OpFunctionEnd
%3 = OpFunction %5 None %7
%4 = OpFunctionParameter %6
%4 = OpFunction %5 None %7
%2 = OpFunctionParameter %6
%10 = OpLabel
%11 = OpLoad %6 %4
%11 = OpLoad %6 %2
OpReturn
OpFunctionEnd"#;

Expand Down Expand Up @@ -553,16 +553,16 @@ fn names_and_decorations() {

let result = assemble_and_link(&[&a, &b]).unwrap();

let expect = r#"OpCapability Kernel
OpCapability Linkage
let expect = r#"OpCapability Linkage
OpCapability Kernel
OpMemoryModel Logical OpenCL
OpName %1 "foo"
OpName %2 "param"
OpDecorate %3 Restrict
OpDecorate %3 NonWritable
OpDecorate %2 Restrict
OpDecorate %4 LinkageAttributes "HACK(eddyb) keep function alive" Export
OpDecorate %1 LinkageAttributes "foo" Export
OpDecorate %2 Restrict
%5 = OpTypeVoid
%6 = OpTypeInt 32 0
%7 = OpTypePointer Function %6
Expand Down
11 changes: 5 additions & 6 deletions deny.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,10 @@
# https://embarkstudios.github.io/cargo-deny/checks/advisories/cfg.html
[advisories]
vulnerability = "deny"
# FIXME(eddyb) `ansi_term` and `xml-rs` prevent this from being `deny`.
unmaintained = "warn"
yanked = "warn"
notice = "warn"
ignore = [
# Regex advisory, from some dependency
"RUSTSEC-2022-0013"
]
yanked = "deny"
notice = "deny"

# This section is considered when running `cargo deny check bans`.
# More documentation about the 'bans' section can be found here:
Expand Down Expand Up @@ -60,6 +57,8 @@ allow = [
"ISC",

"Zlib",

"Unicode-DFS-2016",
]
# Allow 1 or more licenses on a per-crate basis, so that particular licenses
# aren't accepted for every possible crate as with the normal allow list
Expand Down
Loading

0 comments on commit d14d58e

Please sign in to comment.