authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-09-19 11:15:07-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-09-19 11:15:07-04:00
log1eb33966b100c34f9a432d76d45dd86176996936
treeb03cf7256bc6c77b79bffecbe83cd384b5e9db91
parent0048bcbd71b9139203d7acee120d524d38e22a0e
parent28c7fe60b6de6e3c32e082a0abfb5a7bac8fc45a
signaturelock-open Commit is signed but in an unrecognized format.

Merge branch 'merge-shawnl-simd5'

This is the commit from Shawn's SIMD patchset regarding `@splat`, plus my fixups.

7 files changed, 229 insertions(+), 21 deletions(-)

doc/langref.html.in+30-6
......@@ -5864,7 +5864,7 @@ volatile (
58645864 : [number] "{rax}" (number),
58655865 [arg1] "{rdi}" (arg1)
58665866// Next is the list of clobbers. These declare a set of registers whose
5867// values will not be preserved by the execution of this assembly code.
5867// values will not be preserved by the execution of this assembly code.
58685868// These do not include output or input registers. The special clobber
58695869// value of "memory" means that the assembly writes to arbitrary undeclared
58705870// memory locations - not only the memory pointed to by a declared indirect
......@@ -5885,7 +5885,7 @@ volatile (
58855885 </p>
58865886 {#header_open|Output Constraints#}
58875887 <p>
5888 Output constraints are still considered to be unstable in Zig, and
5888 Output constraints are still considered to be unstable in Zig, and
58895889 so
58905890 <a href="http://releases.llvm.org/8.0.0/docs/LangRef.html#inline-asm-constraint-string">LLVM documentation</a>
58915891 and
......@@ -5900,7 +5900,7 @@ volatile (
59005900
59015901 {#header_open|Input Constraints#}
59025902 <p>
5903 Input constraints are still considered to be unstable in Zig, and
5903 Input constraints are still considered to be unstable in Zig, and
59045904 so
59055905 <a href="http://releases.llvm.org/8.0.0/docs/LangRef.html#inline-asm-constraint-string">LLVM documentation</a>
59065906 and
......@@ -5919,7 +5919,7 @@ volatile (
59195919 the assembly code. These do not include output or input registers. The special clobber
59205920 value of {#syntax#}"memory"{#endsyntax#} means that the assembly causes writes to
59215921 arbitrary undeclared memory locations - not only the memory pointed to by a declared
5922 indirect output.
5922 indirect output.
59235923 </p>
59245924 <p>
59255925 Failure to declare the full set of clobbers for a given inline assembly
......@@ -7746,6 +7746,30 @@ test "@setRuntimeSafety" {
77467746 </p>
77477747 {#header_close#}
77487748
7749 {#header_open|@splat#}
7750 <pre>{#syntax#}@splat(comptime len: u32, scalar: var) @Vector(len, @typeOf(scalar)){#endsyntax#}</pre>
7751 <p>
7752 Produces a vector of length {#syntax#}len{#endsyntax#} where each element is the value
7753 {#syntax#}scalar{#endsyntax#}:
7754 </p>
7755 {#code_begin|test#}
7756const std = @import("std");
7757const assert = std.debug.assert;
7758
7759test "vector @splat" {
7760 const scalar: u32 = 5;
7761 const result = @splat(4, scalar);
7762 comptime assert(@typeOf(result) == @Vector(4, u32));
7763 assert(std.mem.eql(u32, ([4]u32)(result), [_]u32{ 5, 5, 5, 5 }));
7764}
7765 {#code_end#}
7766 <p>
7767 {#syntax#}scalar{#endsyntax#} must be an {#link|integer|Integers#}, {#link|bool|Primitive Types#},
7768 {#link|float|Floats#}, or {#link|pointer|Pointers#}.
7769 </p>
7770 {#see_also|Vectors|@shuffle#}
7771 {#header_close#}
7772
77497773 {#header_open|@sqrt#}
77507774 <pre>{#syntax#}@sqrt(comptime T: type, value: T) T{#endsyntax#}</pre>
77517775 <p>
......@@ -9456,8 +9480,8 @@ const c = @cImport({
94569480 <li>Does not support Zig-only pointer attributes such as alignment. Use normal {#link|Pointers#}
94579481 please!</li>
94589482 </ul>
9459 <p>When a C pointer is pointing to a single struct (not an array), deference the C pointer to
9460 access to the struct's fields or member data. That syntax looks like
9483 <p>When a C pointer is pointing to a single struct (not an array), deference the C pointer to
9484 access to the struct's fields or member data. That syntax looks like
94619485 this: </p>
94629486 <p>{#syntax#}ptr_to_struct.*.struct_member{#endsyntax#}</p>
94639487 <p>This is comparable to doing {#syntax#}->{#endsyntax#} in C.</p>
src/all_types.hpp+16
......@@ -1612,6 +1612,7 @@ enum BuiltinFnId {
16121612 BuiltinFnIdIntType,
16131613 BuiltinFnIdVectorType,
16141614 BuiltinFnIdShuffle,
1615 BuiltinFnIdSplat,
16151616 BuiltinFnIdSetCold,
16161617 BuiltinFnIdSetRuntimeSafety,
16171618 BuiltinFnIdSetFloatMode,
......@@ -2431,6 +2432,8 @@ enum IrInstructionId {
24312432 IrInstructionIdIntType,
24322433 IrInstructionIdVectorType,
24332434 IrInstructionIdShuffleVector,
2435 IrInstructionIdSplatSrc,
2436 IrInstructionIdSplatGen,
24342437 IrInstructionIdBoolNot,
24352438 IrInstructionIdMemset,
24362439 IrInstructionIdMemcpy,
......@@ -3681,6 +3684,19 @@ struct IrInstructionShuffleVector {
36813684 IrInstruction *mask; // This is in zig-format, not llvm format
36823685};
36833686
3687struct IrInstructionSplatSrc {
3688 IrInstruction base;
3689
3690 IrInstruction *len;
3691 IrInstruction *scalar;
3692};
3693
3694struct IrInstructionSplatGen {
3695 IrInstruction base;
3696
3697 IrInstruction *scalar;
3698};
3699
36843700struct IrInstructionAssertZero {
36853701 IrInstruction base;
36863702
src/codegen.cpp+16
......@@ -4619,6 +4619,18 @@ static LLVMValueRef ir_render_shuffle_vector(CodeGen *g, IrExecutable *executabl
46194619 llvm_mask_value, "");
46204620}
46214621
4622static LLVMValueRef ir_render_splat(CodeGen *g, IrExecutable *executable, IrInstructionSplatGen *instruction) {
4623 ZigType *result_type = instruction->base.value.type;
4624 src_assert(result_type->id == ZigTypeIdVector, instruction->base.source_node);
4625 uint32_t len = result_type->data.vector.len;
4626 LLVMTypeRef op_llvm_type = LLVMVectorType(get_llvm_type(g, instruction->scalar->value.type), 1);
4627 LLVMTypeRef mask_llvm_type = LLVMVectorType(LLVMInt32Type(), len);
4628 LLVMValueRef undef_vector = LLVMGetUndef(op_llvm_type);
4629 LLVMValueRef op_vector = LLVMBuildInsertElement(g->builder, undef_vector,
4630 ir_llvm_value(g, instruction->scalar), LLVMConstInt(LLVMInt32Type(), 0, false), "");
4631 return LLVMBuildShuffleVector(g->builder, op_vector, undef_vector, LLVMConstNull(mask_llvm_type), "");
4632}
4633
46224634static LLVMValueRef ir_render_pop_count(CodeGen *g, IrExecutable *executable, IrInstructionPopCount *instruction) {
46234635 ZigType *int_type = instruction->op->value.type;
46244636 LLVMValueRef fn_val = get_int_builtin_fn(g, int_type, BuiltinFnIdPopCount);
......@@ -5986,6 +5998,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
59865998 case IrInstructionIdFrameSizeSrc:
59875999 case IrInstructionIdAllocaGen:
59886000 case IrInstructionIdAwaitSrc:
6001 case IrInstructionIdSplatSrc:
59896002 zig_unreachable();
59906003
59916004 case IrInstructionIdDeclVarGen:
......@@ -6146,6 +6159,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
61466159 return ir_render_spill_end(g, executable, (IrInstructionSpillEnd *)instruction);
61476160 case IrInstructionIdShuffleVector:
61486161 return ir_render_shuffle_vector(g, executable, (IrInstructionShuffleVector *) instruction);
6162 case IrInstructionIdSplatGen:
6163 return ir_render_splat(g, executable, (IrInstructionSplatGen *) instruction);
61496164 }
61506165 zig_unreachable();
61516166}
......@@ -7837,6 +7852,7 @@ static void define_builtin_fns(CodeGen *g) {
78377852 create_builtin_fn(g, BuiltinFnIdIntType, "IntType", 2); // TODO rename to Int
78387853 create_builtin_fn(g, BuiltinFnIdVectorType, "Vector", 2);
78397854 create_builtin_fn(g, BuiltinFnIdShuffle, "shuffle", 4);
7855 create_builtin_fn(g, BuiltinFnIdSplat, "splat", 2);
78407856 create_builtin_fn(g, BuiltinFnIdSetCold, "setCold", 1);
78417857 create_builtin_fn(g, BuiltinFnIdSetRuntimeSafety, "setRuntimeSafety", 1);
78427858 create_builtin_fn(g, BuiltinFnIdSetFloatMode, "setFloatMode", 1);
src/ir.cpp+106-5
......@@ -721,6 +721,14 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionShuffleVector *)
721721 return IrInstructionIdShuffleVector;
722722}
723723
724static constexpr IrInstructionId ir_instruction_id(IrInstructionSplatSrc *) {
725 return IrInstructionIdSplatSrc;
726}
727
728static constexpr IrInstructionId ir_instruction_id(IrInstructionSplatGen *) {
729 return IrInstructionIdSplatGen;
730}
731
724732static constexpr IrInstructionId ir_instruction_id(IrInstructionBoolNot *) {
725733 return IrInstructionIdBoolNot;
726734}
......@@ -2300,6 +2308,19 @@ static IrInstruction *ir_build_shuffle_vector(IrBuilder *irb, Scope *scope, AstN
23002308 return &instruction->base;
23012309}
23022310
2311static IrInstruction *ir_build_splat_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
2312 IrInstruction *len, IrInstruction *scalar)
2313{
2314 IrInstructionSplatSrc *instruction = ir_build_instruction<IrInstructionSplatSrc>(irb, scope, source_node);
2315 instruction->len = len;
2316 instruction->scalar = scalar;
2317
2318 ir_ref_instruction(len, irb->current_basic_block);
2319 ir_ref_instruction(scalar, irb->current_basic_block);
2320
2321 return &instruction->base;
2322}
2323
23032324static IrInstruction *ir_build_bool_not(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {
23042325 IrInstructionBoolNot *instruction = ir_build_instruction<IrInstructionBoolNot>(irb, scope, source_node);
23052326 instruction->value = value;
......@@ -2356,6 +2377,19 @@ static IrInstruction *ir_build_slice_src(IrBuilder *irb, Scope *scope, AstNode *
23562377 return &instruction->base;
23572378}
23582379
2380static IrInstruction *ir_build_splat_gen(IrAnalyze *ira, IrInstruction *source_instruction, ZigType *result_type,
2381 IrInstruction *scalar)
2382{
2383 IrInstructionSplatGen *instruction = ir_build_instruction<IrInstructionSplatGen>(
2384 &ira->new_irb, source_instruction->scope, source_instruction->source_node);
2385 instruction->base.value.type = result_type;
2386 instruction->scalar = scalar;
2387
2388 ir_ref_instruction(scalar, ira->new_irb.current_basic_block);
2389
2390 return &instruction->base;
2391}
2392
23592393static IrInstruction *ir_build_slice_gen(IrAnalyze *ira, IrInstruction *source_instruction, ZigType *slice_type,
23602394 IrInstruction *ptr, IrInstruction *start, IrInstruction *end, bool safety_check_on, IrInstruction *result_loc)
23612395{
......@@ -4985,6 +5019,22 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
49855019 arg0_value, arg1_value, arg2_value, arg3_value);
49865020 return ir_lval_wrap(irb, scope, shuffle_vector, lval, result_loc);
49875021 }
5022 case BuiltinFnIdSplat:
5023 {
5024 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
5025 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
5026 if (arg0_value == irb->codegen->invalid_instruction)
5027 return arg0_value;
5028
5029 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
5030 IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope);
5031 if (arg1_value == irb->codegen->invalid_instruction)
5032 return arg1_value;
5033
5034 IrInstruction *splat = ir_build_splat_src(irb, scope, node,
5035 arg0_value, arg1_value);
5036 return ir_lval_wrap(irb, scope, splat, lval, result_loc);
5037 }
49885038 case BuiltinFnIdMemcpy:
49895039 {
49905040 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
......@@ -11049,16 +11099,23 @@ static ZigType *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value) {
1104911099 return ir_resolve_const_type(ira->codegen, ira->new_irb.exec, type_value->source_node, val);
1105011100}
1105111101
11102static Error ir_validate_vector_elem_type(IrAnalyze *ira, IrInstruction *source_instr, ZigType *elem_type) {
11103 if (!is_valid_vector_elem_type(elem_type)) {
11104 ir_add_error(ira, source_instr,
11105 buf_sprintf("vector element type must be integer, float, bool, or pointer; '%s' is invalid",
11106 buf_ptr(&elem_type->name)));
11107 return ErrorSemanticAnalyzeFail;
11108 }
11109 return ErrorNone;
11110}
11111
1105211112static ZigType *ir_resolve_vector_elem_type(IrAnalyze *ira, IrInstruction *elem_type_value) {
11113 Error err;
1105311114 ZigType *elem_type = ir_resolve_type(ira, elem_type_value);
1105411115 if (type_is_invalid(elem_type))
1105511116 return ira->codegen->builtin_types.entry_invalid;
11056 if (!is_valid_vector_elem_type(elem_type)) {
11057 ir_add_error(ira, elem_type_value,
11058 buf_sprintf("vector element type must be integer, float, bool, or pointer; '%s' is invalid",
11059 buf_ptr(&elem_type->name)));
11117 if ((err = ir_validate_vector_elem_type(ira, elem_type_value, elem_type)))
1106011118 return ira->codegen->builtin_types.entry_invalid;
11061 }
1106211119 return elem_type;
1106311120}
1106411121
......@@ -22324,6 +22381,45 @@ static IrInstruction *ir_analyze_instruction_shuffle_vector(IrAnalyze *ira, IrIn
2232422381 return ir_analyze_shuffle_vector(ira, &instruction->base, scalar_type, a, b, mask);
2232522382}
2232622383
22384static IrInstruction *ir_analyze_instruction_splat(IrAnalyze *ira, IrInstructionSplatSrc *instruction) {
22385 Error err;
22386
22387 IrInstruction *len = instruction->len->child;
22388 if (type_is_invalid(len->value.type))
22389 return ira->codegen->invalid_instruction;
22390
22391 IrInstruction *scalar = instruction->scalar->child;
22392 if (type_is_invalid(scalar->value.type))
22393 return ira->codegen->invalid_instruction;
22394
22395 uint64_t len_u64;
22396 if (!ir_resolve_unsigned(ira, len, ira->codegen->builtin_types.entry_u32, &len_u64))
22397 return ira->codegen->invalid_instruction;
22398 uint32_t len_int = len_u64;
22399
22400 if ((err = ir_validate_vector_elem_type(ira, scalar, scalar->value.type)))
22401 return ira->codegen->invalid_instruction;
22402
22403 ZigType *return_type = get_vector_type(ira->codegen, len_int, scalar->value.type);
22404
22405 if (instr_is_comptime(scalar)) {
22406 ConstExprValue *scalar_val = ir_resolve_const(ira, scalar, UndefOk);
22407 if (scalar_val == nullptr)
22408 return ira->codegen->invalid_instruction;
22409 if (scalar_val->special == ConstValSpecialUndef)
22410 return ir_const_undef(ira, &instruction->base, return_type);
22411
22412 IrInstruction *result = ir_const(ira, &instruction->base, return_type);
22413 result->value.data.x_array.data.s_none.elements = create_const_vals(len_int);
22414 for (uint32_t i = 0; i < len_int; i += 1) {
22415 copy_const_val(&result->value.data.x_array.data.s_none.elements[i], scalar_val, false);
22416 }
22417 return result;
22418 }
22419
22420 return ir_build_splat_gen(ira, &instruction->base, return_type, scalar);
22421}
22422
2232722423static IrInstruction *ir_analyze_instruction_bool_not(IrAnalyze *ira, IrInstructionBoolNot *instruction) {
2232822424 IrInstruction *value = instruction->value->child;
2232922425 if (type_is_invalid(value->value.type))
......@@ -25778,6 +25874,7 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
2577825874 case IrInstructionIdTestErrGen:
2577925875 case IrInstructionIdFrameSizeGen:
2578025876 case IrInstructionIdAwaitGen:
25877 case IrInstructionIdSplatGen:
2578125878 zig_unreachable();
2578225879
2578325880 case IrInstructionIdReturn:
......@@ -25908,6 +26005,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
2590826005 return ir_analyze_instruction_vector_type(ira, (IrInstructionVectorType *)instruction);
2590926006 case IrInstructionIdShuffleVector:
2591026007 return ir_analyze_instruction_shuffle_vector(ira, (IrInstructionShuffleVector *)instruction);
26008 case IrInstructionIdSplatSrc:
26009 return ir_analyze_instruction_splat(ira, (IrInstructionSplatSrc *)instruction);
2591126010 case IrInstructionIdBoolNot:
2591226011 return ir_analyze_instruction_bool_not(ira, (IrInstructionBoolNot *)instruction);
2591326012 case IrInstructionIdMemset:
......@@ -26244,6 +26343,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
2624426343 case IrInstructionIdIntType:
2624526344 case IrInstructionIdVectorType:
2624626345 case IrInstructionIdShuffleVector:
26346 case IrInstructionIdSplatSrc:
26347 case IrInstructionIdSplatGen:
2624726348 case IrInstructionIdBoolNot:
2624826349 case IrInstructionIdSliceSrc:
2624926350 case IrInstructionIdMemberCount:
src/ir_print.cpp+24
......@@ -44,6 +44,10 @@ static const char* ir_instruction_type_str(IrInstruction* instruction) {
4444 return "Invalid";
4545 case IrInstructionIdShuffleVector:
4646 return "Shuffle";
47 case IrInstructionIdSplatSrc:
48 return "SplatSrc";
49 case IrInstructionIdSplatGen:
50 return "SplatGen";
4751 case IrInstructionIdDeclVarSrc:
4852 return "DeclVarSrc";
4953 case IrInstructionIdDeclVarGen:
......@@ -1222,6 +1226,20 @@ static void ir_print_shuffle_vector(IrPrint *irp, IrInstructionShuffleVector *in
12221226 fprintf(irp->f, ")");
12231227}
12241228
1229static void ir_print_splat_src(IrPrint *irp, IrInstructionSplatSrc *instruction) {
1230 fprintf(irp->f, "@splat(");
1231 ir_print_other_instruction(irp, instruction->len);
1232 fprintf(irp->f, ", ");
1233 ir_print_other_instruction(irp, instruction->scalar);
1234 fprintf(irp->f, ")");
1235}
1236
1237static void ir_print_splat_gen(IrPrint *irp, IrInstructionSplatGen *instruction) {
1238 fprintf(irp->f, "@splat(");
1239 ir_print_other_instruction(irp, instruction->scalar);
1240 fprintf(irp->f, ")");
1241}
1242
12251243static void ir_print_bool_not(IrPrint *irp, IrInstructionBoolNot *instruction) {
12261244 fprintf(irp->f, "! ");
12271245 ir_print_other_instruction(irp, instruction->value);
......@@ -2160,6 +2178,12 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction, bool
21602178 case IrInstructionIdShuffleVector:
21612179 ir_print_shuffle_vector(irp, (IrInstructionShuffleVector *)instruction);
21622180 break;
2181 case IrInstructionIdSplatSrc:
2182 ir_print_splat_src(irp, (IrInstructionSplatSrc *)instruction);
2183 break;
2184 case IrInstructionIdSplatGen:
2185 ir_print_splat_gen(irp, (IrInstructionSplatGen *)instruction);
2186 break;
21632187 case IrInstructionIdBoolNot:
21642188 ir_print_bool_not(irp, (IrInstructionBoolNot *)instruction);
21652189 break;
test/compile_errors.zig+10
......@@ -6507,6 +6507,16 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
65076507 "tmp.zig:2:26: error: vector element type must be integer, float, bool, or pointer; '@Vector(4, u8)' is invalid",
65086508 );
65096509
6510 cases.addTest(
6511 "bad @splat type",
6512 \\export fn entry() void {
6513 \\ const c = 4;
6514 \\ var v = @splat(4, c);
6515 \\}
6516 ,
6517 "tmp.zig:3:23: error: vector element type must be integer, float, bool, or pointer; 'comptime_int' is invalid",
6518 );
6519
65106520 cases.add("compileLog of tagged enum doesn't crash the compiler",
65116521 \\const Bar = union(enum(u32)) {
65126522 \\ X: i32 = 1
test/stage1/behavior/vector.zig+27-10
......@@ -35,12 +35,12 @@ test "vector bin compares with mem.eql" {
3535 fn doTheTest() void {
3636 var v: @Vector(4, i32) = [4]i32{ 2147483647, -2, 30, 40 };
3737 var x: @Vector(4, i32) = [4]i32{ 1, 2147483647, 30, 4 };
38 expect(mem.eql(bool, ([4]bool)(v == x), [4]bool{ false, false, true, false}));
39 expect(mem.eql(bool, ([4]bool)(v != x), [4]bool{ true, true, false, true}));
40 expect(mem.eql(bool, ([4]bool)(v < x), [4]bool{ false, true, false, false}));
41 expect(mem.eql(bool, ([4]bool)(v > x), [4]bool{ true, false, false, true}));
42 expect(mem.eql(bool, ([4]bool)(v <= x), [4]bool{ false, true, true, false}));
43 expect(mem.eql(bool, ([4]bool)(v >= x), [4]bool{ true, false, true, true}));
38 expect(mem.eql(bool, ([4]bool)(v == x), [4]bool{ false, false, true, false }));
39 expect(mem.eql(bool, ([4]bool)(v != x), [4]bool{ true, true, false, true }));
40 expect(mem.eql(bool, ([4]bool)(v < x), [4]bool{ false, true, false, false }));
41 expect(mem.eql(bool, ([4]bool)(v > x), [4]bool{ true, false, false, true }));
42 expect(mem.eql(bool, ([4]bool)(v <= x), [4]bool{ false, true, true, false }));
43 expect(mem.eql(bool, ([4]bool)(v >= x), [4]bool{ true, false, true, true }));
4444 }
4545 };
4646 S.doTheTest();
......@@ -114,22 +114,22 @@ test "vector casts of sizes not divisable by 8" {
114114 const S = struct {
115115 fn doTheTest() void {
116116 {
117 var v: @Vector(4, u3) = [4]u3{ 5, 2, 3, 0};
117 var v: @Vector(4, u3) = [4]u3{ 5, 2, 3, 0 };
118118 var x: [4]u3 = v;
119119 expect(mem.eql(u3, x, ([4]u3)(v)));
120120 }
121121 {
122 var v: @Vector(4, u2) = [4]u2{ 1, 2, 3, 0};
122 var v: @Vector(4, u2) = [4]u2{ 1, 2, 3, 0 };
123123 var x: [4]u2 = v;
124124 expect(mem.eql(u2, x, ([4]u2)(v)));
125125 }
126126 {
127 var v: @Vector(4, u1) = [4]u1{ 1, 0, 1, 0};
127 var v: @Vector(4, u1) = [4]u1{ 1, 0, 1, 0 };
128128 var x: [4]u1 = v;
129129 expect(mem.eql(u1, x, ([4]u1)(v)));
130130 }
131131 {
132 var v: @Vector(4, bool) = [4]bool{ false, false, true, false};
132 var v: @Vector(4, bool) = [4]bool{ false, false, true, false };
133133 var x: [4]bool = v;
134134 expect(mem.eql(bool, x, ([4]bool)(v)));
135135 }
......@@ -138,3 +138,20 @@ test "vector casts of sizes not divisable by 8" {
138138 S.doTheTest();
139139 comptime S.doTheTest();
140140}
141
142test "vector @splat" {
143 const S = struct {
144 fn doTheTest() void {
145 var v: u32 = 5;
146 var x = @splat(4, v);
147 expect(@typeOf(x) == @Vector(4, u32));
148 var array_x: [4]u32 = x;
149 expect(array_x[0] == 5);
150 expect(array_x[1] == 5);
151 expect(array_x[2] == 5);
152 expect(array_x[3] == 5);
153 }
154 };
155 S.doTheTest();
156 comptime S.doTheTest();
157}