| ... | @@ -483,7 +483,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -483,7 +483,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 483 | | 483 | |
| 484 | switch (air_tags[inst]) { | 484 | switch (air_tags[inst]) { |
| 485 | // zig fmt: off | 485 | // zig fmt: off |
| 486 | .add, .ptr_add => @panic("TODO try self.airBinOp(inst)"), | 486 | .add, .ptr_add => try self.airBinOp(inst), |
| 487 | .addwrap => @panic("TODO try self.airAddWrap(inst)"), | 487 | .addwrap => @panic("TODO try self.airAddWrap(inst)"), |
| 488 | .add_sat => @panic("TODO try self.airAddSat(inst)"), | 488 | .add_sat => @panic("TODO try self.airAddSat(inst)"), |
| 489 | .sub, .ptr_sub => @panic("TODO try self.airBinOp(inst)"), | 489 | .sub, .ptr_sub => @panic("TODO try self.airBinOp(inst)"), |
| ... | @@ -825,6 +825,21 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -825,6 +825,21 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { |
| 825 | return self.finishAir(inst, mcv, .{ .none, .none, .none }); | 825 | return self.finishAir(inst, mcv, .{ .none, .none, .none }); |
| 826 | } | 826 | } |
| 827 | | 827 | |
| | 828 | fn airBinOp(self: *Self, inst: Air.Inst.Index) !void { |
| | 829 | const tag = self.air.instructions.items(.tag)[inst]; |
| | 830 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| | 831 | const lhs = try self.resolveInst(bin_op.lhs); |
| | 832 | const rhs = try self.resolveInst(bin_op.rhs); |
| | 833 | const lhs_ty = self.air.typeOf(bin_op.lhs); |
| | 834 | const rhs_ty = self.air.typeOf(bin_op.rhs); |
| | 835 | |
| | 836 | const result: MCValue = if (self.liveness.isUnused(inst)) |
| | 837 | .dead |
| | 838 | else |
| | 839 | try self.binOp(tag, inst, lhs, rhs, lhs_ty, rhs_ty); |
| | 840 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| | 841 | } |
| | 842 | |
| 828 | fn airBitCast(self: *Self, inst: Air.Inst.Index) !void { | 843 | fn airBitCast(self: *Self, inst: Air.Inst.Index) !void { |
| 829 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 844 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 830 | const result = try self.resolveInst(ty_op.operand); | 845 | const result = try self.resolveInst(ty_op.operand); |
| ... | @@ -1601,7 +1616,7 @@ fn binOp( | ... | @@ -1601,7 +1616,7 @@ fn binOp( |
| 1601 | ) InnerError!MCValue { | 1616 | ) InnerError!MCValue { |
| 1602 | const mod = self.bin_file.options.module.?; | 1617 | const mod = self.bin_file.options.module.?; |
| 1603 | switch (tag) { | 1618 | switch (tag) { |
| 1604 | .cmp_eq => { | 1619 | .add, .cmp_eq => { |
| 1605 | switch (lhs_ty.zigTypeTag()) { | 1620 | switch (lhs_ty.zigTypeTag()) { |
| 1606 | .Float => return self.fail("TODO binary operations on floats", .{}), | 1621 | .Float => return self.fail("TODO binary operations on floats", .{}), |
| 1607 | .Vector => return self.fail("TODO binary operations on vectors", .{}), | 1622 | .Vector => return self.fail("TODO binary operations on vectors", .{}), |
| ... | @@ -1609,14 +1624,37 @@ fn binOp( | ... | @@ -1609,14 +1624,37 @@ fn binOp( |
| 1609 | assert(lhs_ty.eql(rhs_ty, mod)); | 1624 | assert(lhs_ty.eql(rhs_ty, mod)); |
| 1610 | const int_info = lhs_ty.intInfo(self.target.*); | 1625 | const int_info = lhs_ty.intInfo(self.target.*); |
| 1611 | if (int_info.bits <= 64) { | 1626 | if (int_info.bits <= 64) { |
| 1612 | // TODO optimize for small (i13) values by putting them inside immediates | 1627 | // Only say yes if the operation is |
| | 1628 | // commutative, i.e. we can swap both of the |
| | 1629 | // operands |
| | 1630 | const lhs_immediate_ok = switch (tag) { |
| | 1631 | .add => lhs == .immediate and lhs.immediate <= std.math.maxInt(u12), |
| | 1632 | .sub, .cmp_eq => false, |
| | 1633 | else => unreachable, |
| | 1634 | }; |
| | 1635 | const rhs_immediate_ok = switch (tag) { |
| | 1636 | .add, |
| | 1637 | .sub, |
| | 1638 | .cmp_eq, |
| | 1639 | => rhs == .immediate and rhs.immediate <= std.math.maxInt(u12), |
| | 1640 | else => unreachable, |
| | 1641 | }; |
| 1613 | | 1642 | |
| 1614 | const mir_tag: Mir.Inst.Tag = switch (tag) { | 1643 | const mir_tag: Mir.Inst.Tag = switch (tag) { |
| | 1644 | .add => .add, |
| 1615 | .cmp_eq => .subcc, | 1645 | .cmp_eq => .subcc, |
| 1616 | else => unreachable, | 1646 | else => unreachable, |
| 1617 | }; | 1647 | }; |
| 1618 | | 1648 | |
| 1619 | return try self.binOpRegister(mir_tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); | 1649 | if (rhs_immediate_ok) { |
| | 1650 | return try self.binOpImmediate(mir_tag, maybe_inst, lhs, rhs, lhs_ty, false); |
| | 1651 | } else if (lhs_immediate_ok) { |
| | 1652 | // swap lhs and rhs |
| | 1653 | return try self.binOpImmediate(mir_tag, maybe_inst, rhs, lhs, rhs_ty, true); |
| | 1654 | } else { |
| | 1655 | // TODO convert large immediates to register before adding |
| | 1656 | return try self.binOpRegister(mir_tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); |
| | 1657 | } |
| 1620 | } else { | 1658 | } else { |
| 1621 | return self.fail("TODO binary operations on int with bits > 64", .{}); | 1659 | return self.fail("TODO binary operations on int with bits > 64", .{}); |
| 1622 | } | 1660 | } |