| ... | ... | @@ -1587,9 +1587,9 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 1587 | 1587 | .round, |
| 1588 | 1588 | => try self.airUnaryMath(inst), |
| 1589 | 1589 | |
| 1590 | | .floor => try self.airRound(inst, Immediate.u(0b1_0_01)), |
| 1591 | | .ceil => try self.airRound(inst, Immediate.u(0b1_0_10)), |
| 1592 | | .trunc_float => try self.airRound(inst, Immediate.u(0b1_0_11)), |
| 1590 | .floor => try self.airRound(inst, 0b1_0_01), |
| 1591 | .ceil => try self.airRound(inst, 0b1_0_10), |
| 1592 | .trunc_float => try self.airRound(inst, 0b1_0_11), |
| 1593 | 1593 | .sqrt => try self.airSqrt(inst), |
| 1594 | 1594 | .neg, .fabs => try self.airFloatSign(inst), |
| 1595 | 1595 | |
| ... | ... | @@ -4509,49 +4509,91 @@ fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void { |
| 4509 | 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 | 4513 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 4514 | 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 | 4516 | const src_mcv = try self.resolveInst(un_op); |
| 4520 | 4517 | const dst_mcv = if (src_mcv.isRegister() and self.reuseOperand(inst, un_op, 0, src_mcv)) |
| 4521 | 4518 | src_mcv |
| 4522 | 4519 | else |
| 4523 | 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 | 4533 | .Float => switch (ty.floatBits(self.target.*)) { |
| 4527 | | 32 => .roundss, |
| 4528 | | 64 => .roundsd, |
| 4529 | | else => return self.fail("TODO implement airRound for {}", .{ |
| 4530 | | ty.fmt(self.bin_file.options.module.?), |
| 4531 | | }), |
| 4534 | 32 => if (self.hasFeature(.avx)) .vroundss else .roundss, |
| 4535 | 64 => if (self.hasFeature(.avx)) .vroundsd else .roundsd, |
| 4536 | 16, 80, 128 => null, |
| 4537 | else => unreachable, |
| 4532 | 4538 | }, |
| 4533 | | else => return self.fail("TODO implement airRound for {}", .{ |
| 4534 | | ty.fmt(self.bin_file.options.module.?), |
| 4535 | | }), |
| 4536 | | }; |
| 4537 | | assert(dst_mcv.isRegister()); |
| 4539 | .Vector => switch (ty.childType().zigTypeTag()) { |
| 4540 | .Float => switch (ty.childType().floatBits(self.target.*)) { |
| 4541 | 32 => switch (ty.vectorLen()) { |
| 4542 | 1 => if (self.hasFeature(.avx)) .vroundss else .roundss, |
| 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 | 4563 | const abi_size = @intCast(u32, ty.abiSize(self.target.*)); |
| 4539 | | const dst_reg = registerAlias(dst_mcv.getReg().?, abi_size); |
| 4540 | | if (src_mcv.isRegister()) |
| 4541 | | try self.asmRegisterRegisterImmediate( |
| 4564 | const dst_alias = registerAlias(dst_reg, abi_size); |
| 4565 | switch (mir_tag) { |
| 4566 | .vroundss, .vroundsd => if (src_mcv.isMemory()) try self.asmRegisterRegisterMemoryImmediate( |
| 4542 | 4567 | mir_tag, |
| 4543 | | dst_reg, |
| 4544 | | registerAlias(src_mcv.getReg().?, abi_size), |
| 4545 | | mode, |
| 4546 | | ) |
| 4547 | | else |
| 4548 | | try self.asmRegisterMemoryImmediate( |
| 4568 | dst_alias, |
| 4569 | dst_alias, |
| 4570 | src_mcv.mem(Memory.PtrSize.fromSize(abi_size)), |
| 4571 | Immediate.u(mode), |
| 4572 | ) else try self.asmRegisterRegisterRegisterImmediate( |
| 4549 | 4573 | mir_tag, |
| 4550 | | dst_reg, |
| 4551 | | src_mcv.mem(Memory.PtrSize.fromSize(@intCast(u32, ty.abiSize(self.target.*)))), |
| 4552 | | mode, |
| 4553 | | ); |
| 4554 | | return self.finishAir(inst, dst_mcv, .{ un_op, .none, .none }); |
| 4574 | dst_alias, |
| 4575 | dst_alias, |
| 4576 | registerAlias(if (src_mcv.isRegister()) |
| 4577 | src_mcv.getReg().? |
| 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 | 4599 | fn airSqrt(self: *Self, inst: Air.Inst.Index) !void { |
| ... | ... | @@ -6188,18 +6230,18 @@ fn genBinOp( |
| 6188 | 6230 | })) |tag| tag else return self.fail("TODO implement genBinOp for {s} {}", .{ |
| 6189 | 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 | 6234 | if (self.hasFeature(.avx)) { |
| 6193 | 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 | 6237 | if (src_mcv.isMemory()) try self.asmRegisterRegisterMemory( |
| 6196 | 6238 | mir_tag, |
| 6197 | | dst_alias, |
| 6239 | dst_reg, |
| 6198 | 6240 | src1_alias, |
| 6199 | 6241 | src_mcv.mem(Memory.PtrSize.fromSize(abi_size)), |
| 6200 | 6242 | ) else try self.asmRegisterRegisterRegister( |
| 6201 | 6243 | mir_tag, |
| 6202 | | dst_alias, |
| 6244 | dst_reg, |
| 6203 | 6245 | src1_alias, |
| 6204 | 6246 | registerAlias(if (src_mcv.isRegister()) |
| 6205 | 6247 | src_mcv.getReg().? |
| ... | ... | @@ -6210,11 +6252,11 @@ fn genBinOp( |
| 6210 | 6252 | assert(copied_to_dst); |
| 6211 | 6253 | if (src_mcv.isMemory()) try self.asmRegisterMemory( |
| 6212 | 6254 | mir_tag, |
| 6213 | | dst_alias, |
| 6255 | dst_reg, |
| 6214 | 6256 | src_mcv.mem(Memory.PtrSize.fromSize(abi_size)), |
| 6215 | 6257 | ) else try self.asmRegisterRegister( |
| 6216 | 6258 | mir_tag, |
| 6217 | | dst_alias, |
| 6259 | dst_reg, |
| 6218 | 6260 | registerAlias(if (src_mcv.isRegister()) |
| 6219 | 6261 | src_mcv.getReg().? |
| 6220 | 6262 | else |
| ... | ... | @@ -6223,60 +6265,16 @@ fn genBinOp( |
| 6223 | 6265 | } |
| 6224 | 6266 | switch (air_tag) { |
| 6225 | 6267 | .add, .sub, .mul, .div_float, .div_exact => {}, |
| 6226 | | .div_trunc, .div_floor => if (self.hasFeature(.sse4_1)) { |
| 6227 | | const round_tag = if (@as(?Mir.Inst.Tag, switch (lhs_ty.zigTypeTag()) { |
| 6228 | | .Float => switch (lhs_ty.floatBits(self.target.*)) { |
| 6229 | | 32 => if (self.hasFeature(.avx)) .vroundss else .roundss, |
| 6230 | | 64 => if (self.hasFeature(.avx)) .vroundsd else .roundsd, |
| 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) { |
| 6268 | .div_trunc, .div_floor => try self.genRound( |
| 6269 | lhs_ty, |
| 6270 | dst_reg, |
| 6271 | .{ .register = dst_reg }, |
| 6272 | switch (air_tag) { |
| 6258 | 6273 | .div_trunc => 0b1_0_11, |
| 6259 | 6274 | .div_floor => 0b1_0_01, |
| 6260 | 6275 | else => unreachable, |
| 6261 | | }); |
| 6262 | | switch (round_tag) { |
| 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 | | }), |
| 6276 | }, |
| 6277 | ), |
| 6280 | 6278 | .max, .min => {}, // TODO: unordered select |
| 6281 | 6279 | else => unreachable, |
| 6282 | 6280 | } |