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 {...@@ -5385,46 +5385,104 @@ fn airAbs(self: *Self, inst: Air.Inst.Index) !void {
5385 const mod = self.bin_file.options.module.?;5385 const mod = self.bin_file.options.module.?;
5386 const ty_op = self.air.instructions.items(.data)[inst].ty_op;5386 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
5387 const ty = self.typeOf(ty_op.operand);5387 const ty = self.typeOf(ty_op.operand);
5388 const scalar_ty = ty.scalarType(mod);
53895388
5390 switch (scalar_ty.zigTypeTag(mod)) {5389 const result: MCValue = result: {
5391 .Int => if (ty.zigTypeTag(mod) == .Vector) {5390 const mir_tag = @as(?Mir.Inst.FixedTag, switch (ty.zigTypeTag(mod)) {
5392 return self.fail("TODO implement airAbs for {}", .{ty.fmt(mod)});5391 else => null,
5393 } else {5392 .Int => {
5394 if (ty.abiSize(mod) > 8) {5393 if (ty.abiSize(mod) > 8) {
5395 return self.fail("TODO implement abs for integer abi sizes larger than 8", .{});5394 return self.fail("TODO implement abs for integer abi sizes larger than 8", .{});
5396 }5395 }
5397 const src_mcv = try self.resolveInst(ty_op.operand);5396 const src_mcv = try self.resolveInst(ty_op.operand);
5398 const dst_mcv = try self.copyToRegisterWithInstTracking(inst, ty, src_mcv);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);5401 const cmov_abi_size = @max(@as(u32, @intCast(ty.abiSize(mod))), 2);
5403 switch (src_mcv) {5402 switch (src_mcv) {
5404 .register => |val_reg| try self.asmCmovccRegisterRegister(5403 .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(
5417 registerAlias(dst_mcv.register, cmov_abi_size),5404 registerAlias(dst_mcv.register, cmov_abi_size),
5418 registerAlias(val_reg, cmov_abi_size),5405 registerAlias(val_reg, cmov_abi_size),
5419 .l,5406 .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 },
5421 },5459 },
5422 }5460 .Float => return self.floatSign(inst, ty_op.operand, ty),
5423 return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none });5461 },
5424 },5462 }) orelse return self.fail("TODO implement airAbs for {}", .{ty.fmt(mod)});
5425 .Float => return self.floatSign(inst, ty_op.operand, ty),5463
5426 else => unreachable,5464 const abi_size: u32 = @intCast(ty.abiSize(mod));
5427 }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 });
5428}5486}
54295487
5430fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {5488fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
src/arch/x86_64/Encoding.zig+4
...@@ -316,6 +316,8 @@ pub const Mnemonic = enum {...@@ -316,6 +316,8 @@ pub const Mnemonic = enum {
316 xorpd,316 xorpd,
317 // SSE3317 // SSE3
318 movddup, movshdup, movsldup,318 movddup, movshdup, movsldup,
319 // SSSE3
320 pabsb, pabsd, pabsw,
319 // SSE4.1321 // SSE4.1
320 blendpd, blendps, blendvpd, blendvps,322 blendpd, blendps, blendvpd, blendvps,
321 extractps,323 extractps,
...@@ -353,6 +355,7 @@ pub const Mnemonic = enum {...@@ -353,6 +355,7 @@ pub const Mnemonic = enum {
353 vmovupd, vmovups,355 vmovupd, vmovups,
354 vmulpd, vmulps, vmulsd, vmulss,356 vmulpd, vmulps, vmulsd, vmulss,
355 vorpd, vorps,357 vorpd, vorps,
358 vpabsb, vpabsd, vpabsw,
356 vpackssdw, vpacksswb, vpackusdw, vpackuswb,359 vpackssdw, vpacksswb, vpackusdw, vpackuswb,
357 vpaddb, vpaddd, vpaddq, vpaddsb, vpaddsw, vpaddusb, vpaddusw, vpaddw,360 vpaddb, vpaddd, vpaddq, vpaddsb, vpaddsw, vpaddusb, vpaddusw, vpaddw,
358 vpand, vpandn,361 vpand, vpandn,
...@@ -750,6 +753,7 @@ pub const Feature = enum {...@@ -750,6 +753,7 @@ pub const Feature = enum {
750 sse2,753 sse2,
751 sse3,754 sse3,
752 sse4_1,755 sse4_1,
756 ssse3,
753 x87,757 x87,
754};758};
755759
src/arch/x86_64/encodings.zig+16
...@@ -1108,6 +1108,14 @@ pub const table = [_]Entry{...@@ -1108,6 +1108,14 @@ pub const table = [_]Entry{
11081108
1109 .{ .movsldup, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0xf3, 0x0f, 0x12 }, 0, .none, .sse3 },1109 .{ .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
1111 // SSE4.11119 // SSE4.1
1112 .{ .blendpd, .rmi, &.{ .xmm, .xmm_m128, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x0d }, 0, .none, .sse4_1 },1120 .{ .blendpd, .rmi, &.{ .xmm, .xmm_m128, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x0d }, 0, .none, .sse4_1 },
11131121
...@@ -1368,6 +1376,10 @@ pub const table = [_]Entry{...@@ -1368,6 +1376,10 @@ pub const table = [_]Entry{
1368 .{ .vorps, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x0f, 0x56 }, 0, .vex_128_wig, .avx },1376 .{ .vorps, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x0f, 0x56 }, 0, .vex_128_wig, .avx },
1369 .{ .vorps, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x0f, 0x56 }, 0, .vex_256_wig, .avx },1377 .{ .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
1371 .{ .vpacksswb, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x63 }, 0, .vex_128_wig, .avx },1383 .{ .vpacksswb, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x63 }, 0, .vex_128_wig, .avx },
1372 .{ .vpackssdw, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x6b }, 0, .vex_128_wig, .avx },1384 .{ .vpackssdw, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x6b }, 0, .vex_128_wig, .avx },
13731385
...@@ -1537,6 +1549,10 @@ pub const table = [_]Entry{...@@ -1537,6 +1549,10 @@ pub const table = [_]Entry{
1537 .{ .vbroadcastss, .rm, &.{ .ymm, .xmm }, &.{ 0x66, 0x0f, 0x38, 0x18 }, 0, .vex_256_w0, .avx2 },1549 .{ .vbroadcastss, .rm, &.{ .ymm, .xmm }, &.{ 0x66, 0x0f, 0x38, 0x18 }, 0, .vex_256_w0, .avx2 },
1538 .{ .vbroadcastsd, .rm, &.{ .ymm, .xmm }, &.{ 0x66, 0x0f, 0x38, 0x19 }, 0, .vex_256_w0, .avx2 },1550 .{ .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
1540 .{ .vpacksswb, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x63 }, 0, .vex_256_wig, .avx2 },1556 .{ .vpacksswb, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x63 }, 0, .vex_256_wig, .avx2 },
1541 .{ .vpackssdw, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x6b }, 0, .vex_256_wig, .avx2 },1557 .{ .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" {...@@ -280,7 +280,7 @@ test "@abs float vectors" {
280 try testAbsFloatVectors(f16, 16);280 try testAbsFloatVectors(f16, 16);
281 try comptime testAbsFloatVectors(f16, 17);281 try comptime testAbsFloatVectors(f16, 17);
282282
283 try testAbsFloatVectors(f32, 17);283 try testAbsFloatVectors(f32, 1);
284 try comptime testAbsFloatVectors(f32, 1);284 try comptime testAbsFloatVectors(f32, 1);
285 try testAbsFloatVectors(f32, 1);285 try testAbsFloatVectors(f32, 1);
286 try comptime testAbsFloatVectors(f32, 2);286 try comptime testAbsFloatVectors(f32, 2);