Import SIMD feature and add some workload samples (#438)
This commit is contained in:
381
core/iwasm/compilation/simd/simd_access_lanes.c
Normal file
381
core/iwasm/compilation/simd/simd_access_lanes.c
Normal file
@ -0,0 +1,381 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "simd_access_lanes.h"
|
||||
#include "simd_common.h"
|
||||
#include "../aot_emit_exception.h"
|
||||
#include "../../aot/aot_runtime.h"
|
||||
|
||||
static LLVMValueRef
|
||||
build_intx16_vector(const AOTCompContext *comp_ctx,
|
||||
const LLVMTypeRef element_type,
|
||||
const int *element_value)
|
||||
{
|
||||
LLVMValueRef vector, elements[16];
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
if (!(elements[i] =
|
||||
LLVMConstInt(element_type, element_value[i], true))) {
|
||||
HANDLE_FAILURE("LLVMConstInst");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(vector = LLVMConstVector(elements, 16))) {
|
||||
HANDLE_FAILURE("LLVMConstVector");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return vector;
|
||||
fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_shuffle(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
const uint8 *frame_ip)
|
||||
{
|
||||
LLVMValueRef vec1, vec2, mask, result;
|
||||
uint8 imm[16] = { 0 };
|
||||
int values[16];
|
||||
unsigned i;
|
||||
|
||||
wasm_runtime_read_v128(frame_ip, (uint64 *)imm, (uint64 *)(imm + 8));
|
||||
for (i = 0; i < 16; i++) {
|
||||
values[i] = imm[i];
|
||||
}
|
||||
|
||||
if (!(vec2 = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, V128_i8x16_TYPE,
|
||||
"vec2"))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(vec1 = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, V128_i8x16_TYPE,
|
||||
"vec1"))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* build a vector <16 x i32> */
|
||||
if (!(mask = build_intx16_vector(comp_ctx, I32_TYPE, values))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(result = LLVMBuildShuffleVector(comp_ctx->builder, vec1, vec2, mask,
|
||||
"new_vector"))) {
|
||||
HANDLE_FAILURE("LLVMBuildShuffleVector");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE,
|
||||
"ret"))) {
|
||||
HANDLE_FAILURE("LLVMBuildBitCast");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
PUSH_V128(result);
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: instructions for other CPUs
|
||||
/* shufflevector is not an option, since it requires *mask as a const */
|
||||
bool
|
||||
aot_compile_simd_swizzle(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||
{
|
||||
LLVMValueRef vector, mask, max_lanes, condition, mask_lanes, result;
|
||||
LLVMTypeRef param_types[2];
|
||||
int max_lane_id[16] = { 16, 16, 16, 16, 16, 16, 16, 16,
|
||||
16, 16, 16, 16, 16, 16, 16, 16 },
|
||||
mask_lane_id[16] = { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||||
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 };
|
||||
|
||||
if (!(mask = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, V128_i8x16_TYPE,
|
||||
"mask"))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx,
|
||||
V128_i8x16_TYPE, "vec"))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* icmp uge <16 x i8> mask, <16, 16, 16, 16, ...> */
|
||||
if (!(max_lanes = build_intx16_vector(comp_ctx, INT8_TYPE, max_lane_id))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(condition = LLVMBuildICmp(comp_ctx->builder, LLVMIntUGE, mask,
|
||||
max_lanes, "compare_with_16"))) {
|
||||
HANDLE_FAILURE("LLVMBuldICmp");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* if the highest bit of every i8 of mask is 1, means doesn't pick up from vector */
|
||||
/* select <16 x i1> %condition, <16 x i8> <0x80, 0x80, ...>, <16 x i8> %mask */
|
||||
if (!(mask_lanes =
|
||||
build_intx16_vector(comp_ctx, INT8_TYPE, mask_lane_id))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(mask = LLVMBuildSelect(comp_ctx->builder, condition, mask_lanes,
|
||||
mask, "mask"))) {
|
||||
HANDLE_FAILURE("LLVMBuildSelect");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
param_types[0] = V128_i8x16_TYPE;
|
||||
param_types[1] = V128_i8x16_TYPE;
|
||||
if (!(result = aot_call_llvm_intrinsic(
|
||||
comp_ctx, "llvm.x86.ssse3.pshuf.b.128", V128_i8x16_TYPE,
|
||||
param_types, 2, vector, mask))) {
|
||||
HANDLE_FAILURE("LLVMBuildCall");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE,
|
||||
"ret"))) {
|
||||
HANDLE_FAILURE("LLVMBuildBitCast");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
PUSH_V128(result);
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
aot_compile_simd_extract(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint8 lane_id,
|
||||
bool need_extend,
|
||||
bool is_signed,
|
||||
LLVMTypeRef vector_type,
|
||||
LLVMTypeRef result_type,
|
||||
unsigned aot_value_type)
|
||||
{
|
||||
LLVMValueRef vector, idx, result;
|
||||
|
||||
if (!(idx = I8_CONST(lane_id))) {
|
||||
HANDLE_FAILURE("LLVMConstInt");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* bitcast <2 x i64> %0 to <vector_type> */
|
||||
if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
|
||||
"vec"))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* extractelement <vector_type> %vector, i8 lane_id*/
|
||||
if (!(result = LLVMBuildExtractElement(comp_ctx->builder, vector, idx,
|
||||
"element"))) {
|
||||
HANDLE_FAILURE("LLVMBuildExtractElement");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (need_extend) {
|
||||
if (is_signed) {
|
||||
/* sext <element_type> %element to <result_type> */
|
||||
if (!(result = LLVMBuildSExt(comp_ctx->builder, result,
|
||||
result_type, "ret"))) {
|
||||
HANDLE_FAILURE("LLVMBuildSExt");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* sext <element_type> %element to <result_type> */
|
||||
if (!(result = LLVMBuildZExt(comp_ctx->builder, result,
|
||||
result_type, "ret"))) {
|
||||
HANDLE_FAILURE("LLVMBuildZExt");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PUSH(result, aot_value_type);
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_extract_i8x16(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint8 lane_id,
|
||||
bool is_signed)
|
||||
{
|
||||
return aot_compile_simd_extract(comp_ctx, func_ctx, lane_id, true,
|
||||
is_signed, V128_i8x16_TYPE, I32_TYPE,
|
||||
VALUE_TYPE_I32);
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_extract_i16x8(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint8 lane_id,
|
||||
bool is_signed)
|
||||
{
|
||||
return aot_compile_simd_extract(comp_ctx, func_ctx, lane_id, true,
|
||||
is_signed, V128_i16x8_TYPE, I32_TYPE,
|
||||
VALUE_TYPE_I32);
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_extract_i32x4(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint8 lane_id)
|
||||
{
|
||||
return aot_compile_simd_extract(comp_ctx, func_ctx, lane_id, false, false,
|
||||
V128_i32x4_TYPE, I32_TYPE, VALUE_TYPE_I32);
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_extract_i64x2(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint8 lane_id)
|
||||
{
|
||||
return aot_compile_simd_extract(comp_ctx, func_ctx, lane_id, false, false,
|
||||
V128_i64x2_TYPE, I64_TYPE, VALUE_TYPE_I64);
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_extract_f32x4(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint8 lane_id)
|
||||
{
|
||||
return aot_compile_simd_extract(comp_ctx, func_ctx, lane_id, false, false,
|
||||
V128_f32x4_TYPE, F32_TYPE, VALUE_TYPE_F32);
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_extract_f64x2(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint8 lane_id)
|
||||
{
|
||||
return aot_compile_simd_extract(comp_ctx, func_ctx, lane_id, false, false,
|
||||
V128_f64x2_TYPE, F64_TYPE, VALUE_TYPE_F64);
|
||||
}
|
||||
|
||||
static bool
|
||||
aot_compile_simd_replace(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint8 lane_id,
|
||||
unsigned new_value_type,
|
||||
LLVMTypeRef vector_type,
|
||||
bool need_reduce,
|
||||
LLVMTypeRef element_type)
|
||||
{
|
||||
LLVMValueRef vector, new_value, idx, result;
|
||||
|
||||
POP(new_value, new_value_type);
|
||||
|
||||
if (!(idx = I8_CONST(lane_id))) {
|
||||
HANDLE_FAILURE("LLVMConstInt");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* bitcast <2 x i64> %0 to <vector_type> */
|
||||
|
||||
if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
|
||||
"vec"))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* bitcast <new_value_type> to <element_type> */
|
||||
if (need_reduce) {
|
||||
if (!(new_value = LLVMBuildTrunc(comp_ctx->builder, new_value,
|
||||
element_type, "element"))) {
|
||||
HANDLE_FAILURE("LLVMBuildTrunc");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* insertelement <vector_type> %vector, <element_type> %element, i8 idx */
|
||||
if (!(result = LLVMBuildInsertElement(comp_ctx->builder, vector, new_value,
|
||||
idx, "new_vector"))) {
|
||||
HANDLE_FAILURE("LLVMBuildInsertElement");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* bitcast <vector_type> %result to <2 x i64> */
|
||||
if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE,
|
||||
"ret"))) {
|
||||
HANDLE_FAILURE("LLVMBuildBitCast");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
PUSH_V128(result);
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_replace_i8x16(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint8 lane_id)
|
||||
{
|
||||
return aot_compile_simd_replace(comp_ctx, func_ctx, lane_id,
|
||||
VALUE_TYPE_I32, V128_i8x16_TYPE, true,
|
||||
INT8_TYPE);
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_replace_i16x8(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint8 lane_id)
|
||||
{
|
||||
return aot_compile_simd_replace(comp_ctx, func_ctx, lane_id,
|
||||
VALUE_TYPE_I32, V128_i16x8_TYPE, true,
|
||||
INT16_TYPE);
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_replace_i32x4(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint8 lane_id)
|
||||
{
|
||||
return aot_compile_simd_replace(comp_ctx, func_ctx, lane_id,
|
||||
VALUE_TYPE_I32, V128_i32x4_TYPE, false,
|
||||
I32_TYPE);
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_replace_i64x2(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint8 lane_id)
|
||||
{
|
||||
return aot_compile_simd_replace(comp_ctx, func_ctx, lane_id,
|
||||
VALUE_TYPE_I64, V128_i64x2_TYPE, false,
|
||||
I64_TYPE);
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_replace_f32x4(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint8 lane_id)
|
||||
{
|
||||
return aot_compile_simd_replace(comp_ctx, func_ctx, lane_id,
|
||||
VALUE_TYPE_F32, V128_f32x4_TYPE, false,
|
||||
F32_TYPE);
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_replace_f64x2(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint8 lane_id)
|
||||
{
|
||||
return aot_compile_simd_replace(comp_ctx, func_ctx, lane_id,
|
||||
VALUE_TYPE_F64, V128_f64x2_TYPE, false,
|
||||
F64_TYPE);
|
||||
}
|
||||
89
core/iwasm/compilation/simd/simd_access_lanes.h
Normal file
89
core/iwasm/compilation/simd/simd_access_lanes.h
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef _SIMD_ACCESS_LANES_H_
|
||||
#define _SIMD_ACCESS_LANES_H_
|
||||
|
||||
#include "../aot_compiler.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
bool
|
||||
aot_compile_simd_shuffle(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
const uint8 *frame_ip);
|
||||
|
||||
bool
|
||||
aot_compile_simd_swizzle(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
|
||||
|
||||
bool
|
||||
aot_compile_simd_extract_i8x16(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint8 lane_id,
|
||||
bool is_signed);
|
||||
|
||||
bool
|
||||
aot_compile_simd_extract_i16x8(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint8 lane_id,
|
||||
bool is_signed);
|
||||
|
||||
bool
|
||||
aot_compile_simd_extract_i32x4(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint8 lane_id);
|
||||
|
||||
bool
|
||||
aot_compile_simd_extract_i64x2(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint8 lane_id);
|
||||
|
||||
bool
|
||||
aot_compile_simd_extract_f32x4(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint8 lane_id);
|
||||
|
||||
bool
|
||||
aot_compile_simd_extract_f64x2(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint8 lane_id);
|
||||
|
||||
bool
|
||||
aot_compile_simd_replace_i8x16(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint8 lane_id);
|
||||
|
||||
bool
|
||||
aot_compile_simd_replace_i16x8(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint8 lane_id);
|
||||
|
||||
bool
|
||||
aot_compile_simd_replace_i32x4(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint8 lane_id);
|
||||
|
||||
bool
|
||||
aot_compile_simd_replace_i64x2(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint8 lane_id);
|
||||
|
||||
bool
|
||||
aot_compile_simd_replace_f32x4(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint8 lane_id);
|
||||
|
||||
bool
|
||||
aot_compile_simd_replace_f64x2(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint8 lane_id);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* end of _SIMD_ACCESS_LANES_H_ */
|
||||
164
core/iwasm/compilation/simd/simd_bit_shifts.c
Normal file
164
core/iwasm/compilation/simd/simd_bit_shifts.c
Normal file
@ -0,0 +1,164 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "simd_bit_shifts.h"
|
||||
#include "simd_common.h"
|
||||
#include "../aot_emit_exception.h"
|
||||
#include "../../aot/aot_runtime.h"
|
||||
|
||||
static bool
|
||||
simd_shift(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
IntShift shift_op,
|
||||
LLVMTypeRef vector_type,
|
||||
LLVMTypeRef element_type,
|
||||
unsigned lane_width)
|
||||
{
|
||||
LLVMValueRef vector, offset, width, undef, zeros, result;
|
||||
LLVMTypeRef zeros_type;
|
||||
|
||||
POP_I32(offset);
|
||||
|
||||
if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
|
||||
"vec"))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(width = LLVMConstInt(I32_TYPE, lane_width, true))) {
|
||||
HANDLE_FAILURE("LLVMConstInt");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(offset =
|
||||
LLVMBuildURem(comp_ctx->builder, offset, width, "remainder"))) {
|
||||
HANDLE_FAILURE("LLVMBuildURem");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (I64_TYPE == element_type) {
|
||||
if (!(offset = LLVMBuildZExt(comp_ctx->builder, offset, element_type,
|
||||
"offset_scalar"))) {
|
||||
HANDLE_FAILURE("LLVMBuildZExt");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!(offset = LLVMBuildTruncOrBitCast(
|
||||
comp_ctx->builder, offset, element_type, "offset_scalar"))) {
|
||||
HANDLE_FAILURE("LLVMBuildTrunc");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* create a vector with offset */
|
||||
if (!(undef = LLVMGetUndef(vector_type))) {
|
||||
HANDLE_FAILURE("LLVMGetUndef");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(zeros_type = LLVMVectorType(I32_TYPE, 128 / lane_width))) {
|
||||
HANDLE_FAILURE("LVMVectorType");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(zeros = LLVMConstNull(zeros_type))) {
|
||||
HANDLE_FAILURE("LLVMConstNull");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(offset = LLVMBuildInsertElement(comp_ctx->builder, undef, offset,
|
||||
I32_ZERO, "base_vector"))) {
|
||||
HANDLE_FAILURE("LLVMBuildInsertElement");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(offset = LLVMBuildShuffleVector(comp_ctx->builder, offset, undef,
|
||||
zeros, "offset_vector"))) {
|
||||
HANDLE_FAILURE("LLVMBuildShuffleVector");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
switch (shift_op) {
|
||||
case INT_SHL:
|
||||
{
|
||||
if (!(result =
|
||||
LLVMBuildShl(comp_ctx->builder, vector, offset, "shl"))) {
|
||||
HANDLE_FAILURE("LLVMBuildShl");
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case INT_SHR_S:
|
||||
{
|
||||
if (!(result = LLVMBuildAShr(comp_ctx->builder, vector, offset,
|
||||
"ashr"))) {
|
||||
HANDLE_FAILURE("LLVMBuildAShr");
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case INT_SHR_U:
|
||||
{
|
||||
if (!(result = LLVMBuildLShr(comp_ctx->builder, vector, offset,
|
||||
"lshr"))) {
|
||||
HANDLE_FAILURE("LLVMBuildLShr");
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
bh_assert(0);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE,
|
||||
"result"))) {
|
||||
HANDLE_FAILURE("LLVMBuildBitCast");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
PUSH_V128(result);
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_i8x16_shift(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
IntShift shift_op)
|
||||
{
|
||||
return simd_shift(comp_ctx, func_ctx, shift_op, V128_i8x16_TYPE, INT8_TYPE,
|
||||
8);
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_i16x8_shift(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
IntShift shift_op)
|
||||
{
|
||||
return simd_shift(comp_ctx, func_ctx, shift_op, V128_i16x8_TYPE,
|
||||
INT16_TYPE, 16);
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_i32x4_shift(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
IntShift shift_op)
|
||||
{
|
||||
return simd_shift(comp_ctx, func_ctx, shift_op, V128_i32x4_TYPE, I32_TYPE,
|
||||
32);
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_i64x2_shift(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
IntShift shift_op)
|
||||
{
|
||||
return simd_shift(comp_ctx, func_ctx, shift_op, V128_i64x2_TYPE, I64_TYPE,
|
||||
64);
|
||||
}
|
||||
39
core/iwasm/compilation/simd/simd_bit_shifts.h
Normal file
39
core/iwasm/compilation/simd/simd_bit_shifts.h
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef _SIMD_BIT_SHIFTS_H_
|
||||
#define _SIMD_BIT_SHIFTS_H_
|
||||
|
||||
#include "../aot_compiler.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
bool
|
||||
aot_compile_simd_i8x16_shift(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
IntShift shift_op);
|
||||
|
||||
bool
|
||||
aot_compile_simd_i16x8_shift(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
IntShift shift_op);
|
||||
|
||||
bool
|
||||
aot_compile_simd_i32x4_shift(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
IntShift shift_op);
|
||||
|
||||
bool
|
||||
aot_compile_simd_i64x2_shift(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
IntShift shift_op);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* end of _SIMD_BIT_SHIFTS_H_ */
|
||||
109
core/iwasm/compilation/simd/simd_bitmask_extracts.c
Normal file
109
core/iwasm/compilation/simd/simd_bitmask_extracts.c
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "simd_bitmask_extracts.h"
|
||||
#include "simd_common.h"
|
||||
#include "../aot_emit_exception.h"
|
||||
#include "../../aot/aot_runtime.h"
|
||||
|
||||
static bool
|
||||
simd_build_bitmask(const AOTCompContext *comp_ctx,
|
||||
const AOTFuncContext *func_ctx,
|
||||
uint8 length,
|
||||
LLVMTypeRef vector_type,
|
||||
LLVMTypeRef element_type,
|
||||
const char *intrinsic)
|
||||
{
|
||||
LLVMValueRef vector, zeros, mask, mask_elements[16], cond, result;
|
||||
LLVMTypeRef param_types[1], vector_ext_type;
|
||||
const uint32 numbers[16] = { 0x1, 0x2, 0x4, 0x8, 0x10, 0x20,
|
||||
0x40, 0x80, 0x100, 0x200, 0x400, 0x800,
|
||||
0x1000, 0x2000, 0x4000, 0x8000 };
|
||||
uint8 i;
|
||||
|
||||
if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
|
||||
"vec"))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(vector_ext_type = LLVMVectorType(I32_TYPE, length))) {
|
||||
HANDLE_FAILURE("LLVMVectorType");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(vector = LLVMBuildSExt(comp_ctx->builder, vector, vector_ext_type,
|
||||
"vec_ext"))) {
|
||||
HANDLE_FAILURE("LLVMBuildSExt");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(zeros = LLVMConstNull(vector_ext_type))) {
|
||||
HANDLE_FAILURE("LLVMConstNull");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
if (!(mask_elements[i] = LLVMConstInt(I32_TYPE, numbers[i], false))) {
|
||||
HANDLE_FAILURE("LLVMConstInt");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(mask = LLVMConstVector(mask_elements, length))) {
|
||||
HANDLE_FAILURE("LLVMConstVector");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(cond = LLVMBuildICmp(comp_ctx->builder, LLVMIntSLT, vector, zeros,
|
||||
"lt_zero"))) {
|
||||
HANDLE_FAILURE("LLVMBuildICmp");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(result =
|
||||
LLVMBuildSelect(comp_ctx->builder, cond, mask, zeros, "select"))) {
|
||||
HANDLE_FAILURE("LLVMBuildSelect");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
param_types[0] = vector_ext_type;
|
||||
if (!(result = aot_call_llvm_intrinsic(comp_ctx, intrinsic, I32_TYPE,
|
||||
param_types, 1, result))) {
|
||||
HANDLE_FAILURE("LLVMBuildCall");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
PUSH_I32(result);
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_i8x16_bitmask(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx)
|
||||
{
|
||||
return simd_build_bitmask(comp_ctx, func_ctx, 16, V128_i8x16_TYPE,
|
||||
INT8_TYPE,
|
||||
"llvm.experimental.vector.reduce.or.v16i32");
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_i16x8_bitmask(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx)
|
||||
{
|
||||
return simd_build_bitmask(comp_ctx, func_ctx, 8, V128_i16x8_TYPE,
|
||||
INT16_TYPE,
|
||||
"llvm.experimental.vector.reduce.or.v8i32");
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_i32x4_bitmask(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx)
|
||||
{
|
||||
return simd_build_bitmask(comp_ctx, func_ctx, 4, V128_i32x4_TYPE, I32_TYPE,
|
||||
"llvm.experimental.vector.reduce.or.v4i32");
|
||||
}
|
||||
29
core/iwasm/compilation/simd/simd_bitmask_extracts.h
Normal file
29
core/iwasm/compilation/simd/simd_bitmask_extracts.h
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef _SIMD_BITMASK_EXTRACTS_H_
|
||||
#define _SIMD_BITMASK_EXTRACTS_H_
|
||||
|
||||
#include "../aot_compiler.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
bool
|
||||
aot_compile_simd_i8x16_bitmask(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
|
||||
|
||||
bool
|
||||
aot_compile_simd_i16x8_bitmask(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
|
||||
|
||||
bool
|
||||
aot_compile_simd_i32x4_bitmask(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* end of _SIMD_BITMASK_EXTRACTS_H_ */
|
||||
|
||||
146
core/iwasm/compilation/simd/simd_bitwise_ops.c
Normal file
146
core/iwasm/compilation/simd/simd_bitwise_ops.c
Normal file
@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "simd_bitwise_ops.h"
|
||||
#include "../aot_emit_exception.h"
|
||||
#include "../../aot/aot_runtime.h"
|
||||
|
||||
static bool
|
||||
v128_bitwise_two_component(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
V128Bitwise bitwise_op)
|
||||
{
|
||||
LLVMValueRef vector1, vector2, result;
|
||||
|
||||
POP_V128(vector2);
|
||||
POP_V128(vector1);
|
||||
|
||||
switch (bitwise_op) {
|
||||
case V128_AND:
|
||||
if (!(result = LLVMBuildAnd(comp_ctx->builder, vector1, vector2,
|
||||
"and"))) {
|
||||
HANDLE_FAILURE("LLVMBuildAnd");
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
case V128_OR:
|
||||
if (!(result =
|
||||
LLVMBuildOr(comp_ctx->builder, vector1, vector2, "or"))) {
|
||||
HANDLE_FAILURE("LLVMBuildAnd");
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
case V128_XOR:
|
||||
if (!(result = LLVMBuildXor(comp_ctx->builder, vector1, vector2,
|
||||
"xor"))) {
|
||||
HANDLE_FAILURE("LLVMBuildAnd");
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
case V128_ANDNOT:
|
||||
{
|
||||
/* v128.and(a, v128.not(b)) */
|
||||
if (!(vector2 = LLVMBuildNot(comp_ctx->builder, vector2, "not"))) {
|
||||
HANDLE_FAILURE("LLVMBuildNot");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(result = LLVMBuildAnd(comp_ctx->builder, vector1, vector2,
|
||||
"and"))) {
|
||||
HANDLE_FAILURE("LLVMBuildAnd");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
bh_assert(0);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
PUSH_V128(result);
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
v128_bitwise_not(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||
{
|
||||
LLVMValueRef vector, result;
|
||||
|
||||
POP_V128(vector);
|
||||
|
||||
if (!(result = LLVMBuildNot(comp_ctx->builder, vector, "not"))) {
|
||||
HANDLE_FAILURE("LLVMBuildNot");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
PUSH_V128(result);
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
/* v128.or(v128.and(v1, c), v128.and(v2, v128.not(c))) */
|
||||
static bool
|
||||
v128_bitwise_bit_select(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||
{
|
||||
LLVMValueRef vector1, vector2, vector3, result;
|
||||
|
||||
POP_V128(vector3);
|
||||
POP_V128(vector2);
|
||||
POP_V128(vector1);
|
||||
|
||||
if (!(vector1 =
|
||||
LLVMBuildAnd(comp_ctx->builder, vector1, vector3, "a_and_c"))) {
|
||||
HANDLE_FAILURE("LLVMBuildAdd");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(vector3 = LLVMBuildNot(comp_ctx->builder, vector3, "not_c"))) {
|
||||
HANDLE_FAILURE("LLVMBuildNot");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(vector2 =
|
||||
LLVMBuildAnd(comp_ctx->builder, vector2, vector3, "b_and_c"))) {
|
||||
HANDLE_FAILURE("LLVMBuildAdd");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(result =
|
||||
LLVMBuildOr(comp_ctx->builder, vector1, vector2, "a_or_b"))) {
|
||||
HANDLE_FAILURE("LLVMBuildOr");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
PUSH_V128(result);
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_v128_bitwise(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
V128Bitwise bitwise_op)
|
||||
{
|
||||
switch (bitwise_op) {
|
||||
case V128_AND:
|
||||
case V128_OR:
|
||||
case V128_XOR:
|
||||
case V128_ANDNOT:
|
||||
return v128_bitwise_two_component(comp_ctx, func_ctx, bitwise_op);
|
||||
case V128_NOT:
|
||||
return v128_bitwise_not(comp_ctx, func_ctx);
|
||||
case V128_BITSELECT:
|
||||
return v128_bitwise_bit_select(comp_ctx, func_ctx);
|
||||
default:
|
||||
bh_assert(0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
24
core/iwasm/compilation/simd/simd_bitwise_ops.h
Normal file
24
core/iwasm/compilation/simd/simd_bitwise_ops.h
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef _SIMD_BITWISE_OPS_H_
|
||||
#define _SIMD_BITWISE_OPS_H_
|
||||
|
||||
#include "../aot_compiler.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
bool
|
||||
aot_compile_simd_v128_bitwise(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
V128Bitwise bitwise_op);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* end of _SIMD_BITWISE_OPS_H_ */
|
||||
183
core/iwasm/compilation/simd/simd_bool_reductions.c
Normal file
183
core/iwasm/compilation/simd/simd_bool_reductions.c
Normal file
@ -0,0 +1,183 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "simd_bool_reductions.h"
|
||||
#include "simd_common.h"
|
||||
#include "../aot_emit_exception.h"
|
||||
#include "../../aot/aot_runtime.h"
|
||||
|
||||
static bool
|
||||
simd_any_true(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
LLVMTypeRef vector_type,
|
||||
LLVMTypeRef element_type,
|
||||
const char *intrinsic)
|
||||
{
|
||||
LLVMValueRef vector, zeros, non_zero, result;
|
||||
|
||||
if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
|
||||
"vec"))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(zeros = LLVMConstNull(vector_type))) {
|
||||
HANDLE_FAILURE("LLVMConstNull");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* icmp eq <N x iX> %vector, zeroinitialize */
|
||||
if (!(non_zero = LLVMBuildICmp(comp_ctx->builder, LLVMIntNE, vector, zeros,
|
||||
"non_zero"))) {
|
||||
HANDLE_FAILURE("LLVMBuildICmp");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* zext <N x i1> to <N x iX> */
|
||||
if (!(non_zero = LLVMBuildZExt(comp_ctx->builder, non_zero, vector_type,
|
||||
"non_zero_ex"))) {
|
||||
HANDLE_FAILURE("LLVMBuildZExt");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(result = aot_call_llvm_intrinsic(comp_ctx, intrinsic, element_type,
|
||||
&vector_type, 1, non_zero))) {
|
||||
HANDLE_FAILURE("LLVMBuildCall");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(zeros = LLVMConstNull(element_type))) {
|
||||
HANDLE_FAILURE("LLVMConstNull");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(result = LLVMBuildICmp(comp_ctx->builder, LLVMIntNE, result, zeros,
|
||||
"gt_zero"))) {
|
||||
HANDLE_FAILURE("LLVMBuildICmp");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(result =
|
||||
LLVMBuildZExt(comp_ctx->builder, result, I32_TYPE, "ret"))) {
|
||||
HANDLE_FAILURE("LLVMBuildZExt");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
PUSH_I32(result);
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_i8x16_any_true(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx)
|
||||
{
|
||||
return simd_any_true(comp_ctx, func_ctx, V128_i8x16_TYPE, INT8_TYPE,
|
||||
"llvm.experimental.vector.reduce.add.v16i8");
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_i16x8_any_true(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx)
|
||||
{
|
||||
return simd_any_true(comp_ctx, func_ctx, V128_i16x8_TYPE, INT16_TYPE,
|
||||
"llvm.experimental.vector.reduce.add.v8i16");
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_i32x4_any_true(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx)
|
||||
{
|
||||
return simd_any_true(comp_ctx, func_ctx, V128_i32x4_TYPE, I32_TYPE,
|
||||
"llvm.experimental.vector.reduce.add.v4i32");
|
||||
}
|
||||
|
||||
static bool
|
||||
simd_all_true(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
LLVMTypeRef vector_type,
|
||||
LLVMTypeRef element_type,
|
||||
const char *intrinsic)
|
||||
{
|
||||
LLVMValueRef vector, zeros, is_zero, result;
|
||||
|
||||
if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
|
||||
"vec"))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(zeros = LLVMConstNull(vector_type))) {
|
||||
HANDLE_FAILURE("LLVMConstNull");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* icmp eq <N x iX> %vector, zeroinitialize */
|
||||
if (!(is_zero = LLVMBuildICmp(comp_ctx->builder, LLVMIntEQ, vector, zeros,
|
||||
"is_zero"))) {
|
||||
HANDLE_FAILURE("LLVMBuildICmp");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* zext <N x i1> to <N x iX> */
|
||||
if (!(is_zero = LLVMBuildZExt(comp_ctx->builder, is_zero, vector_type,
|
||||
"is_zero_ex"))) {
|
||||
HANDLE_FAILURE("LLVMBuildZExt");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(result = aot_call_llvm_intrinsic(comp_ctx, intrinsic, element_type,
|
||||
&vector_type, 1, is_zero))) {
|
||||
HANDLE_FAILURE("LLVMBuildCall");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(zeros = LLVMConstNull(element_type))) {
|
||||
HANDLE_FAILURE("LLVMConstNull");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(result = LLVMBuildICmp(comp_ctx->builder, LLVMIntEQ, result, zeros,
|
||||
"none"))) {
|
||||
HANDLE_FAILURE("LLVMBuildICmp");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(result =
|
||||
LLVMBuildZExt(comp_ctx->builder, result, I32_TYPE, "ret"))) {
|
||||
HANDLE_FAILURE("LLVMBuildZExt");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
PUSH_I32(result);
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_i8x16_all_true(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx)
|
||||
{
|
||||
return simd_all_true(comp_ctx, func_ctx, V128_i8x16_TYPE, INT8_TYPE,
|
||||
"llvm.experimental.vector.reduce.add.v16i8");
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_i16x8_all_true(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx)
|
||||
{
|
||||
return simd_all_true(comp_ctx, func_ctx, V128_i16x8_TYPE, INT16_TYPE,
|
||||
"llvm.experimental.vector.reduce.add.v8i16");
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_i32x4_all_true(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx)
|
||||
{
|
||||
return simd_all_true(comp_ctx, func_ctx, V128_i32x4_TYPE, I32_TYPE,
|
||||
"llvm.experimental.vector.reduce.add.v4i32");
|
||||
}
|
||||
43
core/iwasm/compilation/simd/simd_bool_reductions.h
Normal file
43
core/iwasm/compilation/simd/simd_bool_reductions.h
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef _SIMD_BOOL_REDUCTIONS_H_
|
||||
#define _SIMD_BOOL_REDUCTIONS_H_
|
||||
|
||||
#include "../aot_compiler.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
bool
|
||||
aot_compile_simd_i8x16_any_true(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx);
|
||||
|
||||
bool
|
||||
aot_compile_simd_i16x8_any_true(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx);
|
||||
|
||||
bool
|
||||
aot_compile_simd_i32x4_any_true(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx);
|
||||
|
||||
bool
|
||||
aot_compile_simd_i8x16_all_true(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx);
|
||||
|
||||
bool
|
||||
aot_compile_simd_i16x8_all_true(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx);
|
||||
|
||||
bool
|
||||
aot_compile_simd_i32x4_all_true(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* end of _SIMD_BOOL_REDUCTIONS_H_ */
|
||||
47
core/iwasm/compilation/simd/simd_common.c
Normal file
47
core/iwasm/compilation/simd/simd_common.c
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "simd_common.h"
|
||||
|
||||
LLVMValueRef
|
||||
simd_pop_v128_and_bitcast(const AOTCompContext *comp_ctx,
|
||||
const AOTFuncContext *func_ctx,
|
||||
LLVMTypeRef vec_type,
|
||||
const char *name)
|
||||
{
|
||||
LLVMValueRef number;
|
||||
|
||||
POP_V128(number);
|
||||
|
||||
if (!(number =
|
||||
LLVMBuildBitCast(comp_ctx->builder, number, vec_type, name))) {
|
||||
HANDLE_FAILURE("LLVMBuildBitCast");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return number;
|
||||
fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
simd_bitcast_and_push_v128(const AOTCompContext *comp_ctx,
|
||||
const AOTFuncContext *func_ctx,
|
||||
LLVMValueRef vector,
|
||||
const char *name)
|
||||
{
|
||||
if (!(vector = LLVMBuildBitCast(comp_ctx->builder, vector, V128_i64x2_TYPE,
|
||||
name))) {
|
||||
HANDLE_FAILURE("LLVMBuildBitCast");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* push result into the stack */
|
||||
PUSH_V128(vector);
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
23
core/iwasm/compilation/simd/simd_common.h
Normal file
23
core/iwasm/compilation/simd/simd_common.h
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef _SIMD_COMMON_H_
|
||||
#define _SIMD_COMMON_H_
|
||||
|
||||
#include "../aot_compiler.h"
|
||||
|
||||
LLVMValueRef
|
||||
simd_pop_v128_and_bitcast(const AOTCompContext *comp_ctx,
|
||||
const AOTFuncContext *func_ctx,
|
||||
LLVMTypeRef vec_type,
|
||||
const char *name);
|
||||
|
||||
bool
|
||||
simd_bitcast_and_push_v128(const AOTCompContext *comp_ctx,
|
||||
const AOTFuncContext *func_ctx,
|
||||
LLVMValueRef vector,
|
||||
const char *name);
|
||||
|
||||
#endif /* _SIMD_COMMON_H_ */
|
||||
231
core/iwasm/compilation/simd/simd_comparisons.c
Normal file
231
core/iwasm/compilation/simd/simd_comparisons.c
Normal file
@ -0,0 +1,231 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "simd_comparisons.h"
|
||||
#include "simd_common.h"
|
||||
#include "../aot_emit_exception.h"
|
||||
#include "../../aot/aot_runtime.h"
|
||||
|
||||
static bool
|
||||
float_cond_2_predicate(FloatCond cond, LLVMRealPredicate *out)
|
||||
{
|
||||
switch (cond) {
|
||||
case FLOAT_EQ:
|
||||
*out = LLVMRealOEQ;
|
||||
break;
|
||||
case FLOAT_NE:
|
||||
*out = LLVMRealUNE;
|
||||
break;
|
||||
case FLOAT_LT:
|
||||
*out = LLVMRealOLT;
|
||||
break;
|
||||
case FLOAT_GT:
|
||||
*out = LLVMRealOGT;
|
||||
break;
|
||||
case FLOAT_LE:
|
||||
*out = LLVMRealOLE;
|
||||
break;
|
||||
case FLOAT_GE:
|
||||
*out = LLVMRealOGE;
|
||||
break;
|
||||
default:
|
||||
bh_assert(0);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
int_cond_2_predicate(IntCond cond, LLVMIntPredicate *out)
|
||||
{
|
||||
switch (cond) {
|
||||
case INT_EQZ:
|
||||
case INT_EQ:
|
||||
*out = LLVMIntEQ;
|
||||
break;
|
||||
case INT_NE:
|
||||
*out = LLVMIntNE;
|
||||
break;
|
||||
case INT_LT_S:
|
||||
*out = LLVMIntSLT;
|
||||
break;
|
||||
case INT_LT_U:
|
||||
*out = LLVMIntULT;
|
||||
break;
|
||||
case INT_GT_S:
|
||||
*out = LLVMIntSGT;
|
||||
break;
|
||||
case INT_GT_U:
|
||||
*out = LLVMIntUGT;
|
||||
break;
|
||||
case INT_LE_S:
|
||||
*out = LLVMIntSLE;
|
||||
break;
|
||||
case INT_LE_U:
|
||||
*out = LLVMIntULE;
|
||||
break;
|
||||
case INT_GE_S:
|
||||
*out = LLVMIntSGE;
|
||||
break;
|
||||
case INT_GE_U:
|
||||
*out = LLVMIntUGE;
|
||||
break;
|
||||
default:
|
||||
bh_assert(0);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
interger_vector_compare(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
IntCond cond,
|
||||
LLVMTypeRef vector_type)
|
||||
{
|
||||
LLVMValueRef vec1, vec2, result;
|
||||
LLVMIntPredicate int_pred;
|
||||
|
||||
if (!(vec2 = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
|
||||
"vec2"))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(vec1 = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
|
||||
"vec1"))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!int_cond_2_predicate(cond, &int_pred)) {
|
||||
HANDLE_FAILURE("int_cond_2_predicate");
|
||||
goto fail;
|
||||
}
|
||||
/* icmp <N x iX> %vec1, %vec2 */
|
||||
if (!(result =
|
||||
LLVMBuildICmp(comp_ctx->builder, int_pred, vec1, vec2, "cmp"))) {
|
||||
HANDLE_FAILURE("LLVMBuildICmp");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* sext <N x i1> %result to <N x iX> */
|
||||
if (!(result =
|
||||
LLVMBuildSExt(comp_ctx->builder, result, vector_type, "ext"))) {
|
||||
HANDLE_FAILURE("LLVMBuildSExt");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* bitcast <N x iX> %result to <2 x i64> */
|
||||
if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE,
|
||||
"result"))) {
|
||||
HANDLE_FAILURE("LLVMBuildBitCast");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
PUSH_V128(result);
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_i8x16_compare(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
IntCond cond)
|
||||
{
|
||||
return interger_vector_compare(comp_ctx, func_ctx, cond, V128_i8x16_TYPE);
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_i16x8_compare(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
IntCond cond)
|
||||
{
|
||||
return interger_vector_compare(comp_ctx, func_ctx, cond, V128_i16x8_TYPE);
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_i32x4_compare(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
IntCond cond)
|
||||
{
|
||||
return interger_vector_compare(comp_ctx, func_ctx, cond, V128_i32x4_TYPE);
|
||||
}
|
||||
|
||||
static bool
|
||||
float_vector_compare(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
FloatCond cond,
|
||||
LLVMTypeRef vector_type,
|
||||
LLVMTypeRef result_type)
|
||||
{
|
||||
LLVMValueRef vec1, vec2, result;
|
||||
LLVMRealPredicate real_pred;
|
||||
|
||||
if (!(vec2 = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
|
||||
"vec2"))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(vec1 = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
|
||||
"vec1"))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!float_cond_2_predicate(cond, &real_pred)) {
|
||||
HANDLE_FAILURE("float_cond_2_predicate");
|
||||
goto fail;
|
||||
}
|
||||
/* fcmp <N x iX> %vec1, %vec2 */
|
||||
if (!(result =
|
||||
LLVMBuildFCmp(comp_ctx->builder, real_pred, vec1, vec2, "cmp"))) {
|
||||
HANDLE_FAILURE("LLVMBuildFCmp");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* sext <N x i1> %result to <N x iX> */
|
||||
if (!(result =
|
||||
LLVMBuildSExt(comp_ctx->builder, result, result_type, "ext"))) {
|
||||
HANDLE_FAILURE("LLVMBuildSExt");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* bitcast <N x iX> %result to <2 x i64> */
|
||||
if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE,
|
||||
"result"))) {
|
||||
HANDLE_FAILURE("LLVMBuildBitCast");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
PUSH_V128(result);
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_f32x4_compare(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
FloatCond cond)
|
||||
{
|
||||
return float_vector_compare(comp_ctx, func_ctx, cond, V128_f32x4_TYPE,
|
||||
V128_i32x4_TYPE);
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_f64x2_compare(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
FloatCond cond)
|
||||
{
|
||||
return float_vector_compare(comp_ctx, func_ctx, cond, V128_f64x2_TYPE,
|
||||
V128_i64x2_TYPE);
|
||||
}
|
||||
44
core/iwasm/compilation/simd/simd_comparisons.h
Normal file
44
core/iwasm/compilation/simd/simd_comparisons.h
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef _SIMD_COMPARISONS_H_
|
||||
#define _SIMD_COMPARISONS_H_
|
||||
|
||||
#include "../aot_compiler.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
bool
|
||||
aot_compile_simd_i8x16_compare(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
IntCond cond);
|
||||
|
||||
bool
|
||||
aot_compile_simd_i16x8_compare(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
IntCond cond);
|
||||
|
||||
bool
|
||||
aot_compile_simd_i32x4_compare(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
IntCond cond);
|
||||
|
||||
bool
|
||||
aot_compile_simd_f32x4_compare(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
FloatCond cond);
|
||||
|
||||
bool
|
||||
aot_compile_simd_f64x2_compare(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
FloatCond cond);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* end of _SIMD_COMPARISONS_H_ */
|
||||
190
core/iwasm/compilation/simd/simd_construct_values.c
Normal file
190
core/iwasm/compilation/simd/simd_construct_values.c
Normal file
@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "simd_construct_values.h"
|
||||
#include "../aot_emit_exception.h"
|
||||
#include "../interpreter/wasm_opcode.h"
|
||||
#include "../../aot/aot_runtime.h"
|
||||
|
||||
bool
|
||||
aot_compile_simd_v128_const(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
const uint8 *imm_bytes)
|
||||
{
|
||||
uint64 imm1, imm2;
|
||||
LLVMValueRef undef, first_long, agg1, second_long, agg2;
|
||||
|
||||
wasm_runtime_read_v128(imm_bytes, &imm1, &imm2);
|
||||
|
||||
if (!(undef = LLVMGetUndef(V128_i64x2_TYPE))) {
|
||||
HANDLE_FAILURE("LLVMGetUndef");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* %agg1 = insertelement <2 x i64> undef, i16 0, i64 ${*imm} */
|
||||
if (!(first_long = I64_CONST(imm1))) {
|
||||
HANDLE_FAILURE("LLVMConstInt");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(agg1 = LLVMBuildInsertElement(comp_ctx->builder, undef, first_long,
|
||||
I32_ZERO, "agg1"))) {
|
||||
HANDLE_FAILURE("LLVMBuildInsertElement");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* %agg2 = insertelement <2 x i64> %agg1, i16 1, i64 ${*(imm + 1)} */
|
||||
if (!(second_long = I64_CONST(imm2))) {
|
||||
HANDLE_FAILURE("LLVMGetUndef");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(agg2 = LLVMBuildInsertElement(comp_ctx->builder, agg1, second_long,
|
||||
I32_ONE, "agg2"))) {
|
||||
HANDLE_FAILURE("LLVMBuildInsertElement");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
PUSH_V128(agg2);
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_splat(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint8 splat_opcode)
|
||||
{
|
||||
LLVMValueRef value, undef, base, mask, new_vector, result;
|
||||
LLVMTypeRef all_zero_ty;
|
||||
|
||||
switch (splat_opcode) {
|
||||
case SIMD_i8x16_splat:
|
||||
{
|
||||
LLVMValueRef input;
|
||||
POP_I32(input);
|
||||
|
||||
/* trunc i32 %input to i8 */
|
||||
if (!(value = LLVMBuildTrunc(comp_ctx->builder, input, INT8_TYPE,
|
||||
"trunc"))) {
|
||||
HANDLE_FAILURE("LLVMBuildTrunc");
|
||||
goto fail;
|
||||
}
|
||||
undef = LLVMGetUndef(V128_i8x16_TYPE);
|
||||
if (!(all_zero_ty = LLVMVectorType(I32_TYPE, 16))) {
|
||||
HANDLE_FAILURE("LLVMVectorType");
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SIMD_i16x8_splat:
|
||||
{
|
||||
LLVMValueRef input;
|
||||
POP_I32(input);
|
||||
|
||||
/* trunc i32 %input to i16 */
|
||||
if (!(value = LLVMBuildTrunc(comp_ctx->builder, input, INT16_TYPE,
|
||||
"trunc"))) {
|
||||
HANDLE_FAILURE("LLVMBuildTrunc");
|
||||
goto fail;
|
||||
}
|
||||
undef = LLVMGetUndef(V128_i16x8_TYPE);
|
||||
if (!(all_zero_ty = LLVMVectorType(I32_TYPE, 8))) {
|
||||
HANDLE_FAILURE("LLVMVectorType");
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SIMD_i32x4_splat:
|
||||
{
|
||||
POP_I32(value);
|
||||
undef = LLVMGetUndef(V128_i32x4_TYPE);
|
||||
|
||||
if (!(all_zero_ty = LLVMVectorType(I32_TYPE, 4))) {
|
||||
HANDLE_FAILURE("LLVMVectorType");
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SIMD_i64x2_splat:
|
||||
{
|
||||
POP(value, VALUE_TYPE_I64);
|
||||
undef = LLVMGetUndef(V128_i64x2_TYPE);
|
||||
|
||||
if (!(all_zero_ty = LLVMVectorType(I32_TYPE, 2))) {
|
||||
HANDLE_FAILURE("LLVMVectorType");
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SIMD_f32x4_splat:
|
||||
{
|
||||
POP(value, VALUE_TYPE_F32);
|
||||
undef = LLVMGetUndef(V128_f32x4_TYPE);
|
||||
|
||||
if (!(all_zero_ty = LLVMVectorType(I32_TYPE, 4))) {
|
||||
HANDLE_FAILURE("LLVMVectorType");
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SIMD_f64x2_splat:
|
||||
{
|
||||
POP(value, VALUE_TYPE_F64);
|
||||
undef = LLVMGetUndef(V128_f64x2_TYPE);
|
||||
|
||||
if (!(all_zero_ty = LLVMVectorType(I32_TYPE, 2))) {
|
||||
HANDLE_FAILURE("LLVMVectorType");
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
bh_assert(0);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
if (!undef) {
|
||||
HANDLE_FAILURE("LVMGetUndef");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* insertelement <n x ty> undef, ty %value, i32 0 */
|
||||
if (!(base = LLVMBuildInsertElement(comp_ctx->builder, undef, value,
|
||||
I32_ZERO, "base"))) {
|
||||
HANDLE_FAILURE("LLVMBuildInsertElement");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* <n x i32> zeroinitializer */
|
||||
if (!(mask = LLVMConstNull(all_zero_ty))) {
|
||||
HANDLE_FAILURE("LLVMConstNull");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* shufflevector <ty1> %base, <ty2> undef, <n x i32> zeroinitializer */
|
||||
if (!(new_vector = LLVMBuildShuffleVector(comp_ctx->builder, base, undef,
|
||||
mask, "new_vector"))) {
|
||||
HANDLE_FAILURE("LLVMBuildShuffleVector");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* bitcast <ty> <value> to <2 x i64> */
|
||||
if (!(result = LLVMBuildBitCast(comp_ctx->builder, new_vector,
|
||||
V128_i64x2_TYPE, "ret"))) {
|
||||
HANDLE_FAILURE("LLVMBuidlCast");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* push result into the stack */
|
||||
PUSH_V128(result);
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
29
core/iwasm/compilation/simd/simd_construct_values.h
Normal file
29
core/iwasm/compilation/simd/simd_construct_values.h
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef _SIMD_CONSTRUCT_VALUES_H_
|
||||
#define _SIMD_CONSTRUCT_VALUES_H_
|
||||
|
||||
#include "../aot_compiler.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
bool
|
||||
aot_compile_simd_v128_const(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
const uint8 *imm_bytes);
|
||||
|
||||
bool
|
||||
aot_compile_simd_splat(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint8 splat_opcode);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* end of _SIMD_CONSTRUCT_VALUES_H_ */
|
||||
422
core/iwasm/compilation/simd/simd_conversions.c
Normal file
422
core/iwasm/compilation/simd/simd_conversions.c
Normal file
@ -0,0 +1,422 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "simd_conversions.h"
|
||||
#include "simd_common.h"
|
||||
#include "../aot_emit_exception.h"
|
||||
#include "../aot_emit_numberic.h"
|
||||
#include "../../aot/aot_runtime.h"
|
||||
|
||||
static bool
|
||||
simd_integer_narrow(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
bool is_signed,
|
||||
LLVMTypeRef in_vector_type,
|
||||
LLVMTypeRef out_vector_type,
|
||||
const char *instrinsic)
|
||||
{
|
||||
LLVMValueRef vector1, vector2, result;
|
||||
LLVMTypeRef param_types[2] = { in_vector_type, in_vector_type };
|
||||
|
||||
if (!(vector2 = simd_pop_v128_and_bitcast(comp_ctx, func_ctx,
|
||||
in_vector_type, "vec2"))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(vector1 = simd_pop_v128_and_bitcast(comp_ctx, func_ctx,
|
||||
in_vector_type, "vec1"))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(result =
|
||||
aot_call_llvm_intrinsic(comp_ctx, instrinsic, out_vector_type,
|
||||
param_types, 2, vector1, vector2))) {
|
||||
HANDLE_FAILURE("LLVMBuildCall");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE,
|
||||
"ret"))) {
|
||||
HANDLE_FAILURE("LLVMBuildBitCast");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
PUSH_V128(result);
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_i8x16_narrow_i16x8(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
bool is_signed)
|
||||
{
|
||||
return simd_integer_narrow(
|
||||
comp_ctx, func_ctx, is_signed, V128_i16x8_TYPE, V128_i8x16_TYPE,
|
||||
is_signed ? "llvm.x86.sse2.packsswb.128" : "llvm.x86.sse2.packuswb.128");
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_i16x8_narrow_i32x4(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
bool is_signed)
|
||||
{
|
||||
return simd_integer_narrow(
|
||||
comp_ctx, func_ctx, is_signed, V128_i32x4_TYPE, V128_i16x8_TYPE,
|
||||
is_signed ? "llvm.x86.sse2.packssdw.128" : "llvm.x86.sse41.packusdw");
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_i16x8_widen_i8x16(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
bool is_low_half,
|
||||
bool is_signed)
|
||||
{
|
||||
LLVMValueRef vector, undef, mask_high[8], mask_low[8], mask, shuffled,
|
||||
result;
|
||||
uint8 mask_high_value[8] = { 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf },
|
||||
mask_low_value[8] = { 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 }, i;
|
||||
|
||||
if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx,
|
||||
V128_i8x16_TYPE, "vec"))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(undef = LLVMGetUndef(V128_i8x16_TYPE))) {
|
||||
HANDLE_FAILURE("LLVMGetUndef");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* create a mask */
|
||||
for (i = 0; i < 8; i++) {
|
||||
mask_high[i] = LLVMConstInt(I32_TYPE, mask_high_value[i], true);
|
||||
mask_low[i] = LLVMConstInt(I32_TYPE, mask_low_value[i], true);
|
||||
}
|
||||
|
||||
mask = is_low_half ? LLVMConstVector(mask_low, 8)
|
||||
: LLVMConstVector(mask_high, 8);
|
||||
if (!mask) {
|
||||
HANDLE_FAILURE("LLVMConstVector");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* retrive the low or high half */
|
||||
if (!(shuffled = LLVMBuildShuffleVector(comp_ctx->builder, vector, undef,
|
||||
mask, "shuffled"))) {
|
||||
HANDLE_FAILURE("LLVMBuildShuffleVector");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (is_signed) {
|
||||
if (!(result = LLVMBuildSExt(comp_ctx->builder, shuffled,
|
||||
V128_i16x8_TYPE, "ext"))) {
|
||||
HANDLE_FAILURE("LLVMBuildSExt");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!(result = LLVMBuildZExt(comp_ctx->builder, shuffled,
|
||||
V128_i16x8_TYPE, "ext"))) {
|
||||
HANDLE_FAILURE("LLVMBuildZExt");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE,
|
||||
"ret"))) {
|
||||
HANDLE_FAILURE("LLVMBuildBitCast");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
PUSH_V128(result);
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_i32x4_widen_i16x8(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
bool is_low_half,
|
||||
bool is_signed)
|
||||
{
|
||||
LLVMValueRef vector, undef, mask_high[4], mask_low[4], mask, shuffled,
|
||||
result;
|
||||
uint8 mask_high_value[4] = { 0x4, 0x5, 0x6, 0x7 },
|
||||
mask_low_value[4] = { 0x0, 0x1, 0x2, 0x3 }, i;
|
||||
|
||||
if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx,
|
||||
V128_i16x8_TYPE, "vec"))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(undef = LLVMGetUndef(V128_i16x8_TYPE))) {
|
||||
HANDLE_FAILURE("LLVMGetUndef");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* create a mask */
|
||||
for (i = 0; i < 4; i++) {
|
||||
mask_high[i] = LLVMConstInt(I32_TYPE, mask_high_value[i], true);
|
||||
mask_low[i] = LLVMConstInt(I32_TYPE, mask_low_value[i], true);
|
||||
}
|
||||
|
||||
mask = is_low_half ? LLVMConstVector(mask_low, 4)
|
||||
: LLVMConstVector(mask_high, 4);
|
||||
if (!mask) {
|
||||
HANDLE_FAILURE("LLVMConstVector");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* retrive the low or high half */
|
||||
if (!(shuffled = LLVMBuildShuffleVector(comp_ctx->builder, vector, undef,
|
||||
mask, "shuffled"))) {
|
||||
HANDLE_FAILURE("LLVMBuildShuffleVector");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (is_signed) {
|
||||
if (!(result = LLVMBuildSExt(comp_ctx->builder, shuffled,
|
||||
V128_i32x4_TYPE, "ext"))) {
|
||||
HANDLE_FAILURE("LLVMBuildSExt");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!(result = LLVMBuildZExt(comp_ctx->builder, shuffled,
|
||||
V128_i32x4_TYPE, "ext"))) {
|
||||
HANDLE_FAILURE("LLVMBuildZExt");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE,
|
||||
"ret"))) {
|
||||
HANDLE_FAILURE("LLVMBuildBitCast");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
PUSH_V128(result);
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
static LLVMValueRef
|
||||
simd_build_const_f32x4(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
float f)
|
||||
{
|
||||
LLVMValueRef elements[4], vector;
|
||||
|
||||
if (!(elements[0] = LLVMConstReal(F32_TYPE, f))) {
|
||||
HANDLE_FAILURE("LLVMConstInt");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
elements[1] = elements[2] = elements[3] = elements[0];
|
||||
|
||||
if (!(vector = LLVMConstVector(elements, 4))) {
|
||||
HANDLE_FAILURE("LLVMConstVector");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return vector;
|
||||
fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static LLVMValueRef
|
||||
simd_build_const_i32x4(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint64 integer,
|
||||
bool is_signed)
|
||||
{
|
||||
LLVMValueRef elements[4], vector;
|
||||
|
||||
if (!(elements[0] = LLVMConstInt(I32_TYPE, integer, is_signed))) {
|
||||
HANDLE_FAILURE("LLVMConstInt");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
elements[1] = elements[2] = elements[3] = elements[0];
|
||||
|
||||
if (!(vector = LLVMConstVector(elements, 4))) {
|
||||
HANDLE_FAILURE("LLVMConstVector");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return vector;
|
||||
fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_i32x4_trunc_sat_f32x4(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
bool is_signed)
|
||||
{
|
||||
LLVMValueRef vector, zeros, is_nan, max_float_v, min_float_v, is_ge_max,
|
||||
is_le_min, result, max_int_v, min_int_v;
|
||||
uint32 max_ui = 0xFFffFFff, min_ui = 0x0;
|
||||
int32 max_si = 0x7FFFffff, min_si = 0x80000000;
|
||||
float max_f_ui = 4294967296.0f, min_f_ui = 0.0f, max_f_si = 2147483647.0f,
|
||||
min_f_si = -2147483648.0f;
|
||||
|
||||
if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx,
|
||||
V128_f32x4_TYPE, "vec"))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(zeros = LLVMConstNull(V128_f32x4_TYPE))) {
|
||||
HANDLE_FAILURE("LLVMConstNull");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (is_signed) {
|
||||
if (!(max_float_v =
|
||||
simd_build_const_f32x4(comp_ctx, func_ctx, max_f_si))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(min_float_v =
|
||||
simd_build_const_f32x4(comp_ctx, func_ctx, min_f_si))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(max_int_v =
|
||||
simd_build_const_i32x4(comp_ctx, func_ctx, max_si, true))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(min_int_v =
|
||||
simd_build_const_i32x4(comp_ctx, func_ctx, min_si, true))) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!(max_float_v =
|
||||
simd_build_const_f32x4(comp_ctx, func_ctx, max_f_ui))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(min_float_v =
|
||||
simd_build_const_f32x4(comp_ctx, func_ctx, min_f_ui))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(max_int_v =
|
||||
simd_build_const_i32x4(comp_ctx, func_ctx, max_ui, false))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(min_int_v =
|
||||
simd_build_const_i32x4(comp_ctx, func_ctx, min_ui, false))) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(is_nan = LLVMBuildFCmp(comp_ctx->builder, LLVMRealORD, vector, zeros,
|
||||
"is_nan"))) {
|
||||
HANDLE_FAILURE("LLVMBuildFCmp");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(is_le_min = LLVMBuildFCmp(comp_ctx->builder, LLVMRealOLE, vector,
|
||||
min_float_v, "le_min"))) {
|
||||
HANDLE_FAILURE("LLVMBuildFCmp");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(is_ge_max = LLVMBuildFCmp(comp_ctx->builder, LLVMRealOGE, vector,
|
||||
max_float_v, "ge_max"))) {
|
||||
HANDLE_FAILURE("LLVMBuildFCmp");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (is_signed) {
|
||||
if (!(result = LLVMBuildFPToSI(comp_ctx->builder, vector,
|
||||
V128_i32x4_TYPE, "truncated"))) {
|
||||
HANDLE_FAILURE("LLVMBuildSIToFP");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!(result = LLVMBuildFPToUI(comp_ctx->builder, vector,
|
||||
V128_i32x4_TYPE, "truncated"))) {
|
||||
HANDLE_FAILURE("LLVMBuildUIToFP");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(result = LLVMBuildSelect(comp_ctx->builder, is_ge_max, max_int_v,
|
||||
result, "sat_w_max"))) {
|
||||
HANDLE_FAILURE("LLVMBuildSelect");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(result = LLVMBuildSelect(comp_ctx->builder, is_le_min, min_int_v,
|
||||
result, "sat_w_min"))) {
|
||||
HANDLE_FAILURE("LLVMBuildSelect");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(result = LLVMBuildSelect(comp_ctx->builder, is_nan, result,
|
||||
V128_i32x4_ZERO, "sat_w_nan"))) {
|
||||
HANDLE_FAILURE("LLVMBuildSelect");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE,
|
||||
"ret"))) {
|
||||
HANDLE_FAILURE("LLVMBuildBitCast");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
PUSH_V128(result);
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_f32x4_convert_i32x4(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
bool is_signed)
|
||||
{
|
||||
LLVMValueRef vector, result;
|
||||
|
||||
if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx,
|
||||
V128_i32x4_TYPE, "vec"))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (is_signed) {
|
||||
if (!(result = LLVMBuildSIToFP(comp_ctx->builder, vector,
|
||||
V128_f32x4_TYPE, "converted"))) {
|
||||
HANDLE_FAILURE("LLVMBuildSIToFP");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!(result = LLVMBuildUIToFP(comp_ctx->builder, vector,
|
||||
V128_f32x4_TYPE, "converted"))) {
|
||||
HANDLE_FAILURE("LLVMBuildSIToFP");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE,
|
||||
"ret"))) {
|
||||
HANDLE_FAILURE("LLVMBuildBitCast");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
PUSH_V128(result);
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
51
core/iwasm/compilation/simd/simd_conversions.h
Normal file
51
core/iwasm/compilation/simd/simd_conversions.h
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef _SIMD_CONVERSIONS_H_
|
||||
#define _SIMD_CONVERSIONS_H_
|
||||
|
||||
#include "../aot_compiler.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
bool
|
||||
aot_compile_simd_i8x16_narrow_i16x8(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
bool is_signed);
|
||||
|
||||
bool
|
||||
aot_compile_simd_i16x8_narrow_i32x4(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
bool is_signed);
|
||||
|
||||
bool
|
||||
aot_compile_simd_i16x8_widen_i8x16(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
bool is_low,
|
||||
bool is_signed);
|
||||
|
||||
bool
|
||||
aot_compile_simd_i32x4_widen_i16x8(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
bool is_low,
|
||||
bool is_signed);
|
||||
|
||||
bool
|
||||
aot_compile_simd_i32x4_trunc_sat_f32x4(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
bool is_signed);
|
||||
|
||||
bool
|
||||
aot_compile_simd_f32x4_convert_i32x4(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
bool is_signed);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* end of _SIMD_CONVERSIONS_H_ */
|
||||
273
core/iwasm/compilation/simd/simd_floating_point.c
Normal file
273
core/iwasm/compilation/simd/simd_floating_point.c
Normal file
@ -0,0 +1,273 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "simd_floating_point.h"
|
||||
#include "simd_common.h"
|
||||
#include "../aot_emit_exception.h"
|
||||
#include "../aot_emit_numberic.h"
|
||||
#include "../../aot/aot_runtime.h"
|
||||
|
||||
static LLVMValueRef
|
||||
simd_v128_float_cmp(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
FloatArithmetic arith_op,
|
||||
LLVMValueRef lhs,
|
||||
LLVMValueRef rhs)
|
||||
{
|
||||
LLVMValueRef result;
|
||||
LLVMRealPredicate op;
|
||||
|
||||
op = FLOAT_MIN == arith_op ? LLVMRealULT : LLVMRealUGT;
|
||||
|
||||
if (!(result = LLVMBuildFCmp(comp_ctx->builder, op, lhs, rhs, "cmp"))) {
|
||||
HANDLE_FAILURE("LLVMBuildFCmp");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(result =
|
||||
LLVMBuildSelect(comp_ctx->builder, result, lhs, rhs, "select"))) {
|
||||
HANDLE_FAILURE("LLVMBuildSelect");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return result;
|
||||
fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool
|
||||
simd_v128_float_arith(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
FloatArithmetic arith_op,
|
||||
LLVMTypeRef vector_type)
|
||||
{
|
||||
LLVMValueRef lhs, rhs, result;
|
||||
|
||||
if (!(rhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
|
||||
"rhs"))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(lhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
|
||||
"lhs"))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
switch (arith_op) {
|
||||
case FLOAT_ADD:
|
||||
if (!(result =
|
||||
LLVMBuildFAdd(comp_ctx->builder, lhs, rhs, "sum"))) {
|
||||
HANDLE_FAILURE("LLVMBuildFAdd");
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
case FLOAT_SUB:
|
||||
if (!(result = LLVMBuildFSub(comp_ctx->builder, lhs, rhs,
|
||||
"difference"))) {
|
||||
HANDLE_FAILURE("LLVMBuildFSub");
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
case FLOAT_MUL:
|
||||
if (!(result =
|
||||
LLVMBuildFMul(comp_ctx->builder, lhs, rhs, "product"))) {
|
||||
HANDLE_FAILURE("LLVMBuildFMul");
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
case FLOAT_DIV:
|
||||
if (!(result =
|
||||
LLVMBuildFDiv(comp_ctx->builder, lhs, rhs, "quotient"))) {
|
||||
HANDLE_FAILURE("LLVMBuildFDiv");
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
case FLOAT_MIN:
|
||||
if (!(result = simd_v128_float_cmp(comp_ctx, func_ctx, FLOAT_MIN,
|
||||
lhs, rhs))) {
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
case FLOAT_MAX:
|
||||
if (!(result = simd_v128_float_cmp(comp_ctx, func_ctx, FLOAT_MAX,
|
||||
lhs, rhs))) {
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
result = NULL;
|
||||
bh_assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE,
|
||||
"ret"))) {
|
||||
HANDLE_FAILURE("LLVMBuildBitCast");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* push result into the stack */
|
||||
PUSH_V128(result);
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_f32x4_arith(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
FloatArithmetic arith_op)
|
||||
{
|
||||
return simd_v128_float_arith(comp_ctx, func_ctx, arith_op,
|
||||
V128_f32x4_TYPE);
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_f64x2_arith(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
FloatArithmetic arith_op)
|
||||
{
|
||||
return simd_v128_float_arith(comp_ctx, func_ctx, arith_op,
|
||||
V128_f64x2_TYPE);
|
||||
}
|
||||
|
||||
static bool
|
||||
simd_v128_float_neg(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
LLVMTypeRef vector_type)
|
||||
{
|
||||
LLVMValueRef number, result;
|
||||
|
||||
if (!(number = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
|
||||
"number"))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(result = LLVMBuildFNeg(comp_ctx->builder, number, "neg"))) {
|
||||
HANDLE_FAILURE("LLVMBuildFNeg");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE,
|
||||
"ret"))) {
|
||||
HANDLE_FAILURE("LLVMBuildBitCast");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* push result into the stack */
|
||||
PUSH_V128(result);
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_f32x4_neg(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||
{
|
||||
return simd_v128_float_neg(comp_ctx, func_ctx, V128_f32x4_TYPE);
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_f64x2_neg(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||
{
|
||||
return simd_v128_float_neg(comp_ctx, func_ctx, V128_f64x2_TYPE);
|
||||
}
|
||||
|
||||
static bool
|
||||
simd_v128_float_abs(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
LLVMTypeRef vector_type,
|
||||
const char *intrinsic)
|
||||
{
|
||||
LLVMValueRef vector, result;
|
||||
LLVMTypeRef param_types[1] = { vector_type };
|
||||
|
||||
if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
|
||||
"vec"))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(result = aot_call_llvm_intrinsic(comp_ctx, intrinsic, vector_type,
|
||||
param_types, 1, vector))) {
|
||||
HANDLE_FAILURE("LLVMBuildCall");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE,
|
||||
"ret"))) {
|
||||
HANDLE_FAILURE("LLVMBuildBitCast");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* push result into the stack */
|
||||
PUSH_V128(result);
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_f32x4_abs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||
{
|
||||
return simd_v128_float_abs(comp_ctx, func_ctx, V128_f32x4_TYPE,
|
||||
"llvm.fabs.v4f32");
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_f64x2_abs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||
{
|
||||
return simd_v128_float_abs(comp_ctx, func_ctx, V128_f64x2_TYPE,
|
||||
"llvm.fabs.v2f64");
|
||||
}
|
||||
|
||||
static bool
|
||||
simd_v128_float_sqrt(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
LLVMTypeRef vector_type,
|
||||
const char *intrinsic)
|
||||
{
|
||||
LLVMValueRef number, result;
|
||||
LLVMTypeRef param_types[1] = { vector_type };
|
||||
|
||||
if (!(number = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
|
||||
"number"))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(result = aot_call_llvm_intrinsic(comp_ctx, intrinsic, vector_type,
|
||||
param_types, 1, number))) {
|
||||
HANDLE_FAILURE("LLVMBuildCall");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE,
|
||||
"ret"))) {
|
||||
HANDLE_FAILURE("LLVMBuildBitCast");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* push result into the stack */
|
||||
PUSH_V128(result);
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_f32x4_sqrt(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||
{
|
||||
return simd_v128_float_sqrt(comp_ctx, func_ctx, V128_f32x4_TYPE,
|
||||
"llvm.sqrt.v4f32");
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_f64x2_sqrt(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||
{
|
||||
return simd_v128_float_sqrt(comp_ctx, func_ctx, V128_f64x2_TYPE,
|
||||
"llvm.sqrt.v2f64");
|
||||
}
|
||||
49
core/iwasm/compilation/simd/simd_floating_point.h
Normal file
49
core/iwasm/compilation/simd/simd_floating_point.h
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef _SIMD_FLOATING_POINT_H_
|
||||
#define _SIMD_FLOATING_POINT_H_
|
||||
|
||||
#include "../aot_compiler.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
bool
|
||||
aot_compile_simd_f32x4_arith(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
FloatArithmetic arith_op);
|
||||
|
||||
bool
|
||||
aot_compile_simd_f64x2_arith(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
FloatArithmetic arith_op);
|
||||
|
||||
bool
|
||||
aot_compile_simd_f32x4_neg(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
|
||||
|
||||
bool
|
||||
aot_compile_simd_f64x2_neg(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
|
||||
|
||||
bool
|
||||
aot_compile_simd_f32x4_abs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
|
||||
|
||||
bool
|
||||
aot_compile_simd_f64x2_abs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
|
||||
|
||||
bool
|
||||
aot_compile_simd_f32x4_sqrt(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx);
|
||||
|
||||
bool
|
||||
aot_compile_simd_f64x2_sqrt(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* end of _SIMD_FLOATING_POINT_H_ */
|
||||
207
core/iwasm/compilation/simd/simd_int_arith.c
Normal file
207
core/iwasm/compilation/simd/simd_int_arith.c
Normal file
@ -0,0 +1,207 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "simd_int_arith.h"
|
||||
#include "simd_common.h"
|
||||
#include "../aot_emit_exception.h"
|
||||
#include "../../aot/aot_runtime.h"
|
||||
|
||||
static bool
|
||||
simd_v128_integer_arith(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
V128Arithmetic arith_op,
|
||||
LLVMValueRef lhs,
|
||||
LLVMValueRef rhs)
|
||||
{
|
||||
LLVMValueRef result;
|
||||
|
||||
switch (arith_op) {
|
||||
case V128_ADD:
|
||||
if (!(result = LLVMBuildAdd(comp_ctx->builder, lhs, rhs, "sum"))) {
|
||||
HANDLE_FAILURE("LLVMBuildAdd");
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
case V128_SUB:
|
||||
if (!(result =
|
||||
LLVMBuildSub(comp_ctx->builder, lhs, rhs, "difference"))) {
|
||||
HANDLE_FAILURE("LLVMBuildSub");
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
case V128_MUL:
|
||||
if (!(result =
|
||||
LLVMBuildMul(comp_ctx->builder, lhs, rhs, "product"))) {
|
||||
HANDLE_FAILURE("LLVMBuildMul");
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
case V128_NEG:
|
||||
if (!(result = LLVMBuildNeg(comp_ctx->builder, lhs, "neg"))) {
|
||||
HANDLE_FAILURE("LLVMBuildNeg");
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
result = NULL;
|
||||
bh_assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE,
|
||||
"ret"))) {
|
||||
HANDLE_FAILURE("LLVMBuildBitCast");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* push result into the stack */
|
||||
PUSH_V128(result);
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_i8x16_arith(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
V128Arithmetic arith_op)
|
||||
{
|
||||
LLVMValueRef lhs, rhs;
|
||||
|
||||
if (!(rhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, V128_i8x16_TYPE,
|
||||
"rhs"))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(lhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, V128_i8x16_TYPE,
|
||||
"lhs"))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return simd_v128_integer_arith(comp_ctx, func_ctx, arith_op, lhs, rhs);
|
||||
fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_i16x8_arith(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
V128Arithmetic arith_op)
|
||||
{
|
||||
LLVMValueRef lhs, rhs;
|
||||
|
||||
if (!(rhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, V128_i16x8_TYPE,
|
||||
"rhs"))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(lhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, V128_i16x8_TYPE,
|
||||
"lhs"))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return simd_v128_integer_arith(comp_ctx, func_ctx, arith_op, lhs, rhs);
|
||||
fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_i32x4_arith(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
V128Arithmetic arith_op)
|
||||
{
|
||||
LLVMValueRef lhs, rhs;
|
||||
|
||||
if (!(rhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, V128_i32x4_TYPE,
|
||||
"rhs"))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(lhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, V128_i32x4_TYPE,
|
||||
"lhs"))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return simd_v128_integer_arith(comp_ctx, func_ctx, arith_op, lhs, rhs);
|
||||
fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_i64x2_arith(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
V128Arithmetic arith_op)
|
||||
{
|
||||
LLVMValueRef lhs, rhs;
|
||||
|
||||
POP_V128(rhs);
|
||||
POP_V128(lhs);
|
||||
|
||||
return simd_v128_integer_arith(comp_ctx, func_ctx, arith_op, lhs, rhs);
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_i8x16_neg(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||
{
|
||||
LLVMValueRef number;
|
||||
|
||||
if (!(number = simd_pop_v128_and_bitcast(comp_ctx, func_ctx,
|
||||
V128_i8x16_TYPE, "number"))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return simd_v128_integer_arith(comp_ctx, func_ctx, V128_NEG, number, NULL);
|
||||
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_i16x8_neg(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||
{
|
||||
LLVMValueRef number;
|
||||
|
||||
if (!(number = simd_pop_v128_and_bitcast(comp_ctx, func_ctx,
|
||||
V128_i16x8_TYPE, "number"))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return simd_v128_integer_arith(comp_ctx, func_ctx, V128_NEG, number, NULL);
|
||||
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_i32x4_neg(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||
{
|
||||
LLVMValueRef number;
|
||||
|
||||
if (!(number = simd_pop_v128_and_bitcast(comp_ctx, func_ctx,
|
||||
V128_i32x4_TYPE, "number"))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return simd_v128_integer_arith(comp_ctx, func_ctx, V128_NEG, number, NULL);
|
||||
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_i64x2_neg(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||
{
|
||||
LLVMValueRef number;
|
||||
|
||||
POP_V128(number);
|
||||
|
||||
return simd_v128_integer_arith(comp_ctx, func_ctx, V128_NEG, number, NULL);
|
||||
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
51
core/iwasm/compilation/simd/simd_int_arith.h
Normal file
51
core/iwasm/compilation/simd/simd_int_arith.h
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef _SIMD_INT_ARITH_H_
|
||||
#define _SIMD_INT_ARITH_H_
|
||||
|
||||
#include "../aot_compiler.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
bool
|
||||
aot_compile_simd_i8x16_arith(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
V128Arithmetic cond);
|
||||
|
||||
bool
|
||||
aot_compile_simd_i16x8_arith(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
V128Arithmetic cond);
|
||||
|
||||
bool
|
||||
aot_compile_simd_i32x4_arith(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
V128Arithmetic cond);
|
||||
|
||||
bool
|
||||
aot_compile_simd_i64x2_arith(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
V128Arithmetic cond);
|
||||
|
||||
bool
|
||||
aot_compile_simd_i8x16_neg(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
|
||||
|
||||
bool
|
||||
aot_compile_simd_i16x8_neg(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
|
||||
|
||||
bool
|
||||
aot_compile_simd_i32x4_neg(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
|
||||
|
||||
bool
|
||||
aot_compile_simd_i64x2_neg(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* end of _SIMD_INT_ARITH_H_ */
|
||||
301
core/iwasm/compilation/simd/simd_load_store.c
Normal file
301
core/iwasm/compilation/simd/simd_load_store.c
Normal file
@ -0,0 +1,301 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "simd_load_store.h"
|
||||
#include "../aot_emit_exception.h"
|
||||
#include "../aot_emit_memory.h"
|
||||
#include "../../aot/aot_runtime.h"
|
||||
#include "../../interpreter/wasm_opcode.h"
|
||||
|
||||
/* data_length in bytes */
|
||||
static LLVMValueRef
|
||||
simd_load(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint32 align,
|
||||
uint32 offset,
|
||||
uint32 data_length,
|
||||
LLVMTypeRef ptr_type)
|
||||
{
|
||||
LLVMValueRef maddr, data;
|
||||
|
||||
if (!(maddr = aot_check_memory_overflow(comp_ctx, func_ctx, offset,
|
||||
data_length))) {
|
||||
HANDLE_FAILURE("aot_check_memory_overflow");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(maddr = LLVMBuildBitCast(comp_ctx->builder, maddr, ptr_type,
|
||||
"data_ptr"))) {
|
||||
HANDLE_FAILURE("LLVMBuildBitCast");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(data = LLVMBuildLoad(comp_ctx->builder, maddr, "data"))) {
|
||||
HANDLE_FAILURE("LLVMBuildLoad");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
LLVMSetAlignment(data, 1);
|
||||
|
||||
return data;
|
||||
fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* data_length in bytes */
|
||||
static LLVMValueRef
|
||||
simd_splat(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
LLVMValueRef element,
|
||||
LLVMTypeRef vectory_type,
|
||||
unsigned lane_count)
|
||||
{
|
||||
LLVMValueRef undef, zeros, vector;
|
||||
LLVMTypeRef zeros_type;
|
||||
|
||||
if (!(undef = LLVMGetUndef(vectory_type))) {
|
||||
HANDLE_FAILURE("LLVMGetUndef");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(zeros_type = LLVMVectorType(I32_TYPE, lane_count))) {
|
||||
HANDLE_FAILURE("LVMVectorType");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(zeros = LLVMConstNull(zeros_type))) {
|
||||
HANDLE_FAILURE("LLVMConstNull");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(vector = LLVMBuildInsertElement(comp_ctx->builder, undef, element,
|
||||
I32_ZERO, "base"))) {
|
||||
HANDLE_FAILURE("LLVMBuildInsertElement");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(vector = LLVMBuildShuffleVector(comp_ctx->builder, vector, undef,
|
||||
zeros, "vector"))) {
|
||||
HANDLE_FAILURE("LLVMBuildShuffleVector");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return vector;
|
||||
fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_v128_load(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint32 align,
|
||||
uint32 offset)
|
||||
{
|
||||
LLVMValueRef result;
|
||||
|
||||
if (!(result =
|
||||
simd_load(comp_ctx, func_ctx, align, offset, 16, V128_PTR_TYPE))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
PUSH_V128(result);
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_v128_store(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint32 align,
|
||||
uint32 offset)
|
||||
{
|
||||
LLVMValueRef maddr, value, result;
|
||||
|
||||
POP_V128(value);
|
||||
|
||||
if (!(maddr = aot_check_memory_overflow(comp_ctx, func_ctx, offset, 16)))
|
||||
return false;
|
||||
|
||||
if (!(maddr = LLVMBuildBitCast(comp_ctx->builder, maddr, V128_PTR_TYPE,
|
||||
"data_ptr"))) {
|
||||
HANDLE_FAILURE("LLVMBuildBitCast");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(result = LLVMBuildStore(comp_ctx->builder, value, maddr))) {
|
||||
HANDLE_FAILURE("LLVMBuildStore");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
LLVMSetAlignment(result, 1);
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_load_extend(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint8 load_opcode,
|
||||
uint32 align,
|
||||
uint32 offset)
|
||||
{
|
||||
LLVMValueRef sub_vector, result;
|
||||
LLVMTypeRef sub_vector_type, vector_type;
|
||||
bool is_signed;
|
||||
uint32 data_length;
|
||||
|
||||
switch (load_opcode) {
|
||||
case SIMD_i16x8_load8x8_s:
|
||||
case SIMD_i16x8_load8x8_u:
|
||||
{
|
||||
data_length = 8;
|
||||
vector_type = V128_i16x8_TYPE;
|
||||
is_signed = (load_opcode == SIMD_i16x8_load8x8_s);
|
||||
|
||||
if (!(sub_vector_type = LLVMVectorType(INT8_TYPE, 8))) {
|
||||
HANDLE_FAILURE("LLVMVectorType");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case SIMD_i32x4_load16x4_s:
|
||||
case SIMD_i32x4_load16x4_u:
|
||||
{
|
||||
data_length = 8;
|
||||
vector_type = V128_i32x4_TYPE;
|
||||
is_signed = (load_opcode == SIMD_i32x4_load16x4_s);
|
||||
|
||||
if (!(sub_vector_type = LLVMVectorType(INT16_TYPE, 4))) {
|
||||
HANDLE_FAILURE("LLVMVectorType");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case SIMD_i64x2_load32x2_s:
|
||||
case SIMD_i64x2_load32x2_u:
|
||||
{
|
||||
data_length = 8;
|
||||
vector_type = V128_i64x2_TYPE;
|
||||
is_signed = (load_opcode == SIMD_i64x2_load32x2_s);
|
||||
|
||||
if (!(sub_vector_type = LLVMVectorType(I32_TYPE, 2))) {
|
||||
HANDLE_FAILURE("LLVMVectorType");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
bh_assert(0);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* to vector ptr type */
|
||||
if (!(sub_vector_type = LLVMPointerType(sub_vector_type, 0))) {
|
||||
HANDLE_FAILURE("LLVMPointerType");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(sub_vector = simd_load(comp_ctx, func_ctx, align, offset,
|
||||
data_length, sub_vector_type))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (is_signed) {
|
||||
if (!(result = LLVMBuildSExt(comp_ctx->builder, sub_vector,
|
||||
vector_type, "vector"))) {
|
||||
HANDLE_FAILURE("LLVMBuildSExt");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!(result = LLVMBuildZExt(comp_ctx->builder, sub_vector,
|
||||
vector_type, "vector"))) {
|
||||
HANDLE_FAILURE("LLVMBuildZExt");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE,
|
||||
"result"))) {
|
||||
HANDLE_FAILURE("LLVMBuildBitCast");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
PUSH_V128(result);
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_load_splat(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint8 load_opcode,
|
||||
uint32 align,
|
||||
uint32 offset)
|
||||
{
|
||||
LLVMValueRef element, result;
|
||||
LLVMTypeRef element_ptr_type, vector_type;
|
||||
unsigned data_length, lane_count;
|
||||
|
||||
switch (load_opcode) {
|
||||
case SIMD_v8x16_load_splat:
|
||||
data_length = 1;
|
||||
lane_count = 16;
|
||||
element_ptr_type = INT8_PTR_TYPE;
|
||||
vector_type = V128_i8x16_TYPE;
|
||||
break;
|
||||
case SIMD_v16x8_load_splat:
|
||||
data_length = 2;
|
||||
lane_count = 8;
|
||||
element_ptr_type = INT16_PTR_TYPE;
|
||||
vector_type = V128_i16x8_TYPE;
|
||||
break;
|
||||
case SIMD_v32x4_load_splat:
|
||||
data_length = 4;
|
||||
lane_count = 4;
|
||||
element_ptr_type = INT32_PTR_TYPE;
|
||||
vector_type = V128_i32x4_TYPE;
|
||||
break;
|
||||
case SIMD_v64x2_load_splat:
|
||||
data_length = 8;
|
||||
lane_count = 2;
|
||||
element_ptr_type = INT64_PTR_TYPE;
|
||||
vector_type = V128_i64x2_TYPE;
|
||||
break;
|
||||
default:
|
||||
bh_assert(0);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(element = simd_load(comp_ctx, func_ctx, align, offset, data_length,
|
||||
element_ptr_type))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(result = simd_splat(comp_ctx, func_ctx, element, vector_type,
|
||||
lane_count))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE,
|
||||
"result"))) {
|
||||
HANDLE_FAILURE("LLVMBuildBitCast");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
PUSH_V128(result);
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
45
core/iwasm/compilation/simd/simd_load_store.h
Normal file
45
core/iwasm/compilation/simd/simd_load_store.h
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef _SIMD_LOAD_STORE_H_
|
||||
#define _SIMD_LOAD_STORE_H_
|
||||
|
||||
#include "../aot_compiler.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
bool
|
||||
aot_compile_simd_v128_load(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint32 align,
|
||||
uint32 offset);
|
||||
|
||||
bool
|
||||
aot_compile_simd_v128_store(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint32 align,
|
||||
uint32 offset);
|
||||
|
||||
bool
|
||||
aot_compile_simd_load_extend(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint8 load_opcode,
|
||||
uint32 align,
|
||||
uint32 offset);
|
||||
|
||||
bool
|
||||
aot_compile_simd_load_splat(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
uint8 load_opcode,
|
||||
uint32 align,
|
||||
uint32 offset);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* end of _SIMD_LOAD_STORE_H_ */
|
||||
367
core/iwasm/compilation/simd/simd_sat_int_arith.c
Normal file
367
core/iwasm/compilation/simd/simd_sat_int_arith.c
Normal file
@ -0,0 +1,367 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "simd_sat_int_arith.h"
|
||||
#include "simd_common.h"
|
||||
#include "../aot_emit_exception.h"
|
||||
#include "../../aot/aot_runtime.h"
|
||||
|
||||
static bool
|
||||
simd_v128_integer_arith(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
LLVMTypeRef vector_type,
|
||||
char *intrinsics_s_u[2],
|
||||
bool is_signed)
|
||||
{
|
||||
LLVMValueRef lhs, rhs, result;
|
||||
LLVMTypeRef param_types[2];
|
||||
|
||||
if (!(rhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
|
||||
"rhs"))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(lhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
|
||||
"lhs"))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
param_types[0] = vector_type;
|
||||
param_types[1] = vector_type;
|
||||
|
||||
if (!(result = aot_call_llvm_intrinsic(
|
||||
comp_ctx, is_signed ? intrinsics_s_u[0] : intrinsics_s_u[1],
|
||||
vector_type, param_types, 2, lhs, rhs))) {
|
||||
HANDLE_FAILURE("LLVMBuildCall");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE,
|
||||
"ret"))) {
|
||||
HANDLE_FAILURE("LLVMBuildBitCast");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* push result into the stack */
|
||||
PUSH_V128(result);
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_i8x16_saturate(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
V128Arithmetic arith_op,
|
||||
bool is_signed)
|
||||
{
|
||||
char *intrinsics[2] = { 0 };
|
||||
bool result = false;
|
||||
switch (arith_op) {
|
||||
case V128_ADD:
|
||||
intrinsics[0] = "llvm.sadd.sat.v16i8";
|
||||
intrinsics[1] = "llvm.uadd.sat.v16i8";
|
||||
result = simd_v128_integer_arith(
|
||||
comp_ctx, func_ctx, V128_i8x16_TYPE, intrinsics, is_signed);
|
||||
break;
|
||||
case V128_SUB:
|
||||
intrinsics[0] = "llvm.ssub.sat.v16i8";
|
||||
intrinsics[1] = "llvm.usub.sat.v16i8";
|
||||
result = simd_v128_integer_arith(
|
||||
comp_ctx, func_ctx, V128_i8x16_TYPE, intrinsics, is_signed);
|
||||
break;
|
||||
default:
|
||||
bh_assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_i16x8_saturate(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
V128Arithmetic arith_op,
|
||||
bool is_signed)
|
||||
{
|
||||
char *intrinsics[2] = { 0 };
|
||||
bool result = false;
|
||||
switch (arith_op) {
|
||||
case V128_ADD:
|
||||
intrinsics[0] = "llvm.sadd.sat.v8i16";
|
||||
intrinsics[1] = "llvm.uadd.sat.v8i16";
|
||||
result = simd_v128_integer_arith(
|
||||
comp_ctx, func_ctx, V128_i16x8_TYPE, intrinsics, is_signed);
|
||||
break;
|
||||
case V128_SUB:
|
||||
intrinsics[0] = "llvm.ssub.sat.v8i16";
|
||||
intrinsics[1] = "llvm.usub.sat.v8i16";
|
||||
result = simd_v128_integer_arith(
|
||||
comp_ctx, func_ctx, V128_i16x8_TYPE, intrinsics, is_signed);
|
||||
break;
|
||||
default:
|
||||
bh_assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool
|
||||
simd_v128_cmp(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
LLVMTypeRef vector_type,
|
||||
V128Arithmetic arith_op,
|
||||
bool is_signed)
|
||||
{
|
||||
LLVMValueRef lhs, rhs, result;
|
||||
LLVMIntPredicate op;
|
||||
|
||||
if (!(rhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
|
||||
"rhs"))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(lhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
|
||||
"lhs"))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (V128_MIN == arith_op) {
|
||||
op = is_signed ? LLVMIntSLT : LLVMIntULT;
|
||||
}
|
||||
else {
|
||||
op = is_signed ? LLVMIntSGT : LLVMIntUGT;
|
||||
}
|
||||
|
||||
if (!(result = LLVMBuildICmp(comp_ctx->builder, op, lhs, rhs, "cmp"))) {
|
||||
HANDLE_FAILURE("LLVMBuildICmp");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(result =
|
||||
LLVMBuildSelect(comp_ctx->builder, result, lhs, rhs, "select"))) {
|
||||
HANDLE_FAILURE("LLVMBuildSelect");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE,
|
||||
"ret"))) {
|
||||
HANDLE_FAILURE("LLVMBuildBitCast");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* push result into the stack */
|
||||
PUSH_V128(result);
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_i8x16_cmp(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
V128Arithmetic arith_op,
|
||||
bool is_signed)
|
||||
{
|
||||
return simd_v128_cmp(comp_ctx, func_ctx, V128_i8x16_TYPE, arith_op,
|
||||
is_signed);
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_i16x8_cmp(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
V128Arithmetic arith_op,
|
||||
bool is_signed)
|
||||
{
|
||||
return simd_v128_cmp(comp_ctx, func_ctx, V128_i16x8_TYPE, arith_op,
|
||||
is_signed);
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_i32x4_cmp(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
V128Arithmetic arith_op,
|
||||
bool is_signed)
|
||||
{
|
||||
return simd_v128_cmp(comp_ctx, func_ctx, V128_i32x4_TYPE, arith_op,
|
||||
is_signed);
|
||||
}
|
||||
|
||||
static bool
|
||||
simd_v128_abs(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
LLVMTypeRef vector_type)
|
||||
{
|
||||
LLVMValueRef vector, negs, zeros, cond, result;
|
||||
|
||||
if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
|
||||
"vec"))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(negs = LLVMBuildNeg(comp_ctx->builder, vector, "neg"))) {
|
||||
HANDLE_FAILURE("LLVMBuildNeg");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(zeros = LLVMConstNull(vector_type))) {
|
||||
HANDLE_FAILURE("LLVMConstNull");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(cond = LLVMBuildICmp(comp_ctx->builder, LLVMIntSGE, vector, zeros,
|
||||
"ge_zero"))) {
|
||||
HANDLE_FAILURE("LLVMBuildICmp");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(result = LLVMBuildSelect(comp_ctx->builder, cond, vector, negs,
|
||||
"select"))) {
|
||||
HANDLE_FAILURE("LLVMBuildSelect");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE,
|
||||
"ret"))) {
|
||||
HANDLE_FAILURE("LLVMBuildBitCast");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* push result into the stack */
|
||||
PUSH_V128(result);
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_i8x16_abs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||
{
|
||||
return simd_v128_abs(comp_ctx, func_ctx, V128_i8x16_TYPE);
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_i16x8_abs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||
{
|
||||
return simd_v128_abs(comp_ctx, func_ctx, V128_i16x8_TYPE);
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_i32x4_abs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||
{
|
||||
return simd_v128_abs(comp_ctx, func_ctx, V128_i32x4_TYPE);
|
||||
}
|
||||
|
||||
/* (v1 + v2 + 1) / 2 */
|
||||
static bool
|
||||
simd_v128_avg(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
LLVMTypeRef vector_type,
|
||||
LLVMTypeRef element_type,
|
||||
unsigned lane_width)
|
||||
{
|
||||
LLVMValueRef lhs, rhs, undef, zeros, ones, result;
|
||||
LLVMTypeRef ext_type;
|
||||
|
||||
if (!(rhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
|
||||
"rhs"))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(lhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
|
||||
"lhs"))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(ext_type = LLVMVectorType(I32_TYPE, lane_width))) {
|
||||
HANDLE_FAILURE("LLVMVectorType");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(lhs = LLVMBuildZExt(comp_ctx->builder, lhs, ext_type, "left_ext"))) {
|
||||
HANDLE_FAILURE("LLVMBuildZExt");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(rhs =
|
||||
LLVMBuildZExt(comp_ctx->builder, rhs, ext_type, "right_ext"))) {
|
||||
HANDLE_FAILURE("LLVMBuildZExt");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(undef = LLVMGetUndef(ext_type))) {
|
||||
HANDLE_FAILURE("LLVMGetUndef");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(zeros = LLVMConstNull(ext_type))) {
|
||||
HANDLE_FAILURE("LLVMConstNull");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(ones = LLVMConstInt(I32_TYPE, 1, true))) {
|
||||
HANDLE_FAILURE("LLVMConstInt");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(ones = LLVMBuildInsertElement(comp_ctx->builder, undef, ones,
|
||||
I32_ZERO, "base_ones"))) {
|
||||
HANDLE_FAILURE("LLVMBuildInsertElement");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(ones = LLVMBuildShuffleVector(comp_ctx->builder, ones, undef, zeros,
|
||||
"ones"))) {
|
||||
HANDLE_FAILURE("LLVMBuildShuffleVector");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(result = LLVMBuildAdd(comp_ctx->builder, lhs, rhs, "a_add_b"))) {
|
||||
HANDLE_FAILURE("LLVMBuildAdd");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(result = LLVMBuildAdd(comp_ctx->builder, result, ones, "plus_1"))) {
|
||||
HANDLE_FAILURE("LLVMBuildAdd");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(result = LLVMBuildLShr(comp_ctx->builder, result, ones, "avg"))) {
|
||||
HANDLE_FAILURE("LLVMBuildLShr");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(result = LLVMBuildTrunc(comp_ctx->builder, result, vector_type,
|
||||
"avg_trunc"))) {
|
||||
HANDLE_FAILURE("LLVMBuildTrunc");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE,
|
||||
"ret"))) {
|
||||
HANDLE_FAILURE("LLVMBuildBitCast");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* push result into the stack */
|
||||
PUSH_V128(result);
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
bool
|
||||
aot_compile_simd_i8x16_avgr_u(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx)
|
||||
{
|
||||
return simd_v128_avg(comp_ctx, func_ctx, V128_i8x16_TYPE, INT8_TYPE, 16);
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_simd_i16x8_avgr_u(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx)
|
||||
{
|
||||
return simd_v128_avg(comp_ctx, func_ctx, V128_i16x8_TYPE, INT16_TYPE, 8);
|
||||
}
|
||||
66
core/iwasm/compilation/simd/simd_sat_int_arith.h
Normal file
66
core/iwasm/compilation/simd/simd_sat_int_arith.h
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef _SIMD_SAT_INT_ARITH_H_
|
||||
#define _SIMD_SAT_INT_ARITH_H_
|
||||
|
||||
#include "../aot_compiler.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
bool
|
||||
aot_compile_simd_i8x16_saturate(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
V128Arithmetic arith_op,
|
||||
bool is_signed);
|
||||
|
||||
bool
|
||||
aot_compile_simd_i16x8_saturate(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
V128Arithmetic arith_op,
|
||||
bool is_signed);
|
||||
|
||||
bool
|
||||
aot_compile_simd_i8x16_cmp(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
V128Arithmetic arith_op,
|
||||
bool is_signed);
|
||||
|
||||
bool
|
||||
aot_compile_simd_i16x8_cmp(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
V128Arithmetic arith_op,
|
||||
bool is_signed);
|
||||
|
||||
bool
|
||||
aot_compile_simd_i32x4_cmp(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx,
|
||||
V128Arithmetic arith_op,
|
||||
bool is_signed);
|
||||
|
||||
bool
|
||||
aot_compile_simd_i8x16_abs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
|
||||
|
||||
bool
|
||||
aot_compile_simd_i16x8_abs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
|
||||
|
||||
bool
|
||||
aot_compile_simd_i32x4_abs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
|
||||
|
||||
bool
|
||||
aot_compile_simd_i8x16_avgr_u(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx);
|
||||
|
||||
bool
|
||||
aot_compile_simd_i16x8_avgr_u(AOTCompContext *comp_ctx,
|
||||
AOTFuncContext *func_ctx);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* end of _SIMD_SAT_INT_ARITH_H_ */
|
||||
Reference in New Issue
Block a user