| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418 |
- /*
- * 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"
- 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 = simd_build_const_integer_vector(comp_ctx, I32_TYPE, values,
- 16))) {
- goto fail;
- }
- if (!(result = LLVMBuildShuffleVector(comp_ctx->builder, vec1, vec2, mask,
- "new_vector"))) {
- HANDLE_FAILURE("LLVMBuildShuffleVector");
- goto fail;
- }
- return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result");
- fail:
- return false;
- }
- /*TODO: llvm.experimental.vector.*/
- /* shufflevector is not an option, since it requires *mask as a const */
- bool
- aot_compile_simd_swizzle_x86(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
- {
- LLVMValueRef vector, mask, max_lanes, condition, mask_lanes, result;
- LLVMTypeRef param_types[2];
- 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 = simd_build_splat_const_integer_vector(comp_ctx, INT8_TYPE,
- 16, 16))) {
- 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 = simd_build_splat_const_integer_vector(
- comp_ctx, INT8_TYPE, 0x80, 16))) {
- goto fail;
- }
- if (!(condition = LLVMBuildICmp(comp_ctx->builder, LLVMIntUGE, mask,
- max_lanes, "compare_with_16"))) {
- HANDLE_FAILURE("LLVMBuldICmp");
- 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, func_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_swizzle_common(AOTCompContext *comp_ctx,
- AOTFuncContext *func_ctx)
- {
- LLVMValueRef vector, mask, default_lane_value, condition, max_lane_id,
- result, idx, id, replace_with_zero, elem, elem_or_zero, undef;
- uint8 i;
- 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;
- }
- if (!(undef = LLVMGetUndef(V128_i8x16_TYPE))) {
- HANDLE_FAILURE("LLVMGetUndef");
- goto fail;
- }
- /* icmp uge <16 x i8> mask, <16, 16, 16, 16, ...> */
- if (!(max_lane_id = simd_build_splat_const_integer_vector(
- comp_ctx, INT8_TYPE, 16, 16))) {
- goto fail;
- }
- if (!(condition = LLVMBuildICmp(comp_ctx->builder, LLVMIntUGE, mask,
- max_lane_id, "out_of_range"))) {
- HANDLE_FAILURE("LLVMBuldICmp");
- goto fail;
- }
- /* if the id is out of range (>=16), set the id as 0 */
- if (!(default_lane_value = simd_build_splat_const_integer_vector(
- comp_ctx, INT8_TYPE, 0, 16))) {
- goto fail;
- }
- if (!(idx = LLVMBuildSelect(comp_ctx->builder, condition,
- default_lane_value, mask, "mask"))) {
- HANDLE_FAILURE("LLVMBuildSelect");
- goto fail;
- }
- for (i = 0; i < 16; i++) {
- if (!(id = LLVMBuildExtractElement(comp_ctx->builder, idx, I8_CONST(i),
- "id"))) {
- HANDLE_FAILURE("LLVMBuildExtractElement");
- goto fail;
- }
- if (!(replace_with_zero =
- LLVMBuildExtractElement(comp_ctx->builder, condition,
- I8_CONST(i), "replace_with_zero"))) {
- HANDLE_FAILURE("LLVMBuildExtractElement");
- goto fail;
- }
- if (!(elem = LLVMBuildExtractElement(comp_ctx->builder, vector, id,
- "vector[mask[i]]"))) {
- HANDLE_FAILURE("LLVMBuildExtractElement");
- goto fail;
- }
- if (!(elem_or_zero =
- LLVMBuildSelect(comp_ctx->builder, replace_with_zero,
- I8_CONST(0), elem, "elem_or_zero"))) {
- HANDLE_FAILURE("LLVMBuildSelect");
- goto fail;
- }
- if (!(undef =
- LLVMBuildInsertElement(comp_ctx->builder, undef, elem_or_zero,
- I8_CONST(i), "new_vector"))) {
- HANDLE_FAILURE("LLVMBuildInsertElement");
- goto fail;
- }
- }
- if (!(result = LLVMBuildBitCast(comp_ctx->builder, undef, V128_i64x2_TYPE,
- "ret"))) {
- HANDLE_FAILURE("LLVMBuildBitCast");
- goto fail;
- }
- PUSH_V128(result);
- return true;
- fail:
- return false;
- }
- bool
- aot_compile_simd_swizzle(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
- {
- if (is_target_x86(comp_ctx)) {
- return aot_compile_simd_swizzle_x86(comp_ctx, func_ctx);
- }
- else {
- return aot_compile_simd_swizzle_common(comp_ctx, func_ctx);
- }
- }
- 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, lane, result;
- if (!(lane = simd_lane_id_to_llvm_value(comp_ctx, 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, lane,
- "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, lane, result;
- POP(new_value, new_value_type);
- if (!(lane = simd_lane_id_to_llvm_value(comp_ctx, lane_id))) {
- goto fail;
- }
- if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
- "vec"))) {
- goto fail;
- }
- /* trunc <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,
- i32 lane */
- if (!(result = LLVMBuildInsertElement(comp_ctx->builder, vector, new_value,
- lane, "new_vector"))) {
- HANDLE_FAILURE("LLVMBuildInsertElement");
- goto fail;
- }
- return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "reesult");
- 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);
- }
|