Revert "stage2: implement @prefetch"

This reverts commit d48e4245b68bf25c7f41804a5012ac157a5ee546.

I have no idea why this is failing Drone CI, but in a branch, reverting
this commit solved the problem.
This commit is contained in:
Andrew Kelley 2022-01-18 10:47:02 -07:00
parent 4938fb8f5c
commit f423b5949b
14 changed files with 45 additions and 280 deletions

View File

@ -643,12 +643,12 @@ pub const PrefetchOptions = struct {
/// The cache that the prefetch should be preformed on.
cache: Cache = .data,
pub const Rw = enum(u1) {
pub const Rw = enum {
read,
write,
};
pub const Cache = enum(u1) {
pub const Cache = enum {
instruction,
data,
};

View File

@ -515,11 +515,6 @@ pub const Inst = struct {
/// is a `Ref`. Length of the array is given by the vector type.
vector_init,
/// Communicates an intent to load memory.
/// Result is always unused.
/// Uses the `prefetch` field.
prefetch,
pub fn fromCmpOp(op: std.math.CompareOperator) Tag {
return switch (op) {
.lt => .cmp_lt,
@ -591,12 +586,6 @@ pub const Inst = struct {
ptr: Ref,
order: std.builtin.AtomicOrder,
},
prefetch: struct {
ptr: Ref,
rw: std.builtin.PrefetchOptions.Rw,
locality: u2,
cache: std.builtin.PrefetchOptions.Cache,
},
// Make sure we don't accidentally add a field to make this union
// bigger than expected. Note that in Debug builds, Zig is allowed
@ -834,7 +823,6 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
.memset,
.memcpy,
.set_union_tag,
.prefetch,
=> return Type.initTag(.void),
.ptrtoint,

View File

@ -342,11 +342,6 @@ fn analyzeInst(
return trackOperands(a, new_set, inst, main_tomb, .{ operand, .none, .none });
},
.prefetch => {
const prefetch = inst_datas[inst].prefetch;
return trackOperands(a, new_set, inst, main_tomb, .{ prefetch.ptr, .none, .none });
},
.call => {
const inst_data = inst_datas[inst].pl_op;
const callee = inst_data.operand;

View File

@ -10316,53 +10316,49 @@ fn zirStructInitEmpty(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
const src = inst_data.src();
const obj_ty = try sema.resolveType(block, src, inst_data.operand);
const gpa = sema.gpa;
switch (obj_ty.zigTypeTag()) {
.Struct => return structInitEmpty(sema, block, obj_ty, src, src),
.Array => return arrayInitEmpty(sema, obj_ty),
.Struct => {
// This logic must be synchronized with that in `zirStructInit`.
const struct_ty = try sema.resolveTypeFields(block, src, obj_ty);
const struct_obj = struct_ty.castTag(.@"struct").?.data;
// The init values to use for the struct instance.
const field_inits = try gpa.alloc(Air.Inst.Ref, struct_obj.fields.count());
defer gpa.free(field_inits);
var root_msg: ?*Module.ErrorMsg = null;
for (struct_obj.fields.values()) |field, i| {
if (field.default_val.tag() == .unreachable_value) {
const field_name = struct_obj.fields.keys()[i];
const template = "missing struct field: {s}";
const args = .{field_name};
if (root_msg) |msg| {
try sema.errNote(block, src, msg, template, args);
} else {
root_msg = try sema.errMsg(block, src, template, args);
}
} else {
field_inits[i] = try sema.addConstant(field.ty, field.default_val);
}
}
return sema.finishStructInit(block, src, field_inits, root_msg, struct_obj, struct_ty, false);
},
.Array => {
if (obj_ty.sentinel()) |sentinel| {
const val = try Value.Tag.empty_array_sentinel.create(sema.arena, sentinel);
return sema.addConstant(obj_ty, val);
} else {
return sema.addConstant(obj_ty, Value.initTag(.empty_array));
}
},
.Void => return sema.addConstant(obj_ty, Value.void),
else => unreachable,
}
}
fn structInitEmpty(sema: *Sema, block: *Block, obj_ty: Type, dest_src: LazySrcLoc, init_src: LazySrcLoc) CompileError!Air.Inst.Ref {
const gpa = sema.gpa;
// This logic must be synchronized with that in `zirStructInit`.
const struct_ty = try sema.resolveTypeFields(block, dest_src, obj_ty);
const struct_obj = struct_ty.castTag(.@"struct").?.data;
// The init values to use for the struct instance.
const field_inits = try gpa.alloc(Air.Inst.Ref, struct_obj.fields.count());
defer gpa.free(field_inits);
var root_msg: ?*Module.ErrorMsg = null;
for (struct_obj.fields.values()) |field, i| {
if (field.default_val.tag() == .unreachable_value) {
const field_name = struct_obj.fields.keys()[i];
const template = "missing struct field: {s}";
const args = .{field_name};
if (root_msg) |msg| {
try sema.errNote(block, init_src, msg, template, args);
} else {
root_msg = try sema.errMsg(block, init_src, template, args);
}
} else {
field_inits[i] = try sema.addConstant(field.ty, field.default_val);
}
}
return sema.finishStructInit(block, dest_src, field_inits, root_msg, struct_obj, struct_ty, false);
}
fn arrayInitEmpty(sema: *Sema, obj_ty: Type) CompileError!Air.Inst.Ref {
if (obj_ty.sentinel()) |sentinel| {
const val = try Value.Tag.empty_array_sentinel.create(sema.arena, sentinel);
return sema.addConstant(obj_ty, val);
} else {
return sema.addConstant(obj_ty, Value.initTag(.empty_array));
}
}
fn zirUnionInitPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
@ -12330,38 +12326,8 @@ fn zirPrefetch(
extended: Zir.Inst.Extended.InstData,
) CompileError!Air.Inst.Ref {
const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;
const ptr_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
const opts_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = extra.node };
const options_ty = try sema.getBuiltinType(block, opts_src, "PrefetchOptions");
const ptr = sema.resolveInst(extra.lhs);
try sema.checkPtrType(block, ptr_src, sema.typeOf(ptr));
const options = try sema.coerce(block, options_ty, sema.resolveInst(extra.rhs), opts_src);
const rw = try sema.fieldVal(block, opts_src, options, "rw", opts_src);
const rw_val = try sema.resolveConstValue(block, opts_src, rw);
const rw_tag = rw_val.toEnum(std.builtin.PrefetchOptions.Rw);
const locality = try sema.fieldVal(block, opts_src, options, "locality", opts_src);
const locality_val = try sema.resolveConstValue(block, opts_src, locality);
const locality_int = @intCast(u2, locality_val.toUnsignedInt());
const cache = try sema.fieldVal(block, opts_src, options, "cache", opts_src);
const cache_val = try sema.resolveConstValue(block, opts_src, cache);
const cache_tag = cache_val.toEnum(std.builtin.PrefetchOptions.Cache);
if (!block.is_comptime) {
_ = try block.addInst(.{
.tag = .prefetch,
.data = .{ .prefetch = .{
.ptr = ptr,
.rw = rw_tag,
.locality = locality_int,
.cache = cache_tag,
} },
});
}
return Air.Inst.Ref.void_value;
const src: LazySrcLoc = .{ .node_offset = extra.node };
return sema.fail(block, src, "TODO: implement Sema.zirPrefetch", .{});
}
fn zirBuiltinExtern(
@ -13821,11 +13787,6 @@ fn coerce(
},
.Array => switch (inst_ty.zigTypeTag()) {
.Vector => return sema.coerceVectorInMemory(block, dest_ty, dest_ty_src, inst, inst_src),
.Struct => {
if (inst == .empty_struct) {
return arrayInitEmpty(sema, dest_ty);
}
},
else => {},
},
.Vector => switch (inst_ty.zigTypeTag()) {
@ -13833,11 +13794,6 @@ fn coerce(
.Vector => return sema.coerceVectors(block, dest_ty, dest_ty_src, inst, inst_src),
else => {},
},
.Struct => {
if (inst == .empty_struct) {
return structInitEmpty(sema, block, dest_ty, dest_ty_src, inst_src);
}
},
else => {},
}

View File

@ -595,7 +595,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
.error_name => try self.airErrorName(inst),
.splat => try self.airSplat(inst),
.vector_init => try self.airVectorInit(inst),
.prefetch => try self.airPrefetch(inst),
.atomic_store_unordered => try self.airAtomicStore(inst, .Unordered),
.atomic_store_monotonic => try self.airAtomicStore(inst, .Monotonic),
@ -2598,11 +2597,6 @@ fn airVectorInit(self: *Self, inst: Air.Inst.Index) !void {
return bt.finishAir(result);
}
fn airPrefetch(self: *Self, inst: Air.Inst.Index) !void {
const prefetch = self.air.instructions.items(.data)[inst].prefetch;
return self.finishAir(inst, MCValue.dead, .{ prefetch.ptr, .none, .none });
}
fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {
// First section of indexes correspond to a set number of constant values.
const ref_int = @enumToInt(inst);

View File

@ -586,7 +586,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
.error_name => try self.airErrorName(inst),
.splat => try self.airSplat(inst),
.vector_init => try self.airVectorInit(inst),
.prefetch => try self.airPrefetch(inst),
.atomic_store_unordered => try self.airAtomicStore(inst, .Unordered),
.atomic_store_monotonic => try self.airAtomicStore(inst, .Monotonic),
@ -3694,11 +3693,6 @@ fn airVectorInit(self: *Self, inst: Air.Inst.Index) !void {
return bt.finishAir(result);
}
fn airPrefetch(self: *Self, inst: Air.Inst.Index) !void {
const prefetch = self.air.instructions.items(.data)[inst].prefetch;
return self.finishAir(inst, MCValue.dead, .{ prefetch.ptr, .none, .none });
}
fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {
// First section of indexes correspond to a set number of constant values.
const ref_int = @enumToInt(inst);

View File

@ -574,7 +574,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
.error_name => try self.airErrorName(inst),
.splat => try self.airSplat(inst),
.vector_init => try self.airVectorInit(inst),
.prefetch => try self.airPrefetch(inst),
.atomic_store_unordered => try self.airAtomicStore(inst, .Unordered),
.atomic_store_monotonic => try self.airAtomicStore(inst, .Monotonic),
@ -2097,11 +2096,6 @@ fn airVectorInit(self: *Self, inst: Air.Inst.Index) !void {
return bt.finishAir(result);
}
fn airPrefetch(self: *Self, inst: Air.Inst.Index) !void {
const prefetch = self.air.instructions.items(.data)[inst].prefetch;
return self.finishAir(inst, MCValue.dead, .{ prefetch.ptr, .none, .none });
}
fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {
// First section of indexes correspond to a set number of constant values.
const ref_int = @enumToInt(inst);

View File

@ -1297,9 +1297,6 @@ fn copyLocal(self: *Self, value: WValue, ty: Type) InnerError!WValue {
fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
const air_tags = self.air.instructions.items(.tag);
return switch (air_tags[inst]) {
.constant => unreachable,
.const_ty => unreachable,
.add => self.airBinOp(inst, .add),
.addwrap => self.airWrapBinOp(inst, .add),
.sub => self.airBinOp(inst, .sub),
@ -1333,6 +1330,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
.bool_to_int => self.airBoolToInt(inst),
.call => self.airCall(inst),
.cond_br => self.airCondBr(inst),
.constant => unreachable,
.dbg_stmt => WValue.none,
.intcast => self.airIntcast(inst),
.float_to_int => self.airFloatToInt(inst),
@ -1360,9 +1358,6 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
.ret => self.airRet(inst),
.ret_ptr => self.airRetPtr(inst),
.ret_load => self.airRetLoad(inst),
.splat => self.airSplat(inst),
.vector_init => self.airVectorInit(inst),
.prefetch => self.airPrefetch(inst),
.slice => self.airSlice(inst),
.slice_len => self.airSliceLen(inst),
@ -1387,55 +1382,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
.unwrap_errunion_err => self.airUnwrapErrUnionError(inst),
.wrap_errunion_payload => self.airWrapErrUnionPayload(inst),
.wrap_errunion_err => self.airWrapErrUnionErr(inst),
.add_sat,
.sub_sat,
.mul_sat,
.div_float,
.div_floor,
.div_exact,
.rem,
.mod,
.max,
.min,
.assembly,
.shl_exact,
.shl_sat,
.ret_addr,
.clz,
.ctz,
.popcount,
.is_err_ptr,
.is_non_err_ptr,
.fptrunc,
.fpext,
.unwrap_errunion_payload_ptr,
.unwrap_errunion_err_ptr,
.set_union_tag,
.get_union_tag,
.ptr_slice_len_ptr,
.ptr_slice_ptr_ptr,
.int_to_float,
.memcpy,
.cmpxchg_weak,
.cmpxchg_strong,
.fence,
.atomic_load,
.atomic_store_unordered,
.atomic_store_monotonic,
.atomic_store_release,
.atomic_store_seq_cst,
.atomic_rmw,
.tag_name,
.error_name,
// For these 4, probably best to wait until https://github.com/ziglang/zig/issues/10248
// is implemented in the frontend before implementing them here in the wasm backend.
.add_with_overflow,
.sub_with_overflow,
.mul_with_overflow,
.shl_with_overflow,
=> |tag| self.fail("TODO: Implement wasm inst: {s}", .{@tagName(tag)}),
else => |tag| self.fail("TODO: Implement wasm inst: {s}", .{@tagName(tag)}),
};
}
@ -3264,7 +3211,7 @@ fn airFloatToInt(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
return result;
}
fn airSplat(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
fn airSplat(self: *Self, inst: Air.Inst.Index) !void {
if (self.liveness.isUnused(inst)) return WValue{ .none = {} };
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
@ -3275,7 +3222,7 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
return self.fail("TODO: Implement wasm airSplat", .{});
}
fn airVectorInit(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
fn airVectorInit(self: *Self, inst: Air.Inst.Index) !void {
if (self.liveness.isUnused(inst)) return WValue{ .none = {} };
const vector_ty = self.air.typeOfIndex(inst);
@ -3287,12 +3234,6 @@ fn airVectorInit(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
return self.fail("TODO: Wasm backend: implement airVectorInit", .{});
}
fn airPrefetch(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
const prefetch = self.air.instructions.items(.data)[inst].prefetch;
_ = prefetch;
return WValue{ .none = {} };
}
fn cmpOptionals(self: *Self, lhs: WValue, rhs: WValue, operand_ty: Type, op: std.math.CompareOperator) InnerError!WValue {
assert(operand_ty.hasCodeGenBits());
assert(op == .eq or op == .neq);

View File

@ -638,7 +638,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
.error_name => try self.airErrorName(inst),
.splat => try self.airSplat(inst),
.vector_init => try self.airVectorInit(inst),
.prefetch => try self.airPrefetch(inst),
.atomic_store_unordered => try self.airAtomicStore(inst, .Unordered),
.atomic_store_monotonic => try self.airAtomicStore(inst, .Monotonic),
@ -3747,11 +3746,6 @@ fn airVectorInit(self: *Self, inst: Air.Inst.Index) !void {
return bt.finishAir(result);
}
fn airPrefetch(self: *Self, inst: Air.Inst.Index) !void {
const prefetch = self.air.instructions.items(.data)[inst].prefetch;
return self.finishAir(inst, MCValue.dead, .{ prefetch.ptr, .none, .none });
}
fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {
// First section of indexes correspond to a set number of constant values.
const ref_int = @enumToInt(inst);

View File

@ -1278,7 +1278,6 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
.error_name => try airErrorName(f, inst),
.splat => try airSplat(f, inst),
.vector_init => try airVectorInit(f, inst),
.prefetch => try airPrefetch(f, inst),
.int_to_float,
.float_to_int,
@ -3090,18 +3089,6 @@ fn airVectorInit(f: *Function, inst: Air.Inst.Index) !CValue {
return f.fail("TODO: C backend: implement airVectorInit", .{});
}
fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue {
const prefetch = f.air.instructions.items(.data)[inst].prefetch;
const ptr = try f.resolveInst(prefetch.ptr);
const writer = f.object.writer();
try writer.writeAll("zig_prefetch(");
try f.writeCValue(writer, ptr);
try writer.print(", {d}, {d});\n", .{
@enumToInt(prefetch.rw), prefetch.locality,
});
return CValue.none;
}
fn toMemoryOrder(order: std.builtin.AtomicOrder) [:0]const u8 {
return switch (order) {
.Unordered => "memory_order_relaxed",

View File

@ -2073,7 +2073,6 @@ pub const FuncGen = struct {
.error_name => try self.airErrorName(inst),
.splat => try self.airSplat(inst),
.vector_init => try self.airVectorInit(inst),
.prefetch => try self.airPrefetch(inst),
.atomic_store_unordered => try self.airAtomicStore(inst, .Unordered),
.atomic_store_monotonic => try self.airAtomicStore(inst, .Monotonic),
@ -4385,67 +4384,6 @@ pub const FuncGen = struct {
return vector;
}
fn airPrefetch(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
const prefetch = self.air.instructions.items(.data)[inst].prefetch;
comptime assert(@enumToInt(std.builtin.PrefetchOptions.Rw.read) == 0);
comptime assert(@enumToInt(std.builtin.PrefetchOptions.Rw.write) == 1);
// TODO these two asserts should be able to be comptime because the type is a u2
assert(prefetch.locality >= 0);
assert(prefetch.locality <= 3);
comptime assert(@enumToInt(std.builtin.PrefetchOptions.Cache.instruction) == 0);
comptime assert(@enumToInt(std.builtin.PrefetchOptions.Cache.data) == 1);
// LLVM fails during codegen of instruction cache prefetchs for these architectures.
// This is an LLVM bug as the prefetch intrinsic should be a noop if not supported
// by the target.
// To work around this, don't emit llvm.prefetch in this case.
// See https://bugs.llvm.org/show_bug.cgi?id=21037
const target = self.dg.module.getTarget();
switch (prefetch.cache) {
.instruction => switch (target.cpu.arch) {
.x86_64, .i386 => return null,
.arm, .armeb, .thumb, .thumbeb => {
switch (prefetch.rw) {
.write => return null,
else => {},
}
},
else => {},
},
.data => {},
}
const llvm_u8 = self.context.intType(8);
const llvm_ptr_u8 = llvm_u8.pointerType(0);
const llvm_u32 = self.context.intType(32);
const llvm_fn_name = "llvm.prefetch.p0i8";
const fn_val = self.dg.object.llvm_module.getNamedFunction(llvm_fn_name) orelse blk: {
// declare void @llvm.prefetch(i8*, i32, i32, i32)
const llvm_void = self.context.voidType();
const param_types = [_]*const llvm.Type{
llvm_ptr_u8, llvm_u32, llvm_u32, llvm_u32,
};
const fn_type = llvm.functionType(llvm_void, &param_types, param_types.len, .False);
break :blk self.dg.object.llvm_module.addFunction(llvm_fn_name, fn_type);
};
const ptr = try self.resolveInst(prefetch.ptr);
const ptr_u8 = self.builder.buildBitCast(ptr, llvm_ptr_u8, "");
const params = [_]*const llvm.Value{
ptr_u8,
llvm_u32.constInt(@enumToInt(prefetch.rw), .False),
llvm_u32.constInt(prefetch.locality, .False),
llvm_u32.constInt(@enumToInt(prefetch.cache), .False),
};
_ = self.builder.buildCall(fn_val, &params, params.len, .C, .Auto, "");
return null;
}
fn getErrorNameTable(self: *FuncGen) !*const llvm.Value {
if (self.dg.object.error_name_table) |table| {
return table;

View File

@ -74,12 +74,6 @@
#define zig_frame_address() 0
#endif
#if defined(__GNUC__)
#define zig_prefetch(addr, rw, locality) __builtin_prefetch(addr, rw, locality)
#else
#define zig_prefetch(addr, rw, locality)
#endif
#if __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_ATOMICS__)
#include <stdatomic.h>
#define zig_cmpxchg_strong(obj, expected, desired, succ, fail) atomic_compare_exchange_strong_explicit(obj, &(expected), desired, succ, fail)

View File

@ -226,7 +226,6 @@ const Writer = struct {
.cmpxchg_weak, .cmpxchg_strong => try w.writeCmpxchg(s, inst),
.fence => try w.writeFence(s, inst),
.atomic_load => try w.writeAtomicLoad(s, inst),
.prefetch => try w.writePrefetch(s, inst),
.atomic_store_unordered => try w.writeAtomicStore(s, inst, .Unordered),
.atomic_store_monotonic => try w.writeAtomicStore(s, inst, .Monotonic),
.atomic_store_release => try w.writeAtomicStore(s, inst, .Release),
@ -351,15 +350,6 @@ const Writer = struct {
try s.print(", {s}", .{@tagName(atomic_load.order)});
}
fn writePrefetch(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
const prefetch = w.air.instructions.items(.data)[inst].prefetch;
try w.writeOperand(s, inst, 0, prefetch.ptr);
try s.print(", {s}, {d}, {s}", .{
@tagName(prefetch.rw), prefetch.locality, @tagName(prefetch.cache),
});
}
fn writeAtomicStore(
w: *Writer,
s: anytype,

View File

@ -10,7 +10,6 @@ test {
_ = @import("behavior/fn_in_struct_in_comptime.zig");
_ = @import("behavior/hasdecl.zig");
_ = @import("behavior/hasfield.zig");
_ = @import("behavior/prefetch.zig");
_ = @import("behavior/pub_enum.zig");
_ = @import("behavior/type_info.zig");
_ = @import("behavior/type.zig");
@ -179,6 +178,7 @@ test {
_ = @import("behavior/optional_stage1.zig");
_ = @import("behavior/pointers_stage1.zig");
_ = @import("behavior/popcount_stage1.zig");
_ = @import("behavior/prefetch.zig");
_ = @import("behavior/ptrcast_stage1.zig");
_ = @import("behavior/reflection.zig");
_ = @import("behavior/saturating_arithmetic_stage1.zig");