diff options
| author | gingerBill <bill@gingerbill.org> | 2022-05-25 23:01:33 +0100 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2022-05-25 23:01:33 +0100 |
| commit | 140c00aa0cdeac6d1149db3845cc9f3433140cf9 (patch) | |
| tree | 25ac3c11f4cc2be1928e7b6267654ab98895013a /src/llvm_backend_proc.cpp | |
| parent | 808ea30b48b35d1556afbddcd49839ea9014d76e (diff) | |
`intrinsics.simd_shuffle`
Diffstat (limited to 'src/llvm_backend_proc.cpp')
| -rw-r--r-- | src/llvm_backend_proc.cpp | 45 |
1 files changed, 37 insertions, 8 deletions
diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index c09265e7a..1b5d15d9b 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -981,6 +981,24 @@ lbValue lb_emit_call(lbProcedure *p, lbValue value, Array<lbValue> const &args, return result; } +LLVMValueRef llvm_splat_float(i64 count, LLVMTypeRef type, f64 value) { + LLVMValueRef v = LLVMConstReal(type, value); + LLVMValueRef *values = gb_alloc_array(temporary_allocator(), LLVMValueRef, count); + for (i64 i = 0; i < count; i++) { + values[i] = v; + } + return LLVMConstVector(values, cast(unsigned)count); +} +LLVMValueRef llvm_splat_int(i64 count, LLVMTypeRef type, i64 value, bool is_signed=false) { + LLVMValueRef v = LLVMConstInt(type, value, is_signed); + LLVMValueRef *values = gb_alloc_array(temporary_allocator(), LLVMValueRef, count); + for (i64 i = 0; i < count; i++) { + values[i] = v; + } + return LLVMConstVector(values, cast(unsigned)count); +} + + lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv, BuiltinProcId builtin_id) { ast_node(ce, CallExpr, expr); @@ -1060,12 +1078,7 @@ lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAndValue const case BuiltinProc_simd_shr_masked: op_code = is_signed ? LLVMAShr : LLVMLShr; is_masked = true; break; } if (op_code) { - LLVMValueRef bit_value = lb_const_int(m, elem1, sz*8 - 1).value; - LLVMValueRef *values = gb_alloc_array(temporary_allocator(), LLVMValueRef, count); - for (i64 i = 0; i < count; i++) { - values[i] = bit_value; - } - LLVMValueRef bits = LLVMConstVector(values, cast(unsigned)count); + LLVMValueRef bits = llvm_splat_int(count, lb_type(m, elem1), sz*8 - 1); if (is_masked) { // C logic LLVMValueRef shift = LLVMBuildAnd(p->builder, arg1.value, bits, ""); @@ -1077,7 +1090,6 @@ lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAndValue const LLVMValueRef shift = LLVMBuildBinOp(p->builder, op_code, arg0.value, arg1.value, ""); res.value = LLVMBuildSelect(p->builder, mask, shift, zero, ""); } - return res; } } @@ -1264,7 +1276,24 @@ lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAndValue const lbValue res = {}; res.value = LLVMBuildCall(p->builder, ip, args, gb_count_of(args), ""); - res.type = tv.type; + return res; + } + + case BuiltinProc_simd_shuffle: + { + arg1 = lb_build_expr(p, ce->args[1]); + arg2 = lb_build_expr(p, ce->args[2]); + + Type *vt = arg0.type; + GB_ASSERT(vt->kind == Type_SimdVector); + + LLVMValueRef mask = arg2.value; + + i64 max_count = vt->SimdVector.count*2; + LLVMValueRef max_mask = llvm_splat_int(max_count, lb_type(m, arg2.type->SimdVector.elem), max_count-1); + mask = LLVMBuildAnd(p->builder, mask, max_mask, ""); + + res.value = LLVMBuildShuffleVector(p->builder, arg0.value, arg1.value, mask, ""); return res; } } |