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(...@@ -1315,7 +1315,13 @@ fn minMax(
1315 // register.1315 // register.
1316 assert(lhs_reg != rhs_reg); // see note above1316 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
1320 const cond_choose_lhs: Condition = switch (tag) {1326 const cond_choose_lhs: Condition = switch (tag) {
1321 .max => switch (int_info.signedness) {1327 .max => switch (int_info.signedness) {
...@@ -1473,7 +1479,6 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1473,7 +1479,6 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {
1473 const stack_offset = try self.allocMem(inst, tuple_size, tuple_align);1479 const stack_offset = try self.allocMem(inst, tuple_size, tuple_align);
14741480
1475 try self.spillCompareFlagsIfOccupied();1481 try self.spillCompareFlagsIfOccupied();
1476 self.cpsr_flags_inst = null;
14771482
1478 const base_tag: Air.Inst.Tag = switch (tag) {1483 const base_tag: Air.Inst.Tag = switch (tag) {
1479 .add_with_overflow => .add,1484 .add_with_overflow => .add,
...@@ -1493,7 +1498,13 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1493,7 +1498,13 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {
1493 try self.truncRegister(dest_reg, truncated_reg, int_info.signedness, int_info.bits);1498 try self.truncRegister(dest_reg, truncated_reg, int_info.signedness, int_info.bits);
14941499
1495 // cmp dest, truncated1500 // 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
1498 try self.genSetStack(lhs_ty, stack_offset, .{ .register = truncated_reg });1509 try self.genSetStack(lhs_ty, stack_offset, .{ .register = truncated_reg });
1499 try self.genSetStack(Type.initTag(.u1), stack_offset - overflow_bit_offset, .{ .cpsr_flags = .ne });1510 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 {...@@ -1578,7 +1589,6 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
1578 const stack_offset = try self.allocMem(inst, tuple_size, tuple_align);1589 const stack_offset = try self.allocMem(inst, tuple_size, tuple_align);
15791590
1580 try self.spillCompareFlagsIfOccupied();1591 try self.spillCompareFlagsIfOccupied();
1581 self.cpsr_flags_inst = null;
15821592
1583 const base_tag: Mir.Inst.Tag = switch (int_info.signedness) {1593 const base_tag: Mir.Inst.Tag = switch (int_info.signedness) {
1584 .signed => .smulbb,1594 .signed => .smulbb,
...@@ -1598,7 +1608,13 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1598,7 +1608,13 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
1598 try self.truncRegister(dest_reg, truncated_reg, int_info.signedness, int_info.bits);1608 try self.truncRegister(dest_reg, truncated_reg, int_info.signedness, int_info.bits);
15991609
1600 // cmp dest, truncated1610 // 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
1603 try self.genSetStack(lhs_ty, stack_offset, .{ .register = truncated_reg });1619 try self.genSetStack(lhs_ty, stack_offset, .{ .register = truncated_reg });
1604 try self.genSetStack(Type.initTag(.u1), stack_offset - overflow_bit_offset, .{ .cpsr_flags = .ne });1620 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 {...@@ -1608,7 +1624,6 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
1608 const stack_offset = try self.allocMem(inst, tuple_size, tuple_align);1624 const stack_offset = try self.allocMem(inst, tuple_size, tuple_align);
16091625
1610 try self.spillCompareFlagsIfOccupied();1626 try self.spillCompareFlagsIfOccupied();
1611 self.cpsr_flags_inst = null;
16121627
1613 const base_tag: Mir.Inst.Tag = switch (int_info.signedness) {1628 const base_tag: Mir.Inst.Tag = switch (int_info.signedness) {
1614 .signed => .smull,1629 .signed => .smull,
...@@ -1672,7 +1687,13 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1672,7 +1687,13 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
1672 try self.genSetStack(lhs_ty, stack_offset, .{ .register = truncated_reg });1687 try self.genSetStack(lhs_ty, stack_offset, .{ .register = truncated_reg });
16731688
1674 // cmp truncated, rdlo1689 // 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
1677 // mov rdlo, #01698 // mov rdlo, #0
1678 _ = try self.addInst(.{1699 _ = try self.addInst(.{
...@@ -1694,7 +1715,13 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1694,7 +1715,13 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
1694 });1715 });
16951716
1696 // cmp rdhi, #01717 // 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
1699 // movne rdlo, #11726 // movne rdlo, #1
1700 _ = try self.addInst(.{1727 _ = try self.addInst(.{
...@@ -1725,8 +1752,6 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1725,8 +1752,6 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
1725 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;1752 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
1726 if (self.liveness.isUnused(inst)) return self.finishAir(inst, .dead, .{ extra.lhs, extra.rhs, .none });1753 if (self.liveness.isUnused(inst)) return self.finishAir(inst, .dead, .{ extra.lhs, extra.rhs, .none });
1727 const result: MCValue = result: {1754 const result: MCValue = result: {
1728 const lhs = try self.resolveInst(extra.lhs);
1729 const rhs = try self.resolveInst(extra.rhs);
1730 const lhs_ty = self.air.typeOf(extra.lhs);1755 const lhs_ty = self.air.typeOf(extra.lhs);
1731 const rhs_ty = self.air.typeOf(extra.rhs);1756 const rhs_ty = self.air.typeOf(extra.rhs);
17321757
...@@ -1742,28 +1767,107 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1742,28 +1767,107 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
1742 if (int_info.bits <= 32) {1767 if (int_info.bits <= 32) {
1743 const stack_offset = try self.allocMem(inst, tuple_size, tuple_align);1768 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
1751 try self.spillCompareFlagsIfOccupied();1770 try self.spillCompareFlagsIfOccupied();
1752 self.cpsr_flags_inst = null;
17531771
1754 // lsl dest, lhs, rhs1772 const shr_mir_tag: Mir.Inst.Tag = switch (int_info.signedness) {
1755 const dest = try self.binOp(.shl, lhs, rhs, lhs_ty, rhs_ty, null);1773 .signed => Mir.Inst.Tag.asr,
1756 const dest_reg = dest.register;1774 .unsigned => Mir.Inst.Tag.lsr,
1757 const dest_lock = self.register_manager.lockRegAssumeUnused(dest_reg);1775 };
1758 defer self.register_manager.unlockReg(dest_lock);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, rhs1812 try self.truncRegister(dest_reg, dest_reg, int_info.signedness, int_info.bits);
1761 const reconstructed = try self.binOp(.shr, dest, rhs, lhs_ty, rhs_ty, null);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
1763 // cmp lhs, reconstructed1861 // 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 });
1767 try self.genSetStack(Type.initTag(.u1), stack_offset - overflow_bit_offset, .{ .cpsr_flags = .ne });1871 try self.genSetStack(Type.initTag(.u1), stack_offset - overflow_bit_offset, .{ .cpsr_flags = .ne });
17681872
1769 break :result MCValue{ .stack_offset = stack_offset };1873 break :result MCValue{ .stack_offset = stack_offset };
...@@ -2662,8 +2766,8 @@ fn allocRegs(...@@ -2662,8 +2766,8 @@ fn allocRegs(
2662 write_args: []const WriteArg,2766 write_args: []const WriteArg,
2663 reuse_metadata: ?ReuseMetadata,2767 reuse_metadata: ?ReuseMetadata,
2664) InnerError!void {2768) InnerError!void {
2665 // Air instructions have either one output or none (cmp)2769 // Air instructions have exactly one output
2666 assert(!(reuse_metadata != null and write_args.len > 1)); // see note above2770 assert(!(reuse_metadata != null and write_args.len != 1)); // see note above
26672771
2668 // The operand mapping is a 1:1 mapping of read args to their2772 // The operand mapping is a 1:1 mapping of read args to their
2669 // corresponding operand index in the Air instruction2773 // corresponding operand index in the Air instruction
...@@ -2714,7 +2818,7 @@ fn allocRegs(...@@ -2714,7 +2818,7 @@ fn allocRegs(
2714 }2818 }
2715 }2819 }
27162820
2717 if (reuse_metadata != null and write_args.len > 0) {2821 if (reuse_metadata != null) {
2718 const inst = reuse_metadata.?.corresponding_inst;2822 const inst = reuse_metadata.?.corresponding_inst;
2719 const operand_mapping = reuse_metadata.?.operand_mapping;2823 const operand_mapping = reuse_metadata.?.operand_mapping;
2720 const arg = write_args[0];2824 const arg = write_args[0];
...@@ -2826,7 +2930,7 @@ fn binOpRegister(...@@ -2826,7 +2930,7 @@ fn binOpRegister(
2826 };2930 };
2827 try self.allocRegs(2931 try self.allocRegs(
2828 &read_args,2932 &read_args,
2829 if (mir_tag == .cmp) &.{} else &write_args,2933 &write_args,
2830 if (metadata) |md| .{2934 if (metadata) |md| .{
2831 .corresponding_inst = md.inst,2935 .corresponding_inst = md.inst,
2832 .operand_mapping = &.{ 0, 1 },2936 .operand_mapping = &.{ 0, 1 },
...@@ -2846,10 +2950,6 @@ fn binOpRegister(...@@ -2846,10 +2950,6 @@ fn binOpRegister(
2846 .rn = lhs_reg,2950 .rn = lhs_reg,
2847 .op = Instruction.Operand.reg(rhs_reg, Instruction.Operand.Shift.none),2951 .op = Instruction.Operand.reg(rhs_reg, Instruction.Operand.Shift.none),
2848 } },2952 } },
2849 .cmp => .{ .r_op_cmp = .{
2850 .rn = lhs_reg,
2851 .op = Instruction.Operand.reg(rhs_reg, Instruction.Operand.Shift.none),
2852 } },
2853 .lsl,2953 .lsl,
2854 .asr,2954 .asr,
2855 .lsr,2955 .lsr,
...@@ -2918,7 +3018,7 @@ fn binOpImmediate(...@@ -2918,7 +3018,7 @@ fn binOpImmediate(
2918 const operand_mapping: []const Liveness.OperandInt = if (lhs_and_rhs_swapped) &.{1} else &.{0};3018 const operand_mapping: []const Liveness.OperandInt = if (lhs_and_rhs_swapped) &.{1} else &.{0};
2919 try self.allocRegs(3019 try self.allocRegs(
2920 &read_args,3020 &read_args,
2921 if (mir_tag == .cmp) &.{} else &write_args,3021 &write_args,
2922 if (metadata) |md| .{3022 if (metadata) |md| .{
2923 .corresponding_inst = md.inst,3023 .corresponding_inst = md.inst,
2924 .operand_mapping = operand_mapping,3024 .operand_mapping = operand_mapping,
...@@ -2938,10 +3038,6 @@ fn binOpImmediate(...@@ -2938,10 +3038,6 @@ fn binOpImmediate(
2938 .rn = lhs_reg,3038 .rn = lhs_reg,
2939 .op = Instruction.Operand.fromU32(rhs.immediate).?,3039 .op = Instruction.Operand.fromU32(rhs.immediate).?,
2940 } },3040 } },
2941 .cmp => .{ .r_op_cmp = .{
2942 .rn = lhs_reg,
2943 .op = Instruction.Operand.fromU32(rhs.immediate).?,
2944 } },
2945 .lsl,3041 .lsl,
2946 .asr,3042 .asr,
2947 .lsr,3043 .lsr,
...@@ -2991,7 +3087,6 @@ fn binOp(...@@ -2991,7 +3087,6 @@ fn binOp(
2991 switch (tag) {3087 switch (tag) {
2992 .add,3088 .add,
2993 .sub,3089 .sub,
2994 .cmp_eq,
2995 => {3090 => {
2996 switch (lhs_ty.zigTypeTag()) {3091 switch (lhs_ty.zigTypeTag()) {
2997 .Float => return self.fail("TODO ARM binary operations on floats", .{}),3092 .Float => return self.fail("TODO ARM binary operations on floats", .{}),
...@@ -3006,15 +3101,12 @@ fn binOp(...@@ -3006,15 +3101,12 @@ fn binOp(
3006 // operands3101 // operands
3007 const lhs_immediate_ok = switch (tag) {3102 const lhs_immediate_ok = switch (tag) {
3008 .add => lhs == .immediate and Instruction.Operand.fromU32(lhs.immediate) != null,3103 .add => lhs == .immediate and Instruction.Operand.fromU32(lhs.immediate) != null,
3009 .sub,3104 .sub => false,
3010 .cmp_eq,
3011 => false,
3012 else => unreachable,3105 else => unreachable,
3013 };3106 };
3014 const rhs_immediate_ok = switch (tag) {3107 const rhs_immediate_ok = switch (tag) {
3015 .add,3108 .add,
3016 .sub,3109 .sub,
3017 .cmp_eq,
3018 => rhs == .immediate and Instruction.Operand.fromU32(rhs.immediate) != null,3110 => rhs == .immediate and Instruction.Operand.fromU32(rhs.immediate) != null,
3019 else => unreachable,3111 else => unreachable,
3020 };3112 };
...@@ -3022,7 +3114,6 @@ fn binOp(...@@ -3022,7 +3114,6 @@ fn binOp(
3022 const mir_tag: Mir.Inst.Tag = switch (tag) {3114 const mir_tag: Mir.Inst.Tag = switch (tag) {
3023 .add => .add,3115 .add => .add,
3024 .sub => .sub,3116 .sub => .sub,
3025 .cmp_eq => .cmp,
3026 else => unreachable,3117 else => unreachable,
3027 };3118 };
30283119
...@@ -4005,32 +4096,16 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {...@@ -4005,32 +4096,16 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
4005 const lhs_ty = self.air.typeOf(bin_op.lhs);4096 const lhs_ty = self.air.typeOf(bin_op.lhs);
40064097
4007 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else blk: {4098 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else blk: {
4008 const operands: BinOpOperands = .{ .inst = .{4099 break :blk try self.cmp(.{ .inst = bin_op.lhs }, .{ .inst = bin_op.rhs }, lhs_ty, op);
4009 .inst = inst,
4010 .lhs = bin_op.lhs,
4011 .rhs = bin_op.rhs,
4012 } };
4013 break :blk try self.cmp(operands, lhs_ty, op);
4014 };4100 };
40154101
4016 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });4102 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
4017}4103}
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
4031fn cmp(4105fn cmp(
4032 self: *Self,4106 self: *Self,
4033 operands: BinOpOperands,4107 lhs: ReadArg.Bind,
4108 rhs: ReadArg.Bind,
4034 lhs_ty: Type,4109 lhs_ty: Type,
4035 op: math.CompareOperator,4110 op: math.CompareOperator,
4036) !MCValue {4111) !MCValue {
...@@ -4060,22 +4135,47 @@ fn cmp(...@@ -4060,22 +4135,47 @@ fn cmp(
4060 if (int_info.bits <= 32) {4135 if (int_info.bits <= 32) {
4061 try self.spillCompareFlagsIfOccupied();4136 try self.spillCompareFlagsIfOccupied();
40624137
4063 switch (operands) {4138 var lhs_reg: Register = undefined;
4064 .inst => |inst_op| {4139 var rhs_reg: Register = undefined;
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);
40724140
4073 self.cpsr_flags_inst = inst_op.inst;4141 const rhs_mcv = try rhs.resolveToMcv(self);
4074 _ = try self.binOp(.cmp_eq, lhs, rhs, int_ty, int_ty, metadata);4142 const rhs_immediate_ok = rhs_mcv == .immediate and Instruction.Operand.fromU32(rhs_mcv.immediate) != null;
4075 },4143
4076 .mcv => |mcv_op| {4144 if (rhs_immediate_ok) {
4077 _ = try self.binOp(.cmp_eq, mcv_op.lhs, mcv_op.rhs, int_ty, int_ty, null);4145 const read_args = [_]ReadArg{
4078 },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 });
4079 }4179 }
40804180
4081 return switch (int_info.signedness) {4181 return switch (int_info.signedness) {
...@@ -4349,14 +4449,13 @@ fn isNonNull(self: *Self, ty: Type, operand: MCValue) !MCValue {...@@ -4349,14 +4449,13 @@ fn isNonNull(self: *Self, ty: Type, operand: MCValue) !MCValue {
43494449
4350fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue {4450fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue {
4351 const error_type = ty.errorUnionSet();4451 const error_type = ty.errorUnionSet();
4352 const error_int_type = Type.initTag(.u16);
43534452
4354 if (error_type.errorSetIsEmpty()) {4453 if (error_type.errorSetIsEmpty()) {
4355 return MCValue{ .immediate = 0 }; // always false4454 return MCValue{ .immediate = 0 }; // always false
4356 }4455 }
43574456
4358 const error_mcv = try self.errUnionErr(operand, ty);4457 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);
4360 return MCValue{ .cpsr_flags = .hi };4459 return MCValue{ .cpsr_flags = .hi };
4361}4460}
43624461
...@@ -4587,14 +4686,7 @@ fn airSwitch(self: *Self, inst: Air.Inst.Index) !void {...@@ -4587,14 +4686,7 @@ fn airSwitch(self: *Self, inst: Air.Inst.Index) !void {
4587 defer self.gpa.free(branch_into_prong_relocs);4686 defer self.gpa.free(branch_into_prong_relocs);
45884687
4589 for (items) |item, idx| {4688 for (items) |item, idx| {
4590 const condition = try self.resolveInst(pl_op.operand);4689 const cmp_result = try self.cmp(.{ .inst = pl_op.operand }, .{ .inst = item }, condition_ty, .neq);
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);
4598 branch_into_prong_relocs[idx] = try self.condBr(cmp_result);4690 branch_into_prong_relocs[idx] = try self.condBr(cmp_result);
4599 }4691 }
46004692