authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-12-10 18:54:56-08:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2021-12-10 18:54:56-08:00
log97c0373fa7ee125d2d4e73f9b1dc8ea0e2c2e86a
treed2aa342a53aef95f88456a63fa7874f3c51ba3b8
parent75f3e7a4a05db7ea805e581f78117a41768945ae
parent516945d7d9b4d8b969d037076799d4ed29cecdda
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #10295 from ifreund/prefetch

Implement @prefetch()

16 files changed, 395 insertions(+), 7 deletions(-)

doc/langref.html.in+44
...@@ -8674,6 +8674,50 @@ test "@wasmMemoryGrow" {...@@ -8674,6 +8674,50 @@ test "@wasmMemoryGrow" {
8674 {#see_also|@ctz|@clz#}8674 {#see_also|@ctz|@clz#}
8675 {#header_close#}8675 {#header_close#}
86768676
8677 {#header_open|@prefetch#}
8678 <pre>{#syntax#}@prefetch(ptr: anytype, comptime options: std.builtin.PrefetchOptions){#endsyntax#}</pre>
8679 <p>
8680 This builtin tells the compiler to emit a prefetch instruction if supported by the
8681 target CPU. If the target CPU does not support the requested prefetch instruction,
8682 this builtin is a noop. This function has no effect on the behavior of the program,
8683 only on the performance characteristics.
8684 </p>
8685 <p>
8686 The {#syntax#}ptr{#endsyntax#} argument may be any pointer type and determines the memory
8687 address to prefetch. This function does not dereference the pointer, it is perfectly legal
8688 to pass a pointer to invalid memory to this function and no illegal behavior will result.
8689 </p>
8690 <p>
8691 The {#syntax#}options{#endsyntax#} argument is the following struct:
8692 </p>
8693 {#code_begin|syntax|builtin#}
8694/// This data structure is used by the Zig language code generation and
8695/// therefore must be kept in sync with the compiler implementation.
8696pub const PrefetchOptions = struct {
8697 /// Whether the prefetch should prepare for a read or a write.
8698 rw: Rw = .read,
8699 /// 0 means no temporal locality. That is, the data can be immediately
8700 /// dropped from the cache after it is accessed.
8701 ///
8702 /// 3 means high temporal locality. That is, the data should be kept in
8703 /// the cache as it is likely to be accessed again soon.
8704 locality: u2 = 3,
8705 /// The cache that the prefetch should be preformed on.
8706 cache: Cache = .data,
8707
8708 pub const Rw = enum {
8709 read,
8710 write,
8711 };
8712
8713 pub const Cache = enum {
8714 instruction,
8715 data,
8716 };
8717};
8718 {#code_end#}
8719 {#header_close#}
8720
8677 {#header_open|@ptrCast#}8721 {#header_open|@ptrCast#}
8678 <pre>{#syntax#}@ptrCast(comptime DestType: type, value: anytype) DestType{#endsyntax#}</pre>8722 <pre>{#syntax#}@ptrCast(comptime DestType: type, value: anytype) DestType{#endsyntax#}</pre>
8679 <p>8723 <p>
lib/std/builtin.zig+25
...@@ -651,6 +651,31 @@ pub const CallOptions = struct {...@@ -651,6 +651,31 @@ pub const CallOptions = struct {
651 };651 };
652};652};
653653
654/// This data structure is used by the Zig language code generation and
655/// therefore must be kept in sync with the compiler implementation.
656pub const PrefetchOptions = struct {
657 /// Whether the prefetch should prepare for a read or a write.
658 rw: Rw = .read,
659 /// 0 means no temporal locality. That is, the data can be immediately
660 /// dropped from the cache after it is accessed.
661 ///
662 /// 3 means high temporal locality. That is, the data should be kept in
663 /// the cache as it is likely to be accessed again soon.
664 locality: u2 = 3,
665 /// The cache that the prefetch should be preformed on.
666 cache: Cache = .data,
667
668 pub const Rw = enum {
669 read,
670 write,
671 };
672
673 pub const Cache = enum {
674 instruction,
675 data,
676 };
677};
678
654/// This data structure is used by the Zig language code generation and679/// This data structure is used by the Zig language code generation and
655/// therefore must be kept in sync with the compiler implementation.680/// therefore must be kept in sync with the compiler implementation.
656pub const ExportOptions = struct {681pub const ExportOptions = struct {
src/AstGen.zig+20-6
...@@ -6739,7 +6739,6 @@ fn builtinCall(...@@ -6739,7 +6739,6 @@ fn builtinCall(
6739 }6739 }
6740 }6740 }
67416741
6742 // zig fmt: off
6743 switch (info.tag) {6742 switch (info.tag) {
6744 .import => {6743 .import => {
6745 const node_tags = tree.nodes.items(.tag);6744 const node_tags = tree.nodes.items(.tag);
...@@ -6768,7 +6767,7 @@ fn builtinCall(...@@ -6768,7 +6767,7 @@ fn builtinCall(
6768 astgen.extra.items[extra_index] = @enumToInt(param_ref);6767 astgen.extra.items[extra_index] = @enumToInt(param_ref);
6769 extra_index += 1;6768 extra_index += 1;
6770 }6769 }
6771 const result = try gz.addExtendedMultiOpPayloadIndex(.compile_log,payload_index, params.len);6770 const result = try gz.addExtendedMultiOpPayloadIndex(.compile_log, payload_index, params.len);
6772 return rvalue(gz, rl, result, node);6771 return rvalue(gz, rl, result, node);
6773 },6772 },
6774 .field => {6773 .field => {
...@@ -6784,11 +6783,14 @@ fn builtinCall(...@@ -6784,11 +6783,14 @@ fn builtinCall(
6784 });6783 });
6785 return rvalue(gz, rl, result, node);6784 return rvalue(gz, rl, result, node);
6786 },6785 },
6786
6787 // zig fmt: off
6787 .as => return as( gz, scope, rl, node, params[0], params[1]),6788 .as => return as( gz, scope, rl, node, params[0], params[1]),
6788 .bit_cast => return bitCast( gz, scope, rl, node, params[0], params[1]),6789 .bit_cast => return bitCast( gz, scope, rl, node, params[0], params[1]),
6789 .TypeOf => return typeOf( gz, scope, rl, node, params),6790 .TypeOf => return typeOf( gz, scope, rl, node, params),
6790 .union_init => return unionInit(gz, scope, rl, node, params),6791 .union_init => return unionInit(gz, scope, rl, node, params),
6791 .c_import => return cImport( gz, scope, node, params[0]),6792 .c_import => return cImport( gz, scope, node, params[0]),
6793 // zig fmt: on
67926794
6793 .@"export" => {6795 .@"export" => {
6794 const node_tags = tree.nodes.items(.tag);6796 const node_tags = tree.nodes.items(.tag);
...@@ -6858,9 +6860,7 @@ fn builtinCall(...@@ -6858,9 +6860,7 @@ fn builtinCall(
6858 const field_ident = dot_token + 1;6860 const field_ident = dot_token + 1;
6859 decl_name = try astgen.identAsString(field_ident);6861 decl_name = try astgen.identAsString(field_ident);
6860 },6862 },
6861 else => return astgen.failNode(6863 else => return astgen.failNode(params[0], "symbol to export must identify a declaration", .{}),
6862 params[0], "symbol to export must identify a declaration", .{},
6863 ),
6864 }6864 }
6865 const options = try comptimeExpr(gz, scope, .{ .ty = .export_options_type }, params[1]);6865 const options = try comptimeExpr(gz, scope, .{ .ty = .export_options_type }, params[1]);
6866 _ = try gz.addPlNode(.@"export", node, Zir.Inst.Export{6866 _ = try gz.addPlNode(.@"export", node, Zir.Inst.Export{
...@@ -6888,6 +6888,7 @@ fn builtinCall(...@@ -6888,6 +6888,7 @@ fn builtinCall(
68886888
6889 .breakpoint => return simpleNoOpVoid(gz, rl, node, .breakpoint),6889 .breakpoint => return simpleNoOpVoid(gz, rl, node, .breakpoint),
68906890
6891 // zig fmt: off
6891 .This => return rvalue(gz, rl, try gz.addNodeExtended(.this, node), node),6892 .This => return rvalue(gz, rl, try gz.addNodeExtended(.this, node), node),
6892 .return_address => return rvalue(gz, rl, try gz.addNodeExtended(.ret_addr, node), node),6893 .return_address => return rvalue(gz, rl, try gz.addNodeExtended(.ret_addr, node), node),
6893 .src => return rvalue(gz, rl, try gz.addNodeExtended(.builtin_src, node), node),6894 .src => return rvalue(gz, rl, try gz.addNodeExtended(.builtin_src, node), node),
...@@ -6942,6 +6943,8 @@ fn builtinCall(...@@ -6942,6 +6943,8 @@ fn builtinCall(
6942 .err_set_cast => return typeCast(gz, scope, rl, node, params[0], params[1], .err_set_cast),6943 .err_set_cast => return typeCast(gz, scope, rl, node, params[0], params[1], .err_set_cast),
6943 .ptr_cast => return typeCast(gz, scope, rl, node, params[0], params[1], .ptr_cast),6944 .ptr_cast => return typeCast(gz, scope, rl, node, params[0], params[1], .ptr_cast),
6944 .truncate => return typeCast(gz, scope, rl, node, params[0], params[1], .truncate),6945 .truncate => return typeCast(gz, scope, rl, node, params[0], params[1], .truncate),
6946 // zig fmt: on
6947
6945 .align_cast => {6948 .align_cast => {
6946 const dest_align = try comptimeExpr(gz, scope, align_rl, params[0]);6949 const dest_align = try comptimeExpr(gz, scope, align_rl, params[0]);
6947 const rhs = try expr(gz, scope, .none, params[1]);6950 const rhs = try expr(gz, scope, .none, params[1]);
...@@ -6952,6 +6955,7 @@ fn builtinCall(...@@ -6952,6 +6955,7 @@ fn builtinCall(
6952 return rvalue(gz, rl, result, node);6955 return rvalue(gz, rl, result, node);
6953 },6956 },
69546957
6958 // zig fmt: off
6955 .has_decl => return hasDeclOrField(gz, scope, rl, node, params[0], params[1], .has_decl),6959 .has_decl => return hasDeclOrField(gz, scope, rl, node, params[0], params[1], .has_decl),
6956 .has_field => return hasDeclOrField(gz, scope, rl, node, params[0], params[1], .has_field),6960 .has_field => return hasDeclOrField(gz, scope, rl, node, params[0], params[1], .has_field),
69576961
...@@ -6978,6 +6982,7 @@ fn builtinCall(...@@ -6978,6 +6982,7 @@ fn builtinCall(
69786982
6979 .cmpxchg_strong => return cmpxchg(gz, scope, rl, node, params, .cmpxchg_strong),6983 .cmpxchg_strong => return cmpxchg(gz, scope, rl, node, params, .cmpxchg_strong),
6980 .cmpxchg_weak => return cmpxchg(gz, scope, rl, node, params, .cmpxchg_weak),6984 .cmpxchg_weak => return cmpxchg(gz, scope, rl, node, params, .cmpxchg_weak),
6985 // zig fmt: on
69816986
6982 .wasm_memory_size => {6987 .wasm_memory_size => {
6983 const operand = try expr(gz, scope, .{ .ty = .u32_type }, params[0]);6988 const operand = try expr(gz, scope, .{ .ty = .u32_type }, params[0]);
...@@ -7221,8 +7226,17 @@ fn builtinCall(...@@ -7221,8 +7226,17 @@ fn builtinCall(
7221 });7226 });
7222 return rvalue(gz, rl, result, node);7227 return rvalue(gz, rl, result, node);
7223 },7228 },
7229 .prefetch => {
7230 const ptr = try expr(gz, scope, .none, params[0]);
7231 const options = try comptimeExpr(gz, scope, .{ .ty = .prefetch_options_type }, params[1]);
7232 const result = try gz.addExtendedPayload(.prefetch, Zir.Inst.BinNode{
7233 .node = gz.nodeIndexToRelative(node),
7234 .lhs = ptr,
7235 .rhs = options,
7236 });
7237 return rvalue(gz, rl, result, node);
7238 },
7224 }7239 }
7225 // zig fmt: on
7226}7240}
72277241
7228fn simpleNoOpVoid(7242fn simpleNoOpVoid(
src/BuiltinFn.zig+8
...@@ -67,6 +67,7 @@ pub const Tag = enum {...@@ -67,6 +67,7 @@ pub const Tag = enum {
67 mul_with_overflow,67 mul_with_overflow,
68 panic,68 panic,
69 pop_count,69 pop_count,
70 prefetch,
70 ptr_cast,71 ptr_cast,
71 ptr_to_int,72 ptr_to_int,
72 rem,73 rem,
...@@ -615,6 +616,13 @@ pub const list = list: {...@@ -615,6 +616,13 @@ pub const list = list: {
615 .param_count = 2,616 .param_count = 2,
616 },617 },
617 },618 },
619 .{
620 "@prefetch",
621 .{
622 .tag = .prefetch,
623 .param_count = 2,
624 },
625 },
618 .{626 .{
619 "@ptrCast",627 "@ptrCast",
620 .{628 .{
src/Sema.zig+14
...@@ -1042,6 +1042,7 @@ fn zirExtended(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -1042,6 +1042,7 @@ fn zirExtended(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1042 .c_define => return sema.zirCDefine( block, extended),1042 .c_define => return sema.zirCDefine( block, extended),
1043 .wasm_memory_size => return sema.zirWasmMemorySize( block, extended),1043 .wasm_memory_size => return sema.zirWasmMemorySize( block, extended),
1044 .wasm_memory_grow => return sema.zirWasmMemoryGrow( block, extended),1044 .wasm_memory_grow => return sema.zirWasmMemoryGrow( block, extended),
1045 .prefetch => return sema.zirPrefetch( block, extended),
1045 // zig fmt: on1046 // zig fmt: on
1046 }1047 }
1047}1048}
...@@ -11104,6 +11105,16 @@ fn zirWasmMemoryGrow(...@@ -11104,6 +11105,16 @@ fn zirWasmMemoryGrow(
11104 return sema.fail(block, src, "TODO: implement Sema.zirWasmMemoryGrow", .{});11105 return sema.fail(block, src, "TODO: implement Sema.zirWasmMemoryGrow", .{});
11105}11106}
1110611107
11108fn zirPrefetch(
11109 sema: *Sema,
11110 block: *Block,
11111 extended: Zir.Inst.Extended.InstData,
11112) CompileError!Air.Inst.Ref {
11113 const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;
11114 const src: LazySrcLoc = .{ .node_offset = extra.node };
11115 return sema.fail(block, src, "TODO: implement Sema.zirPrefetch", .{});
11116}
11117
11107fn zirBuiltinExtern(11118fn zirBuiltinExtern(
11108 sema: *Sema,11119 sema: *Sema,
11109 block: *Block,11120 block: *Block,
...@@ -14231,6 +14242,7 @@ fn resolveTypeFields(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) Comp...@@ -14231,6 +14242,7 @@ fn resolveTypeFields(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) Comp
14231 .float_mode => return sema.resolveBuiltinTypeFields(block, src, "FloatMode"),14242 .float_mode => return sema.resolveBuiltinTypeFields(block, src, "FloatMode"),
14232 .reduce_op => return sema.resolveBuiltinTypeFields(block, src, "ReduceOp"),14243 .reduce_op => return sema.resolveBuiltinTypeFields(block, src, "ReduceOp"),
14233 .call_options => return sema.resolveBuiltinTypeFields(block, src, "CallOptions"),14244 .call_options => return sema.resolveBuiltinTypeFields(block, src, "CallOptions"),
14245 .prefetch_options => return sema.resolveBuiltinTypeFields(block, src, "PrefetchOptions"),
1423414246
14235 .@"union", .union_tagged => {14247 .@"union", .union_tagged => {
14236 const union_obj = ty.cast(Type.Payload.Union).?.data;14248 const union_obj = ty.cast(Type.Payload.Union).?.data;
...@@ -14819,6 +14831,7 @@ fn typeHasOnePossibleValue(...@@ -14819,6 +14831,7 @@ fn typeHasOnePossibleValue(
14819 .float_mode,14831 .float_mode,
14820 .reduce_op,14832 .reduce_op,
14821 .call_options,14833 .call_options,
14834 .prefetch_options,
14822 .export_options,14835 .export_options,
14823 .extern_options,14836 .extern_options,
14824 .type_info,14837 .type_info,
...@@ -15032,6 +15045,7 @@ pub fn addType(sema: *Sema, ty: Type) !Air.Inst.Ref {...@@ -15032,6 +15045,7 @@ pub fn addType(sema: *Sema, ty: Type) !Air.Inst.Ref {
15032 .float_mode => return .float_mode_type,15045 .float_mode => return .float_mode_type,
15033 .reduce_op => return .reduce_op_type,15046 .reduce_op => return .reduce_op_type,
15034 .call_options => return .call_options_type,15047 .call_options => return .call_options_type,
15048 .prefetch_options => return .prefetch_options_type,
15035 .export_options => return .export_options_type,15049 .export_options => return .export_options_type,
15036 .extern_options => return .extern_options_type,15050 .extern_options => return .extern_options_type,
15037 .type_info => return .type_info_type,15051 .type_info => return .type_info_type,
src/Zir.zig+8
...@@ -1572,6 +1572,9 @@ pub const Inst = struct {...@@ -1572,6 +1572,9 @@ pub const Inst = struct {
1572 wasm_memory_size,1572 wasm_memory_size,
1573 /// `operand` is payload index to `BinNode`.1573 /// `operand` is payload index to `BinNode`.
1574 wasm_memory_grow,1574 wasm_memory_grow,
1575 /// The `@prefetch` builtin.
1576 /// `operand` is payload index to `BinNode`.
1577 prefetch,
15751578
1576 pub const InstData = struct {1579 pub const InstData = struct {
1577 opcode: Extended,1580 opcode: Extended,
...@@ -1648,6 +1651,7 @@ pub const Inst = struct {...@@ -1648,6 +1651,7 @@ pub const Inst = struct {
1648 float_mode_type,1651 float_mode_type,
1649 reduce_op_type,1652 reduce_op_type,
1650 call_options_type,1653 call_options_type,
1654 prefetch_options_type,
1651 export_options_type,1655 export_options_type,
1652 extern_options_type,1656 extern_options_type,
1653 type_info_type,1657 type_info_type,
...@@ -1917,6 +1921,10 @@ pub const Inst = struct {...@@ -1917,6 +1921,10 @@ pub const Inst = struct {
1917 .ty = Type.initTag(.type),1921 .ty = Type.initTag(.type),
1918 .val = Value.initTag(.call_options_type),1922 .val = Value.initTag(.call_options_type),
1919 },1923 },
1924 .prefetch_options_type = .{
1925 .ty = Type.initTag(.type),
1926 .val = Value.initTag(.prefetch_options_type),
1927 },
1920 .export_options_type = .{1928 .export_options_type = .{
1921 .ty = Type.initTag(.type),1929 .ty = Type.initTag(.type),
1922 .val = Value.initTag(.export_options_type),1930 .val = Value.initTag(.export_options_type),
src/print_zir.zig+1-1
...@@ -477,7 +477,7 @@ const Writer = struct {...@@ -477,7 +477,7 @@ const Writer = struct {
477 try self.writeSrc(stream, src);477 try self.writeSrc(stream, src);
478 },478 },
479479
480 .builtin_extern, .c_define, .wasm_memory_grow => {480 .builtin_extern, .c_define, .wasm_memory_grow, .prefetch => {
481 const inst_data = self.code.extraData(Zir.Inst.BinNode, extended.operand).data;481 const inst_data = self.code.extraData(Zir.Inst.BinNode, extended.operand).data;
482 const src: LazySrcLoc = .{ .node_offset = inst_data.node };482 const src: LazySrcLoc = .{ .node_offset = inst_data.node };
483 try self.writeInstRef(stream, inst_data.lhs);483 try self.writeInstRef(stream, inst_data.lhs);
src/stage1/all_types.hpp+34
...@@ -898,6 +898,18 @@ struct AstNodeFnCallExpr {...@@ -898,6 +898,18 @@ struct AstNodeFnCallExpr {
898 bool seen; // used by @compileLog898 bool seen; // used by @compileLog
899};899};
900900
901// Must be kept in sync with std.builtin.PrefetchOptions.Rw
902enum PrefetchRw {
903 PrefetchRwRead,
904 PrefetchRwWrite,
905};
906
907// Must be kept in sync with std.builtin.PrefetchOptions.Cache
908enum PrefetchCache {
909 PrefetchCacheInstruction,
910 PrefetchCacheData,
911};
912
901struct AstNodeArrayAccessExpr {913struct AstNodeArrayAccessExpr {
902 AstNode *array_ref_expr;914 AstNode *array_ref_expr;
903 AstNode *subscript;915 AstNode *subscript;
...@@ -1818,6 +1830,7 @@ enum BuiltinFnId {...@@ -1818,6 +1830,7 @@ enum BuiltinFnId {
1818 BuiltinFnIdReduce,1830 BuiltinFnIdReduce,
1819 BuiltinFnIdMaximum,1831 BuiltinFnIdMaximum,
1820 BuiltinFnIdMinimum,1832 BuiltinFnIdMinimum,
1833 BuiltinFnIdPrefetch,
1821};1834};
18221835
1823struct BuiltinFnEntry {1836struct BuiltinFnEntry {
...@@ -2021,6 +2034,7 @@ struct CodeGen {...@@ -2021,6 +2034,7 @@ struct CodeGen {
2021 LLVMValueRef return_err_fn;2034 LLVMValueRef return_err_fn;
2022 LLVMValueRef wasm_memory_size;2035 LLVMValueRef wasm_memory_size;
2023 LLVMValueRef wasm_memory_grow;2036 LLVMValueRef wasm_memory_grow;
2037 LLVMValueRef prefetch;
2024 LLVMTypeRef anyframe_fn_type;2038 LLVMTypeRef anyframe_fn_type;
20252039
2026 // reminder: hash tables must be initialized before use2040 // reminder: hash tables must be initialized before use
...@@ -2647,6 +2661,7 @@ enum Stage1ZirInstId : uint8_t {...@@ -2647,6 +2661,7 @@ enum Stage1ZirInstId : uint8_t {
2647 Stage1ZirInstIdWasmMemorySize,2661 Stage1ZirInstIdWasmMemorySize,
2648 Stage1ZirInstIdWasmMemoryGrow,2662 Stage1ZirInstIdWasmMemoryGrow,
2649 Stage1ZirInstIdSrc,2663 Stage1ZirInstIdSrc,
2664 Stage1ZirInstIdPrefetch,
2650};2665};
26512666
2652// ir_render_* functions in codegen.cpp consume Gen instructions and produce LLVM IR.2667// ir_render_* functions in codegen.cpp consume Gen instructions and produce LLVM IR.
...@@ -2743,6 +2758,7 @@ enum Stage1AirInstId : uint8_t {...@@ -2743,6 +2758,7 @@ enum Stage1AirInstId : uint8_t {
2743 Stage1AirInstIdWasmMemorySize,2758 Stage1AirInstIdWasmMemorySize,
2744 Stage1AirInstIdWasmMemoryGrow,2759 Stage1AirInstIdWasmMemoryGrow,
2745 Stage1AirInstIdExtern,2760 Stage1AirInstIdExtern,
2761 Stage1AirInstIdPrefetch,
2746};2762};
27472763
2748struct Stage1ZirInst {2764struct Stage1ZirInst {
...@@ -3683,6 +3699,24 @@ struct Stage1ZirInstSrc {...@@ -3683,6 +3699,24 @@ struct Stage1ZirInstSrc {
3683 Stage1ZirInst base;3699 Stage1ZirInst base;
3684};3700};
36853701
3702struct Stage1ZirInstPrefetch {
3703 Stage1ZirInst base;
3704
3705 Stage1ZirInst *ptr;
3706 Stage1ZirInst *options;
3707};
3708
3709struct Stage1AirInstPrefetch {
3710 Stage1AirInst base;
3711
3712 Stage1AirInst *ptr;
3713 PrefetchRw rw;
3714 // Must be in the range 0-3 inclusive
3715 uint8_t locality;
3716 PrefetchCache cache;
3717};
3718
3719
3686struct Stage1ZirInstSlice {3720struct Stage1ZirInstSlice {
3687 Stage1ZirInst base;3721 Stage1ZirInst base;
36883722
src/stage1/astgen.cpp+44
...@@ -349,6 +349,8 @@ void destroy_instruction_src(Stage1ZirInst *inst) {...@@ -349,6 +349,8 @@ void destroy_instruction_src(Stage1ZirInst *inst) {
349 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstWasmMemoryGrow *>(inst));349 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstWasmMemoryGrow *>(inst));
350 case Stage1ZirInstIdSrc:350 case Stage1ZirInstIdSrc:
351 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstSrc *>(inst));351 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstSrc *>(inst));
352 case Stage1ZirInstIdPrefetch:
353 return heap::c_allocator.destroy(reinterpret_cast<Stage1ZirInstPrefetch *>(inst));
352 }354 }
353 zig_unreachable();355 zig_unreachable();
354}356}
...@@ -941,6 +943,10 @@ static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstSrc *) {...@@ -941,6 +943,10 @@ static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstSrc *) {
941 return Stage1ZirInstIdSrc;943 return Stage1ZirInstIdSrc;
942}944}
943945
946static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstPrefetch *) {
947 return Stage1ZirInstIdPrefetch;
948}
949
944template<typename T>950template<typename T>
945static T *ir_create_instruction(Stage1AstGen *ag, Scope *scope, AstNode *source_node) {951static T *ir_create_instruction(Stage1AstGen *ag, Scope *scope, AstNode *source_node) {
946 T *special_instruction = heap::c_allocator.create<T>();952 T *special_instruction = heap::c_allocator.create<T>();
...@@ -2870,6 +2876,21 @@ static Stage1ZirInst *ir_build_src(Stage1AstGen *ag, Scope *scope, AstNode *sour...@@ -2870,6 +2876,21 @@ static Stage1ZirInst *ir_build_src(Stage1AstGen *ag, Scope *scope, AstNode *sour
2870 return &instruction->base;2876 return &instruction->base;
2871}2877}
28722878
2879static Stage1ZirInst *ir_build_prefetch(Stage1AstGen *ag, Scope *scope, AstNode *source_node,
2880 Stage1ZirInst *ptr, Stage1ZirInst *options)
2881{
2882 Stage1ZirInstPrefetch *prefetch_instruction = ir_build_instruction<Stage1ZirInstPrefetch>(
2883 ag, scope, source_node);
2884 prefetch_instruction->ptr = ptr;
2885 prefetch_instruction->options = options;
2886
2887 ir_ref_instruction(ptr, ag->current_basic_block);
2888 ir_ref_instruction(options, ag->current_basic_block);
2889
2890 return &prefetch_instruction->base;
2891}
2892
2893
2873static void ir_count_defers(Stage1AstGen *ag, Scope *inner_scope, Scope *outer_scope, size_t *results) {2894static void ir_count_defers(Stage1AstGen *ag, Scope *inner_scope, Scope *outer_scope, size_t *results) {
2874 results[ReturnKindUnconditional] = 0;2895 results[ReturnKindUnconditional] = 0;
2875 results[ReturnKindError] = 0;2896 results[ReturnKindError] = 0;
...@@ -5416,6 +5437,29 @@ static Stage1ZirInst *astgen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, Ast...@@ -5416,6 +5437,29 @@ static Stage1ZirInst *astgen_builtin_fn_call(Stage1AstGen *ag, Scope *scope, Ast
5416 Stage1ZirInst *src_inst = ir_build_src(ag, scope, node);5437 Stage1ZirInst *src_inst = ir_build_src(ag, scope, node);
5417 return ir_lval_wrap(ag, scope, src_inst, lval, result_loc);5438 return ir_lval_wrap(ag, scope, src_inst, lval, result_loc);
5418 }5439 }
5440 case BuiltinFnIdPrefetch:
5441 {
5442 ZigType *options_type = get_builtin_type(ag->codegen, "PrefetchOptions");
5443 Stage1ZirInst *options_type_inst = ir_build_const_type(ag, scope, node, options_type);
5444 ResultLocCast *result_loc_cast = ir_build_cast_result_loc(ag, options_type_inst, no_result_loc());
5445
5446 AstNode *ptr_node = node->data.fn_call_expr.params.at(0);
5447 Stage1ZirInst *ptr_value = astgen_node(ag, ptr_node, scope);
5448 if (ptr_value == ag->codegen->invalid_inst_src)
5449 return ptr_value;
5450
5451 AstNode *options_node = node->data.fn_call_expr.params.at(1);
5452 Stage1ZirInst *options_value = astgen_node_extra(ag, options_node,
5453 scope, LValNone, &result_loc_cast->base);
5454 if (options_value == ag->codegen->invalid_inst_src)
5455 return options_value;
5456
5457 Stage1ZirInst *casted_options_value = ir_build_implicit_cast(
5458 ag, scope, options_node, options_value, result_loc_cast);
5459
5460 Stage1ZirInst *ir_extern = ir_build_prefetch(ag, scope, node, ptr_value, casted_options_value);
5461 return ir_lval_wrap(ag, scope, ir_extern, lval, result_loc);
5462 }
5419 }5463 }
5420 zig_unreachable();5464 zig_unreachable();
5421}5465}
src/stage1/codegen.cpp+67
...@@ -1139,6 +1139,24 @@ static LLVMValueRef gen_wasm_memory_grow(CodeGen *g) {...@@ -1139,6 +1139,24 @@ static LLVMValueRef gen_wasm_memory_grow(CodeGen *g) {
1139 return g->wasm_memory_grow;1139 return g->wasm_memory_grow;
1140}1140}
11411141
1142static LLVMValueRef gen_prefetch(CodeGen *g) {
1143 if (g->prefetch)
1144 return g->prefetch;
1145
1146 // declare void @llvm.prefetch(i8*, i32, i32, i32)
1147 LLVMTypeRef param_types[] = {
1148 LLVMPointerType(LLVMInt8Type(), 0),
1149 LLVMInt32Type(),
1150 LLVMInt32Type(),
1151 LLVMInt32Type(),
1152 };
1153 LLVMTypeRef fn_type = LLVMFunctionType(LLVMVoidType(), param_types, 4, false);
1154 g->prefetch = LLVMAddFunction(g->module, "llvm.prefetch.p0i8", fn_type);
1155 assert(LLVMGetIntrinsicID(g->prefetch));
1156
1157 return g->prefetch;
1158}
1159
1142static LLVMValueRef get_stacksave_fn_val(CodeGen *g) {1160static LLVMValueRef get_stacksave_fn_val(CodeGen *g) {
1143 if (g->stacksave_fn_val)1161 if (g->stacksave_fn_val)
1144 return g->stacksave_fn_val;1162 return g->stacksave_fn_val;
...@@ -5899,6 +5917,52 @@ static LLVMValueRef ir_render_wasm_memory_grow(CodeGen *g, Stage1Air *executable...@@ -5899,6 +5917,52 @@ static LLVMValueRef ir_render_wasm_memory_grow(CodeGen *g, Stage1Air *executable
5899 return val;5917 return val;
5900}5918}
59015919
5920static LLVMValueRef ir_render_prefetch(CodeGen *g, Stage1Air *executable, Stage1AirInstPrefetch *instruction) {
5921 static_assert(PrefetchRwRead == 0, "");
5922 static_assert(PrefetchRwWrite == 1, "");
5923 assert(instruction->rw == PrefetchRwRead || instruction->rw == PrefetchRwWrite);
5924
5925 assert(instruction->locality >= 0 && instruction->locality <= 3);
5926
5927 static_assert(PrefetchCacheInstruction == 0, "");
5928 static_assert(PrefetchCacheData == 1, "");
5929 assert(instruction->cache == PrefetchCacheData || instruction->cache == PrefetchCacheInstruction);
5930
5931 // LLVM fails during codegen of instruction cache prefetchs for these architectures.
5932 // This is an LLVM bug as the prefetch intrinsic should be a noop if not supported by the target.
5933 // To work around this, simply don't emit llvm.prefetch in this case.
5934 // See https://bugs.llvm.org/show_bug.cgi?id=21037
5935 if (instruction->cache == PrefetchCacheInstruction) {
5936 switch (g->zig_target->arch) {
5937 case ZigLLVM_x86:
5938 case ZigLLVM_x86_64:
5939 return nullptr;
5940 default:
5941 break;
5942 }
5943 }
5944
5945 // Another case of the same LLVM bug described above
5946 if (instruction->rw == PrefetchRwWrite && instruction->cache == PrefetchCacheInstruction) {
5947 switch (g->zig_target->arch) {
5948 case ZigLLVM_arm:
5949 return nullptr;
5950 default:
5951 break;
5952 }
5953
5954 }
5955
5956 LLVMValueRef params[] = {
5957 LLVMBuildBitCast(g->builder, ir_llvm_value(g, instruction->ptr), LLVMPointerType(LLVMInt8Type(), 0), ""),
5958 LLVMConstInt(LLVMInt32Type(), instruction->rw, false),
5959 LLVMConstInt(LLVMInt32Type(), instruction->locality, false),
5960 LLVMConstInt(LLVMInt32Type(), instruction->cache, false),
5961 };
5962 LLVMValueRef val = LLVMBuildCall(g->builder, gen_prefetch(g), params, 4, "");
5963 return val;
5964}
5965
5902static LLVMValueRef ir_render_slice(CodeGen *g, Stage1Air *executable, Stage1AirInstSlice *instruction) {5966static LLVMValueRef ir_render_slice(CodeGen *g, Stage1Air *executable, Stage1AirInstSlice *instruction) {
5903 Error err;5967 Error err;
59045968
...@@ -7150,6 +7214,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, Stage1Air *executable, Sta...@@ -7150,6 +7214,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, Stage1Air *executable, Sta
7150 return ir_render_wasm_memory_grow(g, executable, (Stage1AirInstWasmMemoryGrow *) instruction);7214 return ir_render_wasm_memory_grow(g, executable, (Stage1AirInstWasmMemoryGrow *) instruction);
7151 case Stage1AirInstIdExtern:7215 case Stage1AirInstIdExtern:
7152 return ir_render_extern(g, executable, (Stage1AirInstExtern *) instruction);7216 return ir_render_extern(g, executable, (Stage1AirInstExtern *) instruction);
7217 case Stage1AirInstIdPrefetch:
7218 return ir_render_prefetch(g, executable, (Stage1AirInstPrefetch *) instruction);
7153 }7219 }
7154 zig_unreachable();7220 zig_unreachable();
7155}7221}
...@@ -9120,6 +9186,7 @@ static void define_builtin_fns(CodeGen *g) {...@@ -9120,6 +9186,7 @@ static void define_builtin_fns(CodeGen *g) {
9120 create_builtin_fn(g, BuiltinFnIdReduce, "reduce", 2);9186 create_builtin_fn(g, BuiltinFnIdReduce, "reduce", 2);
9121 create_builtin_fn(g, BuiltinFnIdMaximum, "maximum", 2);9187 create_builtin_fn(g, BuiltinFnIdMaximum, "maximum", 2);
9122 create_builtin_fn(g, BuiltinFnIdMinimum, "minimum", 2);9188 create_builtin_fn(g, BuiltinFnIdMinimum, "minimum", 2);
9189 create_builtin_fn(g, BuiltinFnIdPrefetch, "prefetch", 2);
9123}9190}
91249191
9125static const char *bool_to_str(bool b) {9192static const char *bool_to_str(bool b) {
src/stage1/ir.cpp+56
...@@ -467,6 +467,8 @@ void destroy_instruction_gen(Stage1AirInst *inst) {...@@ -467,6 +467,8 @@ void destroy_instruction_gen(Stage1AirInst *inst) {
467 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstWasmMemoryGrow *>(inst));467 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstWasmMemoryGrow *>(inst));
468 case Stage1AirInstIdExtern:468 case Stage1AirInstIdExtern:
469 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstExtern *>(inst));469 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstExtern *>(inst));
470 case Stage1AirInstIdPrefetch:
471 return heap::c_allocator.destroy(reinterpret_cast<Stage1AirInstPrefetch *>(inst));
470 }472 }
471 zig_unreachable();473 zig_unreachable();
472}474}
...@@ -1115,6 +1117,10 @@ static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstExtern *) {...@@ -1115,6 +1117,10 @@ static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstExtern *) {
1115 return Stage1AirInstIdExtern;1117 return Stage1AirInstIdExtern;
1116}1118}
11171119
1120static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstPrefetch *) {
1121 return Stage1AirInstIdPrefetch;
1122}
1123
1118template<typename T>1124template<typename T>
1119static T *ir_create_inst_gen(IrBuilderGen *irb, Scope *scope, AstNode *source_node) {1125static T *ir_create_inst_gen(IrBuilderGen *irb, Scope *scope, AstNode *source_node) {
1120 T *special_instruction = heap::c_allocator.create<T>();1126 T *special_instruction = heap::c_allocator.create<T>();
...@@ -24853,6 +24859,52 @@ static Stage1AirInst *ir_analyze_instruction_src(IrAnalyze *ira, Stage1ZirInstSr...@@ -24853,6 +24859,52 @@ static Stage1AirInst *ir_analyze_instruction_src(IrAnalyze *ira, Stage1ZirInstSr
24853 return ir_const_move(ira, instruction->base.scope, instruction->base.source_node, result);24859 return ir_const_move(ira, instruction->base.scope, instruction->base.source_node, result);
24854}24860}
2485524861
24862static Stage1AirInst *ir_analyze_instruction_prefetch(IrAnalyze *ira, Stage1ZirInstPrefetch *instruction) {
24863 Stage1AirInst *ptr = instruction->ptr->child;
24864 if (type_is_invalid(ptr->value->type))
24865 return ira->codegen->invalid_inst_gen;
24866
24867 Stage1AirInst *raw_options_inst = instruction->options->child;
24868 if (type_is_invalid(raw_options_inst->value->type))
24869 return ira->codegen->invalid_inst_gen;
24870
24871 ZigType *options_type = get_builtin_type(ira->codegen, "PrefetchOptions");
24872 Stage1AirInst *options_inst = ir_implicit_cast(ira, raw_options_inst, options_type);
24873 if (type_is_invalid(options_inst->value->type))
24874 return ira->codegen->invalid_inst_gen;
24875
24876 ZigValue *options_val = ir_resolve_const(ira, options_inst, UndefBad);
24877 if (options_val == nullptr)
24878 return ira->codegen->invalid_inst_gen;
24879
24880 ZigValue *rw_val = get_const_field(ira, options_inst->source_node, options_val, "rw", 0);
24881 if (rw_val == nullptr)
24882 return ira->codegen->invalid_inst_gen;
24883 PrefetchRw rw = (PrefetchRw)bigint_as_u8(&rw_val->data.x_enum_tag);
24884
24885 ZigValue *locality_val = get_const_field(ira, options_inst->source_node, options_val, "locality", 1);
24886 if (locality_val == nullptr)
24887 return ira->codegen->invalid_inst_gen;
24888 uint8_t locality = bigint_as_u8(&locality_val->data.x_bigint);
24889 assert(locality <= 3);
24890
24891 ZigValue *cache_val = get_const_field(ira, options_inst->source_node, options_val, "cache", 2);
24892 if (cache_val == nullptr)
24893 return ira->codegen->invalid_inst_gen;
24894 PrefetchCache cache = (PrefetchCache)bigint_as_u8(&cache_val->data.x_enum_tag);
24895
24896 Stage1AirInstPrefetch *air_instruction = ir_build_inst_void<Stage1AirInstPrefetch>(&ira->new_irb,
24897 instruction->base.scope, instruction->base.source_node);
24898 air_instruction->ptr = ptr;
24899 air_instruction->rw = rw;
24900 air_instruction->locality = locality;
24901 air_instruction->cache = cache;
24902
24903 ir_ref_inst_gen(ptr);
24904
24905 return &air_instruction->base;
24906}
24907
24856static Stage1AirInst *ir_analyze_instruction_base(IrAnalyze *ira, Stage1ZirInst *instruction) {24908static Stage1AirInst *ir_analyze_instruction_base(IrAnalyze *ira, Stage1ZirInst *instruction) {
24857 switch (instruction->id) {24909 switch (instruction->id) {
24858 case Stage1ZirInstIdInvalid:24910 case Stage1ZirInstIdInvalid:
...@@ -25138,6 +25190,8 @@ static Stage1AirInst *ir_analyze_instruction_base(IrAnalyze *ira, Stage1ZirInst...@@ -25138,6 +25190,8 @@ static Stage1AirInst *ir_analyze_instruction_base(IrAnalyze *ira, Stage1ZirInst
25138 return ir_analyze_instruction_wasm_memory_grow(ira, (Stage1ZirInstWasmMemoryGrow *)instruction);25190 return ir_analyze_instruction_wasm_memory_grow(ira, (Stage1ZirInstWasmMemoryGrow *)instruction);
25139 case Stage1ZirInstIdSrc:25191 case Stage1ZirInstIdSrc:
25140 return ir_analyze_instruction_src(ira, (Stage1ZirInstSrc *)instruction);25192 return ir_analyze_instruction_src(ira, (Stage1ZirInstSrc *)instruction);
25193 case Stage1ZirInstIdPrefetch:
25194 return ir_analyze_instruction_prefetch(ira, (Stage1ZirInstPrefetch *)instruction);
25141 }25195 }
25142 zig_unreachable();25196 zig_unreachable();
25143}25197}
...@@ -25305,6 +25359,7 @@ bool ir_inst_gen_has_side_effects(Stage1AirInst *instruction) {...@@ -25305,6 +25359,7 @@ bool ir_inst_gen_has_side_effects(Stage1AirInst *instruction) {
25305 case Stage1AirInstIdSpillBegin:25359 case Stage1AirInstIdSpillBegin:
25306 case Stage1AirInstIdWasmMemoryGrow:25360 case Stage1AirInstIdWasmMemoryGrow:
25307 case Stage1AirInstIdExtern:25361 case Stage1AirInstIdExtern:
25362 case Stage1AirInstIdPrefetch:
25308 return true;25363 return true;
2530925364
25310 case Stage1AirInstIdPhi:25365 case Stage1AirInstIdPhi:
...@@ -25444,6 +25499,7 @@ bool ir_inst_src_has_side_effects(Stage1ZirInst *instruction) {...@@ -25444,6 +25499,7 @@ bool ir_inst_src_has_side_effects(Stage1ZirInst *instruction) {
25444 case Stage1ZirInstIdAwait:25499 case Stage1ZirInstIdAwait:
25445 case Stage1ZirInstIdSpillBegin:25500 case Stage1ZirInstIdSpillBegin:
25446 case Stage1ZirInstIdWasmMemoryGrow:25501 case Stage1ZirInstIdWasmMemoryGrow:
25502 case Stage1ZirInstIdPrefetch:
25447 return true;25503 return true;
2544825504
25449 case Stage1ZirInstIdPhi:25505 case Stage1ZirInstIdPhi:
src/stage1/ir_print.cpp+22
...@@ -371,6 +371,8 @@ const char* ir_inst_src_type_str(Stage1ZirInstId id) {...@@ -371,6 +371,8 @@ const char* ir_inst_src_type_str(Stage1ZirInstId id) {
371 return "SrcWasmMemoryGrow";371 return "SrcWasmMemoryGrow";
372 case Stage1ZirInstIdSrc:372 case Stage1ZirInstIdSrc:
373 return "SrcSrc";373 return "SrcSrc";
374 case Stage1ZirInstIdPrefetch:
375 return "SrcPrefetch";
374 }376 }
375 zig_unreachable();377 zig_unreachable();
376}378}
...@@ -559,6 +561,8 @@ const char* ir_inst_gen_type_str(Stage1AirInstId id) {...@@ -559,6 +561,8 @@ const char* ir_inst_gen_type_str(Stage1AirInstId id) {
559 return "GenWasmMemoryGrow";561 return "GenWasmMemoryGrow";
560 case Stage1AirInstIdExtern:562 case Stage1AirInstIdExtern:
561 return "GenExtern";563 return "GenExtern";
564 case Stage1AirInstIdPrefetch:
565 return "GenPrefetch";
562 }566 }
563 zig_unreachable();567 zig_unreachable();
564}568}
...@@ -2436,6 +2440,18 @@ static void ir_print_extern(IrPrintSrc *irp, Stage1ZirInstExtern *instruction) {...@@ -2436,6 +2440,18 @@ static void ir_print_extern(IrPrintSrc *irp, Stage1ZirInstExtern *instruction) {
2436 fprintf(irp->f, ")");2440 fprintf(irp->f, ")");
2437}2441}
24382442
2443static void ir_print_prefetch(IrPrintSrc *irp, Stage1ZirInstPrefetch *instruction) {
2444 fprintf(irp->f, "@prefetch(");
2445 ir_print_other_inst_src(irp, instruction->ptr);
2446 fprintf(irp->f, ",");
2447 ir_print_other_inst_src(irp, instruction->options);
2448 fprintf(irp->f, ")");
2449}
2450
2451static void ir_print_prefetch(IrPrintGen *irp, Stage1AirInstPrefetch *instruction) {
2452 fprintf(irp->f, "@prefetch(...)");
2453}
2454
2439static void ir_print_error_return_trace(IrPrintSrc *irp, Stage1ZirInstErrorReturnTrace *instruction) {2455static void ir_print_error_return_trace(IrPrintSrc *irp, Stage1ZirInstErrorReturnTrace *instruction) {
2440 fprintf(irp->f, "@errorReturnTrace(");2456 fprintf(irp->f, "@errorReturnTrace(");
2441 switch (instruction->optional) {2457 switch (instruction->optional) {
...@@ -3108,6 +3124,9 @@ static void ir_print_inst_src(IrPrintSrc *irp, Stage1ZirInst *instruction, bool...@@ -3108,6 +3124,9 @@ static void ir_print_inst_src(IrPrintSrc *irp, Stage1ZirInst *instruction, bool
3108 case Stage1ZirInstIdSrc:3124 case Stage1ZirInstIdSrc:
3109 ir_print_builtin_src(irp, (Stage1ZirInstSrc *)instruction);3125 ir_print_builtin_src(irp, (Stage1ZirInstSrc *)instruction);
3110 break;3126 break;
3127 case Stage1ZirInstIdPrefetch:
3128 ir_print_prefetch(irp, (Stage1ZirInstPrefetch *)instruction);
3129 break;
3111 }3130 }
3112 fprintf(irp->f, "\n");3131 fprintf(irp->f, "\n");
3113}3132}
...@@ -3387,6 +3406,9 @@ static void ir_print_inst_gen(IrPrintGen *irp, Stage1AirInst *instruction, bool...@@ -3387,6 +3406,9 @@ static void ir_print_inst_gen(IrPrintGen *irp, Stage1AirInst *instruction, bool
3387 case Stage1AirInstIdExtern:3406 case Stage1AirInstIdExtern:
3388 ir_print_extern(irp, (Stage1AirInstExtern *)instruction);3407 ir_print_extern(irp, (Stage1AirInstExtern *)instruction);
3389 break;3408 break;
3409 case Stage1AirInstIdPrefetch:
3410 ir_print_prefetch(irp, (Stage1AirInstPrefetch *)instruction);
3411 break;
33903412
3391 }3413 }
3392 fprintf(irp->f, "\n");3414 fprintf(irp->f, "\n");
src/type.zig+19
...@@ -123,6 +123,7 @@ pub const Type = extern union {...@@ -123,6 +123,7 @@ pub const Type = extern union {
123 .empty_struct_literal,123 .empty_struct_literal,
124 .@"struct",124 .@"struct",
125 .call_options,125 .call_options,
126 .prefetch_options,
126 .export_options,127 .export_options,
127 .extern_options,128 .extern_options,
128 => return .Struct,129 => return .Struct,
...@@ -798,6 +799,7 @@ pub const Type = extern union {...@@ -798,6 +799,7 @@ pub const Type = extern union {
798 .float_mode,799 .float_mode,
799 .reduce_op,800 .reduce_op,
800 .call_options,801 .call_options,
802 .prefetch_options,
801 .export_options,803 .export_options,
802 .extern_options,804 .extern_options,
803 .type_info,805 .type_info,
...@@ -1027,6 +1029,7 @@ pub const Type = extern union {...@@ -1027,6 +1029,7 @@ pub const Type = extern union {
1027 .float_mode => return writer.writeAll("std.builtin.FloatMode"),1029 .float_mode => return writer.writeAll("std.builtin.FloatMode"),
1028 .reduce_op => return writer.writeAll("std.builtin.ReduceOp"),1030 .reduce_op => return writer.writeAll("std.builtin.ReduceOp"),
1029 .call_options => return writer.writeAll("std.builtin.CallOptions"),1031 .call_options => return writer.writeAll("std.builtin.CallOptions"),
1032 .prefetch_options => return writer.writeAll("std.builtin.PrefetchOptions"),
1030 .export_options => return writer.writeAll("std.builtin.ExportOptions"),1033 .export_options => return writer.writeAll("std.builtin.ExportOptions"),
1031 .extern_options => return writer.writeAll("std.builtin.ExternOptions"),1034 .extern_options => return writer.writeAll("std.builtin.ExternOptions"),
1032 .type_info => return writer.writeAll("std.builtin.TypeInfo"),1035 .type_info => return writer.writeAll("std.builtin.TypeInfo"),
...@@ -1318,6 +1321,7 @@ pub const Type = extern union {...@@ -1318,6 +1321,7 @@ pub const Type = extern union {
1318 .float_mode => return "FloatMode",1321 .float_mode => return "FloatMode",
1319 .reduce_op => return "ReduceOp",1322 .reduce_op => return "ReduceOp",
1320 .call_options => return "CallOptions",1323 .call_options => return "CallOptions",
1324 .prefetch_options => return "PrefetchOptions",
1321 .export_options => return "ExportOptions",1325 .export_options => return "ExportOptions",
1322 .extern_options => return "ExternOptions",1326 .extern_options => return "ExternOptions",
1323 .type_info => return "TypeInfo",1327 .type_info => return "TypeInfo",
...@@ -1376,6 +1380,7 @@ pub const Type = extern union {...@@ -1376,6 +1380,7 @@ pub const Type = extern union {
1376 .float_mode,1380 .float_mode,
1377 .reduce_op,1381 .reduce_op,
1378 .call_options,1382 .call_options,
1383 .prefetch_options,
1379 .export_options,1384 .export_options,
1380 .extern_options,1385 .extern_options,
1381 .manyptr_u8,1386 .manyptr_u8,
...@@ -1502,6 +1507,7 @@ pub const Type = extern union {...@@ -1502,6 +1507,7 @@ pub const Type = extern union {
1502 .float_mode => return Value.initTag(.float_mode_type),1507 .float_mode => return Value.initTag(.float_mode_type),
1503 .reduce_op => return Value.initTag(.reduce_op_type),1508 .reduce_op => return Value.initTag(.reduce_op_type),
1504 .call_options => return Value.initTag(.call_options_type),1509 .call_options => return Value.initTag(.call_options_type),
1510 .prefetch_options => return Value.initTag(.prefetch_options_type),
1505 .export_options => return Value.initTag(.export_options_type),1511 .export_options => return Value.initTag(.export_options_type),
1506 .extern_options => return Value.initTag(.extern_options_type),1512 .extern_options => return Value.initTag(.extern_options_type),
1507 .type_info => return Value.initTag(.type_info_type),1513 .type_info => return Value.initTag(.type_info_type),
...@@ -1563,6 +1569,7 @@ pub const Type = extern union {...@@ -1563,6 +1569,7 @@ pub const Type = extern union {
1563 .float_mode,1569 .float_mode,
1564 .reduce_op,1570 .reduce_op,
1565 .call_options,1571 .call_options,
1572 .prefetch_options,
1566 .export_options,1573 .export_options,
1567 .extern_options,1574 .extern_options,
1568 .@"anyframe",1575 .@"anyframe",
...@@ -1750,6 +1757,7 @@ pub const Type = extern union {...@@ -1750,6 +1757,7 @@ pub const Type = extern union {
1750 .float_mode,1757 .float_mode,
1751 .reduce_op,1758 .reduce_op,
1752 .call_options,1759 .call_options,
1760 .prefetch_options,
1753 .export_options,1761 .export_options,
1754 .extern_options,1762 .extern_options,
1755 => return 1,1763 => return 1,
...@@ -1929,6 +1937,7 @@ pub const Type = extern union {...@@ -1929,6 +1937,7 @@ pub const Type = extern union {
1929 .var_args_param => unreachable,1937 .var_args_param => unreachable,
1930 .generic_poison => unreachable,1938 .generic_poison => unreachable,
1931 .call_options => unreachable, // missing call to resolveTypeFields1939 .call_options => unreachable, // missing call to resolveTypeFields
1940 .prefetch_options => unreachable, // missing call to resolveTypeFields
1932 .export_options => unreachable, // missing call to resolveTypeFields1941 .export_options => unreachable, // missing call to resolveTypeFields
1933 .extern_options => unreachable, // missing call to resolveTypeFields1942 .extern_options => unreachable, // missing call to resolveTypeFields
1934 .type_info => unreachable, // missing call to resolveTypeFields1943 .type_info => unreachable, // missing call to resolveTypeFields
...@@ -2269,6 +2278,7 @@ pub const Type = extern union {...@@ -2269,6 +2278,7 @@ pub const Type = extern union {
2269 .float_mode,2278 .float_mode,
2270 .reduce_op,2279 .reduce_op,
2271 .call_options,2280 .call_options,
2281 .prefetch_options,
2272 .export_options,2282 .export_options,
2273 .extern_options,2283 .extern_options,
2274 .type_info,2284 .type_info,
...@@ -2794,6 +2804,7 @@ pub const Type = extern union {...@@ -2794,6 +2804,7 @@ pub const Type = extern union {
2794 .float_mode,2804 .float_mode,
2795 .reduce_op,2805 .reduce_op,
2796 .call_options,2806 .call_options,
2807 .prefetch_options,
2797 .export_options,2808 .export_options,
2798 .extern_options,2809 .extern_options,
2799 .type_info,2810 .type_info,
...@@ -3294,6 +3305,7 @@ pub const Type = extern union {...@@ -3294,6 +3305,7 @@ pub const Type = extern union {
3294 .float_mode,3305 .float_mode,
3295 .reduce_op,3306 .reduce_op,
3296 .call_options,3307 .call_options,
3308 .prefetch_options,
3297 .export_options,3309 .export_options,
3298 .extern_options,3310 .extern_options,
3299 .type_info,3311 .type_info,
...@@ -3502,6 +3514,7 @@ pub const Type = extern union {...@@ -3502,6 +3514,7 @@ pub const Type = extern union {
3502 .float_mode,3514 .float_mode,
3503 .reduce_op,3515 .reduce_op,
3504 .call_options,3516 .call_options,
3517 .prefetch_options,
3505 .export_options,3518 .export_options,
3506 .extern_options,3519 .extern_options,
3507 => @panic("TODO resolve std.builtin types"),3520 => @panic("TODO resolve std.builtin types"),
...@@ -3577,6 +3590,7 @@ pub const Type = extern union {...@@ -3577,6 +3590,7 @@ pub const Type = extern union {
3577 .float_mode,3590 .float_mode,
3578 .reduce_op,3591 .reduce_op,
3579 .call_options,3592 .call_options,
3593 .prefetch_options,
3580 .export_options,3594 .export_options,
3581 .extern_options,3595 .extern_options,
3582 => @panic("TODO resolve std.builtin types"),3596 => @panic("TODO resolve std.builtin types"),
...@@ -3701,6 +3715,7 @@ pub const Type = extern union {...@@ -3701,6 +3715,7 @@ pub const Type = extern union {
3701 .float_mode,3715 .float_mode,
3702 .reduce_op,3716 .reduce_op,
3703 .call_options,3717 .call_options,
3718 .prefetch_options,
3704 .export_options,3719 .export_options,
3705 .extern_options,3720 .extern_options,
3706 .type_info,3721 .type_info,
...@@ -3741,6 +3756,7 @@ pub const Type = extern union {...@@ -3741,6 +3756,7 @@ pub const Type = extern union {
3741 .float_mode,3756 .float_mode,
3742 .reduce_op,3757 .reduce_op,
3743 .call_options,3758 .call_options,
3759 .prefetch_options,
3744 .export_options,3760 .export_options,
3745 .extern_options,3761 .extern_options,
3746 .type_info,3762 .type_info,
...@@ -3801,6 +3817,7 @@ pub const Type = extern union {...@@ -3801,6 +3817,7 @@ pub const Type = extern union {
3801 .float_mode,3817 .float_mode,
3802 .reduce_op,3818 .reduce_op,
3803 .call_options,3819 .call_options,
3820 .prefetch_options,
3804 .export_options,3821 .export_options,
3805 .extern_options,3822 .extern_options,
3806 => @panic("TODO resolve std.builtin types"),3823 => @panic("TODO resolve std.builtin types"),
...@@ -3862,6 +3879,7 @@ pub const Type = extern union {...@@ -3862,6 +3879,7 @@ pub const Type = extern union {
3862 float_mode,3879 float_mode,
3863 reduce_op,3880 reduce_op,
3864 call_options,3881 call_options,
3882 prefetch_options,
3865 export_options,3883 export_options,
3866 extern_options,3884 extern_options,
3867 type_info,3885 type_info,
...@@ -3989,6 +4007,7 @@ pub const Type = extern union {...@@ -3989,6 +4007,7 @@ pub const Type = extern union {
3989 .float_mode,4007 .float_mode,
3990 .reduce_op,4008 .reduce_op,
3991 .call_options,4009 .call_options,
4010 .prefetch_options,
3992 .export_options,4011 .export_options,
3993 .extern_options,4012 .extern_options,
3994 .type_info,4013 .type_info,
src/value.zig+5
...@@ -67,6 +67,7 @@ pub const Value = extern union {...@@ -67,6 +67,7 @@ pub const Value = extern union {
67 float_mode_type,67 float_mode_type,
68 reduce_op_type,68 reduce_op_type,
69 call_options_type,69 call_options_type,
70 prefetch_options_type,
70 export_options_type,71 export_options_type,
71 extern_options_type,72 extern_options_type,
72 type_info_type,73 type_info_type,
...@@ -244,6 +245,7 @@ pub const Value = extern union {...@@ -244,6 +245,7 @@ pub const Value = extern union {
244 .float_mode_type,245 .float_mode_type,
245 .reduce_op_type,246 .reduce_op_type,
246 .call_options_type,247 .call_options_type,
248 .prefetch_options_type,
247 .export_options_type,249 .export_options_type,
248 .extern_options_type,250 .extern_options_type,
249 .type_info_type,251 .type_info_type,
...@@ -434,6 +436,7 @@ pub const Value = extern union {...@@ -434,6 +436,7 @@ pub const Value = extern union {
434 .float_mode_type,436 .float_mode_type,
435 .reduce_op_type,437 .reduce_op_type,
436 .call_options_type,438 .call_options_type,
439 .prefetch_options_type,
437 .export_options_type,440 .export_options_type,
438 .extern_options_type,441 .extern_options_type,
439 .type_info_type,442 .type_info_type,
...@@ -652,6 +655,7 @@ pub const Value = extern union {...@@ -652,6 +655,7 @@ pub const Value = extern union {
652 .float_mode_type => return out_stream.writeAll("std.builtin.FloatMode"),655 .float_mode_type => return out_stream.writeAll("std.builtin.FloatMode"),
653 .reduce_op_type => return out_stream.writeAll("std.builtin.ReduceOp"),656 .reduce_op_type => return out_stream.writeAll("std.builtin.ReduceOp"),
654 .call_options_type => return out_stream.writeAll("std.builtin.CallOptions"),657 .call_options_type => return out_stream.writeAll("std.builtin.CallOptions"),
658 .prefetch_options_type => return out_stream.writeAll("std.builtin.PrefetchOptions"),
655 .export_options_type => return out_stream.writeAll("std.builtin.ExportOptions"),659 .export_options_type => return out_stream.writeAll("std.builtin.ExportOptions"),
656 .extern_options_type => return out_stream.writeAll("std.builtin.ExternOptions"),660 .extern_options_type => return out_stream.writeAll("std.builtin.ExternOptions"),
657 .type_info_type => return out_stream.writeAll("std.builtin.TypeInfo"),661 .type_info_type => return out_stream.writeAll("std.builtin.TypeInfo"),
...@@ -829,6 +833,7 @@ pub const Value = extern union {...@@ -829,6 +833,7 @@ pub const Value = extern union {
829 .float_mode_type => Type.initTag(.float_mode),833 .float_mode_type => Type.initTag(.float_mode),
830 .reduce_op_type => Type.initTag(.reduce_op),834 .reduce_op_type => Type.initTag(.reduce_op),
831 .call_options_type => Type.initTag(.call_options),835 .call_options_type => Type.initTag(.call_options),
836 .prefetch_options_type => Type.initTag(.prefetch_options),
832 .export_options_type => Type.initTag(.export_options),837 .export_options_type => Type.initTag(.export_options),
833 .extern_options_type => Type.initTag(.extern_options),838 .extern_options_type => Type.initTag(.extern_options),
834 .type_info_type => Type.initTag(.type_info),839 .type_info_type => Type.initTag(.type_info),
test/behavior.zig+1
...@@ -169,6 +169,7 @@ test {...@@ -169,6 +169,7 @@ test {
169 _ = @import("behavior/optional_stage1.zig");169 _ = @import("behavior/optional_stage1.zig");
170 _ = @import("behavior/pointers_stage1.zig");170 _ = @import("behavior/pointers_stage1.zig");
171 _ = @import("behavior/popcount_stage1.zig");171 _ = @import("behavior/popcount_stage1.zig");
172 _ = @import("behavior/prefetch.zig");
172 _ = @import("behavior/ptrcast_stage1.zig");173 _ = @import("behavior/ptrcast_stage1.zig");
173 _ = @import("behavior/reflection.zig");174 _ = @import("behavior/reflection.zig");
174 _ = @import("behavior/saturating_arithmetic_stage1.zig");175 _ = @import("behavior/saturating_arithmetic_stage1.zig");
test/behavior/prefetch.zig created+27
...@@ -0,0 +1,27 @@
1const std = @import("std");
2
3test "@prefetch()" {
4 var a: u32 = 42;
5
6 @prefetch(&a, .{});
7
8 @prefetch(&a, .{ .rw = .read, .locality = 3, .cache = .data });
9 @prefetch(&a, .{ .rw = .read, .locality = 2, .cache = .data });
10 @prefetch(&a, .{ .rw = .read, .locality = 1, .cache = .data });
11 @prefetch(&a, .{ .rw = .read, .locality = 0, .cache = .data });
12
13 @prefetch(&a, .{ .rw = .write, .locality = 3, .cache = .data });
14 @prefetch(&a, .{ .rw = .write, .locality = 2, .cache = .data });
15 @prefetch(&a, .{ .rw = .write, .locality = 1, .cache = .data });
16 @prefetch(&a, .{ .rw = .write, .locality = 0, .cache = .data });
17
18 @prefetch(&a, .{ .rw = .read, .locality = 3, .cache = .instruction });
19 @prefetch(&a, .{ .rw = .read, .locality = 2, .cache = .instruction });
20 @prefetch(&a, .{ .rw = .read, .locality = 1, .cache = .instruction });
21 @prefetch(&a, .{ .rw = .read, .locality = 0, .cache = .instruction });
22
23 @prefetch(&a, .{ .rw = .write, .locality = 3, .cache = .instruction });
24 @prefetch(&a, .{ .rw = .write, .locality = 2, .cache = .instruction });
25 @prefetch(&a, .{ .rw = .write, .locality = 1, .cache = .instruction });
26 @prefetch(&a, .{ .rw = .write, .locality = 0, .cache = .instruction });
27}