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
signaturelock-open 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 {
16121612 BuiltinFnIdIntType,
16131613 BuiltinFnIdVectorType,
16141614 BuiltinFnIdShuffle,
1615 BuiltinFnIdSplat,
16151616 BuiltinFnIdSetCold,
16161617 BuiltinFnIdSetRuntimeSafety,
16171618 BuiltinFnIdSetFloatMode,
......@@ -2431,6 +2432,7 @@ enum IrInstructionId {
24312432 IrInstructionIdIntType,
24322433 IrInstructionIdVectorType,
24332434 IrInstructionIdShuffleVector,
2435 IrInstructionIdSplat,
24342436 IrInstructionIdBoolNot,
24352437 IrInstructionIdMemset,
24362438 IrInstructionIdMemcpy,
......@@ -3681,6 +3683,13 @@ struct IrInstructionShuffleVector {
36813683 IrInstruction *mask; // This is in zig-format, not llvm format
36823684};
36833685
3686struct IrInstructionSplat {
3687 IrInstruction base;
3688
3689 IrInstruction *len;
3690 IrInstruction *scalar;
3691};
3692
36843693struct IrInstructionAssertZero {
36853694 IrInstruction base;
36863695
src/codegen.cpp+17
......@@ -4619,6 +4619,20 @@ 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, 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
46224636static LLVMValueRef ir_render_pop_count(CodeGen *g, IrExecutable *executable, IrInstructionPopCount *instruction) {
46234637 ZigType *int_type = instruction->op->value.type;
46244638 LLVMValueRef fn_val = get_int_builtin_fn(g, int_type, BuiltinFnIdPopCount);
......@@ -6146,6 +6160,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
61466160 return ir_render_spill_end(g, executable, (IrInstructionSpillEnd *)instruction);
61476161 case IrInstructionIdShuffleVector:
61486162 return ir_render_shuffle_vector(g, executable, (IrInstructionShuffleVector *) instruction);
6163 case IrInstructionIdSplat:
6164 return ir_render_splat(g, executable, (IrInstructionSplat *) instruction);
61496165 }
61506166 zig_unreachable();
61516167}
......@@ -7837,6 +7853,7 @@ static void define_builtin_fns(CodeGen *g) {
78377853 create_builtin_fn(g, BuiltinFnIdIntType, "IntType", 2); // TODO rename to Int
78387854 create_builtin_fn(g, BuiltinFnIdVectorType, "Vector", 2);
78397855 create_builtin_fn(g, BuiltinFnIdShuffle, "shuffle", 4);
7856 create_builtin_fn(g, BuiltinFnIdSplat, "splat", 2);
78407857 create_builtin_fn(g, BuiltinFnIdSetCold, "setCold", 1);
78417858 create_builtin_fn(g, BuiltinFnIdSetRuntimeSafety, "setRuntimeSafety", 1);
78427859 create_builtin_fn(g, BuiltinFnIdSetFloatMode, "setFloatMode", 1);
src/ir.cpp+82
......@@ -721,6 +721,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionShuffleVector *)
721721 return IrInstructionIdShuffleVector;
722722}
723723
724static constexpr IrInstructionId ir_instruction_id(IrInstructionSplat *) {
725 return IrInstructionIdSplat;
726}
727
724728static constexpr IrInstructionId ir_instruction_id(IrInstructionBoolNot *) {
725729 return IrInstructionIdBoolNot;
726730}
......@@ -2300,6 +2304,19 @@ static IrInstruction *ir_build_shuffle_vector(IrBuilder *irb, Scope *scope, AstN
23002304 return &instruction->base;
23012305}
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
23032320static IrInstruction *ir_build_bool_not(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {
23042321 IrInstructionBoolNot *instruction = ir_build_instruction<IrInstructionBoolNot>(irb, scope, source_node);
23052322 instruction->value = value;
......@@ -4985,6 +5002,22 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
49855002 arg0_value, arg1_value, arg2_value, arg3_value);
49865003 return ir_lval_wrap(irb, scope, shuffle_vector, lval, result_loc);
49875004 }
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 }
49885021 case BuiltinFnIdMemcpy:
49895022 {
49905023 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
2232422357 return ir_analyze_shuffle_vector(ira, &instruction->base, scalar_type, a, b, mask);
2232522358}
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
2232722406static IrInstruction *ir_analyze_instruction_bool_not(IrAnalyze *ira, IrInstructionBoolNot *instruction) {
2232822407 IrInstruction *value = instruction->value->child;
2232922408 if (type_is_invalid(value->value.type))
......@@ -25908,6 +25987,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
2590825987 return ir_analyze_instruction_vector_type(ira, (IrInstructionVectorType *)instruction);
2590925988 case IrInstructionIdShuffleVector:
2591025989 return ir_analyze_instruction_shuffle_vector(ira, (IrInstructionShuffleVector *)instruction);
25990 case IrInstructionIdSplat:
25991 return ir_analyze_instruction_splat(ira, (IrInstructionSplat *)instruction);
2591125992 case IrInstructionIdBoolNot:
2591225993 return ir_analyze_instruction_bool_not(ira, (IrInstructionBoolNot *)instruction);
2591325994 case IrInstructionIdMemset:
......@@ -26244,6 +26325,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
2624426325 case IrInstructionIdIntType:
2624526326 case IrInstructionIdVectorType:
2624626327 case IrInstructionIdShuffleVector:
26328 case IrInstructionIdSplat:
2624726329 case IrInstructionIdBoolNot:
2624826330 case IrInstructionIdSliceSrc:
2624926331 case IrInstructionIdMemberCount:
src/ir_print.cpp+13
......@@ -44,6 +44,8 @@ static const char* ir_instruction_type_str(IrInstruction* instruction) {
4444 return "Invalid";
4545 case IrInstructionIdShuffleVector:
4646 return "Shuffle";
47 case IrInstructionIdSplat:
48 return "Splat";
4749 case IrInstructionIdDeclVarSrc:
4850 return "DeclVarSrc";
4951 case IrInstructionIdDeclVarGen:
......@@ -1222,6 +1224,14 @@ static void ir_print_shuffle_vector(IrPrint *irp, IrInstructionShuffleVector *in
12221224 fprintf(irp->f, ")");
12231225}
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
12251235static void ir_print_bool_not(IrPrint *irp, IrInstructionBoolNot *instruction) {
12261236 fprintf(irp->f, "! ");
12271237 ir_print_other_instruction(irp, instruction->value);
......@@ -2160,6 +2170,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction, bool
21602170 case IrInstructionIdShuffleVector:
21612171 ir_print_shuffle_vector(irp, (IrInstructionShuffleVector *)instruction);
21622172 break;
2173 case IrInstructionIdSplat:
2174 ir_print_splat(irp, (IrInstructionSplat *)instruction);
2175 break;
21632176 case IrInstructionIdBoolNot:
21642177 ir_print_bool_not(irp, (IrInstructionBoolNot *)instruction);
21652178 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:20: 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+26-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,19 @@ 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 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}