authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-08-20 22:29:52+02:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-09-09 19:17:17+02:00
log86dd123392c8ab26432303ff2e5c96e73d747757
treede76d70e13c092b38951053d2206b22cfbf4c9b8
parent0414ef591a0cb42629d7efb5912612f689ea8910
signature Commit is signed but in an unrecognized format.

stage2 ARM: move cmp to new allocReg mechanism; remove from binOp


1 files changed, 181 insertions(+), 89 deletions(-)

src/arch/arm/CodeGen.zig+181-89
......@@ -1315,7 +1315,13 @@ fn minMax(
13151315 // register.
13161316 assert(lhs_reg != rhs_reg); // see note above
13171317
1318 _ = try self.binOpRegister(.cmp, .{ .register = lhs_reg }, .{ .register = rhs_reg }, lhs_ty, rhs_ty, null);
1318 _ = try self.addInst(.{
1319 .tag = .cmp,
1320 .data = .{ .r_op_cmp = .{
1321 .rn = lhs_reg,
1322 .op = Instruction.Operand.reg(rhs_reg, Instruction.Operand.Shift.none),
1323 } },
1324 });
13191325
13201326 const cond_choose_lhs: Condition = switch (tag) {
13211327 .max => switch (int_info.signedness) {
......@@ -1473,7 +1479,6 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {
14731479 const stack_offset = try self.allocMem(inst, tuple_size, tuple_align);
14741480
14751481 try self.spillCompareFlagsIfOccupied();
1476 self.cpsr_flags_inst = null;
14771482
14781483 const base_tag: Air.Inst.Tag = switch (tag) {
14791484 .add_with_overflow => .add,
......@@ -1493,7 +1498,13 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {
14931498 try self.truncRegister(dest_reg, truncated_reg, int_info.signedness, int_info.bits);
14941499
14951500 // cmp dest, truncated
1496 _ = try self.binOp(.cmp_eq, dest, .{ .register = truncated_reg }, Type.usize, Type.usize, null);
1501 _ = try self.addInst(.{
1502 .tag = .cmp,
1503 .data = .{ .r_op_cmp = .{
1504 .rn = dest_reg,
1505 .op = Instruction.Operand.reg(truncated_reg, Instruction.Operand.Shift.none),
1506 } },
1507 });
14971508
14981509 try self.genSetStack(lhs_ty, stack_offset, .{ .register = truncated_reg });
14991510 try self.genSetStack(Type.initTag(.u1), stack_offset - overflow_bit_offset, .{ .cpsr_flags = .ne });
......@@ -1578,7 +1589,6 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
15781589 const stack_offset = try self.allocMem(inst, tuple_size, tuple_align);
15791590
15801591 try self.spillCompareFlagsIfOccupied();
1581 self.cpsr_flags_inst = null;
15821592
15831593 const base_tag: Mir.Inst.Tag = switch (int_info.signedness) {
15841594 .signed => .smulbb,
......@@ -1598,7 +1608,13 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
15981608 try self.truncRegister(dest_reg, truncated_reg, int_info.signedness, int_info.bits);
15991609
16001610 // cmp dest, truncated
1601 _ = try self.binOp(.cmp_eq, dest, .{ .register = truncated_reg }, Type.usize, Type.usize, null);
1611 _ = try self.addInst(.{
1612 .tag = .cmp,
1613 .data = .{ .r_op_cmp = .{
1614 .rn = dest_reg,
1615 .op = Instruction.Operand.reg(truncated_reg, Instruction.Operand.Shift.none),
1616 } },
1617 });
16021618
16031619 try self.genSetStack(lhs_ty, stack_offset, .{ .register = truncated_reg });
16041620 try self.genSetStack(Type.initTag(.u1), stack_offset - overflow_bit_offset, .{ .cpsr_flags = .ne });
......@@ -1608,7 +1624,6 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
16081624 const stack_offset = try self.allocMem(inst, tuple_size, tuple_align);
16091625
16101626 try self.spillCompareFlagsIfOccupied();
1611 self.cpsr_flags_inst = null;
16121627
16131628 const base_tag: Mir.Inst.Tag = switch (int_info.signedness) {
16141629 .signed => .smull,
......@@ -1672,7 +1687,13 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
16721687 try self.genSetStack(lhs_ty, stack_offset, .{ .register = truncated_reg });
16731688
16741689 // cmp truncated, rdlo
1675 _ = try self.binOp(.cmp_eq, .{ .register = truncated_reg }, .{ .register = rdlo }, Type.usize, Type.usize, null);
1690 _ = try self.addInst(.{
1691 .tag = .cmp,
1692 .data = .{ .r_op_cmp = .{
1693 .rn = truncated_reg,
1694 .op = Instruction.Operand.reg(rdlo, Instruction.Operand.Shift.none),
1695 } },
1696 });
16761697
16771698 // mov rdlo, #0
16781699 _ = try self.addInst(.{
......@@ -1694,7 +1715,13 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
16941715 });
16951716
16961717 // cmp rdhi, #0
1697 _ = try self.binOp(.cmp_eq, .{ .register = rdhi }, .{ .immediate = 0 }, Type.usize, Type.usize, null);
1718 _ = try self.addInst(.{
1719 .tag = .cmp,
1720 .data = .{ .r_op_cmp = .{
1721 .rn = rdhi,
1722 .op = Instruction.Operand.fromU32(0).?,
1723 } },
1724 });
16981725
16991726 // movne rdlo, #1
17001727 _ = try self.addInst(.{
......@@ -1725,8 +1752,6 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
17251752 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
17261753 if (self.liveness.isUnused(inst)) return self.finishAir(inst, .dead, .{ extra.lhs, extra.rhs, .none });
17271754 const result: MCValue = result: {
1728 const lhs = try self.resolveInst(extra.lhs);
1729 const rhs = try self.resolveInst(extra.rhs);
17301755 const lhs_ty = self.air.typeOf(extra.lhs);
17311756 const rhs_ty = self.air.typeOf(extra.rhs);
17321757
......@@ -1742,28 +1767,107 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
17421767 if (int_info.bits <= 32) {
17431768 const stack_offset = try self.allocMem(inst, tuple_size, tuple_align);
17441769
1745 const lhs_lock: ?RegisterLock = if (lhs == .register)
1746 self.register_manager.lockRegAssumeUnused(lhs.register)
1747 else
1748 null;
1749 defer if (lhs_lock) |reg| self.register_manager.unlockReg(reg);
1750
17511770 try self.spillCompareFlagsIfOccupied();
1752 self.cpsr_flags_inst = null;
17531771
1754 // lsl dest, lhs, rhs
1755 const dest = try self.binOp(.shl, lhs, rhs, lhs_ty, rhs_ty, null);
1756 const dest_reg = dest.register;
1757 const dest_lock = self.register_manager.lockRegAssumeUnused(dest_reg);
1758 defer self.register_manager.unlockReg(dest_lock);
1772 const shr_mir_tag: Mir.Inst.Tag = switch (int_info.signedness) {
1773 .signed => Mir.Inst.Tag.asr,
1774 .unsigned => Mir.Inst.Tag.lsr,
1775 };
1776
1777 var lhs_reg: Register = undefined;
1778 var rhs_reg: Register = undefined;
1779 var dest_reg: Register = undefined;
1780 var reconstructed_reg: Register = undefined;
1781
1782 const rhs_mcv = try self.resolveInst(extra.rhs);
1783 const rhs_immediate_ok = rhs_mcv == .immediate and Instruction.Operand.fromU32(rhs_mcv.immediate) != null;
1784
1785 const lhs_bind: ReadArg.Bind = .{ .inst = extra.lhs };
1786 const rhs_bind: ReadArg.Bind = .{ .inst = extra.rhs };
1787
1788 if (rhs_immediate_ok) {
1789 const read_args = [_]ReadArg{
1790 .{ .ty = lhs_ty, .bind = lhs_bind, .class = gp, .reg = &lhs_reg },
1791 };
1792 const write_args = [_]WriteArg{
1793 .{ .ty = lhs_ty, .bind = .none, .class = gp, .reg = &dest_reg },
1794 .{ .ty = lhs_ty, .bind = .none, .class = gp, .reg = &reconstructed_reg },
1795 };
1796 try self.allocRegs(
1797 &read_args,
1798 &write_args,
1799 null,
1800 );
1801
1802 // lsl dest, lhs, rhs
1803 _ = try self.addInst(.{
1804 .tag = .lsl,
1805 .data = .{ .rr_shift = .{
1806 .rd = dest_reg,
1807 .rm = lhs_reg,
1808 .shift_amount = Instruction.ShiftAmount.imm(@intCast(u5, rhs_mcv.immediate)),
1809 } },
1810 });
17591811
1760 // asr/lsr reconstructed, dest, rhs
1761 const reconstructed = try self.binOp(.shr, dest, rhs, lhs_ty, rhs_ty, null);
1812 try self.truncRegister(dest_reg, dest_reg, int_info.signedness, int_info.bits);
1813
1814 // asr/lsr reconstructed, dest, rhs
1815 _ = try self.addInst(.{
1816 .tag = shr_mir_tag,
1817 .data = .{ .rr_shift = .{
1818 .rd = reconstructed_reg,
1819 .rm = dest_reg,
1820 .shift_amount = Instruction.ShiftAmount.imm(@intCast(u5, rhs_mcv.immediate)),
1821 } },
1822 });
1823 } else {
1824 const read_args = [_]ReadArg{
1825 .{ .ty = lhs_ty, .bind = lhs_bind, .class = gp, .reg = &lhs_reg },
1826 .{ .ty = rhs_ty, .bind = rhs_bind, .class = gp, .reg = &rhs_reg },
1827 };
1828 const write_args = [_]WriteArg{
1829 .{ .ty = lhs_ty, .bind = .none, .class = gp, .reg = &dest_reg },
1830 .{ .ty = lhs_ty, .bind = .none, .class = gp, .reg = &reconstructed_reg },
1831 };
1832 try self.allocRegs(
1833 &read_args,
1834 &write_args,
1835 null,
1836 );
1837
1838 // lsl dest, lhs, rhs
1839 _ = try self.addInst(.{
1840 .tag = .lsl,
1841 .data = .{ .rr_shift = .{
1842 .rd = dest_reg,
1843 .rm = lhs_reg,
1844 .shift_amount = Instruction.ShiftAmount.reg(rhs_reg),
1845 } },
1846 });
1847
1848 try self.truncRegister(dest_reg, dest_reg, int_info.signedness, int_info.bits);
1849
1850 // asr/lsr reconstructed, dest, rhs
1851 _ = try self.addInst(.{
1852 .tag = shr_mir_tag,
1853 .data = .{ .rr_shift = .{
1854 .rd = reconstructed_reg,
1855 .rm = dest_reg,
1856 .shift_amount = Instruction.ShiftAmount.reg(rhs_reg),
1857 } },
1858 });
1859 }
17621860
17631861 // cmp lhs, reconstructed
1764 _ = try self.binOp(.cmp_eq, lhs, reconstructed, lhs_ty, lhs_ty, null);
1862 _ = try self.addInst(.{
1863 .tag = .cmp,
1864 .data = .{ .r_op_cmp = .{
1865 .rn = lhs_reg,
1866 .op = Instruction.Operand.reg(reconstructed_reg, Instruction.Operand.Shift.none),
1867 } },
1868 });
17651869
1766 try self.genSetStack(lhs_ty, stack_offset, dest);
1870 try self.genSetStack(lhs_ty, stack_offset, .{ .register = dest_reg });
17671871 try self.genSetStack(Type.initTag(.u1), stack_offset - overflow_bit_offset, .{ .cpsr_flags = .ne });
17681872
17691873 break :result MCValue{ .stack_offset = stack_offset };
......@@ -2662,8 +2766,8 @@ fn allocRegs(
26622766 write_args: []const WriteArg,
26632767 reuse_metadata: ?ReuseMetadata,
26642768) InnerError!void {
2665 // Air instructions have either one output or none (cmp)
2666 assert(!(reuse_metadata != null and write_args.len > 1)); // see note above
2769 // Air instructions have exactly one output
2770 assert(!(reuse_metadata != null and write_args.len != 1)); // see note above
26672771
26682772 // The operand mapping is a 1:1 mapping of read args to their
26692773 // corresponding operand index in the Air instruction
......@@ -2714,7 +2818,7 @@ fn allocRegs(
27142818 }
27152819 }
27162820
2717 if (reuse_metadata != null and write_args.len > 0) {
2821 if (reuse_metadata != null) {
27182822 const inst = reuse_metadata.?.corresponding_inst;
27192823 const operand_mapping = reuse_metadata.?.operand_mapping;
27202824 const arg = write_args[0];
......@@ -2826,7 +2930,7 @@ fn binOpRegister(
28262930 };
28272931 try self.allocRegs(
28282932 &read_args,
2829 if (mir_tag == .cmp) &.{} else &write_args,
2933 &write_args,
28302934 if (metadata) |md| .{
28312935 .corresponding_inst = md.inst,
28322936 .operand_mapping = &.{ 0, 1 },
......@@ -2846,10 +2950,6 @@ fn binOpRegister(
28462950 .rn = lhs_reg,
28472951 .op = Instruction.Operand.reg(rhs_reg, Instruction.Operand.Shift.none),
28482952 } },
2849 .cmp => .{ .r_op_cmp = .{
2850 .rn = lhs_reg,
2851 .op = Instruction.Operand.reg(rhs_reg, Instruction.Operand.Shift.none),
2852 } },
28532953 .lsl,
28542954 .asr,
28552955 .lsr,
......@@ -2918,7 +3018,7 @@ fn binOpImmediate(
29183018 const operand_mapping: []const Liveness.OperandInt = if (lhs_and_rhs_swapped) &.{1} else &.{0};
29193019 try self.allocRegs(
29203020 &read_args,
2921 if (mir_tag == .cmp) &.{} else &write_args,
3021 &write_args,
29223022 if (metadata) |md| .{
29233023 .corresponding_inst = md.inst,
29243024 .operand_mapping = operand_mapping,
......@@ -2938,10 +3038,6 @@ fn binOpImmediate(
29383038 .rn = lhs_reg,
29393039 .op = Instruction.Operand.fromU32(rhs.immediate).?,
29403040 } },
2941 .cmp => .{ .r_op_cmp = .{
2942 .rn = lhs_reg,
2943 .op = Instruction.Operand.fromU32(rhs.immediate).?,
2944 } },
29453041 .lsl,
29463042 .asr,
29473043 .lsr,
......@@ -2991,7 +3087,6 @@ fn binOp(
29913087 switch (tag) {
29923088 .add,
29933089 .sub,
2994 .cmp_eq,
29953090 => {
29963091 switch (lhs_ty.zigTypeTag()) {
29973092 .Float => return self.fail("TODO ARM binary operations on floats", .{}),
......@@ -3006,15 +3101,12 @@ fn binOp(
30063101 // operands
30073102 const lhs_immediate_ok = switch (tag) {
30083103 .add => lhs == .immediate and Instruction.Operand.fromU32(lhs.immediate) != null,
3009 .sub,
3010 .cmp_eq,
3011 => false,
3104 .sub => false,
30123105 else => unreachable,
30133106 };
30143107 const rhs_immediate_ok = switch (tag) {
30153108 .add,
30163109 .sub,
3017 .cmp_eq,
30183110 => rhs == .immediate and Instruction.Operand.fromU32(rhs.immediate) != null,
30193111 else => unreachable,
30203112 };
......@@ -3022,7 +3114,6 @@ fn binOp(
30223114 const mir_tag: Mir.Inst.Tag = switch (tag) {
30233115 .add => .add,
30243116 .sub => .sub,
3025 .cmp_eq => .cmp,
30263117 else => unreachable,
30273118 };
30283119
......@@ -4005,32 +4096,16 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
40054096 const lhs_ty = self.air.typeOf(bin_op.lhs);
40064097
40074098 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else blk: {
4008 const operands: BinOpOperands = .{ .inst = .{
4009 .inst = inst,
4010 .lhs = bin_op.lhs,
4011 .rhs = bin_op.rhs,
4012 } };
4013 break :blk try self.cmp(operands, lhs_ty, op);
4099 break :blk try self.cmp(.{ .inst = bin_op.lhs }, .{ .inst = bin_op.rhs }, lhs_ty, op);
40144100 };
40154101
40164102 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
40174103}
40184104
4019const BinOpOperands = union(enum) {
4020 inst: struct {
4021 inst: Air.Inst.Index,
4022 lhs: Air.Inst.Ref,
4023 rhs: Air.Inst.Ref,
4024 },
4025 mcv: struct {
4026 lhs: MCValue,
4027 rhs: MCValue,
4028 },
4029};
4030
40314105fn cmp(
40324106 self: *Self,
4033 operands: BinOpOperands,
4107 lhs: ReadArg.Bind,
4108 rhs: ReadArg.Bind,
40344109 lhs_ty: Type,
40354110 op: math.CompareOperator,
40364111) !MCValue {
......@@ -4060,22 +4135,47 @@ fn cmp(
40604135 if (int_info.bits <= 32) {
40614136 try self.spillCompareFlagsIfOccupied();
40624137
4063 switch (operands) {
4064 .inst => |inst_op| {
4065 const metadata: BinOpMetadata = .{
4066 .inst = inst_op.inst,
4067 .lhs = inst_op.lhs,
4068 .rhs = inst_op.rhs,
4069 };
4070 const lhs = try self.resolveInst(inst_op.lhs);
4071 const rhs = try self.resolveInst(inst_op.rhs);
4138 var lhs_reg: Register = undefined;
4139 var rhs_reg: Register = undefined;
40724140
4073 self.cpsr_flags_inst = inst_op.inst;
4074 _ = try self.binOp(.cmp_eq, lhs, rhs, int_ty, int_ty, metadata);
4075 },
4076 .mcv => |mcv_op| {
4077 _ = try self.binOp(.cmp_eq, mcv_op.lhs, mcv_op.rhs, int_ty, int_ty, null);
4078 },
4141 const rhs_mcv = try rhs.resolveToMcv(self);
4142 const rhs_immediate_ok = rhs_mcv == .immediate and Instruction.Operand.fromU32(rhs_mcv.immediate) != null;
4143
4144 if (rhs_immediate_ok) {
4145 const read_args = [_]ReadArg{
4146 .{ .ty = int_ty, .bind = lhs, .class = gp, .reg = &lhs_reg },
4147 };
4148 try self.allocRegs(
4149 &read_args,
4150 &.{},
4151 null, // we won't be able to reuse a register as there are no write_regs
4152 );
4153
4154 _ = try self.addInst(.{
4155 .tag = .cmp,
4156 .data = .{ .r_op_cmp = .{
4157 .rn = lhs_reg,
4158 .op = Instruction.Operand.fromU32(rhs_mcv.immediate).?,
4159 } },
4160 });
4161 } else {
4162 const read_args = [_]ReadArg{
4163 .{ .ty = int_ty, .bind = lhs, .class = gp, .reg = &lhs_reg },
4164 .{ .ty = int_ty, .bind = rhs, .class = gp, .reg = &rhs_reg },
4165 };
4166 try self.allocRegs(
4167 &read_args,
4168 &.{},
4169 null, // we won't be able to reuse a register as there are no write_regs
4170 );
4171
4172 _ = try self.addInst(.{
4173 .tag = .cmp,
4174 .data = .{ .r_op_cmp = .{
4175 .rn = lhs_reg,
4176 .op = Instruction.Operand.reg(rhs_reg, Instruction.Operand.Shift.none),
4177 } },
4178 });
40794179 }
40804180
40814181 return switch (int_info.signedness) {
......@@ -4349,14 +4449,13 @@ fn isNonNull(self: *Self, ty: Type, operand: MCValue) !MCValue {
43494449
43504450fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue {
43514451 const error_type = ty.errorUnionSet();
4352 const error_int_type = Type.initTag(.u16);
43534452
43544453 if (error_type.errorSetIsEmpty()) {
43554454 return MCValue{ .immediate = 0 }; // always false
43564455 }
43574456
43584457 const error_mcv = try self.errUnionErr(operand, ty);
4359 _ = try self.binOp(.cmp_eq, error_mcv, .{ .immediate = 0 }, error_int_type, error_int_type, null);
4458 _ = try self.cmp(.{ .mcv = error_mcv }, .{ .mcv = .{ .immediate = 0 } }, error_type, .neq);
43604459 return MCValue{ .cpsr_flags = .hi };
43614460}
43624461
......@@ -4587,14 +4686,7 @@ fn airSwitch(self: *Self, inst: Air.Inst.Index) !void {
45874686 defer self.gpa.free(branch_into_prong_relocs);
45884687
45894688 for (items) |item, idx| {
4590 const condition = try self.resolveInst(pl_op.operand);
4591 const item_mcv = try self.resolveInst(item);
4592
4593 const operands: BinOpOperands = .{ .mcv = .{
4594 .lhs = condition,
4595 .rhs = item_mcv,
4596 } };
4597 const cmp_result = try self.cmp(operands, condition_ty, .neq);
4689 const cmp_result = try self.cmp(.{ .inst = pl_op.operand }, .{ .inst = item }, condition_ty, .neq);
45984690 branch_into_prong_relocs[idx] = try self.condBr(cmp_result);
45994691 }
46004692