aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAndrzej Janik <[email protected]>2020-09-20 17:29:38 +0200
committerAndrzej Janik <[email protected]>2020-09-20 17:29:38 +0200
commitb11ce92d2cd1c4ed62b2691da7f8dfd9c822f0a5 (patch)
tree2a3a79365ad8ff88d3af4dcdc1ce1a1a00a11244
parentdcaea507ba84e375d57c4ed051477439423ae8ef (diff)
downloadZLUDA-b11ce92d2cd1c4ed62b2691da7f8dfd9c822f0a5.tar.gz
ZLUDA-b11ce92d2cd1c4ed62b2691da7f8dfd9c822f0a5.zip
Better propagate information about address-mov and emit conversion for it
-rw-r--r--ptx/src/ast.rs36
-rw-r--r--ptx/src/ptx.lalrpop2
-rw-r--r--ptx/src/test/spirv_run/mov_address.spvtxt49
-rw-r--r--ptx/src/translate.rs200
4 files changed, 59 insertions, 228 deletions
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<ID> {
pub enum Instruction<P: ArgParams> {
Ld(LdData, Arg2<P>),
- Mov(MovType, Arg2Mov<P>),
+ Mov(MovDetails, Arg2<P>),
MovVector(MovVectorDetails, Arg2Vec<P>),
Mul(MulDetails, Arg3<P>),
Add(AddDetails, Arg3<P>),
@@ -354,7 +354,6 @@ pub struct CallInst<P: ArgParams> {
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<P: ArgParams> {
pub src: P::Operand,
}
-pub struct Arg2Mov<P: ArgParams> {
- pub dst: P::ID,
- pub src: P::MovOperand,
-}
-
-impl<'input> From<Arg2<ParsedArgParams<'input>>> for Arg2Mov<ParsedArgParams<'input>> {
- fn from(a: Arg2<ParsedArgParams<'input>>) -> Arg2Mov<ParsedArgParams<'input>> {
- 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<P: ArgParams> {
pub src1: P::Operand,
pub src2: P::Operand,
@@ -434,14 +413,6 @@ pub struct Arg5<P: ArgParams> {
}
#[derive(Copy, Clone)]
-pub enum MovOperand<ID> {
- Reg(ID),
- Address(ID),
- RegOffset(ID, i32),
- AddressOffset(ID, i32),
- Imm(u32),
-}
-#[derive(Copy, Clone)]
pub enum Operand<ID> {
Reg(ID),
RegOffset(ID, i32),
@@ -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<ast::ParsedArgParams<'input>> = {
"mov" <t:MovType> <a:Arg2> => {
- ast::Instruction::Mov(t, a.into())
+ ast::Instruction::Mov(ast::MovDetails{ src_is_address: false, typ: t }, a)
},
"mov" <t:MovVectorType> <a:Arg2Vec> => {
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<NormalizedArgParams, ExpandedArgParams>
}));
Ok(new_id)
}
-
- fn mov_operand(
- &mut self,
- desc: ArgumentDescriptor<ast::MovOperand<spirv::Word>>,
- typ: ast::Type,
- ) -> Result<spirv::Word, TranslateError> {
- 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<ast::Instruction<NormalizedArgParams>, Norma
impl ast::ArgParams for NormalizedArgParams {
type ID = spirv::Word;
type Operand = ast::Operand<spirv::Word>;
- type MovOperand = ast::MovOperand<spirv::Word>;
type CallOperand = ast::CallOperand<spirv::Word>;
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<spirv::Word>) -> 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<T: ArgParamsEx, U: ArgParamsEx> {
@@ -2313,11 +2266,6 @@ trait ArgumentMapVisitor<T: ArgParamsEx, U: ArgParamsEx> {
desc: ArgumentDescriptor<T::Operand>,
typ: ast::Type,
) -> Result<U::Operand, TranslateError>;
- fn mov_operand(
- &mut self,
- desc: ArgumentDescriptor<T::MovOperand>,
- typ: ast::Type,
- ) -> Result<U::MovOperand, TranslateError>;
fn src_call_operand(
&mut self,
desc: ArgumentDescriptor<T::CallOperand>,
@@ -2353,14 +2301,6 @@ where
self(desc, Some(t))
}
- fn mov_operand(
- &mut self,
- desc: ArgumentDescriptor<spirv::Word>,
- t: ast::Type,
- ) -> Result<spirv::Word, TranslateError> {
- self(desc, Some(t))
- }
-
fn src_call_operand(
&mut self,
desc: ArgumentDescriptor<spirv::Word>,
@@ -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::MovOperand<&str>>,
- _: ast::Type,
- ) -> Result<ast::MovOperand<spirv::Word>, 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<Op> {
@@ -2479,7 +2403,7 @@ impl<T: ArgParamsEx> ast::Instruction<T> {
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<T: ArgParamsEx> ast::Instruction<T> {
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<T: ArgParamsEx> ast::Instruction<T> {
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<T: ArgParamsEx> ast::Instruction<T> {
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<ast::MovOperand<spirv::Word>>,
- t: ast::Type,
- ) -> Result<ast::MovOperand<spirv::Word>, 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<T: ArgParamsEx> ast::Arg2<T> {
fn map<U: ArgParamsEx, V: ArgumentMapVisitor<T, U>>(
self,
visitor: &mut V,
+ src_is_addr: bool,
t: ast::Type,
) -> Result<ast::Arg2<U>, TranslateError> {
let new_dst = visitor.variable(
@@ -2850,7 +2754,11 @@ impl<T: ArgParamsEx> ast::Arg2<T> {
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<T: ArgParamsEx> ast::Arg2<T> {
}
}
-impl<T: ArgParamsEx> ast::Arg2Mov<T> {
- fn map<U: ArgParamsEx, V: ArgumentMapVisitor<T, U>>(
- self,
- visitor: &mut V,
- t: ast::Type,
- ) -> Result<ast::Arg2Mov<U>, 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<T> ast::MovOperand<T> {
- 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<T: ArgParamsEx> ast::Arg2St<T> {
fn map<U: ArgParamsEx, V: ArgumentMapVisitor<T, U>>(
self,