use cranelift_codegen::ir::condcodes::IntCC;
use cranelift_codegen::ir::types;
use cranelift_codegen::ir::{InstBuilder, MemFlags, Type};
use cranelift_frontend::FunctionBuilder;
use super::block_args;
pub(super) fn build_transform_edges(mut bcx: FunctionBuilder, ptr_type: Type) {
let entry = bcx.create_block();
let loop_body = bcx.create_block();
let exit = bcx.create_block();
bcx.append_block_params_for_function_params(entry);
bcx.switch_to_block(entry);
bcx.seal_block(entry);
let edges_ptr = bcx.block_params(entry)[0]; let count = bcx.block_params(entry)[1]; let m00 = bcx.block_params(entry)[2]; let m01 = bcx.block_params(entry)[3];
let m10 = bcx.block_params(entry)[4];
let m11 = bcx.block_params(entry)[5];
let m20 = bcx.block_params(entry)[6];
let m21 = bcx.block_params(entry)[7];
let col_a = bcx.ins().splat(types::F64X2, m00);
let col_a = bcx.ins().insertlane(col_a, m01, 1);
let col_c = bcx.ins().splat(types::F64X2, m10);
let col_c = bcx.ins().insertlane(col_c, m11, 1);
let trans = bcx.ins().splat(types::F64X2, m20);
let trans = bcx.ins().insertlane(trans, m21, 1);
let zero = bcx.ins().iconst(ptr_type, 0);
let is_zero = bcx.ins().icmp(IntCC::Equal, count, zero);
bcx.ins().brif(
is_zero,
exit,
&[],
loop_body,
&block_args(&[edges_ptr, count]),
);
bcx.append_block_param(loop_body, ptr_type); bcx.append_block_param(loop_body, ptr_type); bcx.switch_to_block(loop_body);
let ptr = bcx.block_params(loop_body)[0];
let remaining = bcx.block_params(loop_body)[1];
let mem = MemFlags::trusted();
let p0 = bcx.ins().load(types::F64X2, mem, ptr, 0);
let x0 = bcx.ins().extractlane(p0, 0);
let x0_splat = bcx.ins().splat(types::F64X2, x0);
let y0 = bcx.ins().extractlane(p0, 1);
let y0_splat = bcx.ins().splat(types::F64X2, y0);
let r0 = bcx.ins().fmul(x0_splat, col_a);
let r0 = bcx.ins().fma(y0_splat, col_c, r0);
let r0 = bcx.ins().fadd(r0, trans);
let p1 = bcx.ins().load(types::F64X2, mem, ptr, 16);
let x1 = bcx.ins().extractlane(p1, 0);
let x1_splat = bcx.ins().splat(types::F64X2, x1);
let y1 = bcx.ins().extractlane(p1, 1);
let y1_splat = bcx.ins().splat(types::F64X2, y1);
let r1 = bcx.ins().fmul(x1_splat, col_a);
let r1 = bcx.ins().fma(y1_splat, col_c, r1);
let r1 = bcx.ins().fadd(r1, trans);
bcx.ins().store(mem, r0, ptr, 0);
bcx.ins().store(mem, r1, ptr, 16);
let stride = bcx.ins().iconst(ptr_type, 32);
let next_ptr = bcx.ins().iadd(ptr, stride);
let one = bcx.ins().iconst(ptr_type, 1);
let next_remaining = bcx.ins().isub(remaining, one);
let done = bcx.ins().icmp(IntCC::Equal, next_remaining, zero);
bcx.ins().brif(
done,
exit,
&[],
loop_body,
&block_args(&[next_ptr, next_remaining]),
);
bcx.switch_to_block(exit);
bcx.seal_block(exit);
bcx.seal_block(loop_body);
bcx.ins().return_(&[]);
bcx.finalize();
}