| ... | ... | @@ -2036,21 +2036,34 @@ fn binOp( |
| 2036 | 2036 | assert(lhs_ty.eql(rhs_ty, mod)); |
| 2037 | 2037 | const int_info = lhs_ty.intInfo(self.target.*); |
| 2038 | 2038 | if (int_info.bits <= 64) { |
| 2039 | | // If LHS is immediate, then swap it with RHS. |
| 2040 | | const lhs_is_imm = lhs == .immediate; |
| 2041 | | const new_lhs = if (lhs_is_imm) rhs else lhs; |
| 2042 | | const new_rhs = if (lhs_is_imm) lhs else rhs; |
| 2043 | | const new_lhs_ty = if (lhs_is_imm) rhs_ty else lhs_ty; |
| 2044 | | const new_rhs_ty = if (lhs_is_imm) lhs_ty else rhs_ty; |
| 2045 | | |
| 2046 | | // At this point, RHS might be an immediate |
| 2047 | | // If it's a power of two immediate then we emit an shl instead |
| 2048 | | // TODO add similar checks for LHS |
| 2049 | | if (new_rhs == .immediate and math.isPowerOfTwo(new_rhs.immediate)) { |
| 2050 | | return try self.binOp(.shl, new_lhs, .{ .immediate = math.log2(new_rhs.immediate) }, new_lhs_ty, Type.usize, metadata); |
| 2051 | | } |
| 2039 | // Only say yes if the operation is |
| 2040 | // commutative, i.e. we can swap both of the |
| 2041 | // operands |
| 2042 | const lhs_immediate_ok = switch (tag) { |
| 2043 | .mul => lhs == .immediate and lhs.immediate <= std.math.maxInt(u12), |
| 2044 | else => unreachable, |
| 2045 | }; |
| 2046 | const rhs_immediate_ok = switch (tag) { |
| 2047 | .mul => rhs == .immediate and rhs.immediate <= std.math.maxInt(u12), |
| 2048 | else => unreachable, |
| 2049 | }; |
| 2052 | 2050 | |
| 2053 | | return try self.binOpRegister(.mulx, new_lhs, new_rhs, new_lhs_ty, new_rhs_ty, metadata); |
| 2051 | const mir_tag: Mir.Inst.Tag = switch (tag) { |
| 2052 | .mul => .mulx, |
| 2053 | else => unreachable, |
| 2054 | }; |
| 2055 | |
| 2056 | if (rhs_immediate_ok) { |
| 2057 | // At this point, rhs is an immediate |
| 2058 | return try self.binOpImmediate(mir_tag, lhs, rhs, lhs_ty, false, metadata); |
| 2059 | } else if (lhs_immediate_ok) { |
| 2060 | // swap lhs and rhs |
| 2061 | // At this point, lhs is an immediate |
| 2062 | return try self.binOpImmediate(mir_tag, rhs, lhs, rhs_ty, true, metadata); |
| 2063 | } else { |
| 2064 | // TODO convert large immediates to register before adding |
| 2065 | return try self.binOpRegister(mir_tag, lhs, rhs, lhs_ty, rhs_ty, metadata); |
| 2066 | } |
| 2054 | 2067 | } else { |
| 2055 | 2068 | return self.fail("TODO binary operations on int with bits > 64", .{}); |
| 2056 | 2069 | } |