mirror of
https://github.com/vosen/ZLUDA.git
synced 2025-04-20 00:14:45 +00:00
Implement integer multiplication
This commit is contained in:
parent
18e5147fdc
commit
b068a89c38
8 changed files with 1201 additions and 995 deletions
|
@ -11,5 +11,5 @@ members = [
|
|||
]
|
||||
|
||||
[patch.crates-io]
|
||||
rspirv = { git = 'https://github.com/vosen/rspirv', branch = 'notcuda' }
|
||||
spirv_headers = { git = 'https://github.com/vosen/rspirv', branch = 'notcuda' }
|
||||
rspirv = { git = 'https://github.com/vosen/rspirv', rev = '4523d54d785faff59c1e928dd1f210c531a70258' }
|
||||
spirv_headers = { git = 'https://github.com/vosen/rspirv', rev = '4523d54d785faff59c1e928dd1f210c531a70258' }
|
|
@ -1,6 +1,9 @@
|
|||
use crate::ptx;
|
||||
use crate::translate;
|
||||
use rspirv::{binary::Disassemble, dr::{Block, Function, Instruction, Loader, Operand}};
|
||||
use rspirv::{
|
||||
binary::Assemble,
|
||||
dr::{Block, Function, Instruction, Loader, Operand},
|
||||
};
|
||||
use spirv_headers::Word;
|
||||
use spirv_tools_sys::{
|
||||
spv_binary, spv_endianness_t, spv_parsed_instruction_t, spv_result_t, spv_target_env,
|
||||
|
@ -37,9 +40,9 @@ macro_rules! test_ptx {
|
|||
}
|
||||
|
||||
test_ptx!(ld_st, [1u64], [1u64]);
|
||||
//test_ptx!(mov, [1u64], [1u64]);
|
||||
//test_ptx!(mul_lo, [1u64], [2u64]);
|
||||
//test_ptx!(mul_hi, [u64::max_value()], [1u64]);
|
||||
test_ptx!(mov, [1u64], [1u64]);
|
||||
test_ptx!(mul_lo, [1u64], [2u64]);
|
||||
test_ptx!(mul_hi, [u64::max_value()], [1u64]);
|
||||
|
||||
struct DisplayError<T: Display + Debug> {
|
||||
err: T,
|
||||
|
@ -155,9 +158,31 @@ fn test_spvtxt_assert<'a>(
|
|||
let mut loader = Loader::new();
|
||||
rspirv::binary::parse_words(&parsed_spirv, &mut loader)?;
|
||||
let spvtxt_mod = loader.module();
|
||||
unsafe { spirv_tools::spvBinaryDestroy(spv_binary) };
|
||||
if !is_spirv_fn_equal(&ptx_mod.functions[0], &spvtxt_mod.functions[0]) {
|
||||
panic!(ptx_mod.disassemble())
|
||||
// We could simply use ptx_mod.disassemble, but SPIRV-Tools text formattinmg is so much nicer
|
||||
let spv_from_ptx_binary = ptx_mod.assemble();
|
||||
let mut spv_text: spirv_tools::spv_text = ptr::null_mut();
|
||||
let result = unsafe {
|
||||
spirv_tools::spvBinaryToText(
|
||||
spv_context,
|
||||
spv_from_ptx_binary.as_ptr(),
|
||||
spv_from_ptx_binary.len(),
|
||||
(spirv_tools::spv_binary_to_text_options_t::SPV_BINARY_TO_TEXT_OPTION_INDENT | spirv_tools::spv_binary_to_text_options_t::SPV_BINARY_TO_TEXT_OPTION_NO_HEADER | spirv_tools::spv_binary_to_text_options_t::SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES).0,
|
||||
&mut spv_text as *mut _,
|
||||
ptr::null_mut()
|
||||
)
|
||||
};
|
||||
assert_eq!(result, spv_result_t::SPV_SUCCESS);
|
||||
let raw_text = unsafe {
|
||||
std::slice::from_raw_parts((*spv_text).str_ as *const u8, (*spv_text).length)
|
||||
};
|
||||
let spv_from_ptx_text = unsafe { str::from_utf8_unchecked(raw_text) };
|
||||
// TODO: stop leaking kernel text
|
||||
unsafe { spirv_tools::spvContextDestroy(spv_context) };
|
||||
panic!(spv_from_ptx_text);
|
||||
}
|
||||
unsafe { spirv_tools::spvContextDestroy(spv_context) };
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
@ -1,26 +1,43 @@
|
|||
OpCapability GenericPointer
|
||||
OpCapability Linkage
|
||||
OpCapability Addresses
|
||||
OpCapability Kernel
|
||||
OpCapability Int64
|
||||
OpCapability Int8
|
||||
%1 = OpExtInstImport "OpenCL.std"
|
||||
OpMemoryModel Physical64 OpenCL
|
||||
OpEntryPoint Kernel %5 "mov"
|
||||
%2 = OpTypeVoid
|
||||
%3 = OpTypeInt 64 0
|
||||
%4 = OpTypeFunction %2 %3 %3
|
||||
%19 = OpTypePointer Generic %3
|
||||
%5 = OpFunction %2 None %4
|
||||
%6 = OpFunctionParameter %3
|
||||
%7 = OpFunctionParameter %3
|
||||
%18 = OpLabel
|
||||
%13 = OpCopyObject %3 %6
|
||||
%14 = OpCopyObject %3 %7
|
||||
%15 = OpConvertUToPtr %19 %13
|
||||
%16 = OpLoad %3 %15
|
||||
%100 = OpCopyObject %3 %16
|
||||
%17 = OpConvertUToPtr %19 %14
|
||||
OpStore %17 %100
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
; SPIR-V
|
||||
; Version: 1.5
|
||||
; Generator: Khronos SPIR-V Tools Assembler; 0
|
||||
; Bound: 23
|
||||
; Schema: 0
|
||||
OpCapability GenericPointer
|
||||
OpCapability Linkage
|
||||
OpCapability Addresses
|
||||
OpCapability Kernel
|
||||
OpCapability Int64
|
||||
OpCapability Int8
|
||||
%1 = OpExtInstImport "OpenCL.std"
|
||||
OpMemoryModel Physical64 OpenCL
|
||||
OpEntryPoint Kernel %2 "mov"
|
||||
%void = OpTypeVoid
|
||||
%ulong = OpTypeInt 64 0
|
||||
%5 = OpTypeFunction %void %ulong %ulong
|
||||
%_ptr_Function_ulong = OpTypePointer Function %ulong
|
||||
%_ptr_Generic_ulong = OpTypePointer Generic %ulong
|
||||
%2 = OpFunction %void None %5
|
||||
%8 = OpFunctionParameter %ulong
|
||||
%9 = OpFunctionParameter %ulong
|
||||
%10 = OpLabel
|
||||
%11 = OpVariable %_ptr_Function_ulong Function
|
||||
%12 = OpVariable %_ptr_Function_ulong Function
|
||||
%13 = OpVariable %_ptr_Function_ulong Function
|
||||
%14 = OpVariable %_ptr_Function_ulong Function
|
||||
OpStore %11 %8
|
||||
OpStore %12 %9
|
||||
%15 = OpLoad %ulong %11
|
||||
%16 = OpConvertUToPtr %_ptr_Generic_ulong %15
|
||||
%17 = OpLoad %ulong %16
|
||||
OpStore %13 %17
|
||||
%18 = OpLoad %ulong %13
|
||||
%19 = OpCopyObject %ulong %18
|
||||
OpStore %14 %19
|
||||
%20 = OpLoad %ulong %12
|
||||
%21 = OpLoad %ulong %14
|
||||
%22 = OpConvertUToPtr %_ptr_Generic_ulong %20
|
||||
OpStore %22 %21
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
|
|
@ -1,26 +1,43 @@
|
|||
OpCapability GenericPointer
|
||||
OpCapability Linkage
|
||||
OpCapability Addresses
|
||||
OpCapability Kernel
|
||||
OpCapability Int64
|
||||
OpCapability Int8
|
||||
%1 = OpExtInstImport "OpenCL.std"
|
||||
OpMemoryModel Physical64 OpenCL
|
||||
OpEntryPoint Kernel %5 "mul_hi"
|
||||
%2 = OpTypeVoid
|
||||
%3 = OpTypeInt 64 0
|
||||
%4 = OpTypeFunction %2 %3 %3
|
||||
%19 = OpTypePointer Generic %3
|
||||
%5 = OpFunction %2 None %4
|
||||
%6 = OpFunctionParameter %3
|
||||
%7 = OpFunctionParameter %3
|
||||
%18 = OpLabel
|
||||
%13 = OpCopyObject %3 %6
|
||||
%14 = OpCopyObject %3 %7
|
||||
%15 = OpConvertUToPtr %19 %13
|
||||
%16 = OpLoad %3 %15
|
||||
%100 = OpCopyObject %3 %16
|
||||
%17 = OpConvertUToPtr %19 %14
|
||||
OpStore %17 %100
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
; SPIR-V
|
||||
; Version: 1.5
|
||||
; Generator: Khronos SPIR-V Tools Assembler; 0
|
||||
; Bound: 24
|
||||
; Schema: 0
|
||||
OpCapability GenericPointer
|
||||
OpCapability Linkage
|
||||
OpCapability Addresses
|
||||
OpCapability Kernel
|
||||
OpCapability Int64
|
||||
OpCapability Int8
|
||||
%1 = OpExtInstImport "OpenCL.std"
|
||||
OpMemoryModel Physical64 OpenCL
|
||||
OpEntryPoint Kernel %2 "mul_hi"
|
||||
%void = OpTypeVoid
|
||||
%ulong = OpTypeInt 64 0
|
||||
%5 = OpTypeFunction %void %ulong %ulong
|
||||
%_ptr_Function_ulong = OpTypePointer Function %ulong
|
||||
%_ptr_Generic_ulong = OpTypePointer Generic %ulong
|
||||
%ulong_2 = OpConstant %ulong 2
|
||||
%2 = OpFunction %void None %5
|
||||
%9 = OpFunctionParameter %ulong
|
||||
%10 = OpFunctionParameter %ulong
|
||||
%11 = OpLabel
|
||||
%12 = OpVariable %_ptr_Function_ulong Function
|
||||
%13 = OpVariable %_ptr_Function_ulong Function
|
||||
%14 = OpVariable %_ptr_Function_ulong Function
|
||||
%15 = OpVariable %_ptr_Function_ulong Function
|
||||
OpStore %12 %9
|
||||
OpStore %13 %10
|
||||
%16 = OpLoad %ulong %12
|
||||
%17 = OpConvertUToPtr %_ptr_Generic_ulong %16
|
||||
%18 = OpLoad %ulong %17
|
||||
OpStore %14 %18
|
||||
%19 = OpLoad %ulong %14
|
||||
%20 = OpExtInst %ulong %1 u_mul_hi %19 %ulong_2
|
||||
OpStore %15 %20
|
||||
%21 = OpLoad %ulong %13
|
||||
%22 = OpLoad %ulong %15
|
||||
%23 = OpConvertUToPtr %_ptr_Generic_ulong %21
|
||||
OpStore %23 %22
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
|
|
|
@ -1,26 +1,38 @@
|
|||
OpCapability GenericPointer
|
||||
OpCapability Linkage
|
||||
OpCapability Addresses
|
||||
OpCapability Kernel
|
||||
OpCapability Int64
|
||||
OpCapability Int8
|
||||
%1 = OpExtInstImport "OpenCL.std"
|
||||
OpMemoryModel Physical64 OpenCL
|
||||
OpEntryPoint Kernel %5 "mul_lo"
|
||||
%2 = OpTypeVoid
|
||||
%3 = OpTypeInt 64 0
|
||||
%4 = OpTypeFunction %2 %3 %3
|
||||
%19 = OpTypePointer Generic %3
|
||||
%5 = OpFunction %2 None %4
|
||||
%6 = OpFunctionParameter %3
|
||||
%7 = OpFunctionParameter %3
|
||||
%18 = OpLabel
|
||||
%13 = OpCopyObject %3 %6
|
||||
%14 = OpCopyObject %3 %7
|
||||
%15 = OpConvertUToPtr %19 %13
|
||||
%16 = OpLoad %3 %15
|
||||
%100 = OpCopyObject %3 %16
|
||||
%17 = OpConvertUToPtr %19 %14
|
||||
OpStore %17 %100
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
OpCapability GenericPointer
|
||||
OpCapability Linkage
|
||||
OpCapability Addresses
|
||||
OpCapability Kernel
|
||||
OpCapability Int64
|
||||
OpCapability Int8
|
||||
%1 = OpExtInstImport "OpenCL.std"
|
||||
OpMemoryModel Physical64 OpenCL
|
||||
OpEntryPoint Kernel %5 "mul_lo"
|
||||
%void = OpTypeVoid
|
||||
%ulong = OpTypeInt 64 0
|
||||
%4 = OpTypeFunction %void %ulong %ulong
|
||||
%_ptr_Function_ulong = OpTypePointer Function %ulong
|
||||
%_ptr_Generic_ulong = OpTypePointer Generic %ulong
|
||||
%ulong_2 = OpConstant %ulong 2
|
||||
%5 = OpFunction %void None %4
|
||||
%6 = OpFunctionParameter %ulong
|
||||
%7 = OpFunctionParameter %ulong
|
||||
%21 = OpLabel
|
||||
%8 = OpVariable %_ptr_Function_ulong Function
|
||||
%9 = OpVariable %_ptr_Function_ulong Function
|
||||
%10 = OpVariable %_ptr_Function_ulong Function
|
||||
%11 = OpVariable %_ptr_Function_ulong Function
|
||||
OpStore %8 %6
|
||||
OpStore %9 %7
|
||||
%12 = OpLoad %ulong %8
|
||||
%19 = OpConvertUToPtr %_ptr_Generic_ulong %12
|
||||
%13 = OpLoad %ulong %19
|
||||
OpStore %10 %13
|
||||
%14 = OpLoad %ulong %10
|
||||
%15 = OpIMul %ulong %14 %ulong_2
|
||||
OpStore %11 %15
|
||||
%16 = OpLoad %ulong %9
|
||||
%17 = OpLoad %ulong %11
|
||||
%20 = OpConvertUToPtr %_ptr_Generic_ulong %16
|
||||
OpStore %20 %17
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
|
|
|
@ -107,11 +107,11 @@ pub fn to_spirv_module(ast: ast::Module) -> Result<dr::Module, dr::Error> {
|
|||
builder.set_version(1, 0);
|
||||
emit_capabilities(&mut builder);
|
||||
emit_extensions(&mut builder);
|
||||
emit_extended_instruction_sets(&mut builder);
|
||||
let opencl_id = emit_opencl_import(&mut builder);
|
||||
emit_memory_model(&mut builder);
|
||||
let mut map = TypeWordMap::new(&mut builder);
|
||||
for f in ast.functions {
|
||||
emit_function(&mut builder, &mut map, f)?;
|
||||
emit_function(&mut builder, &mut map, opencl_id, f)?;
|
||||
}
|
||||
Ok(builder.module())
|
||||
}
|
||||
|
@ -132,8 +132,8 @@ fn emit_capabilities(builder: &mut dr::Builder) {
|
|||
|
||||
fn emit_extensions(_: &mut dr::Builder) {}
|
||||
|
||||
fn emit_extended_instruction_sets(builder: &mut dr::Builder) {
|
||||
builder.ext_inst_import("OpenCL.std");
|
||||
fn emit_opencl_import(builder: &mut dr::Builder) -> spirv::Word {
|
||||
builder.ext_inst_import("OpenCL.std")
|
||||
}
|
||||
|
||||
fn emit_memory_model(builder: &mut dr::Builder) {
|
||||
|
@ -146,6 +146,7 @@ fn emit_memory_model(builder: &mut dr::Builder) {
|
|||
fn emit_function<'a>(
|
||||
builder: &mut dr::Builder,
|
||||
map: &mut TypeWordMap,
|
||||
opencl_id: spirv::Word,
|
||||
f: ast::Function<'a>,
|
||||
) -> Result<spirv::Word, rspirv::dr::Error> {
|
||||
let func_type = get_function_type(builder, map, &f.args);
|
||||
|
@ -158,7 +159,7 @@ fn emit_function<'a>(
|
|||
let id_offset = builder.reserve_ids(unique_ids);
|
||||
emit_function_args(builder, id_offset, map, &f.args);
|
||||
apply_id_offset(&mut func_body, id_offset);
|
||||
emit_function_body_ops(builder, map, &func_body)?;
|
||||
emit_function_body_ops(builder, map, opencl_id, &func_body)?;
|
||||
builder.end_function()?;
|
||||
Ok(func_id)
|
||||
}
|
||||
|
@ -265,7 +266,9 @@ fn insert_mem_ssa_statements(
|
|||
match s {
|
||||
Statement::Instruction(inst) => match inst {
|
||||
Instruction::Ld(
|
||||
ld @ ast::LdData {
|
||||
ld
|
||||
@
|
||||
ast::LdData {
|
||||
state_space: ast::LdStateSpace::Param,
|
||||
..
|
||||
},
|
||||
|
@ -638,6 +641,7 @@ fn collect_label_ids<'a>(
|
|||
fn emit_function_body_ops(
|
||||
builder: &mut dr::Builder,
|
||||
map: &mut TypeWordMap,
|
||||
opencl: spirv::Word,
|
||||
func: &[ExpandedStatement],
|
||||
) -> Result<(), dr::Error> {
|
||||
for s in func {
|
||||
|
@ -658,7 +662,36 @@ fn emit_function_body_ops(
|
|||
}
|
||||
builder.variable(type_id, Some(*id), spirv::StorageClass::Function, None);
|
||||
}
|
||||
Statement::Constant(_) => todo!(),
|
||||
Statement::Constant(cnst) => {
|
||||
let typ_id = map.get_or_add_scalar(builder, cnst.typ);
|
||||
match cnst.typ {
|
||||
ast::ScalarType::B8 | ast::ScalarType::U8 => {
|
||||
builder.constant_u32(typ_id, Some(cnst.dst), cnst.value as u8 as u32);
|
||||
}
|
||||
ast::ScalarType::B16 | ast::ScalarType::U16 => {
|
||||
builder.constant_u32(typ_id, Some(cnst.dst), cnst.value as u16 as u32);
|
||||
}
|
||||
ast::ScalarType::B32 | ast::ScalarType::U32 => {
|
||||
builder.constant_u32(typ_id, Some(cnst.dst), cnst.value as u32);
|
||||
}
|
||||
ast::ScalarType::B64 | ast::ScalarType::U64 => {
|
||||
builder.constant_u64(typ_id, Some(cnst.dst), cnst.value as u64);
|
||||
}
|
||||
ast::ScalarType::S8 => {
|
||||
builder.constant_u32(typ_id, Some(cnst.dst), cnst.value as i8 as u32);
|
||||
}
|
||||
ast::ScalarType::S16 => {
|
||||
builder.constant_u32(typ_id, Some(cnst.dst), cnst.value as i16 as u32);
|
||||
}
|
||||
ast::ScalarType::S32 => {
|
||||
builder.constant_u32(typ_id, Some(cnst.dst), cnst.value as i32 as u32);
|
||||
}
|
||||
ast::ScalarType::S64 => {
|
||||
builder.constant_u64(typ_id, Some(cnst.dst), cnst.value as i64 as u64);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
Statement::Converison(cv) => emit_implicit_conversion(builder, map, cv)?,
|
||||
Statement::Conditional(bra) => {
|
||||
builder.branch_conditional(bra.predicate, bra.if_true, bra.if_false, [])?;
|
||||
|
@ -700,17 +733,14 @@ fn emit_function_body_ops(
|
|||
}
|
||||
Instruction::Mul(mul, arg) => match mul.desc {
|
||||
ast::MulDescriptor::Int(ref ctr) => {
|
||||
emit_mul_int(builder, map, mul.typ, ctr, arg)
|
||||
emit_mul_int(builder, map, opencl, mul.typ, ctr, arg)?;
|
||||
}
|
||||
ast::MulDescriptor::Float(_) => todo!(),
|
||||
},
|
||||
_ => todo!(),
|
||||
},
|
||||
Statement::LoadVar(arg, typ) => {
|
||||
let type_id = map.get_or_add(
|
||||
builder,
|
||||
SpirvType::from(*typ),
|
||||
);
|
||||
let type_id = map.get_or_add(builder, SpirvType::from(*typ));
|
||||
builder.load(type_id, Some(arg.dst), arg.src, None, [])?;
|
||||
}
|
||||
Statement::StoreVar(arg, typ) => {
|
||||
|
@ -722,14 +752,36 @@ fn emit_function_body_ops(
|
|||
}
|
||||
|
||||
fn emit_mul_int(
|
||||
_builder: &mut dr::Builder,
|
||||
_map: &mut TypeWordMap,
|
||||
_typ: ast::Type,
|
||||
_ctr: &ast::MulIntControl,
|
||||
_arg: &Arg3,
|
||||
) {
|
||||
//let inst_type = map.get_or_add(builder, SpirvType::from(typ));
|
||||
//builder.i_mul(inst_type, Some(arg.dst), Some(arg.src1), Some(arg.src2));
|
||||
builder: &mut dr::Builder,
|
||||
map: &mut TypeWordMap,
|
||||
opencl: spirv::Word,
|
||||
typ: ast::Type,
|
||||
ctr: &ast::MulIntControl,
|
||||
arg: &Arg3,
|
||||
) -> Result<(), dr::Error> {
|
||||
let inst_type = map.get_or_add(builder, SpirvType::from(typ));
|
||||
match ctr {
|
||||
ast::MulIntControl::Low => {
|
||||
builder.i_mul(inst_type, Some(arg.dst), arg.src1, arg.src2)?;
|
||||
}
|
||||
ast::MulIntControl::High => {
|
||||
let ocl_mul_hi = match typ.try_as_scalar().unwrap().kind() {
|
||||
ScalarKind::Signed => spirv::CLOp::s_mul_hi,
|
||||
ScalarKind::Unsigned => spirv::CLOp::u_mul_hi,
|
||||
ScalarKind::Float => unreachable!(),
|
||||
ScalarKind::Byte => unreachable!(),
|
||||
};
|
||||
builder.ext_inst(
|
||||
inst_type,
|
||||
Some(arg.dst),
|
||||
1,
|
||||
ocl_mul_hi as spirv::Word,
|
||||
[arg.src1, arg.src2],
|
||||
)?;
|
||||
}
|
||||
ast::MulIntControl::Wide => todo!(),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn emit_implicit_conversion(
|
||||
|
|
|
@ -1 +1 @@
|
|||
bindgen --whitelist-type="spv.*" --whitelist-function="spv.*" --size_t-is-usize --default-enum-style=rust ext/SPIRV-Tools/include/spirv-tools/libspirv.h -o lib.rs
|
||||
bindgen --whitelist-type="spv.*" --whitelist-function="spv.*" --size_t-is-usize --default-enum-style=rust --bitfield-enum="spv_text_to_binary_options_t|spv_binary_to_text_options_t" ../ext/SPIRV-Tools/include/spirv-tools/libspirv.h -o src/spirv_tools.rs
|
File diff suppressed because it is too large
Load diff
Loading…
Add table
Reference in a new issue