Make vector extraction honor relaxed implicit conversion semantics

This commit is contained in:
Andrzej Janik 2021-06-06 00:10:26 +02:00
commit 491e71e346

View file

@ -1560,6 +1560,12 @@ impl<'a, 'b> VectorRepackVisitor<'a, 'b> {
fn convert_vector( fn convert_vector(
&mut self, &mut self,
is_dst: bool, is_dst: bool,
non_default_implicit_conversion: Option<
fn(
(ast::StateSpace, &ast::Type),
(ast::StateSpace, &ast::Type),
) -> Result<Option<ConversionKind>, TranslateError>,
>,
typ: &ast::Type, typ: &ast::Type,
state_space: ast::StateSpace, state_space: ast::StateSpace,
idx: Vec<spirv::Word>, idx: Vec<spirv::Word>,
@ -1577,6 +1583,7 @@ impl<'a, 'b> VectorRepackVisitor<'a, 'b> {
typ: scalar_t, typ: scalar_t,
packed: temp_vec, packed: temp_vec,
unpacked: idx, unpacked: idx,
non_default_implicit_conversion,
}); });
if is_dst { if is_dst {
self.post_stmts = Some(statement); self.post_stmts = Some(statement);
@ -1609,9 +1616,13 @@ impl<'a, 'b> ArgumentMapVisitor<NormalizedArgParams, TypedArgParams>
ast::Operand::RegOffset(reg, offset) => TypedOperand::RegOffset(reg, offset), ast::Operand::RegOffset(reg, offset) => TypedOperand::RegOffset(reg, offset),
ast::Operand::Imm(x) => TypedOperand::Imm(x), ast::Operand::Imm(x) => TypedOperand::Imm(x),
ast::Operand::VecMember(vec, idx) => TypedOperand::VecMember(vec, idx), ast::Operand::VecMember(vec, idx) => TypedOperand::VecMember(vec, idx),
ast::Operand::VecPack(vec) => { ast::Operand::VecPack(vec) => TypedOperand::Reg(self.convert_vector(
TypedOperand::Reg(self.convert_vector(desc.is_dst, typ, state_space, vec)?) desc.is_dst,
} desc.non_default_implicit_conversion,
typ,
state_space,
vec,
)?),
}) })
} }
} }
@ -5320,6 +5331,12 @@ struct RepackVectorDetails {
typ: ast::ScalarType, typ: ast::ScalarType,
packed: spirv::Word, packed: spirv::Word,
unpacked: Vec<spirv::Word>, unpacked: Vec<spirv::Word>,
non_default_implicit_conversion: Option<
fn(
(ast::StateSpace, &ast::Type),
(ast::StateSpace, &ast::Type),
) -> Result<Option<ConversionKind>, TranslateError>,
>,
} }
impl RepackVectorDetails { impl RepackVectorDetails {
@ -5335,7 +5352,6 @@ impl RepackVectorDetails {
ArgumentDescriptor { ArgumentDescriptor {
op: self.packed, op: self.packed,
is_dst: !self.is_extract, is_dst: !self.is_extract,
non_default_implicit_conversion: None, non_default_implicit_conversion: None,
}, },
Some(( Some((
@ -5345,6 +5361,7 @@ impl RepackVectorDetails {
)?; )?;
let scalar_type = self.typ; let scalar_type = self.typ;
let is_extract = self.is_extract; let is_extract = self.is_extract;
let non_default_implicit_conversion = self.non_default_implicit_conversion;
let vector = self let vector = self
.unpacked .unpacked
.into_iter() .into_iter()
@ -5353,7 +5370,7 @@ impl RepackVectorDetails {
ArgumentDescriptor { ArgumentDescriptor {
op: id, op: id,
is_dst: is_extract, is_dst: is_extract,
non_default_implicit_conversion: None, non_default_implicit_conversion,
}, },
Some((&ast::Type::Scalar(scalar_type), ast::StateSpace::Reg)), Some((&ast::Type::Scalar(scalar_type), ast::StateSpace::Reg)),
) )
@ -5364,6 +5381,7 @@ impl RepackVectorDetails {
typ: self.typ, typ: self.typ,
packed: scalar, packed: scalar,
unpacked: vector, unpacked: vector,
non_default_implicit_conversion,
}) })
} }
} }
@ -7168,6 +7186,19 @@ impl ast::StateSpace {
|| self == ast::StateSpace::Sreg && other == ast::StateSpace::Reg || self == ast::StateSpace::Sreg && other == ast::StateSpace::Reg
} }
fn coerces_to_generic(self) -> bool {
match self {
ast::StateSpace::Global
| ast::StateSpace::Const
| ast::StateSpace::Local
| ast::StateSpace::Shared => true,
ast::StateSpace::Reg
| ast::StateSpace::Param
| ast::StateSpace::Generic
| ast::StateSpace::Sreg => false,
}
}
fn is_addressable(self) -> bool { fn is_addressable(self) -> bool {
match self { match self {
ast::StateSpace::Const ast::StateSpace::Const
@ -7254,7 +7285,11 @@ fn default_implicit_conversion_space(
(operand_space, operand_type): (ast::StateSpace, &ast::Type), (operand_space, operand_type): (ast::StateSpace, &ast::Type),
(instruction_space, instruction_type): (ast::StateSpace, &ast::Type), (instruction_space, instruction_type): (ast::StateSpace, &ast::Type),
) -> Result<Option<ConversionKind>, TranslateError> { ) -> Result<Option<ConversionKind>, TranslateError> {
if operand_space.is_compatible(ast::StateSpace::Reg) { if (instruction_space == ast::StateSpace::Generic && operand_space.coerces_to_generic())
|| (operand_space == ast::StateSpace::Generic && instruction_space.coerces_to_generic())
{
Ok(Some(ConversionKind::PtrToPtr))
} else if operand_space.is_compatible(ast::StateSpace::Reg) {
match operand_type { match operand_type {
ast::Type::Pointer(operand_ptr_type, operand_ptr_space) ast::Type::Pointer(operand_ptr_type, operand_ptr_space)
if *operand_ptr_space == instruction_space => if *operand_ptr_space == instruction_space =>