authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-03-27 04:05:19-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-03-27 05:58:00-04:00
log6c5442841565196ddeb90735496aad04db3ecdfd
tree1341d3296e497ef8f692d4f0b1a8da8bd083b530
parent587eacefec7d00c60cb32a10f7084dd7e61a970a

x86_64: implement trunc with large source


1 files changed, 32 insertions(+), 46 deletions(-)

src/arch/x86_64/CodeGen.zig+32-46
......@@ -1549,43 +1549,31 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
15491549
15501550fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {
15511551 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1552 if (self.liveness.isUnused(inst))
1553 return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none });
1554
1555 const src_ty = self.air.typeOf(ty_op.operand);
1556 const dst_ty = self.air.typeOfIndex(inst);
1557 const operand = try self.resolveInst(ty_op.operand);
1558
1559 const src_ty_size = src_ty.abiSize(self.target.*);
1560 const dst_ty_size = dst_ty.abiSize(self.target.*);
1552 const result = if (self.liveness.isUnused(inst)) .dead else result: {
1553 const dst_ty = self.air.typeOfIndex(inst);
1554 const dst_abi_size = dst_ty.abiSize(self.target.*);
1555 if (dst_abi_size > 8) {
1556 return self.fail("TODO implement trunc for abi sizes larger than 8", .{});
1557 }
15611558
1562 if (src_ty_size > 8 or dst_ty_size > 8) {
1563 return self.fail("TODO implement trunc for abi sizes larger than 8", .{});
1564 }
1559 const src_mcv = try self.resolveInst(ty_op.operand);
1560 const src_lock = switch (src_mcv) {
1561 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
1562 else => null,
1563 };
1564 defer if (src_lock) |lock| self.register_manager.unlockReg(lock);
15651565
1566 const operand_lock: ?RegisterLock = switch (operand) {
1567 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
1568 else => null,
1569 };
1570 defer if (operand_lock) |lock| self.register_manager.unlockReg(lock);
1566 const dst_mcv = if (src_mcv.isRegister() and self.reuseOperand(inst, ty_op.operand, 0, src_mcv))
1567 src_mcv
1568 else
1569 try self.copyToRegisterWithInstTracking(inst, dst_ty, src_mcv);
15711570
1572 const reg: Register = blk: {
1573 if (operand.isRegister()) {
1574 if (self.reuseOperand(inst, ty_op.operand, 0, operand)) {
1575 break :blk operand.register.to64();
1576 }
1577 }
1578 const mcv = try self.copyToRegisterWithInstTracking(inst, src_ty, operand);
1579 break :blk mcv.register.to64();
1571 // when truncating a `u16` to `u5`, for example, those top 3 bits in the result
1572 // have to be removed. this only happens if the dst if not a power-of-two size.
1573 if (self.regExtraBits(dst_ty) > 0) try self.truncateRegister(dst_ty, dst_mcv.register.to64());
1574 break :result dst_mcv;
15801575 };
1581
1582 // when truncating a `u16` to `u5`, for example, those top 3 bits in the result
1583 // have to be removed. this only happens if the dst if not a power-of-two size.
1584 if (self.regExtraBits(dst_ty) > 0) {
1585 try self.truncateRegister(dst_ty, reg);
1586 }
1587
1588 return self.finishAir(inst, .{ .register = reg }, .{ ty_op.operand, .none, .none });
1576 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
15891577}
15901578
15911579fn airBoolToInt(self: *Self, inst: Air.Inst.Index) !void {
......@@ -3499,23 +3487,21 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
34993487 const elem_ty = self.air.typeOfIndex(inst);
35003488 const elem_size = elem_ty.abiSize(self.target.*);
35013489 const result: MCValue = result: {
3502 if (!elem_ty.hasRuntimeBitsIgnoreComptime())
3503 break :result MCValue.none;
3490 if (!elem_ty.hasRuntimeBitsIgnoreComptime()) break :result .none;
3491
3492 try self.spillRegisters(&.{ .rdi, .rsi, .rcx });
3493 const reg_locks = self.register_manager.lockRegsAssumeUnused(3, .{ .rdi, .rsi, .rcx });
3494 defer for (reg_locks) |lock| self.register_manager.unlockReg(lock);
35043495
35053496 const ptr = try self.resolveInst(ty_op.operand);
35063497 const is_volatile = self.air.typeOf(ty_op.operand).isVolatilePtr();
3507 if (self.liveness.isUnused(inst) and !is_volatile)
3508 break :result MCValue.dead;
3498 if (self.liveness.isUnused(inst) and !is_volatile) break :result .dead;
35093499
3510 const dst_mcv: MCValue = blk: {
3511 if (elem_size <= 8 and self.reuseOperand(inst, ty_op.operand, 0, ptr)) {
3512 // The MCValue that holds the pointer can be re-used as the value.
3513 break :blk ptr;
3514 } else {
3515 break :blk try self.allocRegOrMem(inst, true);
3516 }
3517 };
3518 log.debug("airLoad(%{d}): {} <- {}", .{ inst, dst_mcv, ptr });
3500 const dst_mcv: MCValue = if (elem_size <= 8 and self.reuseOperand(inst, ty_op.operand, 0, ptr))
3501 // The MCValue that holds the pointer can be re-used as the value.
3502 ptr
3503 else
3504 try self.allocRegOrMem(inst, true);
35193505 try self.load(dst_mcv, ptr, self.air.typeOf(ty_op.operand));
35203506 break :result dst_mcv;
35213507 };