summaryrefslogtreecommitdiffstats
path: root/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_bitmask_extracts.c
blob: 67d965426f011f94e714c1550e93b1a1f774528c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/*
 * 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"

enum integer_bitmask_type {
    e_bitmask_i8x16,
    e_bitmask_i16x8,
    e_bitmask_i32x4,
    e_bitmask_i64x2,
};

/* TODO: should use a much clever intrinsic */
static bool
simd_build_bitmask(const AOTCompContext *comp_ctx,
                   const AOTFuncContext *func_ctx,
                   enum integer_bitmask_type itype)
{
    LLVMValueRef vector, mask, result;
    uint8 i;
    LLVMTypeRef vector_ext_type;

    uint32 lanes[] = { 16, 8, 4, 2 };
    uint32 lane_bits[] = { 8, 16, 32, 64 };
    LLVMTypeRef element_type[] = { INT8_TYPE, INT16_TYPE, I32_TYPE, I64_TYPE };
    LLVMTypeRef vector_type[] = { V128_i8x16_TYPE, V128_i16x8_TYPE,
                                  V128_i32x4_TYPE, V128_i64x2_TYPE };
    int32 mask_element[16] = { 0 };
    const char *intrinsic[] = {
        "llvm.vector.reduce.or.v16i64",
        "llvm.vector.reduce.or.v8i64",
        "llvm.vector.reduce.or.v4i64",
        "llvm.vector.reduce.or.v2i64",
    };

    LLVMValueRef ashr_distance;

    if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx,
                                             vector_type[itype], "vec"))) {
        goto fail;
    }

    /* fill every bit in a lange with its sign bit */
    if (!(ashr_distance = simd_build_splat_const_integer_vector(
              comp_ctx, element_type[itype], lane_bits[itype] - 1,
              lanes[itype]))) {
        goto fail;
    }

    if (!(vector = LLVMBuildAShr(comp_ctx->builder, vector, ashr_distance,
                                 "vec_ashr"))) {
        HANDLE_FAILURE("LLVMBuildAShr");
        goto fail;
    }

    if (!(vector_ext_type = LLVMVectorType(I64_TYPE, lanes[itype]))) {
        HANDLE_FAILURE("LLVMVectorType");
        goto fail;
    }

    if (e_bitmask_i64x2 != itype) {
        if (!(vector = LLVMBuildSExt(comp_ctx->builder, vector, vector_ext_type,
                                     "zext_to_i64"))) {
            goto fail;
        }
    }

    for (i = 0; i < 16; i++) {
        mask_element[i] = 0x1 << i;
    }

    if (!(mask = simd_build_const_integer_vector(comp_ctx, I64_TYPE,
                                                 mask_element, lanes[itype]))) {
        goto fail;
    }

    if (!(vector =
              LLVMBuildAnd(comp_ctx->builder, vector, mask, "mask_bits"))) {
        HANDLE_FAILURE("LLVMBuildAnd");
        goto fail;
    }

    if (!(result =
              aot_call_llvm_intrinsic(comp_ctx, func_ctx, intrinsic[itype],
                                      I64_TYPE, &vector_ext_type, 1, vector))) {
        goto fail;
    }

    if (!(result =
              LLVMBuildTrunc(comp_ctx->builder, result, I32_TYPE, "to_i32"))) {
        HANDLE_FAILURE("LLVMBuildTrunc");
        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, e_bitmask_i8x16);
}

bool
aot_compile_simd_i16x8_bitmask(AOTCompContext *comp_ctx,
                               AOTFuncContext *func_ctx)
{
    return simd_build_bitmask(comp_ctx, func_ctx, e_bitmask_i16x8);
}

bool
aot_compile_simd_i32x4_bitmask(AOTCompContext *comp_ctx,
                               AOTFuncContext *func_ctx)
{
    return simd_build_bitmask(comp_ctx, func_ctx, e_bitmask_i32x4);
}

bool
aot_compile_simd_i64x2_bitmask(AOTCompContext *comp_ctx,
                               AOTFuncContext *func_ctx)
{
    return simd_build_bitmask(comp_ctx, func_ctx, e_bitmask_i64x2);
}