authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-10-07 22:04:21-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-10-08 04:41:55-04:00
logb8f00ae337a9c36cb33181292c5b6ba345add9ab
tree1b20786f3a34cd765e8653d1833f4c21f0d644e1
parent24d76500d2d0220d313b5f79c880855b776d61c2

x86_64: implement `@abs` for some integer vector types


4 files changed, 112 insertions(+), 34 deletions(-)

src/arch/x86_64/CodeGen.zig+91-33
......@@ -5385,46 +5385,104 @@ fn airAbs(self: *Self, inst: Air.Inst.Index) !void {
53855385 const mod = self.bin_file.options.module.?;
53865386 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
53875387 const ty = self.typeOf(ty_op.operand);
5388 const scalar_ty = ty.scalarType(mod);
53895388
5390 switch (scalar_ty.zigTypeTag(mod)) {
5391 .Int => if (ty.zigTypeTag(mod) == .Vector) {
5392 return self.fail("TODO implement airAbs for {}", .{ty.fmt(mod)});
5393 } else {
5394 if (ty.abiSize(mod) > 8) {
5395 return self.fail("TODO implement abs for integer abi sizes larger than 8", .{});
5396 }
5397 const src_mcv = try self.resolveInst(ty_op.operand);
5398 const dst_mcv = try self.copyToRegisterWithInstTracking(inst, ty, src_mcv);
5389 const result: MCValue = result: {
5390 const mir_tag = @as(?Mir.Inst.FixedTag, switch (ty.zigTypeTag(mod)) {
5391 else => null,
5392 .Int => {
5393 if (ty.abiSize(mod) > 8) {
5394 return self.fail("TODO implement abs for integer abi sizes larger than 8", .{});
5395 }
5396 const src_mcv = try self.resolveInst(ty_op.operand);
5397 const dst_mcv = try self.copyToRegisterWithInstTracking(inst, ty, src_mcv);
53995398
5400 try self.genUnOpMir(.{ ._, .neg }, ty, dst_mcv);
5399 try self.genUnOpMir(.{ ._, .neg }, ty, dst_mcv);
54015400
5402 const cmov_abi_size = @max(@as(u32, @intCast(ty.abiSize(mod))), 2);
5403 switch (src_mcv) {
5404 .register => |val_reg| try self.asmCmovccRegisterRegister(
5405 registerAlias(dst_mcv.register, cmov_abi_size),
5406 registerAlias(val_reg, cmov_abi_size),
5407 .l,
5408 ),
5409 .memory, .indirect, .load_frame => try self.asmCmovccRegisterMemory(
5410 registerAlias(dst_mcv.register, cmov_abi_size),
5411 src_mcv.mem(Memory.PtrSize.fromSize(cmov_abi_size)),
5412 .l,
5413 ),
5414 else => {
5415 const val_reg = try self.copyToTmpRegister(ty, src_mcv);
5416 try self.asmCmovccRegisterRegister(
5401 const cmov_abi_size = @max(@as(u32, @intCast(ty.abiSize(mod))), 2);
5402 switch (src_mcv) {
5403 .register => |val_reg| try self.asmCmovccRegisterRegister(
54175404 registerAlias(dst_mcv.register, cmov_abi_size),
54185405 registerAlias(val_reg, cmov_abi_size),
54195406 .l,
5420 );
5407 ),
5408 .memory, .indirect, .load_frame => try self.asmCmovccRegisterMemory(
5409 registerAlias(dst_mcv.register, cmov_abi_size),
5410 src_mcv.mem(Memory.PtrSize.fromSize(cmov_abi_size)),
5411 .l,
5412 ),
5413 else => {
5414 const val_reg = try self.copyToTmpRegister(ty, src_mcv);
5415 try self.asmCmovccRegisterRegister(
5416 registerAlias(dst_mcv.register, cmov_abi_size),
5417 registerAlias(val_reg, cmov_abi_size),
5418 .l,
5419 );
5420 },
5421 }
5422 break :result dst_mcv;
5423 },
5424 .Float => return self.floatSign(inst, ty_op.operand, ty),
5425 .Vector => switch (ty.childType(mod).zigTypeTag(mod)) {
5426 else => null,
5427 .Int => switch (ty.childType(mod).intInfo(mod).bits) {
5428 else => null,
5429 8 => switch (ty.vectorLen(mod)) {
5430 else => null,
5431 1...16 => if (self.hasFeature(.avx))
5432 .{ .vp_b, .abs }
5433 else if (self.hasFeature(.ssse3))
5434 .{ .p_b, .abs }
5435 else
5436 null,
5437 17...32 => if (self.hasFeature(.avx2)) .{ .vp_b, .abs } else null,
5438 },
5439 16 => switch (ty.vectorLen(mod)) {
5440 else => null,
5441 1...8 => if (self.hasFeature(.avx))
5442 .{ .vp_w, .abs }
5443 else if (self.hasFeature(.ssse3))
5444 .{ .p_w, .abs }
5445 else
5446 null,
5447 9...16 => if (self.hasFeature(.avx2)) .{ .vp_w, .abs } else null,
5448 },
5449 32 => switch (ty.vectorLen(mod)) {
5450 else => null,
5451 1...4 => if (self.hasFeature(.avx))
5452 .{ .vp_d, .abs }
5453 else if (self.hasFeature(.ssse3))
5454 .{ .p_d, .abs }
5455 else
5456 null,
5457 5...8 => if (self.hasFeature(.avx2)) .{ .vp_d, .abs } else null,
5458 },
54215459 },
5422 }
5423 return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none });
5424 },
5425 .Float => return self.floatSign(inst, ty_op.operand, ty),
5426 else => unreachable,
5427 }
5460 .Float => return self.floatSign(inst, ty_op.operand, ty),
5461 },
5462 }) orelse return self.fail("TODO implement airAbs for {}", .{ty.fmt(mod)});
5463
5464 const abi_size: u32 = @intCast(ty.abiSize(mod));
5465 const src_mcv = try self.resolveInst(ty_op.operand);
5466 const dst_reg = if (src_mcv.isRegister() and self.reuseOperand(inst, ty_op.operand, 0, src_mcv))
5467 src_mcv.getReg().?
5468 else
5469 try self.register_manager.allocReg(inst, self.regClassForType(ty));
5470 const dst_alias = registerAlias(dst_reg, abi_size);
5471 if (src_mcv.isMemory()) try self.asmRegisterMemory(
5472 mir_tag,
5473 dst_alias,
5474 src_mcv.mem(self.memPtrSize(ty)),
5475 ) else try self.asmRegisterRegister(
5476 mir_tag,
5477 dst_alias,
5478 registerAlias(if (src_mcv.isRegister())
5479 src_mcv.getReg().?
5480 else
5481 try self.copyToTmpRegister(ty, src_mcv), abi_size),
5482 );
5483 break :result .{ .register = dst_reg };
5484 };
5485 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
54285486}
54295487
54305488fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
src/arch/x86_64/Encoding.zig+4
......@@ -316,6 +316,8 @@ pub const Mnemonic = enum {
316316 xorpd,
317317 // SSE3
318318 movddup, movshdup, movsldup,
319 // SSSE3
320 pabsb, pabsd, pabsw,
319321 // SSE4.1
320322 blendpd, blendps, blendvpd, blendvps,
321323 extractps,
......@@ -353,6 +355,7 @@ pub const Mnemonic = enum {
353355 vmovupd, vmovups,
354356 vmulpd, vmulps, vmulsd, vmulss,
355357 vorpd, vorps,
358 vpabsb, vpabsd, vpabsw,
356359 vpackssdw, vpacksswb, vpackusdw, vpackuswb,
357360 vpaddb, vpaddd, vpaddq, vpaddsb, vpaddsw, vpaddusb, vpaddusw, vpaddw,
358361 vpand, vpandn,
......@@ -750,6 +753,7 @@ pub const Feature = enum {
750753 sse2,
751754 sse3,
752755 sse4_1,
756 ssse3,
753757 x87,
754758};
755759
src/arch/x86_64/encodings.zig+16
......@@ -1108,6 +1108,14 @@ pub const table = [_]Entry{
11081108
11091109 .{ .movsldup, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0xf3, 0x0f, 0x12 }, 0, .none, .sse3 },
11101110
1111 // SSSE3
1112 .{ .pabsb, .rm, &.{ .mm, .mm_m64 }, &.{ 0x0f, 0x38, 0x1c }, 0, .none, .ssse3 },
1113 .{ .pabsb, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x38, 0x1c }, 0, .none, .ssse3 },
1114 .{ .pabsd, .rm, &.{ .mm, .mm_m64 }, &.{ 0x0f, 0x38, 0x1e }, 0, .none, .ssse3 },
1115 .{ .pabsd, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x38, 0x1e }, 0, .none, .ssse3 },
1116 .{ .pabsw, .rm, &.{ .mm, .mm_m64 }, &.{ 0x0f, 0x38, 0x1d }, 0, .none, .ssse3 },
1117 .{ .pabsw, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x38, 0x1d }, 0, .none, .ssse3 },
1118
11111119 // SSE4.1
11121120 .{ .blendpd, .rmi, &.{ .xmm, .xmm_m128, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x0d }, 0, .none, .sse4_1 },
11131121
......@@ -1368,6 +1376,10 @@ pub const table = [_]Entry{
13681376 .{ .vorps, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x0f, 0x56 }, 0, .vex_128_wig, .avx },
13691377 .{ .vorps, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x0f, 0x56 }, 0, .vex_256_wig, .avx },
13701378
1379 .{ .vpabsb, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x38, 0x1c }, 0, .vex_128_wig, .avx },
1380 .{ .vpabsd, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x38, 0x1e }, 0, .vex_128_wig, .avx },
1381 .{ .vpabsw, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x38, 0x1d }, 0, .vex_128_wig, .avx },
1382
13711383 .{ .vpacksswb, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x63 }, 0, .vex_128_wig, .avx },
13721384 .{ .vpackssdw, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x6b }, 0, .vex_128_wig, .avx },
13731385
......@@ -1537,6 +1549,10 @@ pub const table = [_]Entry{
15371549 .{ .vbroadcastss, .rm, &.{ .ymm, .xmm }, &.{ 0x66, 0x0f, 0x38, 0x18 }, 0, .vex_256_w0, .avx2 },
15381550 .{ .vbroadcastsd, .rm, &.{ .ymm, .xmm }, &.{ 0x66, 0x0f, 0x38, 0x19 }, 0, .vex_256_w0, .avx2 },
15391551
1552 .{ .vpabsb, .rm, &.{ .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x38, 0x1c }, 0, .vex_256_wig, .avx2 },
1553 .{ .vpabsd, .rm, &.{ .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x38, 0x1e }, 0, .vex_256_wig, .avx2 },
1554 .{ .vpabsw, .rm, &.{ .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x38, 0x1d }, 0, .vex_256_wig, .avx2 },
1555
15401556 .{ .vpacksswb, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x63 }, 0, .vex_256_wig, .avx2 },
15411557 .{ .vpackssdw, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x6b }, 0, .vex_256_wig, .avx2 },
15421558
test/behavior/abs.zig+1-1
......@@ -280,7 +280,7 @@ test "@abs float vectors" {
280280 try testAbsFloatVectors(f16, 16);
281281 try comptime testAbsFloatVectors(f16, 17);
282282
283 try testAbsFloatVectors(f32, 17);
283 try testAbsFloatVectors(f32, 1);
284284 try comptime testAbsFloatVectors(f32, 1);
285285 try testAbsFloatVectors(f32, 1);
286286 try comptime testAbsFloatVectors(f32, 2);