[spv-out] Add multiply instructions (#219)

This commit is contained in:
Timo de Kort
2020-10-06 22:57:30 +02:00
committed by GitHub
parent 773408663b
commit f67dfd251a
2 changed files with 205 additions and 43 deletions

View File

@@ -520,6 +520,34 @@ pub(super) fn instruction_composite_construct(
// Arithmetic Instructions
//
pub(super) fn instruction_i_mul(
result_type_id: Word,
id: Word,
operand_1: Word,
operand_2: Word,
) -> Instruction {
let mut instruction = Instruction::new(Op::IMul);
instruction.set_type(result_type_id);
instruction.set_result(id);
instruction.add_operand(operand_1);
instruction.add_operand(operand_2);
instruction
}
pub(super) fn instruction_f_mul(
result_type_id: Word,
id: Word,
operand_1: Word,
operand_2: Word,
) -> Instruction {
let mut instruction = Instruction::new(Op::FMul);
instruction.set_type(result_type_id);
instruction.set_result(id);
instruction.add_operand(operand_1);
instruction.add_operand(operand_2);
instruction
}
pub(super) fn instruction_vector_times_scalar(
result_type_id: Word,
id: Word,
@@ -534,6 +562,62 @@ pub(super) fn instruction_vector_times_scalar(
instruction
}
pub(super) fn instruction_matrix_times_scalar(
result_type_id: Word,
id: Word,
matrix_id: Word,
scalar_id: Word,
) -> Instruction {
let mut instruction = Instruction::new(Op::MatrixTimesScalar);
instruction.set_type(result_type_id);
instruction.set_result(id);
instruction.add_operand(matrix_id);
instruction.add_operand(scalar_id);
instruction
}
pub(super) fn instruction_vector_times_matrix(
result_type_id: Word,
id: Word,
vector_id: Word,
matrix_id: Word,
) -> Instruction {
let mut instruction = Instruction::new(Op::VectorTimesMatrix);
instruction.set_type(result_type_id);
instruction.set_result(id);
instruction.add_operand(vector_id);
instruction.add_operand(matrix_id);
instruction
}
pub(super) fn instruction_matrix_times_vector(
result_type_id: Word,
id: Word,
matrix_id: Word,
vector_id: Word,
) -> Instruction {
let mut instruction = Instruction::new(Op::MatrixTimesVector);
instruction.set_type(result_type_id);
instruction.set_result(id);
instruction.add_operand(matrix_id);
instruction.add_operand(vector_id);
instruction
}
pub(super) fn instruction_matrix_times_matrix(
result_type_id: Word,
id: Word,
left_matrix: Word,
right_matrix: Word,
) -> Instruction {
let mut instruction = Instruction::new(Op::MatrixTimesMatrix);
instruction.set_type(result_type_id);
instruction.set_result(id);
instruction.add_operand(left_matrix);
instruction.add_operand(right_matrix);
instruction
}
//
// Bit Instructions
//

View File

@@ -875,7 +875,6 @@ impl Writer {
crate::Expression::Binary { op, left, right } => {
match op {
crate::BinaryOperator::Multiply => {
// TODO OpVectorTimesScalar is only supported
let id = self.generate_id();
let left_expression = &ir_function.expressions[*left];
let right_expression = &ir_function.expressions[*right];
@@ -898,53 +897,129 @@ impl Writer {
)
.unwrap();
let left_ty_inner = &ir_module.types[left_ty.unwrap()].inner;
let right_ty_inner = &ir_module.types[right_ty.unwrap()].inner;
let left_ty = left_ty.unwrap();
let right_ty = right_ty.unwrap();
let (result_type_id, vector_id, scalar_id) =
match (left_ty_inner, right_ty_inner) {
(
crate::TypeInner::Vector { .. },
crate::TypeInner::Scalar { .. },
) => (
self.get_type_id(
&ir_module.types,
LookupType::Handle(left_ty.unwrap()),
),
let left_ty_inner = &ir_module.types[left_ty].inner;
let right_ty_inner = &ir_module.types[right_ty].inner;
let left_result_type_id =
self.get_type_id(&ir_module.types, LookupType::Handle(left_ty));
let right_result_type_id =
self.get_type_id(&ir_module.types, LookupType::Handle(right_ty));
let left_id = match *left_expression {
crate::Expression::LocalVariable(_)
| crate::Expression::GlobalVariable(_) => {
let load_id = self.generate_id();
block.body.push(super::instructions::instruction_load(
left_result_type_id,
load_id,
left_id,
None,
));
load_id
}
_ => left_id,
};
let right_id = match *right_expression {
crate::Expression::LocalVariable(..)
| crate::Expression::GlobalVariable(..) => {
let load_id = self.generate_id();
block.body.push(super::instructions::instruction_load(
right_result_type_id,
load_id,
right_id,
),
(
crate::TypeInner::Scalar { .. },
crate::TypeInner::Vector { .. },
) => (
self.get_type_id(
&ir_module.types,
LookupType::Handle(right_ty.unwrap()),
None,
));
load_id
}
_ => right_id,
};
let (instruction, ty) = match left_ty_inner {
crate::TypeInner::Vector { .. } => match right_ty_inner {
crate::TypeInner::Scalar { .. } => (
super::instructions::instruction_vector_times_scalar(
left_result_type_id,
id,
left_id,
right_id,
),
right_id,
left_id,
left_ty,
),
_ => unreachable!("Expression requires both a scalar and vector"),
};
crate::TypeInner::Matrix { .. } => (
super::instructions::instruction_vector_times_matrix(
left_result_type_id,
id,
left_id,
right_id,
),
left_ty,
),
_ => unreachable!(),
},
crate::TypeInner::Matrix { .. } => match right_ty_inner {
crate::TypeInner::Scalar { .. } => (
super::instructions::instruction_matrix_times_scalar(
left_result_type_id,
id,
left_id,
right_id,
),
left_ty,
),
crate::TypeInner::Vector { .. } => (
super::instructions::instruction_matrix_times_vector(
right_result_type_id,
id,
left_id,
right_id,
),
right_ty,
),
crate::TypeInner::Matrix { .. } => (
super::instructions::instruction_matrix_times_matrix(
left_result_type_id,
id,
left_id,
right_id,
),
left_ty,
),
_ => unreachable!(),
},
crate::TypeInner::Scalar { kind, .. } => {
// Always assuming left and hand side are equal scalar types.
match kind {
crate::ScalarKind::Float => (
super::instructions::instruction_f_mul(
left_result_type_id,
id,
left_id,
right_id,
),
left_ty,
),
crate::ScalarKind::Sint | crate::ScalarKind::Uint => (
super::instructions::instruction_i_mul(
left_result_type_id,
id,
left_id,
right_id,
),
left_ty,
),
_ => unreachable!(),
}
}
_ => unreachable!(),
};
let load_id = self.generate_id();
let load_instruction = super::instructions::instruction_load(
result_type_id,
load_id,
vector_id,
None,
);
block.body.push(load_instruction);
let instruction = super::instructions::instruction_vector_times_scalar(
result_type_id,
id,
load_id,
scalar_id,
);
block.body.push(instruction);
Some((id, None))
Some((id, Some(ty)))
}
_ => unimplemented!("{:?}", op),
@@ -1144,7 +1219,8 @@ impl Writer {
.unwrap();
let id = match *expression {
crate::Expression::LocalVariable(_) => {
crate::Expression::LocalVariable(_)
| crate::Expression::GlobalVariable(_) => {
let load_id = self.generate_id();
let value_ty_id = self.get_type_id(
&ir_module.types,
@@ -1158,6 +1234,7 @@ impl Writer {
));
load_id
}
_ => id,
};
super::instructions::instruction_return_value(id)
@@ -1188,7 +1265,8 @@ impl Writer {
.unwrap();
let value_id = match value_expression {
crate::Expression::LocalVariable(_) => {
crate::Expression::LocalVariable(_)
| crate::Expression::GlobalVariable(_) => {
let load_id = self.generate_id();
let value_ty_id = self.get_type_id(
&ir_module.types,