authorgravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2021-07-26 02:37:11+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-07-26 20:05:48-04:00
log50a29f7c213d4a906839dfd625b6280663348781
treef0371b90219e295987d33f6335ad0aeb60fd2f7a
parentfc105f268149b195ea4a4189da59d40e96e455b4

Add @select

@select( comptime T: type, pred: std.meta.Vector(len, bool), a: std.meta.Vector(len, T), b: std.meta.Vector(len, T) ) std.meta.Vector(len, T) Constructs a vector from a & b, based on the values in the predicate vector. For indices where the predicate value is true, the corresponding element from the a vector is selected, and otherwise from b.

12 files changed, 309 insertions(+), 2 deletions(-)

doc/langref.html.in+10
......@@ -7125,6 +7125,7 @@ fn func(y: *i32) void {
71257125 an integer or an enum.
71267126 </p>
71277127 {#header_close#}
7128
71287129 {#header_open|@bitCast#}
71297130 <pre>{#syntax#}@bitCast(comptime DestType: type, value: anytype) DestType{#endsyntax#}</pre>
71307131 <p>
......@@ -8177,6 +8178,15 @@ test "@wasmMemoryGrow" {
81778178 a calling function, the returned address will apply to the calling function.
81788179 </p>
81798180 {#header_close#}
8181
8182 {#header_open|@select#}
8183 <pre>{#syntax#}@select(comptime T: type, pred: std.meta.Vector(len, bool), a: std.meta.Vector(len, T), b: std.meta.Vector(len, T)) std.meta.Vector(len, T){#endsyntax#}</pre>
8184 <p>
8185 Selects values element-wise from {#syntax#}a{#endsyntax#} or {#syntax#}b{#endsyntax#} based on {#syntax#}pred{#endsyntax#}. If {#syntax#}pred[i]{#endsyntax#} is {#syntax#}true{#endsyntax#}, the corresponding element in the result will be {#syntax#}a[i]{#endsyntax#} and otherwise {#syntax#}b[i]{#endsyntax#}.
8186 </p>
8187 {#see_also|SIMD|Vectors#}
8188 {#header_close#}
8189
81808190 {#header_open|@setAlignStack#}
81818191 <pre>{#syntax#}@setAlignStack(comptime alignment: u29){#endsyntax#}</pre>
81828192 <p>
src/AstGen.zig+10
......@@ -2090,6 +2090,7 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: ast.Node.Index) Inner
20902090 .splat,
20912091 .reduce,
20922092 .shuffle,
2093 .select,
20932094 .atomic_load,
20942095 .atomic_rmw,
20952096 .atomic_store,
......@@ -7375,6 +7376,15 @@ fn builtinCall(
73757376 });
73767377 return rvalue(gz, rl, result, node);
73777378 },
7379 .select => {
7380 const result = try gz.addPlNode(.select, node, Zir.Inst.Select{
7381 .elem_type = try typeExpr(gz, scope, params[0]),
7382 .pred = try expr(gz, scope, .none, params[1]),
7383 .a = try expr(gz, scope, .none, params[2]),
7384 .b = try expr(gz, scope, .none, params[3]),
7385 });
7386 return rvalue(gz, rl, result, node);
7387 },
73787388 .async_call => {
73797389 const result = try gz.addPlNode(.builtin_async_call, node, Zir.Inst.AsyncCall{
73807390 .frame_buffer = try expr(gz, scope, .none, params[0]),
src/BuiltinFn.zig+8
......@@ -69,6 +69,7 @@ pub const Tag = enum {
6969 ptr_to_int,
7070 rem,
7171 return_address,
72 select,
7273 set_align_stack,
7374 set_cold,
7475 set_eval_branch_quota,
......@@ -601,6 +602,13 @@ pub const list = list: {
601602 .param_count = 0,
602603 },
603604 },
605 .{
606 "@select",
607 .{
608 .tag = .select,
609 .param_count = 4,
610 },
611 },
604612 .{
605613 "@setAlignStack",
606614 .{
src/Sema.zig+7
......@@ -338,6 +338,7 @@ pub fn analyzeBody(
338338 .splat => try sema.zirSplat(block, inst),
339339 .reduce => try sema.zirReduce(block, inst),
340340 .shuffle => try sema.zirShuffle(block, inst),
341 .select => try sema.zirSelect(block, inst),
341342 .atomic_load => try sema.zirAtomicLoad(block, inst),
342343 .atomic_rmw => try sema.zirAtomicRmw(block, inst),
343344 .atomic_store => try sema.zirAtomicStore(block, inst),
......@@ -6099,6 +6100,12 @@ fn zirShuffle(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErr
60996100 return sema.mod.fail(&block.base, src, "TODO: Sema.zirShuffle", .{});
61006101}
61016102
6103fn zirSelect(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
6104 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
6105 const src = inst_data.src();
6106 return sema.mod.fail(&block.base, src, "TODO: Sema.zirSelect", .{});
6107}
6108
61026109fn zirAtomicLoad(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
61036110 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
61046111 const src = inst_data.src();
src/Zir.zig+13
......@@ -890,6 +890,9 @@ pub const Inst = struct {
890890 /// Implements the `@shuffle` builtin.
891891 /// Uses the `pl_node` union field with payload `Shuffle`.
892892 shuffle,
893 /// Implements the `@select` builtin.
894 /// Uses the `pl_node` union field with payload `Select`.
895 select,
893896 /// Implements the `@atomicLoad` builtin.
894897 /// Uses the `pl_node` union field with payload `Bin`.
895898 atomic_load,
......@@ -1181,6 +1184,7 @@ pub const Inst = struct {
11811184 .splat,
11821185 .reduce,
11831186 .shuffle,
1187 .select,
11841188 .atomic_load,
11851189 .atomic_rmw,
11861190 .atomic_store,
......@@ -1451,6 +1455,7 @@ pub const Inst = struct {
14511455 .splat = .pl_node,
14521456 .reduce = .pl_node,
14531457 .shuffle = .pl_node,
1458 .select = .pl_node,
14541459 .atomic_load = .pl_node,
14551460 .atomic_rmw = .pl_node,
14561461 .atomic_store = .pl_node,
......@@ -2725,6 +2730,13 @@ pub const Inst = struct {
27252730 mask: Ref,
27262731 };
27272732
2733 pub const Select = struct {
2734 elem_type: Ref,
2735 pred: Ref,
2736 a: Ref,
2737 b: Ref,
2738 };
2739
27282740 pub const AsyncCall = struct {
27292741 frame_buffer: Ref,
27302742 result_ptr: Ref,
......@@ -2935,6 +2947,7 @@ const Writer = struct {
29352947 .cmpxchg_strong,
29362948 .cmpxchg_weak,
29372949 .shuffle,
2950 .select,
29382951 .atomic_rmw,
29392952 .atomic_store,
29402953 .mul_add,
src/stage1/all_types.hpp+20
......@@ -1755,6 +1755,7 @@ enum BuiltinFnId {
17551755 BuiltinFnIdIntToEnum,
17561756 BuiltinFnIdVectorType,
17571757 BuiltinFnIdShuffle,
1758 BuiltinFnIdSelect,
17581759 BuiltinFnIdSplat,
17591760 BuiltinFnIdSetCold,
17601761 BuiltinFnIdSetRuntimeSafety,
......@@ -2544,6 +2545,7 @@ enum Stage1ZirInstId : uint8_t {
25442545 Stage1ZirInstIdBoolToInt,
25452546 Stage1ZirInstIdVectorType,
25462547 Stage1ZirInstIdShuffleVector,
2548 Stage1ZirInstIdSelect,
25472549 Stage1ZirInstIdSplat,
25482550 Stage1ZirInstIdBoolNot,
25492551 Stage1ZirInstIdMemset,
......@@ -2664,6 +2666,7 @@ enum Stage1AirInstId : uint8_t {
26642666 Stage1AirInstIdReduce,
26652667 Stage1AirInstIdTruncate,
26662668 Stage1AirInstIdShuffleVector,
2669 Stage1AirInstIdSelect,
26672670 Stage1AirInstIdSplat,
26682671 Stage1AirInstIdBoolNot,
26692672 Stage1AirInstIdMemset,
......@@ -4295,6 +4298,23 @@ struct Stage1AirInstShuffleVector {
42954298 Stage1AirInst *mask; // This is in zig-format, not llvm format
42964299};
42974300
4301struct Stage1ZirInstSelect {
4302 Stage1ZirInst base;
4303
4304 Stage1ZirInst *scalar_type;
4305 Stage1ZirInst *pred; // This is in zig-format, not llvm format
4306 Stage1ZirInst *a;
4307 Stage1ZirInst *b;
4308};
4309
4310struct Stage1AirInstSelect {
4311 Stage1AirInst base;
4312
4313 Stage1AirInst *pred; // This is in zig-format, not llvm format
4314 Stage1AirInst *a;
4315 Stage1AirInst *b;
4316};
4317
42984318struct Stage1ZirInstSplat {
42994319 Stage1ZirInst base;
43004320
src/stage1/astgen.cpp+51
......@@ -196,6 +196,8 @@ void destroy_instruction_src(Stage1ZirInst *inst) {
196196 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstVectorType *>(inst));
197197 case Stage1ZirInstIdShuffleVector:
198198 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstShuffleVector *>(inst));
199 case Stage1ZirInstIdSelect:
200 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstSelect *>(inst));
199201 case Stage1ZirInstIdSplat:
200202 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstSplat *>(inst));
201203 case Stage1ZirInstIdBoolNot:
......@@ -651,6 +653,10 @@ static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstShuffleVector *) {
651653 return Stage1ZirInstIdShuffleVector;
652654}
653655
656static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstSelect *) {
657 return Stage1ZirInstIdSelect;
658}
659
654660static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstSplat *) {
655661 return Stage1ZirInstIdSplat;
656662}
......@@ -2037,6 +2043,22 @@ static Stage1ZirInst *ir_build_shuffle_vector(Stage1AstGen *ag, Scope *scope, As
20372043 return &instruction->base;
20382044}
20392045
2046static Stage1ZirInst *ir_build_select(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2047 Stage1ZirInst *scalar_type, Stage1ZirInst *pred, Stage1ZirInst *a, Stage1ZirInst *b)
2048{
2049 Stage1ZirInstSelect *instruction = ir_build_instruction<Stage1ZirInstSelect>(ag, scope, source_node);
2050 instruction->scalar_type = scalar_type;
2051 instruction->pred = pred;
2052 instruction->a = a;
2053 instruction->b = b;
2054
2055 ir_ref_instruction(pred, ag->current_basic_block);
2056 ir_ref_instruction(a, ag->current_basic_block);
2057 ir_ref_instruction(b, ag->current_basic_block);
2058
2059 return &instruction->base;
2060}
2061
20402062static Stage1ZirInst *ir_build_splat_src(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
20412063 Stage1ZirInst *len, Stage1ZirInst *scalar)
20422064{
......@@ -4619,6 +4641,35 @@ static Stage1ZirInst *astgen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, Ast
46194641 arg0_value, arg1_value, arg2_value, arg3_value);
46204642 return ir_lval_wrap(ag, scope, shuffle_vector, lval, result_loc);
46214643 }
4644 case BuiltinFnIdSelect:
4645 {
4646 // Used for the type expr
4647 Scope *comptime_scope = create_comptime_scope(ag->codegen, node, scope);
4648
4649 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4650 Stage1ZirInst *arg0_value = astgen_node(ag, arg0_node, comptime_scope);
4651 if (arg0_value == ag->codegen->invalid_inst_src)
4652 return arg0_value;
4653
4654 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
4655 Stage1ZirInst *arg1_value = astgen_node(ag, arg1_node, scope);
4656 if (arg0_value == ag->codegen->invalid_inst_src)
4657 return arg1_value;
4658
4659 AstNode *arg2_node = node->data.fn_call_expr.params.at(2);
4660 Stage1ZirInst *arg2_value = astgen_node(ag, arg2_node, scope);
4661 if (arg1_value == ag->codegen->invalid_inst_src)
4662 return arg2_value;
4663
4664 AstNode *arg3_node = node->data.fn_call_expr.params.at(3);
4665 Stage1ZirInst *arg3_value = astgen_node(ag, arg3_node, scope);
4666 if (arg2_value == ag->codegen->invalid_inst_src)
4667 return arg3_value;
4668
4669 Stage1ZirInst *select = ir_build_select(ag, scope, node,
4670 arg0_value, arg1_value, arg2_value, arg3_value);
4671 return ir_lval_wrap(ag, scope, select, lval, result_loc);
4672 }
46224673 case BuiltinFnIdSplat:
46234674 {
46244675 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
src/stage1/codegen.cpp+10
......@@ -5162,6 +5162,13 @@ static LLVMValueRef ir_render_shuffle_vector(CodeGen *g, Stage1Air *executable,
51625162 llvm_mask_value, "");
51635163}
51645164
5165static LLVMValueRef ir_render_select(CodeGen *g, Stage1Air *executable, Stage1AirInstSelect *instruction) {
5166 LLVMValueRef pred = ir_llvm_value(g, instruction->pred);
5167 LLVMValueRef a = ir_llvm_value(g, instruction->a);
5168 LLVMValueRef b = ir_llvm_value(g, instruction->b);
5169 return LLVMBuildSelect(g->builder, pred, a, b, "");
5170}
5171
51655172static LLVMValueRef ir_render_splat(CodeGen *g, Stage1Air *executable, Stage1AirInstSplat *instruction) {
51665173 ZigType *result_type = instruction->base.value->type;
51675174 ir_assert(result_type->id == ZigTypeIdVector, &instruction->base);
......@@ -7015,6 +7022,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, Stage1Air *executable, Sta
70157022 return ir_render_spill_end(g, executable, (Stage1AirInstSpillEnd *)instruction);
70167023 case Stage1AirInstIdShuffleVector:
70177024 return ir_render_shuffle_vector(g, executable, (Stage1AirInstShuffleVector *) instruction);
7025 case Stage1AirInstIdSelect:
7026 return ir_render_select(g, executable, (Stage1AirInstSelect *) instruction);
70187027 case Stage1AirInstIdSplat:
70197028 return ir_render_splat(g, executable, (Stage1AirInstSplat *) instruction);
70207029 case Stage1AirInstIdVectorExtractElem:
......@@ -8920,6 +8929,7 @@ static void define_builtin_fns(CodeGen *g) {
89208929 create_builtin_fn(g, BuiltinFnIdCompileLog, "compileLog", SIZE_MAX);
89218930 create_builtin_fn(g, BuiltinFnIdVectorType, "Vector", 2);
89228931 create_builtin_fn(g, BuiltinFnIdShuffle, "shuffle", 4);
8932 create_builtin_fn(g, BuiltinFnIdSelect, "select", 4);
89238933 create_builtin_fn(g, BuiltinFnIdSplat, "splat", 2);
89248934 create_builtin_fn(g, BuiltinFnIdSetCold, "setCold", 1);
89258935 create_builtin_fn(g, BuiltinFnIdSetRuntimeSafety, "setRuntimeSafety", 1);
src/stage1/ir.cpp+122-2
......@@ -355,6 +355,8 @@ void destroy_instruction_gen(Stage1AirInst *inst) {
355355 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstTruncate *>(inst));
356356 case Stage1AirInstIdShuffleVector:
357357 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstShuffleVector *>(inst));
358 case Stage1AirInstIdSelect:
359 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstSelect *>(inst));
358360 case Stage1AirInstIdSplat:
359361 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstSplat *>(inst));
360362 case Stage1AirInstIdBoolNot:
......@@ -901,6 +903,10 @@ static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstShuffleVector *) {
901903 return Stage1AirInstIdShuffleVector;
902904}
903905
906static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstSelect *) {
907 return Stage1AirInstIdSelect;
908}
909
904910static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstSplat *) {
905911 return Stage1AirInstIdSplat;
906912}
......@@ -1756,6 +1762,22 @@ static Stage1AirInst *ir_build_shuffle_vector_gen(IrAnalyze *ira, Scope *scope,
17561762 return &inst->base;
17571763}
17581764
1765static Stage1AirInst *ir_build_select_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node,
1766 ZigType *result_type, Stage1AirInst *pred, Stage1AirInst *a, Stage1AirInst *b)
1767{
1768 Stage1AirInstSelect *inst = ir_build_inst_gen<Stage1AirInstSelect>(&ira->new_irb, scope, source_node);
1769 inst->base.value->type = result_type;
1770 inst->pred = pred;
1771 inst->a = a;
1772 inst->b = b;
1773
1774 ir_ref_inst_gen(pred);
1775 ir_ref_inst_gen(a);
1776 ir_ref_inst_gen(b);
1777
1778 return &inst->base;
1779}
1780
17591781static Stage1AirInst *ir_build_splat_gen(IrAnalyze *ira, Scope *scope, AstNode *source_node, ZigType *result_type,
17601782 Stage1AirInst *scalar)
17611783{
......@@ -20318,6 +20340,100 @@ static Stage1AirInst *ir_analyze_instruction_shuffle_vector(IrAnalyze *ira, Stag
2031820340 return ir_analyze_shuffle_vector(ira, instruction->base.scope, instruction->base.source_node, scalar_type, a, b, mask);
2031920341}
2032020342
20343static Stage1AirInst *ir_analyze_instruction_select(IrAnalyze *ira, Stage1ZirInstSelect *instruction) {
20344 Error err;
20345
20346 ZigType *scalar_type = ir_resolve_vector_elem_type(ira, instruction->scalar_type->child);
20347 if (type_is_invalid(scalar_type))
20348 return ira->codegen->invalid_inst_gen;
20349
20350 if ((err = ir_validate_vector_elem_type(ira, instruction->base.source_node, scalar_type)))
20351 return ira->codegen->invalid_inst_gen;
20352
20353 Stage1AirInst *pred = instruction->pred->child;
20354 if (type_is_invalid(pred->value->type))
20355 return ira->codegen->invalid_inst_gen;
20356
20357 Stage1AirInst *a = instruction->a->child;
20358 if (type_is_invalid(a->value->type))
20359 return ira->codegen->invalid_inst_gen;
20360
20361 Stage1AirInst *b = instruction->b->child;
20362 if (type_is_invalid(b->value->type))
20363 return ira->codegen->invalid_inst_gen;
20364
20365 if (pred->value->type->id != ZigTypeIdVector) {
20366 ir_add_error(ira, pred,
20367 buf_sprintf("expected vector type, found '%s'",
20368 buf_ptr(&pred->value->type->name)));
20369 return ira->codegen->invalid_inst_gen;
20370 }
20371
20372 uint32_t pred_len = pred->value->type->data.vector.len;
20373 pred = ir_implicit_cast(ira, pred, get_vector_type(ira->codegen, pred_len,
20374 ira->codegen->builtin_types.entry_bool));
20375 if (type_is_invalid(pred->value->type))
20376 return ira->codegen->invalid_inst_gen;
20377
20378 if (a->value->type->id != ZigTypeIdVector) {
20379 ir_add_error(ira, a,
20380 buf_sprintf("expected vector type, found '%s'",
20381 buf_ptr(&a->value->type->name)));
20382 return ira->codegen->invalid_inst_gen;
20383 }
20384
20385 if (b->value->type->id != ZigTypeIdVector) {
20386 ir_add_error(ira, b,
20387 buf_sprintf("expected vector type, found '%s'",
20388 buf_ptr(&b->value->type->name)));
20389 return ira->codegen->invalid_inst_gen;
20390 }
20391
20392 ZigType *result_type = get_vector_type(ira->codegen, pred_len, scalar_type);
20393
20394 a = ir_implicit_cast(ira, a, result_type);
20395 if (type_is_invalid(a->value->type))
20396 return ira->codegen->invalid_inst_gen;
20397
20398 b = ir_implicit_cast(ira, b, result_type);
20399 if (type_is_invalid(a->value->type))
20400 return ira->codegen->invalid_inst_gen;
20401
20402 if (instr_is_comptime(pred) && instr_is_comptime(a) && instr_is_comptime(b)) {
20403 ZigValue *pred_val = ir_resolve_const(ira, pred, UndefBad);
20404 if (pred_val == nullptr)
20405 return ira->codegen->invalid_inst_gen;
20406
20407 ZigValue *a_val = ir_resolve_const(ira, a, UndefBad);
20408 if (a_val == nullptr)
20409 return ira->codegen->invalid_inst_gen;
20410
20411 ZigValue *b_val = ir_resolve_const(ira, b, UndefBad);
20412 if (b_val == nullptr)
20413 return ira->codegen->invalid_inst_gen;
20414
20415 expand_undef_array(ira->codegen, a_val);
20416 expand_undef_array(ira->codegen, b_val);
20417
20418 Stage1AirInst *result = ir_const(ira, instruction->base.scope, instruction->base.source_node, result_type);
20419 result->value->data.x_array.data.s_none.elements = ira->codegen->pass1_arena->allocate<ZigValue>(pred_len);
20420
20421 for (uint64_t i = 0; i < pred_len; i += 1) {
20422 ZigValue *dst_elem_val = &result->value->data.x_array.data.s_none.elements[i];
20423 ZigValue *pred_elem_val = &pred_val->data.x_array.data.s_none.elements[i];
20424 ZigValue *a_elem_val = &a_val->data.x_array.data.s_none.elements[i];
20425 ZigValue *b_elem_val = &b_val->data.x_array.data.s_none.elements[i];
20426 ZigValue *result_elem_val = pred_elem_val->data.x_bool ? a_elem_val : b_elem_val;
20427 copy_const_val(ira->codegen, dst_elem_val, result_elem_val);
20428 }
20429
20430 result->value->special = ConstValSpecialStatic;
20431 return result;
20432 }
20433
20434 return ir_build_select_gen(ira, instruction->base.scope, instruction->base.source_node, result_type, pred, a, b);
20435}
20436
2032120437static Stage1AirInst *ir_analyze_instruction_splat(IrAnalyze *ira, Stage1ZirInstSplat *instruction) {
2032220438 Error err;
2032320439
......@@ -24595,7 +24711,9 @@ static Stage1AirInst *ir_analyze_instruction_base(IrAnalyze *ira, Stage1ZirInst
2459524711 return ir_analyze_instruction_vector_type(ira, (Stage1ZirInstVectorType *)instruction);
2459624712 case Stage1ZirInstIdShuffleVector:
2459724713 return ir_analyze_instruction_shuffle_vector(ira, (Stage1ZirInstShuffleVector *)instruction);
24598 case Stage1ZirInstIdSplat:
24714 case Stage1ZirInstIdSelect:
24715 return ir_analyze_instruction_select(ira, (Stage1ZirInstSelect *)instruction);
24716 case Stage1ZirInstIdSplat:
2459924717 return ir_analyze_instruction_splat(ira, (Stage1ZirInstSplat *)instruction);
2460024718 case Stage1ZirInstIdBoolNot:
2460124719 return ir_analyze_instruction_bool_not(ira, (Stage1ZirInstBoolNot *)instruction);
......@@ -24931,6 +25049,7 @@ bool ir_inst_gen_has_side_effects(Stage1AirInst *instruction) {
2493125049 case Stage1AirInstIdUnionTag:
2493225050 case Stage1AirInstIdTruncate:
2493325051 case Stage1AirInstIdShuffleVector:
25052 case Stage1AirInstIdSelect:
2493425053 case Stage1AirInstIdSplat:
2493525054 case Stage1AirInstIdBoolNot:
2493625055 case Stage1AirInstIdReturnAddress:
......@@ -25084,6 +25203,7 @@ bool ir_inst_src_has_side_effects(Stage1ZirInst *instruction) {
2508425203 case Stage1ZirInstIdTruncate:
2508525204 case Stage1ZirInstIdVectorType:
2508625205 case Stage1ZirInstIdShuffleVector:
25206 case Stage1ZirInstIdSelect:
2508725207 case Stage1ZirInstIdSplat:
2508825208 case Stage1ZirInstIdBoolNot:
2508925209 case Stage1ZirInstIdSlice:
......@@ -25751,7 +25871,7 @@ static Error ir_resolve_lazy_recurse_array(AstNode *source_node, ZigValue *val,
2575125871
2575225872static Error ir_resolve_lazy_recurse(AstNode *source_node, ZigValue *val) {
2575325873 Error err;
25754 if ((err = ir_resolve_lazy_raw(source_node, val)))
25874 if ((err = ir_resolve_lazy_raw(source_node, val)))
2575525875 return err;
2575625876 assert(val->special != ConstValSpecialRuntime);
2575725877 assert(val->special != ConstValSpecialLazy);
src/stage1/ir_print.cpp+32
......@@ -93,6 +93,8 @@ const char* ir_inst_src_type_str(Stage1ZirInstId id) {
9393 return "SrcInvalid";
9494 case Stage1ZirInstIdShuffleVector:
9595 return "SrcShuffle";
96 case Stage1ZirInstIdSelect:
97 return "SrcSelect";
9698 case Stage1ZirInstIdSplat:
9799 return "SrcSplat";
98100 case Stage1ZirInstIdDeclVar:
......@@ -379,6 +381,8 @@ const char* ir_inst_gen_type_str(Stage1AirInstId id) {
379381 return "GenInvalid";
380382 case Stage1AirInstIdShuffleVector:
381383 return "GenShuffle";
384 case Stage1AirInstIdSelect:
385 return "GenSelect";
382386 case Stage1AirInstIdSplat:
383387 return "GenSplat";
384388 case Stage1AirInstIdDeclVar:
......@@ -1722,6 +1726,28 @@ static void ir_print_shuffle_vector(IrPrintGen *irp, Stage1AirInstShuffleVector
17221726 fprintf(irp->f, ")");
17231727}
17241728
1729static void ir_print_select(IrPrintSrc *irp, Stage1ZirInstSelect *instruction) {
1730 fprintf(irp->f, "@select(");
1731 ir_print_other_inst_src(irp, instruction->scalar_type);
1732 fprintf(irp->f, ", ");
1733 ir_print_other_inst_src(irp, instruction->pred);
1734 fprintf(irp->f, ", ");
1735 ir_print_other_inst_src(irp, instruction->a);
1736 fprintf(irp->f, ", ");
1737 ir_print_other_inst_src(irp, instruction->b);
1738 fprintf(irp->f, ")");
1739}
1740
1741static void ir_print_select(IrPrintGen *irp, Stage1AirInstSelect *instruction) {
1742 fprintf(irp->f, "@select(");
1743 ir_print_other_inst_gen(irp, instruction->pred);
1744 fprintf(irp->f, ", ");
1745 ir_print_other_inst_gen(irp, instruction->a);
1746 fprintf(irp->f, ", ");
1747 ir_print_other_inst_gen(irp, instruction->b);
1748 fprintf(irp->f, ")");
1749}
1750
17251751static void ir_print_splat_src(IrPrintSrc *irp, Stage1ZirInstSplat *instruction) {
17261752 fprintf(irp->f, "@splat(");
17271753 ir_print_other_inst_src(irp, instruction->len);
......@@ -2836,6 +2862,9 @@ static void ir_print_inst_src(IrPrintSrc *irp, Stage1ZirInst *instruction, bool
28362862 case Stage1ZirInstIdShuffleVector:
28372863 ir_print_shuffle_vector(irp, (Stage1ZirInstShuffleVector *)instruction);
28382864 break;
2865 case Stage1ZirInstIdSelect:
2866 ir_print_select(irp, (Stage1ZirInstSelect *)instruction);
2867 break;
28392868 case Stage1ZirInstIdSplat:
28402869 ir_print_splat_src(irp, (Stage1ZirInstSplat *)instruction);
28412870 break;
......@@ -3178,6 +3207,9 @@ static void ir_print_inst_gen(IrPrintGen *irp, Stage1AirInst *instruction, bool
31783207 case Stage1AirInstIdShuffleVector:
31793208 ir_print_shuffle_vector(irp, (Stage1AirInstShuffleVector *)instruction);
31803209 break;
3210 case Stage1AirInstIdSelect:
3211 ir_print_select(irp, (Stage1AirInstSelect *)instruction);
3212 break;
31813213 case Stage1AirInstIdSplat:
31823214 ir_print_splat_gen(irp, (Stage1AirInstSplat *)instruction);
31833215 break;
test/behavior.zig+1
......@@ -118,6 +118,7 @@ test {
118118 _ = @import("behavior/ref_var_in_if_after_if_2nd_switch_prong.zig");
119119 _ = @import("behavior/reflection.zig");
120120 _ = @import("behavior/shuffle.zig");
121 _ = @import("behavior/select.zig");
121122 _ = @import("behavior/sizeof_and_typeof.zig");
122123 _ = @import("behavior/slice.zig");
123124 _ = @import("behavior/slice_sentinel_comptime.zig");
test/behavior/select.zig created+25
......@@ -0,0 +1,25 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const mem = std.mem;
4const expect = std.testing.expect;
5const Vector = std.meta.Vector;
6
7test "@select" {
8 const S = struct {
9 fn doTheTest() !void {
10 var a: Vector(4, bool) = [4]bool{ true, false, true, false };
11 var b: Vector(4, i32) = [4]i32{ -1, 4, 999, -31 };
12 var c: Vector(4, i32) = [4]i32{ -5, 1, 0, 1234 };
13 var abc = @select(i32, a, b, c);
14 try expect(mem.eql(i32, &@as([4]i32, abc), &[4]i32{ -1, 1, 999, 1234 }));
15
16 var x: Vector(4, bool) = [4]bool{ false, false, false, true };
17 var y: Vector(4, f32) = [4]f32{ 0.001, 33.4, 836, -3381.233 };
18 var z: Vector(4, f32) = [4]f32{ 0.0, 312.1, -145.9, 9993.55 };
19 var xyz = @select(f32, x, y, z);
20 try expect(mem.eql(f32, &@as([4]f32, xyz), &[4]f32{ 0.0, 312.1, -145.9, -3381.233 }));
21 }
22 };
23 try S.doTheTest();
24 comptime try S.doTheTest();
25}