| ... | @@ -1019,6 +1019,7 @@ fn binOpRegister( | ... | @@ -1019,6 +1019,7 @@ fn binOpRegister( |
| 1019 | .add => .add, | 1019 | .add => .add, |
| 1020 | .sub => .sub, | 1020 | .sub => .sub, |
| 1021 | .cmp_eq => .cmp_eq, | 1021 | .cmp_eq => .cmp_eq, |
| | 1022 | .cmp_neq => .cmp_neq, |
| 1022 | .cmp_gt => .cmp_gt, | 1023 | .cmp_gt => .cmp_gt, |
| 1023 | .cmp_gte => .cmp_gte, | 1024 | .cmp_gte => .cmp_gte, |
| 1024 | .cmp_lt => .cmp_lt, | 1025 | .cmp_lt => .cmp_lt, |
| ... | @@ -1185,6 +1186,8 @@ fn airAddWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1185,6 +1186,8 @@ fn airAddWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 1185 | const rhs_ty = self.typeOf(extra.rhs); | 1186 | const rhs_ty = self.typeOf(extra.rhs); |
| 1186 | | 1187 | |
| 1187 | const add_result_mcv = try self.binOp(.add, null, lhs, rhs, lhs_ty, rhs_ty); | 1188 | const add_result_mcv = try self.binOp(.add, null, lhs, rhs, lhs_ty, rhs_ty); |
| | 1189 | const add_result_lock = self.register_manager.lockRegAssumeUnused(add_result_mcv.register); |
| | 1190 | defer self.register_manager.unlockReg(add_result_lock); |
| 1188 | | 1191 | |
| 1189 | const tuple_ty = self.typeOfIndex(inst); | 1192 | const tuple_ty = self.typeOfIndex(inst); |
| 1190 | const int_info = lhs_ty.intInfo(mod); | 1193 | const int_info = lhs_ty.intInfo(mod); |
| ... | @@ -1196,15 +1199,44 @@ fn airAddWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1196,15 +1199,44 @@ fn airAddWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 1196 | | 1199 | |
| 1197 | const result_offset = tuple_ty.structFieldOffset(0, mod) + offset; | 1200 | const result_offset = tuple_ty.structFieldOffset(0, mod) + offset; |
| 1198 | | 1201 | |
| 1199 | // set the result first as we don't have a lock on the add_result_mcv register and it will | | |
| 1200 | // get clobbered in the next binOp. | | |
| 1201 | try self.genSetStack(lhs_ty, @intCast(result_offset), add_result_mcv); | 1202 | try self.genSetStack(lhs_ty, @intCast(result_offset), add_result_mcv); |
| 1202 | | 1203 | |
| 1203 | if (int_info.bits >= 8 and math.isPowerOfTwo(int_info.bits)) { | 1204 | if (int_info.bits >= 8 and math.isPowerOfTwo(int_info.bits)) { |
| 1204 | if (int_info.signedness == .unsigned) { | 1205 | if (int_info.signedness == .unsigned) { |
| 1205 | const overflow_offset = tuple_ty.structFieldOffset(1, mod) + offset; | 1206 | const overflow_offset = tuple_ty.structFieldOffset(1, mod) + offset; |
| 1206 | | 1207 | |
| 1207 | const overflow_mcv = try self.binOp(.cmp_lt, null, add_result_mcv, lhs, lhs_ty, lhs_ty); | 1208 | const max_val = std.math.pow(u16, 2, int_info.bits) - 1; |
| | 1209 | |
| | 1210 | const overflow_reg, const overflow_lock = try self.allocReg(); |
| | 1211 | defer self.register_manager.unlockReg(overflow_lock); |
| | 1212 | |
| | 1213 | const add_reg, const add_lock = blk: { |
| | 1214 | if (add_result_mcv == .register) break :blk .{ add_result_mcv.register, null }; |
| | 1215 | |
| | 1216 | const add_reg, const add_lock = try self.allocReg(); |
| | 1217 | try self.genSetReg(lhs_ty, add_reg, add_result_mcv); |
| | 1218 | break :blk .{ add_reg, add_lock }; |
| | 1219 | }; |
| | 1220 | defer if (add_lock) |lock| self.register_manager.unlockReg(lock); |
| | 1221 | |
| | 1222 | _ = try self.addInst(.{ |
| | 1223 | .tag = .andi, |
| | 1224 | .data = .{ .i_type = .{ |
| | 1225 | .rd = overflow_reg, |
| | 1226 | .rs1 = add_reg, |
| | 1227 | .imm12 = @intCast(max_val), |
| | 1228 | } }, |
| | 1229 | }); |
| | 1230 | |
| | 1231 | const overflow_mcv = try self.binOp( |
| | 1232 | .cmp_neq, |
| | 1233 | null, |
| | 1234 | .{ .register = overflow_reg }, |
| | 1235 | .{ .register = add_reg }, |
| | 1236 | lhs_ty, |
| | 1237 | lhs_ty, |
| | 1238 | ); |
| | 1239 | |
| 1208 | try self.genSetStack(Type.u1, @intCast(overflow_offset), overflow_mcv); | 1240 | try self.genSetStack(Type.u1, @intCast(overflow_offset), overflow_mcv); |
| 1209 | | 1241 | |
| 1210 | break :result result_mcv; | 1242 | break :result result_mcv; |
| ... | @@ -3042,7 +3074,15 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_val: MCValue) InnerError! | ... | @@ -3042,7 +3074,15 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_val: MCValue) InnerError! |
| 3042 | | 3074 | |
| 3043 | fn airIntFromPtr(self: *Self, inst: Air.Inst.Index) !void { | 3075 | fn airIntFromPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 3044 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; | 3076 | const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 3045 | const result = try self.resolveInst(un_op); | 3077 | const result = result: { |
| | 3078 | const src_mcv = try self.resolveInst(un_op); |
| | 3079 | if (self.reuseOperand(inst, un_op, 0, src_mcv)) break :result src_mcv; |
| | 3080 | |
| | 3081 | const dst_mcv = try self.allocRegOrMem(inst, true); |
| | 3082 | const dst_ty = self.typeOfIndex(inst); |
| | 3083 | try self.setValue(dst_ty, dst_mcv, src_mcv); |
| | 3084 | break :result dst_mcv; |
| | 3085 | }; |
| 3046 | return self.finishAir(inst, result, .{ un_op, .none, .none }); | 3086 | return self.finishAir(inst, result, .{ un_op, .none, .none }); |
| 3047 | } | 3087 | } |
| 3048 | | 3088 | |