mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 21:08:36 +00:00
port packed vector elem ptr logic from stage1
Closes #12812 Closes #13925
This commit is contained in:
parent
0d92fcf6a5
commit
8a0a6b7387
10
src/Air.zig
10
src/Air.zig
@ -737,6 +737,10 @@ pub const Inst = struct {
|
||||
/// Uses the `ty_pl` field.
|
||||
save_err_return_trace_index,
|
||||
|
||||
/// Store an element to a vector pointer at an index.
|
||||
/// Uses the `vector_store_elem` field.
|
||||
vector_store_elem,
|
||||
|
||||
pub fn fromCmpOp(op: std.math.CompareOperator, optimized: bool) Tag {
|
||||
switch (op) {
|
||||
.lt => return if (optimized) .cmp_lt_optimized else .cmp_lt,
|
||||
@ -814,6 +818,11 @@ pub const Inst = struct {
|
||||
operand: Ref,
|
||||
operation: std.builtin.ReduceOp,
|
||||
},
|
||||
vector_store_elem: struct {
|
||||
vector_ptr: Ref,
|
||||
// Index into a different array.
|
||||
payload: u32,
|
||||
},
|
||||
|
||||
// Make sure we don't accidentally add a field to make this union
|
||||
// bigger than expected. Note that in Debug builds, Zig is allowed
|
||||
@ -1177,6 +1186,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
|
||||
.set_union_tag,
|
||||
.prefetch,
|
||||
.set_err_return_trace,
|
||||
.vector_store_elem,
|
||||
=> return Type.void,
|
||||
|
||||
.ptrtoint,
|
||||
|
||||
@ -212,6 +212,15 @@ pub fn categorizeOperand(
|
||||
return .write;
|
||||
},
|
||||
|
||||
.vector_store_elem => {
|
||||
const o = air_datas[inst].vector_store_elem;
|
||||
const extra = air.extraData(Air.Bin, o.payload).data;
|
||||
if (o.vector_ptr == operand_ref) return matchOperandSmallIndex(l, inst, 0, .write);
|
||||
if (extra.lhs == operand_ref) return matchOperandSmallIndex(l, inst, 1, .none);
|
||||
if (extra.rhs == operand_ref) return matchOperandSmallIndex(l, inst, 2, .none);
|
||||
return .write;
|
||||
},
|
||||
|
||||
.arg,
|
||||
.alloc,
|
||||
.ret_ptr,
|
||||
@ -824,6 +833,12 @@ fn analyzeInst(
|
||||
return trackOperands(a, new_set, inst, main_tomb, .{ o.lhs, o.rhs, .none });
|
||||
},
|
||||
|
||||
.vector_store_elem => {
|
||||
const o = inst_datas[inst].vector_store_elem;
|
||||
const extra = a.air.extraData(Air.Bin, o.payload).data;
|
||||
return trackOperands(a, new_set, inst, main_tomb, .{ o.vector_ptr, extra.lhs, extra.rhs });
|
||||
},
|
||||
|
||||
.arg,
|
||||
.alloc,
|
||||
.ret_ptr,
|
||||
|
||||
64
src/Sema.zig
64
src/Sema.zig
@ -25952,6 +25952,30 @@ fn storePtr2(
|
||||
|
||||
try sema.requireRuntimeBlock(block, src, runtime_src);
|
||||
try sema.queueFullTypeResolution(elem_ty);
|
||||
|
||||
if (ptr_ty.ptrInfo().data.vector_index == .runtime) {
|
||||
const ptr_inst = Air.refToIndex(ptr).?;
|
||||
const air_tags = sema.air_instructions.items(.tag);
|
||||
if (air_tags[ptr_inst] == .ptr_elem_ptr) {
|
||||
const ty_pl = sema.air_instructions.items(.data)[ptr_inst].ty_pl;
|
||||
const bin_op = sema.getTmpAir().extraData(Air.Bin, ty_pl.payload).data;
|
||||
_ = try block.addInst(.{
|
||||
.tag = .vector_store_elem,
|
||||
.data = .{ .vector_store_elem = .{
|
||||
.vector_ptr = bin_op.lhs,
|
||||
.payload = try block.sema.addExtra(Air.Bin{
|
||||
.lhs = bin_op.rhs,
|
||||
.rhs = operand,
|
||||
}),
|
||||
} },
|
||||
});
|
||||
return;
|
||||
}
|
||||
return sema.fail(block, ptr_src, "unable to determine vector element index of type '{}'", .{
|
||||
ptr_ty.fmt(sema.mod),
|
||||
});
|
||||
}
|
||||
|
||||
if (is_ret) {
|
||||
_ = try block.addBinOp(.store, ptr, operand);
|
||||
} else {
|
||||
@ -27827,6 +27851,19 @@ fn analyzeLoad(
|
||||
}
|
||||
}
|
||||
|
||||
if (ptr_ty.ptrInfo().data.vector_index == .runtime) {
|
||||
const ptr_inst = Air.refToIndex(ptr).?;
|
||||
const air_tags = sema.air_instructions.items(.tag);
|
||||
if (air_tags[ptr_inst] == .ptr_elem_ptr) {
|
||||
const ty_pl = sema.air_instructions.items(.data)[ptr_inst].ty_pl;
|
||||
const bin_op = sema.getTmpAir().extraData(Air.Bin, ty_pl.payload).data;
|
||||
return block.addBinOp(.ptr_elem_val, bin_op.lhs, bin_op.rhs);
|
||||
}
|
||||
return sema.fail(block, ptr_src, "unable to determine vector element index of type '{}'", .{
|
||||
ptr_ty.fmt(sema.mod),
|
||||
});
|
||||
}
|
||||
|
||||
return block.addTyOp(.load, elem_ty, ptr);
|
||||
}
|
||||
|
||||
@ -32697,23 +32734,24 @@ fn elemPtrType(sema: *Sema, ptr_ty: Type, offset: ?usize) !Type {
|
||||
const target = sema.mod.getTarget();
|
||||
const parent_ty = ptr_ty.childType();
|
||||
|
||||
const VI = Type.Payload.Pointer.Data.VectorIndex;
|
||||
|
||||
const vector_info: struct {
|
||||
host_size: u16,
|
||||
bit_offset: u16,
|
||||
alignment: u32,
|
||||
host_size: u16 = 0,
|
||||
alignment: u32 = 0,
|
||||
vector_index: VI = .none,
|
||||
} = if (parent_ty.tag() == .vector) blk: {
|
||||
const elem_bits = elem_ty.bitSize(target);
|
||||
const is_packed = elem_bits != 0 and (elem_bits & (elem_bits - 1)) != 0;
|
||||
// TODO: runtime-known index
|
||||
assert(!is_packed or offset != null);
|
||||
const is_packed_with_offset = is_packed and offset != null and offset.? != 0;
|
||||
const target_offset = if (is_packed_with_offset) (if (target.cpu.arch.endian() == .Big) (parent_ty.vectorLen() - 1 - offset.?) else offset.?) else 0;
|
||||
if (elem_bits == 0) break :blk .{};
|
||||
const is_packed = elem_bits < 8 or !std.math.isPowerOfTwo(elem_bits);
|
||||
if (!is_packed) break :blk .{};
|
||||
|
||||
break :blk .{
|
||||
.host_size = if (is_packed_with_offset) @intCast(u16, parent_ty.abiSize(target)) else 0,
|
||||
.bit_offset = if (is_packed_with_offset) @intCast(u16, elem_bits * target_offset) else 0,
|
||||
.alignment = if (is_packed_with_offset) @intCast(u16, parent_ty.abiAlignment(target)) else 0,
|
||||
.host_size = @intCast(u16, parent_ty.arrayLen()),
|
||||
.alignment = @intCast(u16, parent_ty.abiAlignment(target)),
|
||||
.vector_index = if (offset) |some| @intToEnum(VI, some) else .runtime,
|
||||
};
|
||||
} else .{ .host_size = 0, .bit_offset = 0, .alignment = 0 };
|
||||
} else .{};
|
||||
|
||||
const alignment: u32 = a: {
|
||||
// Calculate the new pointer alignment.
|
||||
@ -32741,6 +32779,6 @@ fn elemPtrType(sema: *Sema, ptr_ty: Type, offset: ?usize) !Type {
|
||||
.@"volatile" = ptr_info.@"volatile",
|
||||
.@"align" = alignment,
|
||||
.host_size = vector_info.host_size,
|
||||
.bit_offset = vector_info.bit_offset,
|
||||
.vector_index = vector_info.vector_index,
|
||||
});
|
||||
}
|
||||
|
||||
@ -873,6 +873,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
||||
|
||||
.is_named_enum_value => return self.fail("TODO implement is_named_enum_value", .{}),
|
||||
.error_set_has_value => return self.fail("TODO implement error_set_has_value", .{}),
|
||||
.vector_store_elem => return self.fail("TODO implement vector_store_elem", .{}),
|
||||
|
||||
.wasm_memory_size => unreachable,
|
||||
.wasm_memory_grow => unreachable,
|
||||
|
||||
@ -783,6 +783,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
||||
|
||||
.is_named_enum_value => return self.fail("TODO implement is_named_enum_value", .{}),
|
||||
.error_set_has_value => return self.fail("TODO implement error_set_has_value", .{}),
|
||||
.vector_store_elem => return self.fail("TODO implement vector_store_elem", .{}),
|
||||
|
||||
.wasm_memory_size => unreachable,
|
||||
.wasm_memory_grow => unreachable,
|
||||
|
||||
@ -697,6 +697,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
||||
|
||||
.is_named_enum_value => return self.fail("TODO implement is_named_enum_value", .{}),
|
||||
.error_set_has_value => return self.fail("TODO implement error_set_has_value", .{}),
|
||||
.vector_store_elem => return self.fail("TODO implement vector_store_elem", .{}),
|
||||
|
||||
.wasm_memory_size => unreachable,
|
||||
.wasm_memory_grow => unreachable,
|
||||
|
||||
@ -714,6 +714,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
||||
|
||||
.is_named_enum_value => @panic("TODO implement is_named_enum_value"),
|
||||
.error_set_has_value => @panic("TODO implement error_set_has_value"),
|
||||
.vector_store_elem => @panic("TODO implement vector_store_elem"),
|
||||
|
||||
.wasm_memory_size => unreachable,
|
||||
.wasm_memory_grow => unreachable,
|
||||
|
||||
@ -1971,6 +1971,7 @@ fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
|
||||
.is_named_enum_value,
|
||||
.error_set_has_value,
|
||||
.addrspace_cast,
|
||||
.vector_store_elem,
|
||||
=> |tag| return func.fail("TODO: Implement wasm inst: {s}", .{@tagName(tag)}),
|
||||
|
||||
.add_optimized,
|
||||
@ -2213,6 +2214,7 @@ fn airStore(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
|
||||
const ptr_ty = func.air.typeOf(bin_op.lhs);
|
||||
const ptr_info = ptr_ty.ptrInfo().data;
|
||||
const ty = ptr_ty.childType();
|
||||
|
||||
if (ptr_info.host_size == 0) {
|
||||
try func.store(lhs, rhs, ty, 0);
|
||||
} else {
|
||||
|
||||
@ -785,6 +785,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
||||
|
||||
.is_named_enum_value => return self.fail("TODO implement is_named_enum_value", .{}),
|
||||
.error_set_has_value => return self.fail("TODO implement error_set_has_value", .{}),
|
||||
.vector_store_elem => return self.fail("TODO implement vector_store_elem", .{}),
|
||||
|
||||
.wasm_memory_size => unreachable,
|
||||
.wasm_memory_grow => unreachable,
|
||||
|
||||
@ -2908,6 +2908,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
|
||||
|
||||
.is_named_enum_value => return f.fail("TODO: C backend: implement is_named_enum_value", .{}),
|
||||
.error_set_has_value => return f.fail("TODO: C backend: implement error_set_has_value", .{}),
|
||||
.vector_store_elem => return f.fail("TODO: C backend: implement vector_store_elem", .{}),
|
||||
// zig fmt: on
|
||||
};
|
||||
if (result_value == .local) {
|
||||
|
||||
@ -1572,6 +1572,7 @@ pub const Object = struct {
|
||||
ptr_info.@"addrspace" != .generic or
|
||||
ptr_info.bit_offset != 0 or
|
||||
ptr_info.host_size != 0 or
|
||||
ptr_info.vector_index != .none or
|
||||
ptr_info.@"allowzero" or
|
||||
!ptr_info.mutable or
|
||||
ptr_info.@"volatile" or
|
||||
@ -4660,6 +4661,8 @@ pub const FuncGen = struct {
|
||||
.wasm_memory_size => try self.airWasmMemorySize(inst),
|
||||
.wasm_memory_grow => try self.airWasmMemoryGrow(inst),
|
||||
|
||||
.vector_store_elem => try self.airVectorStoreElem(inst),
|
||||
|
||||
.constant => unreachable,
|
||||
.const_ty => unreachable,
|
||||
.unreach => self.airUnreach(inst),
|
||||
@ -5022,7 +5025,7 @@ pub const FuncGen = struct {
|
||||
.data = ret_ty,
|
||||
};
|
||||
const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
|
||||
self.store(ret_ptr, ptr_ty, operand, .NotAtomic);
|
||||
try self.store(ret_ptr, ptr_ty, operand, .NotAtomic);
|
||||
_ = self.builder.buildRetVoid();
|
||||
return null;
|
||||
}
|
||||
@ -5779,6 +5782,10 @@ pub const FuncGen = struct {
|
||||
|
||||
const base_ptr = try self.resolveInst(bin_op.lhs);
|
||||
const rhs = try self.resolveInst(bin_op.rhs);
|
||||
|
||||
const elem_ptr = self.air.getRefType(ty_pl.ty);
|
||||
if (elem_ptr.ptrInfo().data.vector_index != .none) return base_ptr;
|
||||
|
||||
const llvm_elem_ty = try self.dg.lowerPtrElemTy(elem_ty);
|
||||
if (ptr_ty.isSinglePointer()) {
|
||||
// If this is a single-item pointer to an array, we need another index in the GEP.
|
||||
@ -6803,7 +6810,7 @@ pub const FuncGen = struct {
|
||||
.data = payload_ty,
|
||||
};
|
||||
const payload_ptr_ty = Type.initPayload(&ptr_ty_payload.base);
|
||||
self.store(payload_ptr, payload_ptr_ty, operand, .NotAtomic);
|
||||
try self.store(payload_ptr, payload_ptr_ty, operand, .NotAtomic);
|
||||
const non_null_ptr = self.builder.buildStructGEP(llvm_optional_ty, optional_ptr, 1, "");
|
||||
_ = self.builder.buildStore(non_null_bit, non_null_ptr);
|
||||
return optional_ptr;
|
||||
@ -6839,7 +6846,7 @@ pub const FuncGen = struct {
|
||||
.data = payload_ty,
|
||||
};
|
||||
const payload_ptr_ty = Type.initPayload(&ptr_ty_payload.base);
|
||||
self.store(payload_ptr, payload_ptr_ty, operand, .NotAtomic);
|
||||
try self.store(payload_ptr, payload_ptr_ty, operand, .NotAtomic);
|
||||
return result_ptr;
|
||||
}
|
||||
|
||||
@ -6908,6 +6915,28 @@ pub const FuncGen = struct {
|
||||
return self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &args, args.len, .Fast, .Auto, "");
|
||||
}
|
||||
|
||||
fn airVectorStoreElem(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
|
||||
const data = self.air.instructions.items(.data)[inst].vector_store_elem;
|
||||
const extra = self.air.extraData(Air.Bin, data.payload).data;
|
||||
|
||||
const vector_ptr = try self.resolveInst(data.vector_ptr);
|
||||
const vector_ptr_ty = self.air.typeOf(data.vector_ptr);
|
||||
const index = try self.resolveInst(extra.lhs);
|
||||
const operand = try self.resolveInst(extra.rhs);
|
||||
|
||||
const loaded_vector = blk: {
|
||||
const elem_llvm_ty = try self.dg.lowerType(vector_ptr_ty.elemType2());
|
||||
const load_inst = self.builder.buildLoad(elem_llvm_ty, vector_ptr, "");
|
||||
const target = self.dg.module.getTarget();
|
||||
load_inst.setAlignment(vector_ptr_ty.ptrAlignment(target));
|
||||
load_inst.setVolatile(llvm.Bool.fromBool(vector_ptr_ty.isVolatilePtr()));
|
||||
break :blk load_inst;
|
||||
};
|
||||
const modified_vector = self.builder.buildInsertElement(loaded_vector, operand, index, "");
|
||||
try self.store(vector_ptr, vector_ptr_ty, modified_vector, .NotAtomic);
|
||||
return null;
|
||||
}
|
||||
|
||||
fn airMin(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
|
||||
if (self.liveness.isUnused(inst)) return null;
|
||||
|
||||
@ -8135,7 +8164,7 @@ pub const FuncGen = struct {
|
||||
}
|
||||
} else {
|
||||
const src_operand = try self.resolveInst(bin_op.rhs);
|
||||
self.store(dest_ptr, ptr_ty, src_operand, .NotAtomic);
|
||||
try self.store(dest_ptr, ptr_ty, src_operand, .NotAtomic);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -8385,7 +8414,7 @@ pub const FuncGen = struct {
|
||||
element = self.builder.buildZExt(element, abi_ty, "");
|
||||
}
|
||||
}
|
||||
self.store(ptr, ptr_ty, element, ordering);
|
||||
try self.store(ptr, ptr_ty, element, ordering);
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -9178,7 +9207,7 @@ pub const FuncGen = struct {
|
||||
},
|
||||
};
|
||||
const field_ptr_ty = Type.initPayload(&field_ptr_payload.base);
|
||||
self.store(field_ptr, field_ptr_ty, llvm_elem, .NotAtomic);
|
||||
try self.store(field_ptr, field_ptr_ty, llvm_elem, .NotAtomic);
|
||||
}
|
||||
|
||||
return alloca_inst;
|
||||
@ -9216,7 +9245,7 @@ pub const FuncGen = struct {
|
||||
};
|
||||
const elem_ptr = self.builder.buildInBoundsGEP(llvm_result_ty, alloca_inst, &indices, indices.len, "");
|
||||
const llvm_elem = try self.resolveInst(elem);
|
||||
self.store(elem_ptr, elem_ptr_ty, llvm_elem, .NotAtomic);
|
||||
try self.store(elem_ptr, elem_ptr_ty, llvm_elem, .NotAtomic);
|
||||
}
|
||||
if (array_info.sentinel) |sent_val| {
|
||||
const indices: [2]*llvm.Value = .{
|
||||
@ -9229,7 +9258,7 @@ pub const FuncGen = struct {
|
||||
.val = sent_val,
|
||||
});
|
||||
|
||||
self.store(elem_ptr, elem_ptr_ty, llvm_elem, .NotAtomic);
|
||||
try self.store(elem_ptr, elem_ptr_ty, llvm_elem, .NotAtomic);
|
||||
}
|
||||
|
||||
return alloca_inst;
|
||||
@ -9352,7 +9381,7 @@ pub const FuncGen = struct {
|
||||
};
|
||||
const len: c_uint = if (field_size == layout.payload_size) 2 else 3;
|
||||
const field_ptr = self.builder.buildInBoundsGEP(llvm_union_ty, casted_ptr, &indices, len, "");
|
||||
self.store(field_ptr, field_ptr_ty, llvm_payload, .NotAtomic);
|
||||
try self.store(field_ptr, field_ptr_ty, llvm_payload, .NotAtomic);
|
||||
return result_ptr;
|
||||
}
|
||||
|
||||
@ -9364,7 +9393,7 @@ pub const FuncGen = struct {
|
||||
};
|
||||
const len: c_uint = if (field_size == layout.payload_size) 2 else 3;
|
||||
const field_ptr = self.builder.buildInBoundsGEP(llvm_union_ty, casted_ptr, &indices, len, "");
|
||||
self.store(field_ptr, field_ptr_ty, llvm_payload, .NotAtomic);
|
||||
try self.store(field_ptr, field_ptr_ty, llvm_payload, .NotAtomic);
|
||||
}
|
||||
{
|
||||
const indices: [2]*llvm.Value = .{
|
||||
@ -9693,6 +9722,20 @@ pub const FuncGen = struct {
|
||||
const target = self.dg.module.getTarget();
|
||||
const ptr_alignment = info.alignment(target);
|
||||
const ptr_volatile = llvm.Bool.fromBool(ptr_ty.isVolatilePtr());
|
||||
|
||||
assert(info.vector_index != .runtime);
|
||||
if (info.vector_index != .none) {
|
||||
const index_u32 = self.dg.context.intType(32).constInt(@enumToInt(info.vector_index), .False);
|
||||
const vec_elem_ty = try self.dg.lowerType(info.pointee_type);
|
||||
const vec_ty = vec_elem_ty.vectorType(info.host_size);
|
||||
|
||||
const loaded_vector = self.builder.buildLoad(vec_ty, ptr, "");
|
||||
loaded_vector.setAlignment(ptr_alignment);
|
||||
loaded_vector.setVolatile(ptr_volatile);
|
||||
|
||||
return self.builder.buildExtractElement(loaded_vector, index_u32, "");
|
||||
}
|
||||
|
||||
if (info.host_size == 0) {
|
||||
if (isByRef(info.pointee_type)) {
|
||||
return self.loadByRef(ptr, info.pointee_type, ptr_alignment, info.@"volatile");
|
||||
@ -9748,7 +9791,7 @@ pub const FuncGen = struct {
|
||||
ptr_ty: Type,
|
||||
elem: *llvm.Value,
|
||||
ordering: llvm.AtomicOrdering,
|
||||
) void {
|
||||
) !void {
|
||||
const info = ptr_ty.ptrInfo().data;
|
||||
const elem_ty = info.pointee_type;
|
||||
if (!elem_ty.isFnOrHasRuntimeBitsIgnoreComptime()) {
|
||||
@ -9757,6 +9800,26 @@ pub const FuncGen = struct {
|
||||
const target = self.dg.module.getTarget();
|
||||
const ptr_alignment = ptr_ty.ptrAlignment(target);
|
||||
const ptr_volatile = llvm.Bool.fromBool(info.@"volatile");
|
||||
|
||||
assert(info.vector_index != .runtime);
|
||||
if (info.vector_index != .none) {
|
||||
const index_u32 = self.dg.context.intType(32).constInt(@enumToInt(info.vector_index), .False);
|
||||
const vec_elem_ty = try self.dg.lowerType(elem_ty);
|
||||
const vec_ty = vec_elem_ty.vectorType(info.host_size);
|
||||
|
||||
const loaded_vector = self.builder.buildLoad(vec_ty, ptr, "");
|
||||
loaded_vector.setAlignment(ptr_alignment);
|
||||
loaded_vector.setVolatile(ptr_volatile);
|
||||
|
||||
const modified_vector = self.builder.buildInsertElement(loaded_vector, elem, index_u32, "");
|
||||
|
||||
const store_inst = self.builder.buildStore(modified_vector, ptr);
|
||||
assert(ordering == .NotAtomic);
|
||||
store_inst.setAlignment(ptr_alignment);
|
||||
store_inst.setVolatile(ptr_volatile);
|
||||
return;
|
||||
}
|
||||
|
||||
if (info.host_size != 0) {
|
||||
const int_elem_ty = self.context.intType(info.host_size * 8);
|
||||
const int_ptr = self.builder.buildBitCast(ptr, int_elem_ty.pointerType(0), "");
|
||||
|
||||
@ -306,6 +306,7 @@ const Writer = struct {
|
||||
.shuffle => try w.writeShuffle(s, inst),
|
||||
.reduce, .reduce_optimized => try w.writeReduce(s, inst),
|
||||
.cmp_vector, .cmp_vector_optimized => try w.writeCmpVector(s, inst),
|
||||
.vector_store_elem => try w.writeVectorStoreElem(s, inst),
|
||||
|
||||
.dbg_block_begin, .dbg_block_end => {},
|
||||
}
|
||||
@ -478,6 +479,17 @@ const Writer = struct {
|
||||
try w.writeOperand(s, inst, 1, extra.rhs);
|
||||
}
|
||||
|
||||
fn writeVectorStoreElem(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
|
||||
const data = w.air.instructions.items(.data)[inst].vector_store_elem;
|
||||
const extra = w.air.extraData(Air.VectorCmp, data.payload).data;
|
||||
|
||||
try w.writeOperand(s, inst, 0, data.vector_ptr);
|
||||
try s.writeAll(", ");
|
||||
try w.writeOperand(s, inst, 1, extra.lhs);
|
||||
try s.writeAll(", ");
|
||||
try w.writeOperand(s, inst, 2, extra.rhs);
|
||||
}
|
||||
|
||||
fn writeFence(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
|
||||
const atomic_order = w.air.instructions.items(.data)[inst].fence;
|
||||
|
||||
|
||||
30
src/type.zig
30
src/type.zig
@ -748,6 +748,8 @@ pub const Type = extern union {
|
||||
return false;
|
||||
if (info_a.host_size != info_b.host_size)
|
||||
return false;
|
||||
if (info_a.vector_index != info_b.vector_index)
|
||||
return false;
|
||||
if (info_a.@"allowzero" != info_b.@"allowzero")
|
||||
return false;
|
||||
if (info_a.mutable != info_b.mutable)
|
||||
@ -1126,6 +1128,7 @@ pub const Type = extern union {
|
||||
std.hash.autoHash(hasher, info.@"addrspace");
|
||||
std.hash.autoHash(hasher, info.bit_offset);
|
||||
std.hash.autoHash(hasher, info.host_size);
|
||||
std.hash.autoHash(hasher, info.vector_index);
|
||||
std.hash.autoHash(hasher, info.@"allowzero");
|
||||
std.hash.autoHash(hasher, info.mutable);
|
||||
std.hash.autoHash(hasher, info.@"volatile");
|
||||
@ -1467,6 +1470,7 @@ pub const Type = extern union {
|
||||
.@"addrspace" = payload.@"addrspace",
|
||||
.bit_offset = payload.bit_offset,
|
||||
.host_size = payload.host_size,
|
||||
.vector_index = payload.vector_index,
|
||||
.@"allowzero" = payload.@"allowzero",
|
||||
.mutable = payload.mutable,
|
||||
.@"volatile" = payload.@"volatile",
|
||||
@ -1855,12 +1859,17 @@ pub const Type = extern union {
|
||||
.C => try writer.writeAll("[*c]"),
|
||||
.Slice => try writer.writeAll("[]"),
|
||||
}
|
||||
if (payload.@"align" != 0 or payload.host_size != 0) {
|
||||
if (payload.@"align" != 0 or payload.host_size != 0 or payload.vector_index != .none) {
|
||||
try writer.print("align({d}", .{payload.@"align"});
|
||||
|
||||
if (payload.bit_offset != 0 or payload.host_size != 0) {
|
||||
try writer.print(":{d}:{d}", .{ payload.bit_offset, payload.host_size });
|
||||
}
|
||||
if (payload.vector_index == .runtime) {
|
||||
try writer.writeAll(":?");
|
||||
} else if (payload.vector_index != .none) {
|
||||
try writer.print(":{d}", .{@enumToInt(payload.vector_index)});
|
||||
}
|
||||
try writer.writeAll(") ");
|
||||
}
|
||||
if (payload.@"addrspace" != .generic) {
|
||||
@ -2185,12 +2194,17 @@ pub const Type = extern union {
|
||||
.C => try writer.writeAll("[*c]"),
|
||||
.Slice => try writer.writeAll("[]"),
|
||||
}
|
||||
if (info.@"align" != 0 or info.host_size != 0) {
|
||||
if (info.@"align" != 0 or info.host_size != 0 or info.vector_index != .none) {
|
||||
try writer.print("align({d}", .{info.@"align"});
|
||||
|
||||
if (info.bit_offset != 0 or info.host_size != 0) {
|
||||
try writer.print(":{d}:{d}", .{ info.bit_offset, info.host_size });
|
||||
}
|
||||
if (info.vector_index == .runtime) {
|
||||
try writer.writeAll(":?");
|
||||
} else if (info.vector_index != .none) {
|
||||
try writer.print(":{d}", .{@enumToInt(info.vector_index)});
|
||||
}
|
||||
try writer.writeAll(") ");
|
||||
}
|
||||
if (info.@"addrspace" != .generic) {
|
||||
@ -3865,6 +3879,7 @@ pub const Type = extern union {
|
||||
payload.@"addrspace" != .generic or
|
||||
payload.bit_offset != 0 or
|
||||
payload.host_size != 0 or
|
||||
payload.vector_index != .none or
|
||||
payload.@"allowzero" or
|
||||
payload.@"volatile")
|
||||
{
|
||||
@ -3877,6 +3892,7 @@ pub const Type = extern union {
|
||||
.@"addrspace" = payload.@"addrspace",
|
||||
.bit_offset = payload.bit_offset,
|
||||
.host_size = payload.host_size,
|
||||
.vector_index = payload.vector_index,
|
||||
.@"allowzero" = payload.@"allowzero",
|
||||
.mutable = payload.mutable,
|
||||
.@"volatile" = payload.@"volatile",
|
||||
@ -6365,11 +6381,18 @@ pub const Type = extern union {
|
||||
/// When host_size=pointee_abi_size and bit_offset=0, this must be
|
||||
/// represented with host_size=0 instead.
|
||||
host_size: u16 = 0,
|
||||
vector_index: VectorIndex = .none,
|
||||
@"allowzero": bool = false,
|
||||
mutable: bool = true, // TODO rename this to const, not mutable
|
||||
@"volatile": bool = false,
|
||||
size: std.builtin.Type.Pointer.Size = .One,
|
||||
|
||||
pub const VectorIndex = enum(u32) {
|
||||
none = std.math.maxInt(u32),
|
||||
runtime = std.math.maxInt(u32) - 1,
|
||||
_,
|
||||
};
|
||||
|
||||
pub fn alignment(data: Data, target: Target) u32 {
|
||||
if (data.@"align" != 0) return data.@"align";
|
||||
return abiAlignment(data.pointee_type, target);
|
||||
@ -6524,7 +6547,8 @@ pub const Type = extern union {
|
||||
}
|
||||
|
||||
if (d.@"align" == 0 and d.@"addrspace" == .generic and
|
||||
d.bit_offset == 0 and d.host_size == 0 and !d.@"allowzero" and !d.@"volatile")
|
||||
d.bit_offset == 0 and d.host_size == 0 and d.vector_index == .none and
|
||||
!d.@"allowzero" and !d.@"volatile")
|
||||
{
|
||||
if (d.sentinel) |sent| {
|
||||
if (!d.mutable and d.pointee_type.eql(Type.u8, mod)) {
|
||||
|
||||
@ -1234,3 +1234,30 @@ test "array operands to shuffle are coerced to vectors" {
|
||||
var b = @shuffle(u32, a, @splat(5, @as(u24, 0)), mask);
|
||||
try expectEqual([_]u32{ 0, 3, 5, 7, 9 }, b);
|
||||
}
|
||||
|
||||
test "load packed vector element" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
|
||||
var x: @Vector(2, u15) = .{ 1, 4 };
|
||||
try expect((&x[0]).* == 1);
|
||||
try expect((&x[1]).* == 4);
|
||||
}
|
||||
|
||||
test "store packed vector element" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
|
||||
var v = @Vector(4, u1){ 1, 1, 1, 1 };
|
||||
try expectEqual(@Vector(4, u1){ 1, 1, 1, 1 }, v);
|
||||
v[0] = 0;
|
||||
try expectEqual(@Vector(4, u1){ 0, 1, 1, 1 }, v);
|
||||
}
|
||||
|
||||
@ -0,0 +1,17 @@
|
||||
export fn entry() void {
|
||||
var v: @Vector(4, i31) = [_]i31{ 1, 5, 3, undefined };
|
||||
|
||||
var i: u32 = 0;
|
||||
var x = loadv(&v[i]);
|
||||
_ = x;
|
||||
}
|
||||
|
||||
fn loadv(ptr: anytype) i31 {
|
||||
return ptr.*;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=llvm
|
||||
// target=native
|
||||
//
|
||||
// :10:15: error: unable to determine vector element index of type '*align(16:0:4:?) i31'
|
||||
@ -1,17 +0,0 @@
|
||||
export fn entry() void {
|
||||
var v: @import("std").meta.Vector(4, i32) = [_]i32{ 1, 5, 3, undefined };
|
||||
|
||||
var i: u32 = 0;
|
||||
var x = loadv(&v[i]);
|
||||
_ = x;
|
||||
}
|
||||
|
||||
fn loadv(ptr: anytype) i32 {
|
||||
return ptr.*;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:10:12: error: unable to determine vector element index of type '*align(16:0:4:?) i32
|
||||
@ -1,16 +0,0 @@
|
||||
export fn entry() void {
|
||||
var v: @import("std").meta.Vector(4, i32) = [_]i32{ 1, 5, 3, undefined };
|
||||
|
||||
var i: u32 = 0;
|
||||
storev(&v[i], 42);
|
||||
}
|
||||
|
||||
fn storev(ptr: anytype, val: i32) void {
|
||||
ptr.* = val;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage1
|
||||
// target=native
|
||||
//
|
||||
// tmp.zig:9:8: error: unable to determine vector element index of type '*align(16:0:4:?) i32
|
||||
@ -0,0 +1,16 @@
|
||||
export fn entry() void {
|
||||
var v: @Vector(4, i31) = [_]i31{ 1, 5, 3, undefined };
|
||||
|
||||
var i: u32 = 0;
|
||||
storev(&v[i], 42);
|
||||
}
|
||||
|
||||
fn storev(ptr: anytype, val: i31) void {
|
||||
ptr.* = val;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=llvm
|
||||
// target=native
|
||||
//
|
||||
// :9:8: error: unable to determine vector element index of type '*align(16:0:4:?) i31'
|
||||
Loading…
x
Reference in New Issue
Block a user