authorgravatar for shawn@git.icuShawn Landden <shawn@git.icu> 2019-07-21 10:41:43-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-09-19 10:11:06-04:00
log01577a3af480cff02c5f78864f8056487b3d3b44
tree9d029218b191a5c3f5701153fd1784eafae08e3f
parent0048bcbd71b9139203d7acee120d524d38e22a0e
signature Commit is signed but in an unrecognized format.

`@splat`


6 files changed, 157 insertions(+), 10 deletions(-)

src/all_types.hpp+9
...@@ -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,7 @@ enum IrInstructionId {...@@ -2431,6 +2432,7 @@ enum IrInstructionId {
2431 IrInstructionIdIntType,2432 IrInstructionIdIntType,
2432 IrInstructionIdVectorType,2433 IrInstructionIdVectorType,
2433 IrInstructionIdShuffleVector,2434 IrInstructionIdShuffleVector,
2435 IrInstructionIdSplat,
2434 IrInstructionIdBoolNot,2436 IrInstructionIdBoolNot,
2435 IrInstructionIdMemset,2437 IrInstructionIdMemset,
2436 IrInstructionIdMemcpy,2438 IrInstructionIdMemcpy,
...@@ -3681,6 +3683,13 @@ struct IrInstructionShuffleVector {...@@ -3681,6 +3683,13 @@ struct IrInstructionShuffleVector {
3681 IrInstruction *mask; // This is in zig-format, not llvm format3683 IrInstruction *mask; // This is in zig-format, not llvm format
3682};3684};
36833685
3686struct IrInstructionSplat {
3687 IrInstruction base;
3688
3689 IrInstruction *len;
3690 IrInstruction *scalar;
3691};
3692
3684struct IrInstructionAssertZero {3693struct IrInstructionAssertZero {
3685 IrInstruction base;3694 IrInstruction base;
36863695
src/codegen.cpp+17
...@@ -4619,6 +4619,20 @@ static LLVMValueRef ir_render_shuffle_vector(CodeGen *g, IrExecutable *executabl...@@ -4619,6 +4619,20 @@ 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, IrInstructionSplat *instruction) {
4623 uint64_t len = bigint_as_u64(&instruction->len->value.data.x_bigint);
4624 LLVMValueRef wrapped_scalar_undef = LLVMGetUndef(instruction->base.value.type->llvm_type);
4625 LLVMValueRef wrapped_scalar = LLVMBuildInsertElement(g->builder, wrapped_scalar_undef,
4626 ir_llvm_value(g, instruction->scalar),
4627 LLVMConstInt(LLVMInt32Type(), 0, false),
4628 "");
4629 return LLVMBuildShuffleVector(g->builder,
4630 wrapped_scalar,
4631 wrapped_scalar_undef,
4632 LLVMConstNull(LLVMVectorType(g->builtin_types.entry_u32->llvm_type, (uint32_t)len)),
4633 "");
4634}
4635
4622static LLVMValueRef ir_render_pop_count(CodeGen *g, IrExecutable *executable, IrInstructionPopCount *instruction) {4636static LLVMValueRef ir_render_pop_count(CodeGen *g, IrExecutable *executable, IrInstructionPopCount *instruction) {
4623 ZigType *int_type = instruction->op->value.type;4637 ZigType *int_type = instruction->op->value.type;
4624 LLVMValueRef fn_val = get_int_builtin_fn(g, int_type, BuiltinFnIdPopCount);4638 LLVMValueRef fn_val = get_int_builtin_fn(g, int_type, BuiltinFnIdPopCount);
...@@ -6146,6 +6160,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -6146,6 +6160,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
6146 return ir_render_spill_end(g, executable, (IrInstructionSpillEnd *)instruction);6160 return ir_render_spill_end(g, executable, (IrInstructionSpillEnd *)instruction);
6147 case IrInstructionIdShuffleVector:6161 case IrInstructionIdShuffleVector:
6148 return ir_render_shuffle_vector(g, executable, (IrInstructionShuffleVector *) instruction);6162 return ir_render_shuffle_vector(g, executable, (IrInstructionShuffleVector *) instruction);
6163 case IrInstructionIdSplat:
6164 return ir_render_splat(g, executable, (IrInstructionSplat *) instruction);
6149 }6165 }
6150 zig_unreachable();6166 zig_unreachable();
6151}6167}
...@@ -7837,6 +7853,7 @@ static void define_builtin_fns(CodeGen *g) {...@@ -7837,6 +7853,7 @@ static void define_builtin_fns(CodeGen *g) {
7837 create_builtin_fn(g, BuiltinFnIdIntType, "IntType", 2); // TODO rename to Int7853 create_builtin_fn(g, BuiltinFnIdIntType, "IntType", 2); // TODO rename to Int
7838 create_builtin_fn(g, BuiltinFnIdVectorType, "Vector", 2);7854 create_builtin_fn(g, BuiltinFnIdVectorType, "Vector", 2);
7839 create_builtin_fn(g, BuiltinFnIdShuffle, "shuffle", 4);7855 create_builtin_fn(g, BuiltinFnIdShuffle, "shuffle", 4);
7856 create_builtin_fn(g, BuiltinFnIdSplat, "splat", 2);
7840 create_builtin_fn(g, BuiltinFnIdSetCold, "setCold", 1);7857 create_builtin_fn(g, BuiltinFnIdSetCold, "setCold", 1);
7841 create_builtin_fn(g, BuiltinFnIdSetRuntimeSafety, "setRuntimeSafety", 1);7858 create_builtin_fn(g, BuiltinFnIdSetRuntimeSafety, "setRuntimeSafety", 1);
7842 create_builtin_fn(g, BuiltinFnIdSetFloatMode, "setFloatMode", 1);7859 create_builtin_fn(g, BuiltinFnIdSetFloatMode, "setFloatMode", 1);
src/ir.cpp+82
...@@ -721,6 +721,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionShuffleVector *)...@@ -721,6 +721,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionShuffleVector *)
721 return IrInstructionIdShuffleVector;721 return IrInstructionIdShuffleVector;
722}722}
723723
724static constexpr IrInstructionId ir_instruction_id(IrInstructionSplat *) {
725 return IrInstructionIdSplat;
726}
727
724static constexpr IrInstructionId ir_instruction_id(IrInstructionBoolNot *) {728static constexpr IrInstructionId ir_instruction_id(IrInstructionBoolNot *) {
725 return IrInstructionIdBoolNot;729 return IrInstructionIdBoolNot;
726}730}
...@@ -2300,6 +2304,19 @@ static IrInstruction *ir_build_shuffle_vector(IrBuilder *irb, Scope *scope, AstN...@@ -2300,6 +2304,19 @@ static IrInstruction *ir_build_shuffle_vector(IrBuilder *irb, Scope *scope, AstN
2300 return &instruction->base;2304 return &instruction->base;
2301}2305}
23022306
2307static IrInstruction *ir_build_splat(IrBuilder *irb, Scope *scope, AstNode *source_node,
2308 IrInstruction *len, IrInstruction *scalar)
2309{
2310 IrInstructionSplat *instruction = ir_build_instruction<IrInstructionSplat>(irb, scope, source_node);
2311 instruction->len = len;
2312 instruction->scalar = scalar;
2313
2314 ir_ref_instruction(len, irb->current_basic_block);
2315 ir_ref_instruction(scalar, irb->current_basic_block);
2316
2317 return &instruction->base;
2318}
2319
2303static IrInstruction *ir_build_bool_not(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {2320static 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);2321 IrInstructionBoolNot *instruction = ir_build_instruction<IrInstructionBoolNot>(irb, scope, source_node);
2305 instruction->value = value;2322 instruction->value = value;
...@@ -4985,6 +5002,22 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4985,6 +5002,22 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4985 arg0_value, arg1_value, arg2_value, arg3_value);5002 arg0_value, arg1_value, arg2_value, arg3_value);
4986 return ir_lval_wrap(irb, scope, shuffle_vector, lval, result_loc);5003 return ir_lval_wrap(irb, scope, shuffle_vector, lval, result_loc);
4987 }5004 }
5005 case BuiltinFnIdSplat:
5006 {
5007 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
5008 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
5009 if (arg0_value == irb->codegen->invalid_instruction)
5010 return arg0_value;
5011
5012 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
5013 IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope);
5014 if (arg1_value == irb->codegen->invalid_instruction)
5015 return arg1_value;
5016
5017 IrInstruction *splat = ir_build_splat(irb, scope, node,
5018 arg0_value, arg1_value);
5019 return ir_lval_wrap(irb, scope, splat, lval, result_loc);
5020 }
4988 case BuiltinFnIdMemcpy:5021 case BuiltinFnIdMemcpy:
4989 {5022 {
4990 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);5023 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
...@@ -22324,6 +22357,52 @@ static IrInstruction *ir_analyze_instruction_shuffle_vector(IrAnalyze *ira, IrIn...@@ -22324,6 +22357,52 @@ static IrInstruction *ir_analyze_instruction_shuffle_vector(IrAnalyze *ira, IrIn
22324 return ir_analyze_shuffle_vector(ira, &instruction->base, scalar_type, a, b, mask);22357 return ir_analyze_shuffle_vector(ira, &instruction->base, scalar_type, a, b, mask);
22325}22358}
2232622359
22360static IrInstruction *ir_analyze_instruction_splat(IrAnalyze *ira, IrInstructionSplat *instruction) {
22361 IrInstruction *len = instruction->len->child;
22362 if (type_is_invalid(len->value.type))
22363 return ira->codegen->invalid_instruction;
22364
22365 IrInstruction *scalar = instruction->scalar->child;
22366 if (type_is_invalid(scalar->value.type))
22367 return ira->codegen->invalid_instruction;
22368
22369 uint64_t len_int;
22370 if (!ir_resolve_unsigned(ira, len, ira->codegen->builtin_types.entry_u32, &len_int)) {
22371 ir_add_error(ira, len,
22372 buf_sprintf("splat length must be comptime"));
22373 return ira->codegen->invalid_instruction;
22374 }
22375
22376 if (!is_valid_vector_elem_type(scalar->value.type)) {
22377 ir_add_error(ira, len,
22378 buf_sprintf("vector element type must be integer, float, bool, or pointer; '%s' is invalid",
22379 buf_ptr(&scalar->value.type->name)));
22380 return ira->codegen->invalid_instruction;
22381 }
22382
22383 ZigType *return_type = get_vector_type(ira->codegen, len_int, scalar->value.type);
22384
22385 if (instr_is_comptime(scalar)) {
22386 IrInstruction *result = ir_const_undef(ira, scalar, return_type);
22387 result->value.data.x_array.data.s_none.elements =
22388 allocate<ConstExprValue>(len_int);
22389 for (uint32_t i = 0; i < len_int; i++) {
22390 result->value.data.x_array.data.s_none.elements[i] =
22391 scalar->value;
22392 }
22393 result->value.type = return_type;
22394 result->value.special = ConstValSpecialStatic;
22395 return result;
22396 }
22397
22398 IrInstruction *result = ir_build_splat(&ira->new_irb,
22399 instruction->base.scope, instruction->base.source_node,
22400 instruction->len->child, instruction->scalar->child);
22401 result->value.type = return_type;
22402 result->value.special = ConstValSpecialRuntime;
22403 return result;
22404}
22405
22327static IrInstruction *ir_analyze_instruction_bool_not(IrAnalyze *ira, IrInstructionBoolNot *instruction) {22406static IrInstruction *ir_analyze_instruction_bool_not(IrAnalyze *ira, IrInstructionBoolNot *instruction) {
22328 IrInstruction *value = instruction->value->child;22407 IrInstruction *value = instruction->value->child;
22329 if (type_is_invalid(value->value.type))22408 if (type_is_invalid(value->value.type))
...@@ -25908,6 +25987,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction...@@ -25908,6 +25987,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
25908 return ir_analyze_instruction_vector_type(ira, (IrInstructionVectorType *)instruction);25987 return ir_analyze_instruction_vector_type(ira, (IrInstructionVectorType *)instruction);
25909 case IrInstructionIdShuffleVector:25988 case IrInstructionIdShuffleVector:
25910 return ir_analyze_instruction_shuffle_vector(ira, (IrInstructionShuffleVector *)instruction);25989 return ir_analyze_instruction_shuffle_vector(ira, (IrInstructionShuffleVector *)instruction);
25990 case IrInstructionIdSplat:
25991 return ir_analyze_instruction_splat(ira, (IrInstructionSplat *)instruction);
25911 case IrInstructionIdBoolNot:25992 case IrInstructionIdBoolNot:
25912 return ir_analyze_instruction_bool_not(ira, (IrInstructionBoolNot *)instruction);25993 return ir_analyze_instruction_bool_not(ira, (IrInstructionBoolNot *)instruction);
25913 case IrInstructionIdMemset:25994 case IrInstructionIdMemset:
...@@ -26244,6 +26325,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -26244,6 +26325,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
26244 case IrInstructionIdIntType:26325 case IrInstructionIdIntType:
26245 case IrInstructionIdVectorType:26326 case IrInstructionIdVectorType:
26246 case IrInstructionIdShuffleVector:26327 case IrInstructionIdShuffleVector:
26328 case IrInstructionIdSplat:
26247 case IrInstructionIdBoolNot:26329 case IrInstructionIdBoolNot:
26248 case IrInstructionIdSliceSrc:26330 case IrInstructionIdSliceSrc:
26249 case IrInstructionIdMemberCount:26331 case IrInstructionIdMemberCount:
src/ir_print.cpp+13
...@@ -44,6 +44,8 @@ static const char* ir_instruction_type_str(IrInstruction* instruction) {...@@ -44,6 +44,8 @@ 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 IrInstructionIdSplat:
48 return "Splat";
47 case IrInstructionIdDeclVarSrc:49 case IrInstructionIdDeclVarSrc:
48 return "DeclVarSrc";50 return "DeclVarSrc";
49 case IrInstructionIdDeclVarGen:51 case IrInstructionIdDeclVarGen:
...@@ -1222,6 +1224,14 @@ static void ir_print_shuffle_vector(IrPrint *irp, IrInstructionShuffleVector *in...@@ -1222,6 +1224,14 @@ static void ir_print_shuffle_vector(IrPrint *irp, IrInstructionShuffleVector *in
1222 fprintf(irp->f, ")");1224 fprintf(irp->f, ")");
1223}1225}
12241226
1227static void ir_print_splat(IrPrint *irp, IrInstructionSplat *instruction) {
1228 fprintf(irp->f, "@splat(");
1229 ir_print_other_instruction(irp, instruction->len);
1230 fprintf(irp->f, ", ");
1231 ir_print_other_instruction(irp, instruction->scalar);
1232 fprintf(irp->f, ")");
1233}
1234
1225static void ir_print_bool_not(IrPrint *irp, IrInstructionBoolNot *instruction) {1235static void ir_print_bool_not(IrPrint *irp, IrInstructionBoolNot *instruction) {
1226 fprintf(irp->f, "! ");1236 fprintf(irp->f, "! ");
1227 ir_print_other_instruction(irp, instruction->value);1237 ir_print_other_instruction(irp, instruction->value);
...@@ -2160,6 +2170,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction, bool...@@ -2160,6 +2170,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction, bool
2160 case IrInstructionIdShuffleVector:2170 case IrInstructionIdShuffleVector:
2161 ir_print_shuffle_vector(irp, (IrInstructionShuffleVector *)instruction);2171 ir_print_shuffle_vector(irp, (IrInstructionShuffleVector *)instruction);
2162 break;2172 break;
2173 case IrInstructionIdSplat:
2174 ir_print_splat(irp, (IrInstructionSplat *)instruction);
2175 break;
2163 case IrInstructionIdBoolNot:2176 case IrInstructionIdBoolNot:
2164 ir_print_bool_not(irp, (IrInstructionBoolNot *)instruction);2177 ir_print_bool_not(irp, (IrInstructionBoolNot *)instruction);
2165 break;2178 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:20: 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+26-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,19 @@ test "vector casts of sizes not divisable by 8" {...@@ -138,3 +138,19 @@ 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 expect(x[0] == 5);
149 expect(x[1] == 5);
150 expect(x[2] == 5);
151 expect(x[3] == 5);
152 }
153 };
154 S.doTheTest();
155 comptime S.doTheTest();
156}