summaryrefslogtreecommitdiffstats
path: root/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/simd/simd_bit_shifts.c
blob: 675ffbcfe06dc18815bb5ef5586d7d547604705e (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
134
135
136
137
138
139
140
141
142
143
144
/*
 * 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"

enum integer_shift {
    e_shift_i8x16,
    e_shift_i16x8,
    e_shift_i32x4,
    e_shift_i64x2,
};

static bool
simd_shift(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
           IntShift shift_op, enum integer_shift itype)
{
    LLVMValueRef vector, offset, result = NULL;
    LLVMTypeRef vector_type[] = { V128_i8x16_TYPE, V128_i16x8_TYPE,
                                  V128_i32x4_TYPE, V128_i64x2_TYPE };
    LLVMTypeRef element_type[] = { INT8_TYPE, INT16_TYPE, I32_TYPE, I64_TYPE };

    LLVMValueRef undef[] = { LLVM_CONST(i8x16_undef), LLVM_CONST(i16x8_undef),
                             LLVM_CONST(i32x4_undef), LLVM_CONST(i64x2_undef) };
    LLVMValueRef mask[] = { LLVM_CONST(i8x16_vec_zero),
                            LLVM_CONST(i16x8_vec_zero),
                            LLVM_CONST(i32x4_vec_zero),
                            LLVM_CONST(i64x2_vec_zero) };
    LLVMValueRef lane_bits[] = {
        LLVM_CONST(i32_eight),
        LLVMConstInt(I32_TYPE, 16, true),
        LLVMConstInt(I32_TYPE, 32, true),
        LLVMConstInt(I32_TYPE, 64, true),
    };

    POP_I32(offset);

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

    /* offset mod LaneBits */
    if (!lane_bits[itype]
        || !(offset = LLVMBuildSRem(comp_ctx->builder, offset, lane_bits[itype],
                                    "offset_fix"))) {
        HANDLE_FAILURE("LLVMBuildSRem");
        return false;
    }

    /* change type */
    if (itype < e_shift_i32x4) {
        offset = LLVMBuildTrunc(comp_ctx->builder, offset, element_type[itype],
                                "offset_trunc");
    }
    else if (itype == e_shift_i64x2) {
        offset = LLVMBuildZExt(comp_ctx->builder, offset, element_type[itype],
                               "offset_ext");
    }

    if (!offset) {
        HANDLE_FAILURE("LLVMBuildZext/LLVMBuildTrunc");
        return false;
    }

    /* splat to a vector */
    if (!(offset =
              LLVMBuildInsertElement(comp_ctx->builder, undef[itype], offset,
                                     I32_ZERO, "offset_vector_base"))) {
        HANDLE_FAILURE("LLVMBuildInsertElement");
        return false;
    }

    if (!(offset =
              LLVMBuildShuffleVector(comp_ctx->builder, offset, undef[itype],
                                     mask[itype], "offset_vector"))) {
        HANDLE_FAILURE("LLVMBuildShuffleVector");
        return false;
    }

    switch (shift_op) {
        case INT_SHL:
        {
            result = LLVMBuildShl(comp_ctx->builder, vector, offset, "shl");
            break;
        }
        case INT_SHR_S:
        {
            result = LLVMBuildAShr(comp_ctx->builder, vector, offset, "ashr");
            break;
        }
        case INT_SHR_U:
        {
            result = LLVMBuildLShr(comp_ctx->builder, vector, offset, "lshr");
            break;
        }
        default:
        {
            break;
        }
    }

    if (!result) {
        HANDLE_FAILURE("LLVMBuildShl/LLVMBuildLShr/LLVMBuildAShr");
        goto fail;
    }

    return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result");

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, e_shift_i8x16);
}

bool
aot_compile_simd_i16x8_shift(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                             IntShift shift_op)
{
    return simd_shift(comp_ctx, func_ctx, shift_op, e_shift_i16x8);
}

bool
aot_compile_simd_i32x4_shift(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                             IntShift shift_op)
{
    return simd_shift(comp_ctx, func_ctx, shift_op, e_shift_i32x4);
}

bool
aot_compile_simd_i64x2_shift(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                             IntShift shift_op)
{
    return simd_shift(comp_ctx, func_ctx, shift_op, e_shift_i64x2);
}