authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-08-05 19:59:26+02:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-08-05 20:30:52+02:00
logf46c80b267396d02b5008bf8c426e0eb886a05d2
tree07ebb514a1a7edcc37ff583f6220077038e80466
parent508b90fcfa4749b50618f947e2c3573edcf29713
signaturelock-open Commit is signed but in an unrecognized format.

stage2 AArch64: improve correctness of register aliases

Also implements ptr_elem_ptr

1 files changed, 69 insertions(+), 14 deletions(-)

src/arch/aarch64/CodeGen.zig+69-14
...@@ -1314,6 +1314,9 @@ fn binOpRegister(...@@ -1314,6 +1314,9 @@ fn binOpRegister(
1314 const lhs_is_register = lhs == .register;1314 const lhs_is_register = lhs == .register;
1315 const rhs_is_register = rhs == .register;1315 const rhs_is_register = rhs == .register;
13161316
1317 if (lhs_is_register) assert(lhs.register == registerAlias(lhs.register, lhs_ty.abiSize(self.target.*)));
1318 if (rhs_is_register) assert(rhs.register == registerAlias(rhs.register, rhs_ty.abiSize(self.target.*)));
1319
1317 const lhs_lock: ?RegisterLock = if (lhs_is_register)1320 const lhs_lock: ?RegisterLock = if (lhs_is_register)
1318 self.register_manager.lockReg(lhs.register)1321 self.register_manager.lockReg(lhs.register)
1319 else1322 else
...@@ -1343,13 +1346,22 @@ fn binOpRegister(...@@ -1343,13 +1346,22 @@ fn binOpRegister(
1343 const new_lhs_lock = self.register_manager.lockReg(lhs_reg);1346 const new_lhs_lock = self.register_manager.lockReg(lhs_reg);
1344 defer if (new_lhs_lock) |reg| self.register_manager.unlockReg(reg);1347 defer if (new_lhs_lock) |reg| self.register_manager.unlockReg(reg);
13451348
1346 const rhs_reg = if (rhs_is_register) rhs.register else blk: {1349 const rhs_reg = if (rhs_is_register)
1350 // lhs is almost always equal to rhs, except in shifts. In
1351 // order to guarantee that registers will have equal sizes, we
1352 // use the register alias of rhs corresponding to the size of
1353 // lhs.
1354 registerAlias(rhs.register, lhs_ty.abiSize(self.target.*))
1355 else blk: {
1347 const track_inst: ?Air.Inst.Index = if (metadata) |md| inst: {1356 const track_inst: ?Air.Inst.Index = if (metadata) |md| inst: {
1348 break :inst Air.refToIndex(md.rhs).?;1357 break :inst Air.refToIndex(md.rhs).?;
1349 } else null;1358 } else null;
13501359
1351 const raw_reg = try self.register_manager.allocReg(track_inst, gp);1360 const raw_reg = try self.register_manager.allocReg(track_inst, gp);
1352 const reg = registerAlias(raw_reg, rhs_ty.abiAlignment(self.target.*));1361
1362 // Here, we deliberately use lhs as lhs and rhs may differ in
1363 // the case of shifts. See comment above.
1364 const reg = registerAlias(raw_reg, lhs_ty.abiSize(self.target.*));
13531365
1354 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });1366 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
13551367
...@@ -1458,6 +1470,8 @@ fn binOpImmediate(...@@ -1458,6 +1470,8 @@ fn binOpImmediate(
1458) !MCValue {1470) !MCValue {
1459 const lhs_is_register = lhs == .register;1471 const lhs_is_register = lhs == .register;
14601472
1473 if (lhs_is_register) assert(lhs.register == registerAlias(lhs.register, lhs_ty.abiSize(self.target.*)));
1474
1461 const lhs_lock: ?RegisterLock = if (lhs_is_register)1475 const lhs_lock: ?RegisterLock = if (lhs_is_register)
1462 self.register_manager.lockReg(lhs.register)1476 self.register_manager.lockReg(lhs.register)
1463 else1477 else
...@@ -1698,21 +1712,52 @@ fn binOp(...@@ -1698,21 +1712,52 @@ fn binOp(
1698 null;1712 null;
1699 defer if (lhs_lock) |reg| self.register_manager.unlockReg(reg);1713 defer if (lhs_lock) |reg| self.register_manager.unlockReg(reg);
17001714
1701 const lhs_reg = if (lhs_is_register)1715 const rhs_lock: ?RegisterLock = if (rhs_is_register)
1702 lhs.register1716 self.register_manager.lockReg(rhs.register)
1703 else1717 else
1704 try self.register_manager.allocReg(null, gp);1718 null;
1719 defer if (rhs_lock) |reg| self.register_manager.unlockReg(reg);
1720
1721 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
1722
1723 const lhs_reg = if (lhs_is_register) lhs.register else blk: {
1724 const track_inst: ?Air.Inst.Index = if (metadata) |md| inst: {
1725 break :inst Air.refToIndex(md.lhs).?;
1726 } else null;
1727
1728 const raw_reg = try self.register_manager.allocReg(track_inst, gp);
1729 const reg = registerAlias(raw_reg, lhs_ty.abiSize(self.target.*));
1730
1731 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
1732
1733 break :blk reg;
1734 };
1705 const new_lhs_lock = self.register_manager.lockReg(lhs_reg);1735 const new_lhs_lock = self.register_manager.lockReg(lhs_reg);
1706 defer if (new_lhs_lock) |reg| self.register_manager.unlockReg(reg);1736 defer if (new_lhs_lock) |reg| self.register_manager.unlockReg(reg);
17071737
1708 const rhs_reg = if (rhs_is_register)1738 const rhs_reg = if (rhs_is_register) rhs.register else blk: {
1709 rhs.register1739 const track_inst: ?Air.Inst.Index = if (metadata) |md| inst: {
1710 else1740 break :inst Air.refToIndex(md.rhs).?;
1711 try self.register_manager.allocReg(null, gp);1741 } else null;
1742
1743 const raw_reg = try self.register_manager.allocReg(track_inst, gp);
1744 const reg = registerAlias(raw_reg, rhs_ty.abiAlignment(self.target.*));
1745
1746 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
1747
1748 break :blk reg;
1749 };
1712 const new_rhs_lock = self.register_manager.lockReg(rhs_reg);1750 const new_rhs_lock = self.register_manager.lockReg(rhs_reg);
1713 defer if (new_rhs_lock) |reg| self.register_manager.unlockReg(reg);1751 defer if (new_rhs_lock) |reg| self.register_manager.unlockReg(reg);
17141752
1715 const dest_regs = try self.register_manager.allocRegs(2, .{ null, null }, gp);1753 const dest_regs: [2]Register = blk: {
1754 const raw_regs = try self.register_manager.allocRegs(2, .{ null, null }, gp);
1755 const abi_size = lhs_ty.abiSize(self.target.*);
1756 break :blk .{
1757 registerAlias(raw_regs[0], abi_size),
1758 registerAlias(raw_regs[1], abi_size),
1759 };
1760 };
1716 const dest_regs_locks = self.register_manager.lockRegsAssumeUnused(2, dest_regs);1761 const dest_regs_locks = self.register_manager.lockRegsAssumeUnused(2, dest_regs);
1717 defer for (dest_regs_locks) |reg| {1762 defer for (dest_regs_locks) |reg| {
1718 self.register_manager.unlockReg(reg);1763 self.register_manager.unlockReg(reg);
...@@ -2037,7 +2082,7 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -2037,7 +2082,7 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {
2037 try self.truncRegister(dest_reg, truncated_reg, int_info.signedness, int_info.bits);2082 try self.truncRegister(dest_reg, truncated_reg, int_info.signedness, int_info.bits);
20382083
2039 // cmp dest, truncated2084 // cmp dest, truncated
2040 _ = try self.binOp(.cmp_eq, dest, .{ .register = truncated_reg }, Type.usize, Type.usize, null);2085 _ = try self.binOp(.cmp_eq, dest, .{ .register = truncated_reg }, lhs_ty, lhs_ty, null);
20412086
2042 try self.genSetStack(lhs_ty, stack_offset, .{ .register = truncated_reg });2087 try self.genSetStack(lhs_ty, stack_offset, .{ .register = truncated_reg });
2043 try self.genSetStack(Type.initTag(.u1), stack_offset - overflow_bit_offset, .{ .condition_flags = .ne });2088 try self.genSetStack(Type.initTag(.u1), stack_offset - overflow_bit_offset, .{ .condition_flags = .ne });
...@@ -2753,7 +2798,15 @@ fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -2753,7 +2798,15 @@ fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void {
2753fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void {2798fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void {
2754 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;2799 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
2755 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;2800 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
2756 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement ptr_elem_ptr for {}", .{self.target.cpu.arch});2801 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2802 const ptr_mcv = try self.resolveInst(extra.lhs);
2803 const index_mcv = try self.resolveInst(extra.rhs);
2804
2805 const ptr_ty = self.air.typeOf(extra.lhs);
2806
2807 const addr = try self.binOp(.ptr_add, ptr_mcv, index_mcv, ptr_ty, Type.usize, null);
2808 break :result addr;
2809 };
2757 return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });2810 return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });
2758}2811}
27592812
...@@ -3219,6 +3272,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -3219,6 +3272,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
3219 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {3272 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
3220 const mcv = try self.resolveInst(operand);3273 const mcv = try self.resolveInst(operand);
3221 const struct_ty = self.air.typeOf(operand);3274 const struct_ty = self.air.typeOf(operand);
3275 const struct_field_ty = struct_ty.structFieldType(index);
3222 const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, self.target.*));3276 const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, self.target.*));
32233277
3224 switch (mcv) {3278 switch (mcv) {
...@@ -3250,8 +3304,9 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -3250,8 +3304,9 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
3250 break :result field;3304 break :result field;
3251 } else {3305 } else {
3252 // Copy to new register3306 // Copy to new register
3253 const dest_reg = try self.register_manager.allocReg(null, gp);3307 const raw_dest_reg = try self.register_manager.allocReg(null, gp);
3254 try self.genSetReg(struct_ty.structFieldType(index), dest_reg, field);3308 const dest_reg = registerAlias(raw_dest_reg, struct_field_ty.abiSize(self.target.*));
3309 try self.genSetReg(struct_field_ty, dest_reg, field);
32553310
3256 break :result MCValue{ .register = dest_reg };3311 break :result MCValue{ .register = dest_reg };
3257 }3312 }