diff --git a/ptx/src/ast.rs b/ptx/src/ast.rs index 3a5022d..77afee6 100644 --- a/ptx/src/ast.rs +++ b/ptx/src/ast.rs @@ -316,7 +316,7 @@ pub struct PredAt { pub enum Instruction { Ld(LdData, Arg2

), - Mov(MovType, Arg2Mov

), + Mov(MovDetails, Arg2

), MovVector(MovVectorDetails, Arg2Vec

), Mul(MulDetails, Arg3

), Add(AddDetails, Arg3

), @@ -354,7 +354,6 @@ pub struct CallInst { pub trait ArgParams { type ID; type Operand; - type MovOperand; type CallOperand; type VecOperand; } @@ -366,7 +365,6 @@ pub struct ParsedArgParams<'a> { impl<'a> ArgParams for ParsedArgParams<'a> { type ID = &'a str; type Operand = Operand<&'a str>; - type MovOperand = MovOperand<&'a str>; type CallOperand = CallOperand<&'a str>; type VecOperand = (&'a str, u8); } @@ -380,25 +378,6 @@ pub struct Arg2 { pub src: P::Operand, } -pub struct Arg2Mov { - pub dst: P::ID, - pub src: P::MovOperand, -} - -impl<'input> From>> for Arg2Mov> { - fn from(a: Arg2>) -> Arg2Mov> { - let new_src = match a.src { - Operand::Reg(r) => MovOperand::Reg(r), - Operand::RegOffset(r, imm) => MovOperand::RegOffset(r, imm), - Operand::Imm(x) => MovOperand::Imm(x), - }; - Arg2Mov { - dst: a.dst, - src: new_src, - } - } -} - pub struct Arg2St { pub src1: P::Operand, pub src2: P::Operand, @@ -433,14 +412,6 @@ pub struct Arg5 { pub src3: P::Operand, } -#[derive(Copy, Clone)] -pub enum MovOperand { - Reg(ID), - Address(ID), - RegOffset(ID, i32), - AddressOffset(ID, i32), - Imm(u32), -} #[derive(Copy, Clone)] pub enum Operand { Reg(ID), @@ -530,6 +501,11 @@ sub_scalar_type!(MovVectorType { F64, }); +pub struct MovDetails { + pub typ: MovType, + pub src_is_address: bool +} + sub_type! { MovType { Scalar(MovScalarType), diff --git a/ptx/src/ptx.lalrpop b/ptx/src/ptx.lalrpop index 46d0b48..208e076 100644 --- a/ptx/src/ptx.lalrpop +++ b/ptx/src/ptx.lalrpop @@ -496,7 +496,7 @@ LdCacheOperator: ast::LdCacheOperator = { // https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#data-movement-and-conversion-instructions-mov InstMov: ast::Instruction> = { "mov" => { - ast::Instruction::Mov(t, a.into()) + ast::Instruction::Mov(ast::MovDetails{ src_is_address: false, typ: t }, a) }, "mov" => { ast::Instruction::MovVector(ast::MovVectorDetails{typ: t, length: 0}, a) diff --git a/ptx/src/test/spirv_run/mov_address.spvtxt b/ptx/src/test/spirv_run/mov_address.spvtxt index 6810fec..26ae21f 100644 --- a/ptx/src/test/spirv_run/mov_address.spvtxt +++ b/ptx/src/test/spirv_run/mov_address.spvtxt @@ -4,43 +4,30 @@ OpCapability Kernel OpCapability Int64 OpCapability Int8 - %25 = OpExtInstImport "OpenCL.std" + %12 = OpExtInstImport "OpenCL.std" OpMemoryModel Physical64 OpenCL - OpEntryPoint Kernel %1 "add" + OpEntryPoint Kernel %1 "mov_address" %void = OpTypeVoid %ulong = OpTypeInt 64 0 - %28 = OpTypeFunction %void %ulong %ulong + %15 = OpTypeFunction %void %ulong %ulong %_ptr_Function_ulong = OpTypePointer Function %ulong -%_ptr_Generic_ulong = OpTypePointer Generic %ulong - %ulong_1 = OpConstant %ulong 1 - %1 = OpFunction %void None %28 - %8 = OpFunctionParameter %ulong - %9 = OpFunctionParameter %ulong - %23 = OpLabel + %uchar = OpTypeInt 8 0 + %uint = OpTypeInt 32 0 + %uint_8 = OpConstant %uint 8 +%_arr_uchar_uint_8 = OpTypeArray %uchar %uint_8 +%_ptr_Function__arr_uchar_uint_8 = OpTypePointer Function %_arr_uchar_uint_8 + %1 = OpFunction %void None %15 + %6 = OpFunctionParameter %ulong + %7 = OpFunctionParameter %ulong + %10 = OpLabel %2 = OpVariable %_ptr_Function_ulong Function %3 = OpVariable %_ptr_Function_ulong Function - %4 = OpVariable %_ptr_Function_ulong Function + %4 = OpVariable %_ptr_Function__arr_uchar_uint_8 Function %5 = OpVariable %_ptr_Function_ulong Function - %6 = OpVariable %_ptr_Function_ulong Function - %7 = OpVariable %_ptr_Function_ulong Function - OpStore %2 %8 - OpStore %3 %9 - %11 = OpLoad %ulong %2 - %10 = OpCopyObject %ulong %11 - OpStore %4 %10 - %13 = OpLoad %ulong %3 - %12 = OpCopyObject %ulong %13 - OpStore %5 %12 - %15 = OpLoad %ulong %4 - %21 = OpConvertUToPtr %_ptr_Generic_ulong %15 - %14 = OpLoad %ulong %21 - OpStore %6 %14 - %17 = OpLoad %ulong %6 - %16 = OpIAdd %ulong %17 %ulong_1 - OpStore %7 %16 - %18 = OpLoad %ulong %5 - %19 = OpLoad %ulong %7 - %22 = OpConvertUToPtr %_ptr_Generic_ulong %18 - OpStore %22 %19 + OpStore %2 %6 + OpStore %3 %7 + %9 = OpConvertPtrToU %ulong %4 + %8 = OpCopyObject %ulong %9 + OpStore %5 %8 OpReturn OpFunctionEnd diff --git a/ptx/src/translate.rs b/ptx/src/translate.rs index 3e6b495..7726040 100644 --- a/ptx/src/translate.rs +++ b/ptx/src/translate.rs @@ -480,37 +480,19 @@ fn add_types_to_statements( }; Ok(Statement::Instruction(ast::Instruction::St(d, arg))) } - Statement::Instruction(ast::Instruction::Mov(d, mut arg)) => { - arg.src = match arg.src { - ast::MovOperand::Reg(id) => { - let (ss, _) = id_defs.get_typed(id)?; - match ss { - StateSpace::Reg => ast::MovOperand::Reg(id), - StateSpace::Const - | StateSpace::Global - | StateSpace::Local - | StateSpace::Shared - | StateSpace::Param - | StateSpace::ParamReg => ast::MovOperand::Address(id), - } - } - ast::MovOperand::RegOffset(id, imm) => { - let (ss, _) = id_defs.get_typed(id)?; - match ss { - StateSpace::Reg => ast::MovOperand::RegOffset(id, imm), - StateSpace::Const - | StateSpace::Global - | StateSpace::Local - | StateSpace::Shared - | StateSpace::Param - | StateSpace::ParamReg => ast::MovOperand::AddressOffset(id, imm), - } - } - a @ ast::MovOperand::Imm(_) => a, - ast::MovOperand::Address(_) | ast::MovOperand::AddressOffset(_, _) => { - unreachable!() - } - }; + Statement::Instruction(ast::Instruction::Mov(mut d, arg)) => { + if let Some(src_id) = arg.src.underlying() { + let (scope, _) = id_defs.get_typed(*src_id)?; + d.src_is_address = match scope { + StateSpace::Reg => false, + StateSpace::Const + | StateSpace::Global + | StateSpace::Local + | StateSpace::Shared + | StateSpace::Param + | StateSpace::ParamReg => true, + }; + } Ok(Statement::Instruction(ast::Instruction::Mov(d, arg))) } Statement::Instruction(ast::Instruction::MovVector(dets, args)) => { @@ -982,24 +964,6 @@ impl<'a, 'b> ArgumentMapVisitor })); Ok(new_id) } - - fn mov_operand( - &mut self, - desc: ArgumentDescriptor>, - typ: ast::Type, - ) -> Result { - match desc.op { - ast::MovOperand::Reg(r) => self.operand(desc.new_op(ast::Operand::Reg(r)), typ), - ast::MovOperand::RegOffset(r, imm) => { - self.operand(desc.new_op(ast::Operand::RegOffset(r, imm)), typ) - } - ast::MovOperand::Imm(x) => self.operand(desc.new_op(ast::Operand::Imm(x)), typ), - ast::MovOperand::Address(r) => self.operand(desc.new_op(ast::Operand::Reg(r)), typ), - ast::MovOperand::AddressOffset(r, imm) => { - self.operand(desc.new_op(ast::Operand::RegOffset(r, imm)), typ) - } - } - } } /* @@ -1081,7 +1045,7 @@ fn insert_implicit_conversions( ast::Instruction::Mov(d, mut arg) => { // https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#data-movement-and-conversion-instructions-mov-2 // TODO: handle the case of mixed vector/scalar implicit conversions - let inst_typ_is_bit = match d { + let inst_typ_is_bit = match d.typ { ast::MovType::Scalar(t) => { ast::ScalarType::from(t).kind() == ScalarKind::Bit } @@ -1097,7 +1061,7 @@ fn insert_implicit_conversions( id_def, arg.src, src_type, - d.into(), + d.typ.into(), ConversionKind::Default, ); did_vector_implicit = true; @@ -1107,7 +1071,7 @@ fn insert_implicit_conversions( post_conv = Some(get_conversion_dst( id_def, &mut arg.dst, - d.into(), + d.typ.into(), dst_type, ConversionKind::Default, )); @@ -1305,9 +1269,9 @@ fn emit_function_body_ops( } // SPIR-V does not support ret as guaranteed-converged ast::Instruction::Ret(_) => builder.ret()?, - ast::Instruction::Mov(mov_type, arg) => { + ast::Instruction::Mov(d, arg) => { let result_type = - map.get_or_add(builder, SpirvType::from(ast::Type::from(*mov_type))); + map.get_or_add(builder, SpirvType::from(ast::Type::from(d.typ))); builder.copy_object(result_type, Some(arg.dst), arg.src)?; } ast::Instruction::Mul(mul, arg) => match mul { @@ -1690,6 +1654,10 @@ fn emit_implicit_conversion( let from_parts = cv.from.to_parts(); let to_parts = cv.to.to_parts(); match (from_parts.kind, to_parts.kind, cv.kind) { + (_, _, ConversionKind::PtrToBit) => { + let dst_type = map.get_or_add_scalar(builder, ast::ScalarType::B64); + builder.convert_ptr_to_u(dst_type, Some(cv.dst), cv.src)?; + } (_, _, ConversionKind::BitToPtr(space)) => { let dst_type = map.get_or_add( builder, @@ -2214,7 +2182,6 @@ pub trait ArgParamsEx: ast::ArgParams { id: &Self::ID, decl: &'b GlobalFnDeclResolver<'x, 'b>, ) -> Result<&'b FnDecl, TranslateError>; - fn get_src_semantics(m: &Self::MovOperand) -> ArgumentSemantics; } impl<'input> ArgParamsEx for ast::ParsedArgParams<'input> { @@ -2224,10 +2191,6 @@ impl<'input> ArgParamsEx for ast::ParsedArgParams<'input> { ) -> Result<&'b FnDecl, TranslateError> { decl.get_fn_decl_str(id) } - - fn get_src_semantics(_: &Self::MovOperand) -> ArgumentSemantics { - ArgumentSemantics::Default - } } enum NormalizedArgParams {} @@ -2243,7 +2206,6 @@ type UnadornedStatement = Statement, Norma impl ast::ArgParams for NormalizedArgParams { type ID = spirv::Word; type Operand = ast::Operand; - type MovOperand = ast::MovOperand; type CallOperand = ast::CallOperand; type VecOperand = (spirv::Word, u8); } @@ -2255,10 +2217,6 @@ impl ArgParamsEx for NormalizedArgParams { ) -> Result<&'b FnDecl, TranslateError> { decl.get_fn_decl(*id) } - - fn get_src_semantics(m: &ast::MovOperand) -> ArgumentSemantics { - m.src_semantics() - } } #[derive(Copy, Clone)] @@ -2284,7 +2242,6 @@ struct Function<'input> { impl ast::ArgParams for ExpandedArgParams { type ID = spirv::Word; type Operand = spirv::Word; - type MovOperand = spirv::Word; type CallOperand = spirv::Word; type VecOperand = spirv::Word; } @@ -2296,10 +2253,6 @@ impl ArgParamsEx for ExpandedArgParams { ) -> Result<&'b FnDecl, TranslateError> { decl.get_fn_decl(*id) } - - fn get_src_semantics(_: &spirv::Word) -> ArgumentSemantics { - ArgumentSemantics::Default - } } trait ArgumentMapVisitor { @@ -2313,11 +2266,6 @@ trait ArgumentMapVisitor { desc: ArgumentDescriptor, typ: ast::Type, ) -> Result; - fn mov_operand( - &mut self, - desc: ArgumentDescriptor, - typ: ast::Type, - ) -> Result; fn src_call_operand( &mut self, desc: ArgumentDescriptor, @@ -2353,14 +2301,6 @@ where self(desc, Some(t)) } - fn mov_operand( - &mut self, - desc: ArgumentDescriptor, - t: ast::Type, - ) -> Result { - self(desc, Some(t)) - } - fn src_call_operand( &mut self, desc: ArgumentDescriptor, @@ -2423,22 +2363,6 @@ where ) -> Result<(spirv::Word, u8), TranslateError> { Ok((self(desc.op.0)?, desc.op.1)) } - - fn mov_operand( - &mut self, - desc: ArgumentDescriptor>, - _: ast::Type, - ) -> Result, TranslateError> { - match desc.op { - ast::MovOperand::Reg(r) => Ok(ast::MovOperand::Reg(self(r)?)), - ast::MovOperand::Address(a) => Ok(ast::MovOperand::Address(self(a)?)), - ast::MovOperand::RegOffset(r, imm) => Ok(ast::MovOperand::RegOffset(self(r)?, imm)), - ast::MovOperand::AddressOffset(a, imm) => { - Ok(ast::MovOperand::AddressOffset(self(a)?, imm)) - } - ast::MovOperand::Imm(x) => Ok(ast::MovOperand::Imm(x)), - } - } } struct ArgumentDescriptor { @@ -2479,7 +2403,7 @@ impl ast::Instruction { ast::Instruction::MovVector(t, a.map(visitor, (t.typ, t.length))?) } ast::Instruction::Abs(d, arg) => { - ast::Instruction::Abs(d, arg.map(visitor, ast::Type::Scalar(d.typ))?) + ast::Instruction::Abs(d, arg.map(visitor, false, ast::Type::Scalar(d.typ))?) } // Call instruction is converted to a call statement early on ast::Instruction::Call(_) => unreachable!(), @@ -2488,8 +2412,9 @@ impl ast::Instruction { let is_param = d.state_space == ast::LdStateSpace::Param; ast::Instruction::Ld(d, a.map_ld(visitor, inst_type, is_param)?) } - ast::Instruction::Mov(mov_type, a) => { - ast::Instruction::Mov(mov_type, a.map(visitor, mov_type.into())?) + ast::Instruction::Mov(d, a) => { + let mapped = a.map(visitor, d.src_is_address, d.typ.into())?; + ast::Instruction::Mov(d, mapped) } ast::Instruction::Mul(d, a) => { let inst_type = d.get_type(); @@ -2507,7 +2432,7 @@ impl ast::Instruction { let inst_type = d.typ; ast::Instruction::SetpBool(d, a.map(visitor, ast::Type::Scalar(inst_type))?) } - ast::Instruction::Not(t, a) => ast::Instruction::Not(t, a.map(visitor, t.to_type())?), + ast::Instruction::Not(t, a) => ast::Instruction::Not(t, a.map(visitor, false, t.to_type())?), ast::Instruction::Cvt(d, a) => { let (dst_t, src_t) = match &d { ast::CvtDetails::FloatFromFloat(desc) => ( @@ -2541,7 +2466,7 @@ impl ast::Instruction { ast::Instruction::Ret(d) => ast::Instruction::Ret(d), ast::Instruction::Cvta(d, a) => { let inst_type = ast::Type::Scalar(ast::ScalarType::B64); - ast::Instruction::Cvta(d, a.map(visitor, inst_type)?) + ast::Instruction::Cvta(d, a.map(visitor, false, inst_type)?) } }) } @@ -2616,28 +2541,6 @@ where desc.op.1, )) } - - fn mov_operand( - &mut self, - desc: ArgumentDescriptor>, - t: ast::Type, - ) -> Result, TranslateError> { - match desc.op { - ast::MovOperand::Reg(r) => Ok(ast::MovOperand::Reg(self(desc.new_op(r), Some(t))?)), - ast::MovOperand::Address(a) => { - Ok(ast::MovOperand::Address(self(desc.new_op(a), Some(t))?)) - } - ast::MovOperand::RegOffset(r, imm) => Ok(ast::MovOperand::RegOffset( - self(desc.new_op(r), Some(t))?, - imm, - )), - ast::MovOperand::AddressOffset(a, imm) => Ok(ast::MovOperand::AddressOffset( - self(desc.new_op(a), Some(t))?, - imm, - )), - ast::MovOperand::Imm(x) => Ok(ast::MovOperand::Imm(x)), - } - } } impl ast::Type { @@ -2836,6 +2739,7 @@ impl ast::Arg2 { fn map>( self, visitor: &mut V, + src_is_addr: bool, t: ast::Type, ) -> Result, TranslateError> { let new_dst = visitor.variable( @@ -2850,7 +2754,11 @@ impl ast::Arg2 { ArgumentDescriptor { op: self.src, is_dst: false, - sema: ArgumentSemantics::Default, + sema: if src_is_addr { + ArgumentSemantics::Address + } else { + ArgumentSemantics::Default + }, }, t, )?; @@ -2915,46 +2823,6 @@ impl ast::Arg2 { } } -impl ast::Arg2Mov { - fn map>( - self, - visitor: &mut V, - t: ast::Type, - ) -> Result, TranslateError> { - let dst = visitor.variable( - ArgumentDescriptor { - op: self.dst, - is_dst: true, - sema: ArgumentSemantics::Default, - }, - Some(t), - )?; - let src_sema = T::get_src_semantics(&self.src); - let src = visitor.mov_operand( - ArgumentDescriptor { - op: self.src, - is_dst: false, - sema: src_sema, - }, - t, - )?; - Ok(ast::Arg2Mov { dst, src }) - } -} - -impl ast::MovOperand { - fn src_semantics(&self) -> ArgumentSemantics { - match self { - ast::MovOperand::Reg(_) - | ast::MovOperand::RegOffset(_, _) - | ast::MovOperand::Imm(_) => ArgumentSemantics::Default, - ast::MovOperand::Address(_) | ast::MovOperand::AddressOffset(_, _) => { - ArgumentSemantics::Address - } - } - } -} - impl ast::Arg2St { fn map>( self,