EmbarkStudios/spirt

Bring many basic types/insts into SPIR-T (instead of leaving them as SPIR-V).

eddyb opened this issue · 0 comments

eddyb commented

Right now even e.g. bool (OpTypeBool) and its false/true constants, are represented through their SPIR-V instructions, and the few places that need to deal with them (e.g. cfg, print) work with that directly.

Ideally we would have at least these natively represented in SPIR-T:

  • scalar (bool, iN, fN) types/consts
  • pure (and "universal") integer/generic ops (OpI{Add,Sub,Mul,...}, OpSelect, etc.)
    • by "universal" I mostly mean "100% deterministic standard semantics", and so e.g. they can be trivially constant-folded without worrying about any kind of "modifiers"
  • pure floating-point ops (but without necessarily assuming their semantics)
    • EDIT: rustc_apfloat is now available (with license issues resolved) to use as a dependency
    • also relevant: SPV_KHR_float_controls adds entry-point decorations which control floating-point semantics (so they can be used to make decisions, or even give up on constant-folding specifically the cases where that information is lacking, which would still handle a lot of useful cases)
  • memory (load/store) ops
    • this is where going further on the convergence with RVSDG would start becoming relevant, because its (linear) "state" dependencies allow seeing "all potential pasts" (e.g. a load instruction can walk up its "(memory) state" input and see all stores that could be relevant, from the same region/function/etc.)

A lot of the more "universal" concepts can be encoded very compactly (by e.g. factoring out "shapes" vs "inputs").

Also potentially relevant: Rust-GPU's SPIR-V type rules already describes many ops' "signatures" (when type-generic).

In order to make this manageable in terms of lower/lift (plus e.g. disallowing the SPIR-V instructions that have SPIR-T equivalents - see #2), it would probably be good to have as many of these cases handled by listing the equivalence in a macro that generates conversions both ways (and anything else we need), e.g.:

map_spirv_spirt! {
    OpTypeBool <=> TypeCtorKind::Scalar(ScalarType::Bool),
    OpConstantFalse <=> ConstCtorKind::Bool(false),
    OpConstantTrue <=> ConstCtorKind::Bool(true),
}