authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-12-04 01:27:13-05:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-12-04 01:29:07-05:00
log50993a8f08595b690e0b566cea3266c5ce2c5131
tree115dcf108d4016c417d035f4ba9d5fca0f30cff7
parent485e20884cfe7b6597e6d7c615195bb263d38abb

x86_64: implement more operations on vectors with 1-bit elements


3 files changed, 111 insertions(+), 66 deletions(-)

src/arch/x86_64/CodeGen.zig+56-20
...@@ -2478,8 +2478,11 @@ fn regClassForType(self: *Self, ty: Type) RegisterManager.RegisterBitSet {...@@ -2478,8 +2478,11 @@ fn regClassForType(self: *Self, ty: Type) RegisterManager.RegisterBitSet {
2478 else => abi.RegisterClass.sse,2478 else => abi.RegisterClass.sse,
2479 },2479 },
2480 .Vector => switch (ty.childType(mod).toIntern()) {2480 .Vector => switch (ty.childType(mod).toIntern()) {
2481 .bool_type => abi.RegisterClass.gp,2481 .bool_type, .u1_type => abi.RegisterClass.gp,
2482 else => abi.RegisterClass.sse,2482 else => if (ty.isAbiInt(mod) and ty.intInfo(mod).bits == 1)
2483 abi.RegisterClass.gp
2484 else
2485 abi.RegisterClass.sse,
2483 },2486 },
2484 else => abi.RegisterClass.gp,2487 else => abi.RegisterClass.gp,
2485 };2488 };
...@@ -5152,7 +5155,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -5152,7 +5155,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
5152 defer if (index_lock) |lock| self.register_manager.unlockReg(lock);5155 defer if (index_lock) |lock| self.register_manager.unlockReg(lock);
51535156
5154 try self.spillEflagsIfOccupied();5157 try self.spillEflagsIfOccupied();
5155 if (array_ty.isVector(mod) and elem_ty.toIntern() == .bool_type) {5158 if (array_ty.isVector(mod) and elem_ty.bitSize(mod) == 1) {
5156 const index_reg = switch (index_mcv) {5159 const index_reg = switch (index_mcv) {
5157 .register => |reg| reg,5160 .register => |reg| reg,
5158 else => try self.copyToTmpRegister(index_ty, index_mcv),5161 else => try self.copyToTmpRegister(index_ty, index_mcv),
...@@ -15475,26 +15478,59 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {...@@ -15475,26 +15478,59 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
15475 break :result .{ .load_frame = .{ .index = frame_index } };15478 break :result .{ .load_frame = .{ .index = frame_index } };
15476 },15479 },
15477 .Array, .Vector => {15480 .Array, .Vector => {
15478 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(result_ty, mod));
15479 const elem_ty = result_ty.childType(mod);15481 const elem_ty = result_ty.childType(mod);
15480 const elem_size: u32 = @intCast(elem_ty.abiSize(mod));15482 if (result_ty.isVector(mod) and elem_ty.bitSize(mod) == 1) {
15483 const result_size: u32 = @intCast(result_ty.abiSize(mod));
15484 const dst_reg = try self.register_manager.allocReg(inst, abi.RegisterClass.gp);
15485 try self.asmRegisterRegister(
15486 .{ ._, .xor },
15487 registerAlias(dst_reg, @min(result_size, 4)),
15488 registerAlias(dst_reg, @min(result_size, 4)),
15489 );
1548115490
15482 for (elements, 0..) |elem, elem_i| {15491 for (elements, 0..) |elem, elem_i| {
15483 const elem_mcv = try self.resolveInst(elem);15492 const elem_reg = try self.copyToTmpRegister(elem_ty, .{ .air_ref = elem });
15484 const mat_elem_mcv = switch (elem_mcv) {15493 const elem_lock = self.register_manager.lockRegAssumeUnused(elem_reg);
15485 .load_tlv => |sym_index| MCValue{ .lea_tlv = sym_index },15494 defer self.register_manager.unlockReg(elem_lock);
15486 else => elem_mcv,15495
15487 };15496 try self.asmRegisterImmediate(
15488 const elem_off: i32 = @intCast(elem_size * elem_i);15497 .{ ._, .@"and" },
15489 try self.genSetMem(.{ .frame = frame_index }, elem_off, elem_ty, mat_elem_mcv);15498 registerAlias(elem_reg, @min(result_size, 4)),
15499 Immediate.u(1),
15500 );
15501 if (elem_i > 0) try self.asmRegisterImmediate(
15502 .{ ._l, .sh },
15503 registerAlias(elem_reg, result_size),
15504 Immediate.u(@intCast(elem_i)),
15505 );
15506 try self.asmRegisterRegister(
15507 .{ ._, .@"or" },
15508 registerAlias(dst_reg, result_size),
15509 registerAlias(elem_reg, result_size),
15510 );
15511 }
15512 break :result .{ .register = dst_reg };
15513 } else {
15514 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(result_ty, mod));
15515 const elem_size: u32 = @intCast(elem_ty.abiSize(mod));
15516
15517 for (elements, 0..) |elem, elem_i| {
15518 const elem_mcv = try self.resolveInst(elem);
15519 const mat_elem_mcv = switch (elem_mcv) {
15520 .load_tlv => |sym_index| MCValue{ .lea_tlv = sym_index },
15521 else => elem_mcv,
15522 };
15523 const elem_off: i32 = @intCast(elem_size * elem_i);
15524 try self.genSetMem(.{ .frame = frame_index }, elem_off, elem_ty, mat_elem_mcv);
15525 }
15526 if (result_ty.sentinel(mod)) |sentinel| try self.genSetMem(
15527 .{ .frame = frame_index },
15528 @intCast(elem_size * elements.len),
15529 elem_ty,
15530 try self.genTypedValue(.{ .ty = elem_ty, .val = sentinel }),
15531 );
15532 break :result .{ .load_frame = .{ .index = frame_index } };
15490 }15533 }
15491 if (result_ty.sentinel(mod)) |sentinel| try self.genSetMem(
15492 .{ .frame = frame_index },
15493 @intCast(elem_size * elements.len),
15494 elem_ty,
15495 try self.genTypedValue(.{ .ty = elem_ty, .val = sentinel }),
15496 );
15497 break :result .{ .load_frame = .{ .index = frame_index } };
15498 },15534 },
15499 else => unreachable,15535 else => unreachable,
15500 }15536 }
src/codegen.zig+55-45
...@@ -391,53 +391,63 @@ pub fn generateSymbol(...@@ -391,53 +391,63 @@ pub fn generateSymbol(
391 .vector_type => |vector_type| {391 .vector_type => |vector_type| {
392 const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse392 const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse
393 return error.Overflow;393 return error.Overflow;
394 switch (vector_type.child) {394 if (Type.fromInterned(vector_type.child).bitSize(mod) == 1) {
395 .bool_type => {395 const bytes = try code.addManyAsSlice(abi_size);
396 const bytes = try code.addManyAsSlice(abi_size);396 @memset(bytes, 0xaa);
397 @memset(bytes, 0xaa);397 var index: usize = 0;
398 var index: usize = 0;398 const len = math.cast(usize, vector_type.len) orelse return error.Overflow;
399 const len = math.cast(usize, vector_type.len) orelse return error.Overflow;399 while (index < len) : (index += 1) {
400 while (index < len) : (index += 1) {400 const bit_index = switch (endian) {
401 const bit_index = switch (endian) {401 .big => len - 1 - index,
402 .big => len - 1 - index,402 .little => index,
403 .little => index,403 };
404 };404 const byte = &bytes[bit_index / 8];
405 const byte = &bytes[bit_index / 8];405 const mask = @as(u8, 1) << @truncate(bit_index);
406 const mask = @as(u8, 1) << @truncate(bit_index);406 if (switch (switch (aggregate.storage) {
407 if (switch (switch (aggregate.storage) {407 .bytes => unreachable,
408 .bytes => unreachable,408 .elems => |elems| elems[index],
409 .elems => |elems| elems[index],409 .repeated_elem => |elem| elem,
410 .repeated_elem => |elem| elem,410 }) {
411 }) {411 .bool_true => true,
412 .bool_true => true,412 .bool_false => false,
413 .bool_false => false,413 else => |elem| switch (mod.intern_pool.indexToKey(elem)) {
414 else => |elem| {414 .undef => continue,
415 assert(mod.intern_pool.indexToKey(elem).undef == .bool_type);415 .int => |int| switch (int.storage) {
416 continue;416 .u64 => |x| switch (x) {
417 0 => false,
418 1 => true,
419 else => unreachable,
420 },
421 .i64 => |x| switch (x) {
422 -1 => true,
423 0 => false,
424 else => unreachable,
425 },
426 else => unreachable,
417 },427 },
418 }) byte.* |= mask else byte.* &= ~mask;428 else => unreachable,
419 }429 },
420 },430 }) byte.* |= mask else byte.* &= ~mask;
421 else => switch (aggregate.storage) {431 }
422 .bytes => |bytes| try code.appendSlice(bytes),432 } else switch (aggregate.storage) {
423 .elems, .repeated_elem => {433 .bytes => |bytes| try code.appendSlice(bytes),
424 var index: u64 = 0;434 .elems, .repeated_elem => {
425 while (index < vector_type.len) : (index += 1) {435 var index: u64 = 0;
426 switch (try generateSymbol(bin_file, src_loc, .{436 while (index < vector_type.len) : (index += 1) {
427 .ty = Type.fromInterned(vector_type.child),437 switch (try generateSymbol(bin_file, src_loc, .{
428 .val = Value.fromInterned(switch (aggregate.storage) {438 .ty = Type.fromInterned(vector_type.child),
429 .bytes => unreachable,439 .val = Value.fromInterned(switch (aggregate.storage) {
430 .elems => |elems| elems[440 .bytes => unreachable,
431 math.cast(usize, index) orelse return error.Overflow441 .elems => |elems| elems[
432 ],442 math.cast(usize, index) orelse return error.Overflow
433 .repeated_elem => |elem| elem,443 ],
434 }),444 .repeated_elem => |elem| elem,
435 }, code, debug_output, reloc_info)) {445 }),
436 .ok => {},446 }, code, debug_output, reloc_info)) {
437 .fail => |em| return .{ .fail = em },447 .ok => {},
438 }448 .fail => |em| return .{ .fail = em },
439 }449 }
440 },450 }
441 },451 },
442 }452 }
443453
test/behavior/cast.zig-1
...@@ -2420,7 +2420,6 @@ test "@intFromFloat on vector" {...@@ -2420,7 +2420,6 @@ test "@intFromFloat on vector" {
24202420
2421test "@intFromBool on vector" {2421test "@intFromBool on vector" {
2422 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO2422 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
2423 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
2424 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO2423 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2425 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2424 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2426 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2425 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO