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 (...@@ -5864,7 +5864,7 @@ volatile (
5864 : [number] "{rax}" (number),5864 : [number] "{rax}" (number),
5865 [arg1] "{rdi}" (arg1)5865 [arg1] "{rdi}" (arg1)
5866// Next is the list of clobbers. These declare a set of registers whose5866// 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.
5868// These do not include output or input registers. The special clobber5868// These do not include output or input registers. The special clobber
5869// value of "memory" means that the assembly writes to arbitrary undeclared5869// value of "memory" means that the assembly writes to arbitrary undeclared
5870// memory locations - not only the memory pointed to by a declared indirect5870// memory locations - not only the memory pointed to by a declared indirect
...@@ -5885,7 +5885,7 @@ volatile (...@@ -5885,7 +5885,7 @@ volatile (
5885 </p>5885 </p>
5886 {#header_open|Output Constraints#}5886 {#header_open|Output Constraints#}
5887 <p>5887 <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
5889 so5889 so
5890 <a href="http://releases.llvm.org/8.0.0/docs/LangRef.html#inline-asm-constraint-string">LLVM documentation</a>5890 <a href="http://releases.llvm.org/8.0.0/docs/LangRef.html#inline-asm-constraint-string">LLVM documentation</a>
5891 and5891 and
...@@ -5900,7 +5900,7 @@ volatile (...@@ -5900,7 +5900,7 @@ volatile (
59005900
5901 {#header_open|Input Constraints#}5901 {#header_open|Input Constraints#}
5902 <p>5902 <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
5904 so5904 so
5905 <a href="http://releases.llvm.org/8.0.0/docs/LangRef.html#inline-asm-constraint-string">LLVM documentation</a>5905 <a href="http://releases.llvm.org/8.0.0/docs/LangRef.html#inline-asm-constraint-string">LLVM documentation</a>
5906 and5906 and
...@@ -5919,7 +5919,7 @@ volatile (...@@ -5919,7 +5919,7 @@ volatile (
5919 the assembly code. These do not include output or input registers. The special clobber5919 the assembly code. These do not include output or input registers. The special clobber
5920 value of {#syntax#}"memory"{#endsyntax#} means that the assembly causes writes to5920 value of {#syntax#}"memory"{#endsyntax#} means that the assembly causes writes to
5921 arbitrary undeclared memory locations - not only the memory pointed to by a declared5921 arbitrary undeclared memory locations - not only the memory pointed to by a declared
5922 indirect output. 5922 indirect output.
5923 </p>5923 </p>
5924 <p>5924 <p>
5925 Failure to declare the full set of clobbers for a given inline assembly5925 Failure to declare the full set of clobbers for a given inline assembly
...@@ -7746,6 +7746,30 @@ test "@setRuntimeSafety" {...@@ -7746,6 +7746,30 @@ test "@setRuntimeSafety" {
7746 </p>7746 </p>
7747 {#header_close#}7747 {#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
7749 {#header_open|@sqrt#}7773 {#header_open|@sqrt#}
7750 <pre>{#syntax#}@sqrt(comptime T: type, value: T) T{#endsyntax#}</pre>7774 <pre>{#syntax#}@sqrt(comptime T: type, value: T) T{#endsyntax#}</pre>
7751 <p>7775 <p>
...@@ -9456,8 +9480,8 @@ const c = @cImport({...@@ -9456,8 +9480,8 @@ const c = @cImport({
9456 <li>Does not support Zig-only pointer attributes such as alignment. Use normal {#link|Pointers#}9480 <li>Does not support Zig-only pointer attributes such as alignment. Use normal {#link|Pointers#}
9457 please!</li>9481 please!</li>
9458 </ul>9482 </ul>
9459 <p>When a C pointer is pointing to a single struct (not an array), deference the C pointer to 9483 <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 9484 access to the struct's fields or member data. That syntax looks like
9461 this: </p>9485 this: </p>
9462 <p>{#syntax#}ptr_to_struct.*.struct_member{#endsyntax#}</p>9486 <p>{#syntax#}ptr_to_struct.*.struct_member{#endsyntax#}</p>
9463 <p>This is comparable to doing {#syntax#}->{#endsyntax#} in C.</p>9487 <p>This is comparable to doing {#syntax#}->{#endsyntax#} in C.</p>
src/all_types.hpp+16
...@@ -1612,6 +1612,7 @@ enum BuiltinFnId {...@@ -1612,6 +1612,7 @@ enum BuiltinFnId {
1612 BuiltinFnIdIntType,1612 BuiltinFnIdIntType,
1613 BuiltinFnIdVectorType,1613 BuiltinFnIdVectorType,
1614 BuiltinFnIdShuffle,1614 BuiltinFnIdShuffle,
1615 BuiltinFnIdSplat,
1615 BuiltinFnIdSetCold,1616 BuiltinFnIdSetCold,
1616 BuiltinFnIdSetRuntimeSafety,1617 BuiltinFnIdSetRuntimeSafety,
1617 BuiltinFnIdSetFloatMode,1618 BuiltinFnIdSetFloatMode,
...@@ -2431,6 +2432,8 @@ enum IrInstructionId {...@@ -2431,6 +2432,8 @@ enum IrInstructionId {
2431 IrInstructionIdIntType,2432 IrInstructionIdIntType,
2432 IrInstructionIdVectorType,2433 IrInstructionIdVectorType,
2433 IrInstructionIdShuffleVector,2434 IrInstructionIdShuffleVector,
2435 IrInstructionIdSplatSrc,
2436 IrInstructionIdSplatGen,
2434 IrInstructionIdBoolNot,2437 IrInstructionIdBoolNot,
2435 IrInstructionIdMemset,2438 IrInstructionIdMemset,
2436 IrInstructionIdMemcpy,2439 IrInstructionIdMemcpy,
...@@ -3681,6 +3684,19 @@ struct IrInstructionShuffleVector {...@@ -3681,6 +3684,19 @@ struct IrInstructionShuffleVector {
3681 IrInstruction *mask; // This is in zig-format, not llvm format3684 IrInstruction *mask; // This is in zig-format, not llvm format
3682};3685};
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
3684struct IrInstructionAssertZero {3700struct IrInstructionAssertZero {
3685 IrInstruction base;3701 IrInstruction base;
36863702
src/codegen.cpp+16
...@@ -4619,6 +4619,18 @@ static LLVMValueRef ir_render_shuffle_vector(CodeGen *g, IrExecutable *executabl...@@ -4619,6 +4619,18 @@ static LLVMValueRef ir_render_shuffle_vector(CodeGen *g, IrExecutable *executabl
4619 llvm_mask_value, "");4619 llvm_mask_value, "");
4620}4620}
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
4622static LLVMValueRef ir_render_pop_count(CodeGen *g, IrExecutable *executable, IrInstructionPopCount *instruction) {4634static LLVMValueRef ir_render_pop_count(CodeGen *g, IrExecutable *executable, IrInstructionPopCount *instruction) {
4623 ZigType *int_type = instruction->op->value.type;4635 ZigType *int_type = instruction->op->value.type;
4624 LLVMValueRef fn_val = get_int_builtin_fn(g, int_type, BuiltinFnIdPopCount);4636 LLVMValueRef fn_val = get_int_builtin_fn(g, int_type, BuiltinFnIdPopCount);
...@@ -5986,6 +5998,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -5986,6 +5998,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
5986 case IrInstructionIdFrameSizeSrc:5998 case IrInstructionIdFrameSizeSrc:
5987 case IrInstructionIdAllocaGen:5999 case IrInstructionIdAllocaGen:
5988 case IrInstructionIdAwaitSrc:6000 case IrInstructionIdAwaitSrc:
6001 case IrInstructionIdSplatSrc:
5989 zig_unreachable();6002 zig_unreachable();
59906003
5991 case IrInstructionIdDeclVarGen:6004 case IrInstructionIdDeclVarGen:
...@@ -6146,6 +6159,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -6146,6 +6159,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
6146 return ir_render_spill_end(g, executable, (IrInstructionSpillEnd *)instruction);6159 return ir_render_spill_end(g, executable, (IrInstructionSpillEnd *)instruction);
6147 case IrInstructionIdShuffleVector:6160 case IrInstructionIdShuffleVector:
6148 return ir_render_shuffle_vector(g, executable, (IrInstructionShuffleVector *) instruction);6161 return ir_render_shuffle_vector(g, executable, (IrInstructionShuffleVector *) instruction);
6162 case IrInstructionIdSplatGen:
6163 return ir_render_splat(g, executable, (IrInstructionSplatGen *) instruction);
6149 }6164 }
6150 zig_unreachable();6165 zig_unreachable();
6151}6166}
...@@ -7837,6 +7852,7 @@ static void define_builtin_fns(CodeGen *g) {...@@ -7837,6 +7852,7 @@ static void define_builtin_fns(CodeGen *g) {
7837 create_builtin_fn(g, BuiltinFnIdIntType, "IntType", 2); // TODO rename to Int7852 create_builtin_fn(g, BuiltinFnIdIntType, "IntType", 2); // TODO rename to Int
7838 create_builtin_fn(g, BuiltinFnIdVectorType, "Vector", 2);7853 create_builtin_fn(g, BuiltinFnIdVectorType, "Vector", 2);
7839 create_builtin_fn(g, BuiltinFnIdShuffle, "shuffle", 4);7854 create_builtin_fn(g, BuiltinFnIdShuffle, "shuffle", 4);
7855 create_builtin_fn(g, BuiltinFnIdSplat, "splat", 2);
7840 create_builtin_fn(g, BuiltinFnIdSetCold, "setCold", 1);7856 create_builtin_fn(g, BuiltinFnIdSetCold, "setCold", 1);
7841 create_builtin_fn(g, BuiltinFnIdSetRuntimeSafety, "setRuntimeSafety", 1);7857 create_builtin_fn(g, BuiltinFnIdSetRuntimeSafety, "setRuntimeSafety", 1);
7842 create_builtin_fn(g, BuiltinFnIdSetFloatMode, "setFloatMode", 1);7858 create_builtin_fn(g, BuiltinFnIdSetFloatMode, "setFloatMode", 1);
src/ir.cpp+106-5
...@@ -721,6 +721,14 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionShuffleVector *)...@@ -721,6 +721,14 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionShuffleVector *)
721 return IrInstructionIdShuffleVector;721 return IrInstructionIdShuffleVector;
722}722}
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
724static constexpr IrInstructionId ir_instruction_id(IrInstructionBoolNot *) {732static constexpr IrInstructionId ir_instruction_id(IrInstructionBoolNot *) {
725 return IrInstructionIdBoolNot;733 return IrInstructionIdBoolNot;
726}734}
...@@ -2300,6 +2308,19 @@ static IrInstruction *ir_build_shuffle_vector(IrBuilder *irb, Scope *scope, AstN...@@ -2300,6 +2308,19 @@ static IrInstruction *ir_build_shuffle_vector(IrBuilder *irb, Scope *scope, AstN
2300 return &instruction->base;2308 return &instruction->base;
2301}2309}
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
2303static IrInstruction *ir_build_bool_not(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {2324static IrInstruction *ir_build_bool_not(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {
2304 IrInstructionBoolNot *instruction = ir_build_instruction<IrInstructionBoolNot>(irb, scope, source_node);2325 IrInstructionBoolNot *instruction = ir_build_instruction<IrInstructionBoolNot>(irb, scope, source_node);
2305 instruction->value = value;2326 instruction->value = value;
...@@ -2356,6 +2377,19 @@ static IrInstruction *ir_build_slice_src(IrBuilder *irb, Scope *scope, AstNode *...@@ -2356,6 +2377,19 @@ static IrInstruction *ir_build_slice_src(IrBuilder *irb, Scope *scope, AstNode *
2356 return &instruction->base;2377 return &instruction->base;
2357}2378}
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
2359static IrInstruction *ir_build_slice_gen(IrAnalyze *ira, IrInstruction *source_instruction, ZigType *slice_type,2393static IrInstruction *ir_build_slice_gen(IrAnalyze *ira, IrInstruction *source_instruction, ZigType *slice_type,
2360 IrInstruction *ptr, IrInstruction *start, IrInstruction *end, bool safety_check_on, IrInstruction *result_loc)2394 IrInstruction *ptr, IrInstruction *start, IrInstruction *end, bool safety_check_on, IrInstruction *result_loc)
2361{2395{
...@@ -4985,6 +5019,22 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4985,6 +5019,22 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4985 arg0_value, arg1_value, arg2_value, arg3_value);5019 arg0_value, arg1_value, arg2_value, arg3_value);
4986 return ir_lval_wrap(irb, scope, shuffle_vector, lval, result_loc);5020 return ir_lval_wrap(irb, scope, shuffle_vector, lval, result_loc);
4987 }5021 }
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 }
4988 case BuiltinFnIdMemcpy:5038 case BuiltinFnIdMemcpy:
4989 {5039 {
4990 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);5040 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) {...@@ -11049,16 +11099,23 @@ static ZigType *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value) {
11049 return ir_resolve_const_type(ira->codegen, ira->new_irb.exec, type_value->source_node, val);11099 return ir_resolve_const_type(ira->codegen, ira->new_irb.exec, type_value->source_node, val);
11050}11100}
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
11052static ZigType *ir_resolve_vector_elem_type(IrAnalyze *ira, IrInstruction *elem_type_value) {11112static ZigType *ir_resolve_vector_elem_type(IrAnalyze *ira, IrInstruction *elem_type_value) {
11113 Error err;
11053 ZigType *elem_type = ir_resolve_type(ira, elem_type_value);11114 ZigType *elem_type = ir_resolve_type(ira, elem_type_value);
11054 if (type_is_invalid(elem_type))11115 if (type_is_invalid(elem_type))
11055 return ira->codegen->builtin_types.entry_invalid;11116 return ira->codegen->builtin_types.entry_invalid;
11056 if (!is_valid_vector_elem_type(elem_type)) {11117 if ((err = ir_validate_vector_elem_type(ira, elem_type_value, 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)));
11060 return ira->codegen->builtin_types.entry_invalid;11118 return ira->codegen->builtin_types.entry_invalid;
11061 }
11062 return elem_type;11119 return elem_type;
11063}11120}
1106411121
...@@ -22324,6 +22381,45 @@ static IrInstruction *ir_analyze_instruction_shuffle_vector(IrAnalyze *ira, IrIn...@@ -22324,6 +22381,45 @@ static IrInstruction *ir_analyze_instruction_shuffle_vector(IrAnalyze *ira, IrIn
22324 return ir_analyze_shuffle_vector(ira, &instruction->base, scalar_type, a, b, mask);22381 return ir_analyze_shuffle_vector(ira, &instruction->base, scalar_type, a, b, mask);
22325}22382}
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
22327static IrInstruction *ir_analyze_instruction_bool_not(IrAnalyze *ira, IrInstructionBoolNot *instruction) {22423static IrInstruction *ir_analyze_instruction_bool_not(IrAnalyze *ira, IrInstructionBoolNot *instruction) {
22328 IrInstruction *value = instruction->value->child;22424 IrInstruction *value = instruction->value->child;
22329 if (type_is_invalid(value->value.type))22425 if (type_is_invalid(value->value.type))
...@@ -25778,6 +25874,7 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction...@@ -25778,6 +25874,7 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
25778 case IrInstructionIdTestErrGen:25874 case IrInstructionIdTestErrGen:
25779 case IrInstructionIdFrameSizeGen:25875 case IrInstructionIdFrameSizeGen:
25780 case IrInstructionIdAwaitGen:25876 case IrInstructionIdAwaitGen:
25877 case IrInstructionIdSplatGen:
25781 zig_unreachable();25878 zig_unreachable();
2578225879
25783 case IrInstructionIdReturn:25880 case IrInstructionIdReturn:
...@@ -25908,6 +26005,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction...@@ -25908,6 +26005,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
25908 return ir_analyze_instruction_vector_type(ira, (IrInstructionVectorType *)instruction);26005 return ir_analyze_instruction_vector_type(ira, (IrInstructionVectorType *)instruction);
25909 case IrInstructionIdShuffleVector:26006 case IrInstructionIdShuffleVector:
25910 return ir_analyze_instruction_shuffle_vector(ira, (IrInstructionShuffleVector *)instruction);26007 return ir_analyze_instruction_shuffle_vector(ira, (IrInstructionShuffleVector *)instruction);
26008 case IrInstructionIdSplatSrc:
26009 return ir_analyze_instruction_splat(ira, (IrInstructionSplatSrc *)instruction);
25911 case IrInstructionIdBoolNot:26010 case IrInstructionIdBoolNot:
25912 return ir_analyze_instruction_bool_not(ira, (IrInstructionBoolNot *)instruction);26011 return ir_analyze_instruction_bool_not(ira, (IrInstructionBoolNot *)instruction);
25913 case IrInstructionIdMemset:26012 case IrInstructionIdMemset:
...@@ -26244,6 +26343,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -26244,6 +26343,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
26244 case IrInstructionIdIntType:26343 case IrInstructionIdIntType:
26245 case IrInstructionIdVectorType:26344 case IrInstructionIdVectorType:
26246 case IrInstructionIdShuffleVector:26345 case IrInstructionIdShuffleVector:
26346 case IrInstructionIdSplatSrc:
26347 case IrInstructionIdSplatGen:
26247 case IrInstructionIdBoolNot:26348 case IrInstructionIdBoolNot:
26248 case IrInstructionIdSliceSrc:26349 case IrInstructionIdSliceSrc:
26249 case IrInstructionIdMemberCount:26350 case IrInstructionIdMemberCount:
src/ir_print.cpp+24
...@@ -44,6 +44,10 @@ static const char* ir_instruction_type_str(IrInstruction* instruction) {...@@ -44,6 +44,10 @@ static const char* ir_instruction_type_str(IrInstruction* instruction) {
44 return "Invalid";44 return "Invalid";
45 case IrInstructionIdShuffleVector:45 case IrInstructionIdShuffleVector:
46 return "Shuffle";46 return "Shuffle";
47 case IrInstructionIdSplatSrc:
48 return "SplatSrc";
49 case IrInstructionIdSplatGen:
50 return "SplatGen";
47 case IrInstructionIdDeclVarSrc:51 case IrInstructionIdDeclVarSrc:
48 return "DeclVarSrc";52 return "DeclVarSrc";
49 case IrInstructionIdDeclVarGen:53 case IrInstructionIdDeclVarGen:
...@@ -1222,6 +1226,20 @@ static void ir_print_shuffle_vector(IrPrint *irp, IrInstructionShuffleVector *in...@@ -1222,6 +1226,20 @@ static void ir_print_shuffle_vector(IrPrint *irp, IrInstructionShuffleVector *in
1222 fprintf(irp->f, ")");1226 fprintf(irp->f, ")");
1223}1227}
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
1225static void ir_print_bool_not(IrPrint *irp, IrInstructionBoolNot *instruction) {1243static void ir_print_bool_not(IrPrint *irp, IrInstructionBoolNot *instruction) {
1226 fprintf(irp->f, "! ");1244 fprintf(irp->f, "! ");
1227 ir_print_other_instruction(irp, instruction->value);1245 ir_print_other_instruction(irp, instruction->value);
...@@ -2160,6 +2178,12 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction, bool...@@ -2160,6 +2178,12 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction, bool
2160 case IrInstructionIdShuffleVector:2178 case IrInstructionIdShuffleVector:
2161 ir_print_shuffle_vector(irp, (IrInstructionShuffleVector *)instruction);2179 ir_print_shuffle_vector(irp, (IrInstructionShuffleVector *)instruction);
2162 break;2180 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;
2163 case IrInstructionIdBoolNot:2187 case IrInstructionIdBoolNot:
2164 ir_print_bool_not(irp, (IrInstructionBoolNot *)instruction);2188 ir_print_bool_not(irp, (IrInstructionBoolNot *)instruction);
2165 break;2189 break;
test/compile_errors.zig+10
...@@ -6507,6 +6507,16 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -6507,6 +6507,16 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
6507 "tmp.zig:2:26: error: vector element type must be integer, float, bool, or pointer; '@Vector(4, u8)' is invalid",6507 "tmp.zig:2:26: error: vector element type must be integer, float, bool, or pointer; '@Vector(4, u8)' is invalid",
6508 );6508 );
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
6510 cases.add("compileLog of tagged enum doesn't crash the compiler",6520 cases.add("compileLog of tagged enum doesn't crash the compiler",
6511 \\const Bar = union(enum(u32)) {6521 \\const Bar = union(enum(u32)) {
6512 \\ X: i32 = 16522 \\ X: i32 = 1
test/stage1/behavior/vector.zig+27-10
...@@ -35,12 +35,12 @@ test "vector bin compares with mem.eql" {...@@ -35,12 +35,12 @@ test "vector bin compares with mem.eql" {
35 fn doTheTest() void {35 fn doTheTest() void {
36 var v: @Vector(4, i32) = [4]i32{ 2147483647, -2, 30, 40 };36 var v: @Vector(4, i32) = [4]i32{ 2147483647, -2, 30, 40 };
37 var x: @Vector(4, i32) = [4]i32{ 1, 2147483647, 30, 4 };37 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}));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}));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}));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}));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}));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}));43 expect(mem.eql(bool, ([4]bool)(v >= x), [4]bool{ true, false, true, true }));
44 }44 }
45 };45 };
46 S.doTheTest();46 S.doTheTest();
...@@ -114,22 +114,22 @@ test "vector casts of sizes not divisable by 8" {...@@ -114,22 +114,22 @@ test "vector casts of sizes not divisable by 8" {
114 const S = struct {114 const S = struct {
115 fn doTheTest() void {115 fn doTheTest() void {
116 {116 {
117 var v: @Vector(4, u3) = [4]u3{ 5, 2, 3, 0};117 var v: @Vector(4, u3) = [4]u3{ 5, 2, 3, 0 };
118 var x: [4]u3 = v;118 var x: [4]u3 = v;
119 expect(mem.eql(u3, x, ([4]u3)(v)));119 expect(mem.eql(u3, x, ([4]u3)(v)));
120 }120 }
121 {121 {
122 var v: @Vector(4, u2) = [4]u2{ 1, 2, 3, 0};122 var v: @Vector(4, u2) = [4]u2{ 1, 2, 3, 0 };
123 var x: [4]u2 = v;123 var x: [4]u2 = v;
124 expect(mem.eql(u2, x, ([4]u2)(v)));124 expect(mem.eql(u2, x, ([4]u2)(v)));
125 }125 }
126 {126 {
127 var v: @Vector(4, u1) = [4]u1{ 1, 0, 1, 0};127 var v: @Vector(4, u1) = [4]u1{ 1, 0, 1, 0 };
128 var x: [4]u1 = v;128 var x: [4]u1 = v;
129 expect(mem.eql(u1, x, ([4]u1)(v)));129 expect(mem.eql(u1, x, ([4]u1)(v)));
130 }130 }
131 {131 {
132 var v: @Vector(4, bool) = [4]bool{ false, false, true, false};132 var v: @Vector(4, bool) = [4]bool{ false, false, true, false };
133 var x: [4]bool = v;133 var x: [4]bool = v;
134 expect(mem.eql(bool, x, ([4]bool)(v)));134 expect(mem.eql(bool, x, ([4]bool)(v)));
135 }135 }
...@@ -138,3 +138,20 @@ test "vector casts of sizes not divisable by 8" {...@@ -138,3 +138,20 @@ test "vector casts of sizes not divisable by 8" {
138 S.doTheTest();138 S.doTheTest();
139 comptime S.doTheTest();139 comptime S.doTheTest();
140}140}
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}