| ... | @@ -1587,9 +1587,9 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -1587,9 +1587,9 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 1587 | .round, | 1587 | .round, |
| 1588 | => try self.airUnaryMath(inst), | 1588 | => try self.airUnaryMath(inst), |
| 1589 | | 1589 | |
| 1590 | .floor => try self.airRound(inst, Immediate.u(0b1_0_01)), | 1590 | .floor => try self.airRound(inst, 0b1_0_01), |
| 1591 | .ceil => try self.airRound(inst, Immediate.u(0b1_0_10)), | 1591 | .ceil => try self.airRound(inst, 0b1_0_10), |
| 1592 | .trunc_float => try self.airRound(inst, Immediate.u(0b1_0_11)), | 1592 | .trunc_float => try self.airRound(inst, 0b1_0_11), |
| 1593 | .sqrt => try self.airSqrt(inst), | 1593 | .sqrt => try self.airSqrt(inst), |
| 1594 | .neg, .fabs => try self.airFloatSign(inst), | 1594 | .neg, .fabs => try self.airFloatSign(inst), |
| 1595 | | 1595 | |
| ... | @@ -4509,49 +4509,91 @@ fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4509,49 +4509,91 @@ fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void { |
| 4509 | return self.finishAir(inst, dst_mcv, .{ un_op, .none, .none }); | 4509 | return self.finishAir(inst, dst_mcv, .{ un_op, .none, .none }); |
| 4510 | } | 4510 | } |
| 4511 | | 4511 | |
| 4512 | fn airRound(self: *Self, inst: Air.Inst.Index, mode: Immediate) !void { | 4512 | fn airRound(self: *Self, inst: Air.Inst.Index, mode: u4) !void { |
| 4513 | const un_op = self.air.instructions.items(.data)[inst].un_op; | 4513 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 4514 | const ty = self.air.typeOf(un_op); | 4514 | const ty = self.air.typeOf(un_op); |
| 4515 | | 4515 | |
| 4516 | if (!self.hasFeature(.sse4_1)) | | |
| 4517 | return self.fail("TODO implement airRound without sse4_1 feature", .{}); | | |
| 4518 | | | |
| 4519 | const src_mcv = try self.resolveInst(un_op); | 4516 | const src_mcv = try self.resolveInst(un_op); |
| 4520 | const dst_mcv = if (src_mcv.isRegister() and self.reuseOperand(inst, un_op, 0, src_mcv)) | 4517 | const dst_mcv = if (src_mcv.isRegister() and self.reuseOperand(inst, un_op, 0, src_mcv)) |
| 4521 | src_mcv | 4518 | src_mcv |
| 4522 | else | 4519 | else |
| 4523 | try self.copyToRegisterWithInstTracking(inst, ty, src_mcv); | 4520 | try self.copyToRegisterWithInstTracking(inst, ty, src_mcv); |
| | 4521 | const dst_reg = dst_mcv.getReg().?; |
| | 4522 | const dst_lock = self.register_manager.lockReg(dst_reg); |
| | 4523 | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); |
| | 4524 | try self.genRound(ty, dst_reg, src_mcv, mode); |
| | 4525 | return self.finishAir(inst, dst_mcv, .{ un_op, .none, .none }); |
| | 4526 | } |
| 4524 | | 4527 | |
| 4525 | const mir_tag: Mir.Inst.Tag = switch (ty.zigTypeTag()) { | 4528 | fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: u4) !void { |
| | 4529 | if (!self.hasFeature(.sse4_1)) |
| | 4530 | return self.fail("TODO implement genRound without sse4_1 feature", .{}); |
| | 4531 | |
| | 4532 | const mir_tag = if (@as(?Mir.Inst.Tag, switch (ty.zigTypeTag()) { |
| 4526 | .Float => switch (ty.floatBits(self.target.*)) { | 4533 | .Float => switch (ty.floatBits(self.target.*)) { |
| 4527 | 32 => .roundss, | 4534 | 32 => if (self.hasFeature(.avx)) .vroundss else .roundss, |
| 4528 | 64 => .roundsd, | 4535 | 64 => if (self.hasFeature(.avx)) .vroundsd else .roundsd, |
| 4529 | else => return self.fail("TODO implement airRound for {}", .{ | 4536 | 16, 80, 128 => null, |
| 4530 | ty.fmt(self.bin_file.options.module.?), | 4537 | else => unreachable, |
| 4531 | }), | | |
| 4532 | }, | 4538 | }, |
| 4533 | else => return self.fail("TODO implement airRound for {}", .{ | 4539 | .Vector => switch (ty.childType().zigTypeTag()) { |
| 4534 | ty.fmt(self.bin_file.options.module.?), | 4540 | .Float => switch (ty.childType().floatBits(self.target.*)) { |
| 4535 | }), | 4541 | 32 => switch (ty.vectorLen()) { |
| 4536 | }; | 4542 | 1 => if (self.hasFeature(.avx)) .vroundss else .roundss, |
| 4537 | assert(dst_mcv.isRegister()); | 4543 | 2...4 => if (self.hasFeature(.avx)) .vroundps else .roundps, |
| | 4544 | 5...8 => if (self.hasFeature(.avx)) .vroundps else null, |
| | 4545 | else => null, |
| | 4546 | }, |
| | 4547 | 64 => switch (ty.vectorLen()) { |
| | 4548 | 1 => if (self.hasFeature(.avx)) .vroundsd else .roundsd, |
| | 4549 | 2 => if (self.hasFeature(.avx)) .vroundpd else .roundpd, |
| | 4550 | 3...4 => if (self.hasFeature(.avx)) .vroundpd else null, |
| | 4551 | else => null, |
| | 4552 | }, |
| | 4553 | 16, 80, 128 => null, |
| | 4554 | else => unreachable, |
| | 4555 | }, |
| | 4556 | else => null, |
| | 4557 | }, |
| | 4558 | else => unreachable, |
| | 4559 | })) |tag| tag else return self.fail("TODO implement genRound for {}", .{ |
| | 4560 | ty.fmt(self.bin_file.options.module.?), |
| | 4561 | }); |
| | 4562 | |
| 4538 | const abi_size = @intCast(u32, ty.abiSize(self.target.*)); | 4563 | const abi_size = @intCast(u32, ty.abiSize(self.target.*)); |
| 4539 | const dst_reg = registerAlias(dst_mcv.getReg().?, abi_size); | 4564 | const dst_alias = registerAlias(dst_reg, abi_size); |
| 4540 | if (src_mcv.isRegister()) | 4565 | switch (mir_tag) { |
| 4541 | try self.asmRegisterRegisterImmediate( | 4566 | .vroundss, .vroundsd => if (src_mcv.isMemory()) try self.asmRegisterRegisterMemoryImmediate( |
| 4542 | mir_tag, | 4567 | mir_tag, |
| 4543 | dst_reg, | 4568 | dst_alias, |
| 4544 | registerAlias(src_mcv.getReg().?, abi_size), | 4569 | dst_alias, |
| 4545 | mode, | 4570 | src_mcv.mem(Memory.PtrSize.fromSize(abi_size)), |
| 4546 | ) | 4571 | Immediate.u(mode), |
| 4547 | else | 4572 | ) else try self.asmRegisterRegisterRegisterImmediate( |
| 4548 | try self.asmRegisterMemoryImmediate( | | |
| 4549 | mir_tag, | 4573 | mir_tag, |
| 4550 | dst_reg, | 4574 | dst_alias, |
| 4551 | src_mcv.mem(Memory.PtrSize.fromSize(@intCast(u32, ty.abiSize(self.target.*)))), | 4575 | dst_alias, |
| 4552 | mode, | 4576 | registerAlias(if (src_mcv.isRegister()) |
| 4553 | ); | 4577 | src_mcv.getReg().? |
| 4554 | return self.finishAir(inst, dst_mcv, .{ un_op, .none, .none }); | 4578 | else |
| | 4579 | try self.copyToTmpRegister(ty, src_mcv), abi_size), |
| | 4580 | Immediate.u(mode), |
| | 4581 | ), |
| | 4582 | else => if (src_mcv.isMemory()) try self.asmRegisterMemoryImmediate( |
| | 4583 | mir_tag, |
| | 4584 | dst_alias, |
| | 4585 | src_mcv.mem(Memory.PtrSize.fromSize(abi_size)), |
| | 4586 | Immediate.u(mode), |
| | 4587 | ) else try self.asmRegisterRegisterImmediate( |
| | 4588 | mir_tag, |
| | 4589 | dst_alias, |
| | 4590 | registerAlias(if (src_mcv.isRegister()) |
| | 4591 | src_mcv.getReg().? |
| | 4592 | else |
| | 4593 | try self.copyToTmpRegister(ty, src_mcv), abi_size), |
| | 4594 | Immediate.u(mode), |
| | 4595 | ), |
| | 4596 | } |
| 4555 | } | 4597 | } |
| 4556 | | 4598 | |
| 4557 | fn airSqrt(self: *Self, inst: Air.Inst.Index) !void { | 4599 | fn airSqrt(self: *Self, inst: Air.Inst.Index) !void { |
| ... | @@ -6188,18 +6230,18 @@ fn genBinOp( | ... | @@ -6188,18 +6230,18 @@ fn genBinOp( |
| 6188 | })) |tag| tag else return self.fail("TODO implement genBinOp for {s} {}", .{ | 6230 | })) |tag| tag else return self.fail("TODO implement genBinOp for {s} {}", .{ |
| 6189 | @tagName(air_tag), lhs_ty.fmt(self.bin_file.options.module.?), | 6231 | @tagName(air_tag), lhs_ty.fmt(self.bin_file.options.module.?), |
| 6190 | }); | 6232 | }); |
| 6191 | const dst_alias = registerAlias(dst_mcv.getReg().?, abi_size); | 6233 | const dst_reg = registerAlias(dst_mcv.getReg().?, abi_size); |
| 6192 | if (self.hasFeature(.avx)) { | 6234 | if (self.hasFeature(.avx)) { |
| 6193 | const src1_alias = | 6235 | const src1_alias = |
| 6194 | if (copied_to_dst) dst_alias else registerAlias(lhs_mcv.getReg().?, abi_size); | 6236 | if (copied_to_dst) dst_reg else registerAlias(lhs_mcv.getReg().?, abi_size); |
| 6195 | if (src_mcv.isMemory()) try self.asmRegisterRegisterMemory( | 6237 | if (src_mcv.isMemory()) try self.asmRegisterRegisterMemory( |
| 6196 | mir_tag, | 6238 | mir_tag, |
| 6197 | dst_alias, | 6239 | dst_reg, |
| 6198 | src1_alias, | 6240 | src1_alias, |
| 6199 | src_mcv.mem(Memory.PtrSize.fromSize(abi_size)), | 6241 | src_mcv.mem(Memory.PtrSize.fromSize(abi_size)), |
| 6200 | ) else try self.asmRegisterRegisterRegister( | 6242 | ) else try self.asmRegisterRegisterRegister( |
| 6201 | mir_tag, | 6243 | mir_tag, |
| 6202 | dst_alias, | 6244 | dst_reg, |
| 6203 | src1_alias, | 6245 | src1_alias, |
| 6204 | registerAlias(if (src_mcv.isRegister()) | 6246 | registerAlias(if (src_mcv.isRegister()) |
| 6205 | src_mcv.getReg().? | 6247 | src_mcv.getReg().? |
| ... | @@ -6210,11 +6252,11 @@ fn genBinOp( | ... | @@ -6210,11 +6252,11 @@ fn genBinOp( |
| 6210 | assert(copied_to_dst); | 6252 | assert(copied_to_dst); |
| 6211 | if (src_mcv.isMemory()) try self.asmRegisterMemory( | 6253 | if (src_mcv.isMemory()) try self.asmRegisterMemory( |
| 6212 | mir_tag, | 6254 | mir_tag, |
| 6213 | dst_alias, | 6255 | dst_reg, |
| 6214 | src_mcv.mem(Memory.PtrSize.fromSize(abi_size)), | 6256 | src_mcv.mem(Memory.PtrSize.fromSize(abi_size)), |
| 6215 | ) else try self.asmRegisterRegister( | 6257 | ) else try self.asmRegisterRegister( |
| 6216 | mir_tag, | 6258 | mir_tag, |
| 6217 | dst_alias, | 6259 | dst_reg, |
| 6218 | registerAlias(if (src_mcv.isRegister()) | 6260 | registerAlias(if (src_mcv.isRegister()) |
| 6219 | src_mcv.getReg().? | 6261 | src_mcv.getReg().? |
| 6220 | else | 6262 | else |
| ... | @@ -6223,60 +6265,16 @@ fn genBinOp( | ... | @@ -6223,60 +6265,16 @@ fn genBinOp( |
| 6223 | } | 6265 | } |
| 6224 | switch (air_tag) { | 6266 | switch (air_tag) { |
| 6225 | .add, .sub, .mul, .div_float, .div_exact => {}, | 6267 | .add, .sub, .mul, .div_float, .div_exact => {}, |
| 6226 | .div_trunc, .div_floor => if (self.hasFeature(.sse4_1)) { | 6268 | .div_trunc, .div_floor => try self.genRound( |
| 6227 | const round_tag = if (@as(?Mir.Inst.Tag, switch (lhs_ty.zigTypeTag()) { | 6269 | lhs_ty, |
| 6228 | .Float => switch (lhs_ty.floatBits(self.target.*)) { | 6270 | dst_reg, |
| 6229 | 32 => if (self.hasFeature(.avx)) .vroundss else .roundss, | 6271 | .{ .register = dst_reg }, |
| 6230 | 64 => if (self.hasFeature(.avx)) .vroundsd else .roundsd, | 6272 | switch (air_tag) { |
| 6231 | 16, 80, 128 => null, | | |
| 6232 | else => unreachable, | | |
| 6233 | }, | | |
| 6234 | .Vector => switch (lhs_ty.childType().zigTypeTag()) { | | |
| 6235 | .Float => switch (lhs_ty.childType().floatBits(self.target.*)) { | | |
| 6236 | 32 => switch (lhs_ty.vectorLen()) { | | |
| 6237 | 1 => if (self.hasFeature(.avx)) .vroundss else .roundss, | | |
| 6238 | 2...4 => if (self.hasFeature(.avx)) .vroundps else .roundps, | | |
| 6239 | 5...8 => if (self.hasFeature(.avx)) .vroundps else null, | | |
| 6240 | else => null, | | |
| 6241 | }, | | |
| 6242 | 64 => switch (lhs_ty.vectorLen()) { | | |
| 6243 | 1 => if (self.hasFeature(.avx)) .vroundsd else .roundsd, | | |
| 6244 | 2 => if (self.hasFeature(.avx)) .vroundpd else .roundpd, | | |
| 6245 | 3...4 => if (self.hasFeature(.avx)) .vroundpd else null, | | |
| 6246 | else => null, | | |
| 6247 | }, | | |
| 6248 | 16, 80, 128 => null, | | |
| 6249 | else => unreachable, | | |
| 6250 | }, | | |
| 6251 | else => null, | | |
| 6252 | }, | | |
| 6253 | else => unreachable, | | |
| 6254 | })) |tag| tag else return self.fail("TODO implement genBinOp for {s} {}", .{ | | |
| 6255 | @tagName(air_tag), lhs_ty.fmt(self.bin_file.options.module.?), | | |
| 6256 | }); | | |
| 6257 | const round_mode = Immediate.u(switch (air_tag) { | | |
| 6258 | .div_trunc => 0b1_0_11, | 6273 | .div_trunc => 0b1_0_11, |
| 6259 | .div_floor => 0b1_0_01, | 6274 | .div_floor => 0b1_0_01, |
| 6260 | else => unreachable, | 6275 | else => unreachable, |
| 6261 | }); | 6276 | }, |
| 6262 | switch (round_tag) { | 6277 | ), |
| 6263 | .vroundss, .vroundsd => try self.asmRegisterRegisterRegisterImmediate( | | |
| 6264 | round_tag, | | |
| 6265 | dst_alias, | | |
| 6266 | dst_alias, | | |
| 6267 | dst_alias, | | |
| 6268 | round_mode, | | |
| 6269 | ), | | |
| 6270 | else => try self.asmRegisterRegisterImmediate( | | |
| 6271 | round_tag, | | |
| 6272 | dst_alias, | | |
| 6273 | dst_alias, | | |
| 6274 | round_mode, | | |
| 6275 | ), | | |
| 6276 | } | | |
| 6277 | } else return self.fail("TODO implement genBinOp for {s} {} without sse4_1", .{ | | |
| 6278 | @tagName(air_tag), lhs_ty.fmt(self.bin_file.options.module.?), | | |
| 6279 | }), | | |
| 6280 | .max, .min => {}, // TODO: unordered select | 6278 | .max, .min => {}, // TODO: unordered select |
| 6281 | else => unreachable, | 6279 | else => unreachable, |
| 6282 | } | 6280 | } |