authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-05-09 22:31:36+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-05-09 22:31:36+02:00
log20e7f1218b997e3da5d10cb5d038ed782d772716
tree23be728df99e0102bf6fae759b86dd1349b41d19
parent9c3d24ea0bffa53fb08a73493d72a6a0866f6432

x64: make one entry point for binary ops

* rename `genBinMathOp` into `genBinOp` and handle commutativity * rename `genBinMathOpMir` into `genBinOpMir`

1 files changed, 113 insertions(+), 210 deletions(-)

src/arch/x86_64/CodeGen.zig+113-210
...@@ -586,11 +586,11 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -586,11 +586,11 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
586586
587 switch (air_tags[inst]) {587 switch (air_tags[inst]) {
588 // zig fmt: off588 // zig fmt: off
589 .add => try self.airAdd(inst),589 .add => try self.airBinOp(inst),
590 .addwrap => try self.airAdd(inst),590 .addwrap => try self.airBinOp(inst),
591 .add_sat => try self.airAddSat(inst),591 .add_sat => try self.airAddSat(inst),
592 .sub => try self.airSub(inst),592 .sub => try self.airBinOp(inst),
593 .subwrap => try self.airSub(inst),593 .subwrap => try self.airBinOp(inst),
594 .sub_sat => try self.airSubSat(inst),594 .sub_sat => try self.airSubSat(inst),
595 .mul => try self.airMul(inst),595 .mul => try self.airMul(inst),
596 .mulwrap => try self.airMul(inst),596 .mulwrap => try self.airMul(inst),
...@@ -601,8 +601,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -601,8 +601,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
601 .shl_sat => try self.airShlSat(inst),601 .shl_sat => try self.airShlSat(inst),
602 .min => try self.airMin(inst),602 .min => try self.airMin(inst),
603 .max => try self.airMax(inst),603 .max => try self.airMax(inst),
604 .ptr_add => try self.airPtrAdd(inst),604 .ptr_add => try self.airBinOp(inst),
605 .ptr_sub => try self.airPtrSub(inst),605 .ptr_sub => try self.airBinOp(inst),
606 .slice => try self.airSlice(inst),606 .slice => try self.airSlice(inst),
607607
608 .sqrt,608 .sqrt,
...@@ -638,11 +638,11 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -638,11 +638,11 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
638 .cmp_vector => try self.airCmpVector(inst),638 .cmp_vector => try self.airCmpVector(inst),
639 .cmp_lt_errors_len => try self.airCmpLtErrorsLen(inst),639 .cmp_lt_errors_len => try self.airCmpLtErrorsLen(inst),
640640
641 .bool_and => try self.airBoolOp(inst),641 .bool_and => try self.airBinOp(inst),
642 .bool_or => try self.airBoolOp(inst),642 .bool_or => try self.airBinOp(inst),
643 .bit_and => try self.airBitAnd(inst),643 .bit_and => try self.airBinOp(inst),
644 .bit_or => try self.airBitOr(inst),644 .bit_or => try self.airBinOp(inst),
645 .xor => try self.airXor(inst),645 .xor => try self.airBinOp(inst),
646 .shr, .shr_exact => try self.airShr(inst),646 .shr, .shr_exact => try self.airShr(inst),
647647
648 .alloc => try self.airAlloc(inst),648 .alloc => try self.airAlloc(inst),
...@@ -1122,7 +1122,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {...@@ -1122,7 +1122,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {
1122 },1122 },
1123 else => {},1123 else => {},
1124 }1124 }
1125 break :result try self.genBinMathOp(inst, ty_op.operand, .bool_true);1125 break :result try self.genBinOp(inst, ty_op.operand, .bool_true);
1126 };1126 };
1127 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });1127 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1128}1128}
...@@ -1159,7 +1159,7 @@ fn airMin(self: *Self, inst: Air.Inst.Index) !void {...@@ -1159,7 +1159,7 @@ fn airMin(self: *Self, inst: Air.Inst.Index) !void {
1159 };1159 };
1160 defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock);1160 defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock);
11611161
1162 try self.genBinMathOpMir(.cmp, ty, .{ .register = lhs_reg }, rhs_mcv);1162 try self.genBinOpMir(.cmp, ty, .{ .register = lhs_reg }, rhs_mcv);
11631163
1164 const dst_mcv = try self.copyToRegisterWithInstTracking(inst, ty, rhs_mcv);1164 const dst_mcv = try self.copyToRegisterWithInstTracking(inst, ty, rhs_mcv);
1165 _ = try self.addInst(.{1165 _ = try self.addInst(.{
...@@ -1185,63 +1185,12 @@ fn airMax(self: *Self, inst: Air.Inst.Index) !void {...@@ -1185,63 +1185,12 @@ fn airMax(self: *Self, inst: Air.Inst.Index) !void {
1185 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });1185 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1186}1186}
11871187
1188fn genPtrBinMathOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs: Air.Inst.Ref) !MCValue {
1189 const dst_ty = self.air.typeOfIndex(inst);
1190 const elem_size = dst_ty.elemType2().abiSize(self.target.*);
1191 const ptr = try self.resolveInst(op_lhs);
1192 const offset = try self.resolveInst(op_rhs);
1193 const offset_ty = self.air.typeOf(op_rhs);
1194
1195 const offset_lock: ?RegisterLock = switch (offset) {
1196 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
1197 else => null,
1198 };
1199 defer if (offset_lock) |lock| self.register_manager.unlockReg(lock);
1200
1201 const dst_mcv: MCValue = blk: {
1202 if (self.reuseOperand(inst, op_lhs, 0, ptr)) {
1203 if (ptr.isMemory() or ptr.isRegister()) break :blk ptr;
1204 }
1205 break :blk MCValue{ .register = try self.copyToTmpRegister(dst_ty, ptr) };
1206 };
1207
1208 const dst_mcv_lock: ?RegisterLock = switch (dst_mcv) {
1209 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
1210 else => null,
1211 };
1212 defer if (dst_mcv_lock) |lock| self.register_manager.unlockReg(lock);
1213
1214 const offset_mcv: MCValue = blk: {
1215 if (self.reuseOperand(inst, op_rhs, 1, offset)) {
1216 if (offset.isRegister()) break :blk offset;
1217 }
1218 break :blk MCValue{ .register = try self.copyToTmpRegister(offset_ty, offset) };
1219 };
1220
1221 const offset_mcv_lock: ?RegisterLock = switch (offset_mcv) {
1222 .register => |reg| self.register_manager.lockReg(reg),
1223 else => null,
1224 };
1225 defer if (offset_mcv_lock) |lock| self.register_manager.unlockReg(lock);
1226
1227 try self.genIntMulComplexOpMir(offset_ty, offset_mcv, .{ .immediate = elem_size });
1228
1229 const tag = self.air.instructions.items(.tag)[inst];
1230 switch (tag) {
1231 .ptr_add => try self.genBinMathOpMir(.add, dst_ty, dst_mcv, offset_mcv),
1232 .ptr_sub => try self.genBinMathOpMir(.sub, dst_ty, dst_mcv, offset_mcv),
1233 else => unreachable,
1234 }
1235
1236 return dst_mcv;
1237}
1238
1239fn airPtrAdd(self: *Self, inst: Air.Inst.Index) !void {1188fn airPtrAdd(self: *Self, inst: Air.Inst.Index) !void {
1240 const bin_op = self.air.instructions.items(.data)[inst].bin_op;1189 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1241 const result = if (self.liveness.isUnused(inst))1190 const result = if (self.liveness.isUnused(inst))
1242 .dead1191 .dead
1243 else1192 else
1244 try self.genPtrBinMathOp(inst, bin_op.lhs, bin_op.rhs);1193 try self.genBinOp(inst, bin_op.lhs, bin_op.rhs);
1245 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });1194 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1246}1195}
12471196
...@@ -1250,7 +1199,7 @@ fn airPtrSub(self: *Self, inst: Air.Inst.Index) !void {...@@ -1250,7 +1199,7 @@ fn airPtrSub(self: *Self, inst: Air.Inst.Index) !void {
1250 const result = if (self.liveness.isUnused(inst))1199 const result = if (self.liveness.isUnused(inst))
1251 .dead1200 .dead
1252 else1201 else
1253 try self.genPtrBinMathOp(inst, bin_op.lhs, bin_op.rhs);1202 try self.genBinOp(inst, bin_op.lhs, bin_op.rhs);
1254 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });1203 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1255}1204}
12561205
...@@ -1275,21 +1224,12 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void {...@@ -1275,21 +1224,12 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void {
1275 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });1224 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1276}1225}
12771226
1278fn airAdd(self: *Self, inst: Air.Inst.Index) !void {1227fn airBinOp(self: *Self, inst: Air.Inst.Index) !void {
1279 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1280 const result: MCValue = if (self.liveness.isUnused(inst))
1281 .dead
1282 else
1283 try self.genBinMathOp(inst, bin_op.lhs, bin_op.rhs);
1284 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1285}
1286
1287fn airAddWrap(self: *Self, inst: Air.Inst.Index) !void {
1288 const bin_op = self.air.instructions.items(.data)[inst].bin_op;1228 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1289 const result: MCValue = if (self.liveness.isUnused(inst))1229 const result: MCValue = if (self.liveness.isUnused(inst))
1290 .dead1230 .dead
1291 else1231 else
1292 try self.genBinMathOp(inst, bin_op.lhs, bin_op.rhs);1232 try self.genBinOp(inst, bin_op.lhs, bin_op.rhs);
1293 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });1233 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1294}1234}
12951235
...@@ -1302,60 +1242,6 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void {...@@ -1302,60 +1242,6 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void {
1302 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });1242 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1303}1243}
13041244
1305/// Result is always a register.
1306fn genSubOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs: Air.Inst.Ref) !MCValue {
1307 const dst_ty = self.air.typeOf(op_lhs);
1308
1309 const lhs = try self.resolveInst(op_lhs);
1310 const lhs_lock: ?RegisterLock = switch (lhs) {
1311 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
1312 else => null,
1313 };
1314 defer if (lhs_lock) |lock| self.register_manager.unlockReg(lock);
1315
1316 const rhs = try self.resolveInst(op_rhs);
1317 const rhs_lock: ?RegisterLock = switch (rhs) {
1318 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
1319 else => null,
1320 };
1321 defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock);
1322
1323 const dst_mcv: MCValue = blk: {
1324 if (self.reuseOperand(inst, op_lhs, 0, lhs) and lhs.isRegister()) {
1325 break :blk lhs;
1326 }
1327 break :blk try self.copyToRegisterWithInstTracking(inst, dst_ty, lhs);
1328 };
1329 const dst_mcv_lock: ?RegisterLock = switch (dst_mcv) {
1330 .register => |reg| self.register_manager.lockReg(reg),
1331 else => null,
1332 };
1333 defer if (dst_mcv_lock) |lock| self.register_manager.unlockReg(lock);
1334
1335 const rhs_mcv: MCValue = blk: {
1336 if (rhs.isMemory() or rhs.isRegister()) break :blk rhs;
1337 break :blk MCValue{ .register = try self.copyToTmpRegister(dst_ty, rhs) };
1338 };
1339 const rhs_mcv_lock: ?RegisterLock = switch (rhs_mcv) {
1340 .register => |reg| self.register_manager.lockReg(reg),
1341 else => null,
1342 };
1343 defer if (rhs_mcv_lock) |lock| self.register_manager.unlockReg(lock);
1344
1345 try self.genBinMathOpMir(.sub, dst_ty, dst_mcv, rhs_mcv);
1346
1347 return dst_mcv;
1348}
1349
1350fn airSub(self: *Self, inst: Air.Inst.Index) !void {
1351 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1352 const result: MCValue = if (self.liveness.isUnused(inst))
1353 .dead
1354 else
1355 try self.genSubOp(inst, bin_op.lhs, bin_op.rhs);
1356 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1357}
1358
1359fn airSubSat(self: *Self, inst: Air.Inst.Index) !void {1245fn airSubSat(self: *Self, inst: Air.Inst.Index) !void {
1360 const bin_op = self.air.instructions.items(.data)[inst].bin_op;1246 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1361 const result: MCValue = if (self.liveness.isUnused(inst))1247 const result: MCValue = if (self.liveness.isUnused(inst))
...@@ -1422,7 +1308,7 @@ fn airAddWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1422,7 +1308,7 @@ fn airAddWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
1422 try self.spillCompareFlagsIfOccupied();1308 try self.spillCompareFlagsIfOccupied();
1423 self.compare_flags_inst = inst;1309 self.compare_flags_inst = inst;
14241310
1425 const partial = try self.genBinMathOp(inst, bin_op.lhs, bin_op.rhs);1311 const partial = try self.genBinOp(inst, bin_op.lhs, bin_op.rhs);
1426 const result: MCValue = switch (int_info.signedness) {1312 const result: MCValue = switch (int_info.signedness) {
1427 .signed => .{ .register_overflow_signed = partial.register },1313 .signed => .{ .register_overflow_signed = partial.register },
1428 .unsigned => .{ .register_overflow_unsigned = partial.register },1314 .unsigned => .{ .register_overflow_unsigned = partial.register },
...@@ -1454,7 +1340,7 @@ fn airSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1454,7 +1340,7 @@ fn airSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
1454 try self.spillCompareFlagsIfOccupied();1340 try self.spillCompareFlagsIfOccupied();
1455 self.compare_flags_inst = inst;1341 self.compare_flags_inst = inst;
14561342
1457 const partial = try self.genSubOp(inst, bin_op.lhs, bin_op.rhs);1343 const partial = try self.genBinOp(inst, bin_op.lhs, bin_op.rhs);
1458 const result: MCValue = switch (int_info.signedness) {1344 const result: MCValue = switch (int_info.signedness) {
1459 .signed => .{ .register_overflow_signed = partial.register },1345 .signed => .{ .register_overflow_signed = partial.register },
1460 .unsigned => .{ .register_overflow_unsigned = partial.register },1346 .unsigned => .{ .register_overflow_unsigned = partial.register },
...@@ -1605,7 +1491,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1605,7 +1491,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
1605 const scratch_reg = temp_regs[1];1491 const scratch_reg = temp_regs[1];
1606 try self.genSetReg(extended_ty, scratch_reg, .{ .register = dst_reg });1492 try self.genSetReg(extended_ty, scratch_reg, .{ .register = dst_reg });
1607 try self.truncateRegister(ty, scratch_reg);1493 try self.truncateRegister(ty, scratch_reg);
1608 try self.genBinMathOpMir(1494 try self.genBinOpMir(
1609 .cmp,1495 .cmp,
1610 extended_ty,1496 extended_ty,
1611 .{ .register = dst_reg },1497 .{ .register = dst_reg },
...@@ -1622,7 +1508,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1622,7 +1508,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
1622 .data = undefined,1508 .data = undefined,
1623 });1509 });
16241510
1625 try self.genBinMathOpMir(1511 try self.genBinOpMir(
1626 .@"or",1512 .@"or",
1627 Type.u8,1513 Type.u8,
1628 .{ .register = overflow_reg },1514 .{ .register = overflow_reg },
...@@ -1781,7 +1667,7 @@ fn genInlineIntDivFloor(self: *Self, ty: Type, lhs: MCValue, rhs: MCValue) !MCVa...@@ -1781,7 +1667,7 @@ fn genInlineIntDivFloor(self: *Self, ty: Type, lhs: MCValue, rhs: MCValue) !MCVa
1781 }).encode(),1667 }).encode(),
1782 .data = undefined,1668 .data = undefined,
1783 });1669 });
1784 try self.genBinMathOpMir(.add, Type.isize, .{ .register = divisor }, .{ .register = .rax });1670 try self.genBinOpMir(.add, Type.isize, .{ .register = divisor }, .{ .register = .rax });
1785 return MCValue{ .register = divisor };1671 return MCValue{ .register = divisor };
1786}1672}
17871673
...@@ -1945,7 +1831,7 @@ fn airMod(self: *Self, inst: Air.Inst.Index) !void {...@@ -1945,7 +1831,7 @@ fn airMod(self: *Self, inst: Air.Inst.Index) !void {
1945 try self.genIntMulComplexOpMir(ty, div_floor, rhs);1831 try self.genIntMulComplexOpMir(ty, div_floor, rhs);
19461832
1947 const result = try self.copyToRegisterWithInstTracking(inst, ty, lhs);1833 const result = try self.copyToRegisterWithInstTracking(inst, ty, lhs);
1948 try self.genBinMathOpMir(.sub, ty, result, div_floor);1834 try self.genBinOpMir(.sub, ty, result, div_floor);
19491835
1950 break :result result;1836 break :result result;
1951 },1837 },
...@@ -1955,33 +1841,6 @@ fn airMod(self: *Self, inst: Air.Inst.Index) !void {...@@ -1955,33 +1841,6 @@ fn airMod(self: *Self, inst: Air.Inst.Index) !void {
1955 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });1841 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1956}1842}
19571843
1958fn airBitAnd(self: *Self, inst: Air.Inst.Index) !void {
1959 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1960 const result: MCValue = if (self.liveness.isUnused(inst))
1961 .dead
1962 else
1963 try self.genBinMathOp(inst, bin_op.lhs, bin_op.rhs);
1964 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1965}
1966
1967fn airBitOr(self: *Self, inst: Air.Inst.Index) !void {
1968 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1969 const result: MCValue = if (self.liveness.isUnused(inst))
1970 .dead
1971 else
1972 try self.genBinMathOp(inst, bin_op.lhs, bin_op.rhs);
1973 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1974}
1975
1976fn airXor(self: *Self, inst: Air.Inst.Index) !void {
1977 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1978 const result: MCValue = if (self.liveness.isUnused(inst))
1979 .dead
1980 else
1981 try self.genBinMathOp(inst, bin_op.lhs, bin_op.rhs);
1982 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1983}
1984
1985fn airShl(self: *Self, inst: Air.Inst.Index) !void {1844fn airShl(self: *Self, inst: Air.Inst.Index) !void {
1986 const bin_op = self.air.instructions.items(.data)[inst].bin_op;1845 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1987 if (self.liveness.isUnused(inst)) {1846 if (self.liveness.isUnused(inst)) {
...@@ -1989,6 +1848,7 @@ fn airShl(self: *Self, inst: Air.Inst.Index) !void {...@@ -1989,6 +1848,7 @@ fn airShl(self: *Self, inst: Air.Inst.Index) !void {
1989 }1848 }
19901849
1991 const ty = self.air.typeOfIndex(inst);1850 const ty = self.air.typeOfIndex(inst);
1851
1992 const tag = self.air.instructions.items(.tag)[inst];1852 const tag = self.air.instructions.items(.tag)[inst];
1993 switch (tag) {1853 switch (tag) {
1994 .shl_exact => return self.fail("TODO implement {} for type {}", .{ tag, ty.fmtDebug() }),1854 .shl_exact => return self.fail("TODO implement {} for type {}", .{ tag, ty.fmtDebug() }),
...@@ -2470,7 +2330,7 @@ fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue {...@@ -2470,7 +2330,7 @@ fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue {
2470 }2330 }
2471 // TODO we could allocate register here, but need to expect addr register and potentially2331 // TODO we could allocate register here, but need to expect addr register and potentially
2472 // offset register.2332 // offset register.
2473 try self.genBinMathOpMir(.add, slice_ptr_field_type, .{ .register = addr_reg }, .{2333 try self.genBinOpMir(.add, slice_ptr_field_type, .{ .register = addr_reg }, .{
2474 .register = offset_reg,2334 .register = offset_reg,
2475 });2335 });
2476 return MCValue{ .register = addr_reg.to64() };2336 return MCValue{ .register = addr_reg.to64() };
...@@ -2573,7 +2433,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -2573,7 +2433,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
2573 // TODO we could allocate register here, but need to expect addr register and potentially2433 // TODO we could allocate register here, but need to expect addr register and potentially
2574 // offset register.2434 // offset register.
2575 const dst_mcv = try self.allocRegOrMem(inst, false);2435 const dst_mcv = try self.allocRegOrMem(inst, false);
2576 try self.genBinMathOpMir(.add, Type.usize, .{ .register = addr_reg }, .{ .register = offset_reg });2436 try self.genBinOpMir(.add, Type.usize, .{ .register = addr_reg }, .{ .register = offset_reg });
2577 try self.load(dst_mcv, .{ .register = addr_reg.to64() }, array_ty);2437 try self.load(dst_mcv, .{ .register = addr_reg.to64() }, array_ty);
25782438
2579 return self.finishAir(inst, dst_mcv, .{ bin_op.lhs, bin_op.rhs, .none });2439 return self.finishAir(inst, dst_mcv, .{ bin_op.lhs, bin_op.rhs, .none });
...@@ -2613,7 +2473,7 @@ fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -2613,7 +2473,7 @@ fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void {
2613 defer self.register_manager.unlockReg(offset_reg_lock);2473 defer self.register_manager.unlockReg(offset_reg_lock);
26142474
2615 const dst_mcv = try self.copyToRegisterWithInstTracking(inst, ptr_ty, ptr);2475 const dst_mcv = try self.copyToRegisterWithInstTracking(inst, ptr_ty, ptr);
2616 try self.genBinMathOpMir(.add, ptr_ty, dst_mcv, .{ .register = offset_reg });2476 try self.genBinOpMir(.add, ptr_ty, dst_mcv, .{ .register = offset_reg });
26172477
2618 const result: MCValue = result: {2478 const result: MCValue = result: {
2619 if (elem_abi_size > 8) {2479 if (elem_abi_size > 8) {
...@@ -2667,7 +2527,7 @@ fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -2667,7 +2527,7 @@ fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void {
2667 defer self.register_manager.unlockReg(offset_reg_lock);2527 defer self.register_manager.unlockReg(offset_reg_lock);
26682528
2669 const dst_mcv = try self.copyToRegisterWithInstTracking(inst, ptr_ty, ptr);2529 const dst_mcv = try self.copyToRegisterWithInstTracking(inst, ptr_ty, ptr);
2670 try self.genBinMathOpMir(.add, ptr_ty, dst_mcv, .{ .register = offset_reg });2530 try self.genBinOpMir(.add, ptr_ty, dst_mcv, .{ .register = offset_reg });
26712531
2672 return self.finishAir(inst, dst_mcv, .{ extra.lhs, extra.rhs, .none });2532 return self.finishAir(inst, dst_mcv, .{ extra.lhs, extra.rhs, .none });
2673}2533}
...@@ -2700,7 +2560,7 @@ fn airSetUnionTag(self: *Self, inst: Air.Inst.Index) !void {...@@ -2700,7 +2560,7 @@ fn airSetUnionTag(self: *Self, inst: Air.Inst.Index) !void {
2700 const adjusted_ptr: MCValue = if (layout.payload_size > 0 and layout.tag_align < layout.payload_align) blk: {2560 const adjusted_ptr: MCValue = if (layout.payload_size > 0 and layout.tag_align < layout.payload_align) blk: {
2701 // TODO reusing the operand2561 // TODO reusing the operand
2702 const reg = try self.copyToTmpRegister(ptr_ty, ptr);2562 const reg = try self.copyToTmpRegister(ptr_ty, ptr);
2703 try self.genBinMathOpMir(.add, ptr_ty, .{ .register = reg }, .{ .immediate = layout.payload_size });2563 try self.genBinOpMir(.add, ptr_ty, .{ .register = reg }, .{ .immediate = layout.payload_size });
2704 break :blk MCValue{ .register = reg };2564 break :blk MCValue{ .register = reg };
2705 } else ptr;2565 } else ptr;
27062566
...@@ -3267,7 +3127,7 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde...@@ -3267,7 +3127,7 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde
3267 defer self.register_manager.unlockReg(offset_reg_lock);3127 defer self.register_manager.unlockReg(offset_reg_lock);
32683128
3269 const dst_mcv = try self.copyToRegisterWithInstTracking(inst, ptr_ty, mcv);3129 const dst_mcv = try self.copyToRegisterWithInstTracking(inst, ptr_ty, mcv);
3270 try self.genBinMathOpMir(.add, ptr_ty, dst_mcv, .{ .register = offset_reg });3130 try self.genBinOpMir(.add, ptr_ty, dst_mcv, .{ .register = offset_reg });
3271 break :result dst_mcv;3131 break :result dst_mcv;
3272 },3132 },
3273 .ptr_stack_offset => |off| {3133 .ptr_stack_offset => |off| {
...@@ -3297,7 +3157,7 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde...@@ -3297,7 +3157,7 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde
3297 const result_reg_lock = self.register_manager.lockReg(result_reg);3157 const result_reg_lock = self.register_manager.lockReg(result_reg);
3298 defer if (result_reg_lock) |lock| self.register_manager.unlockReg(lock);3158 defer if (result_reg_lock) |lock| self.register_manager.unlockReg(lock);
32993159
3300 try self.genBinMathOpMir(.add, ptr_ty, .{ .register = result_reg }, .{ .register = offset_reg });3160 try self.genBinOpMir(.add, ptr_ty, .{ .register = result_reg }, .{ .register = offset_reg });
3301 break :result MCValue{ .register = result_reg };3161 break :result MCValue{ .register = result_reg };
3302 },3162 },
3303 else => return self.fail("TODO implement codegen struct_field_ptr for {}", .{mcv}),3163 else => return self.fail("TODO implement codegen struct_field_ptr for {}", .{mcv}),
...@@ -3357,7 +3217,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -3357,7 +3217,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
3357 const mask = (~@as(u64, 0)) >> mask_shift;3217 const mask = (~@as(u64, 0)) >> mask_shift;
33583218
3359 const tmp_reg = try self.copyToTmpRegister(Type.usize, .{ .immediate = mask });3219 const tmp_reg = try self.copyToTmpRegister(Type.usize, .{ .immediate = mask });
3360 try self.genBinMathOpMir(.@"and", Type.usize, dst_mcv, .{ .register = tmp_reg });3220 try self.genBinOpMir(.@"and", Type.usize, dst_mcv, .{ .register = tmp_reg });
33613221
3362 const signedness: std.builtin.Signedness = blk: {3222 const signedness: std.builtin.Signedness = blk: {
3363 if (struct_field_ty.zigTypeTag() != .Int) break :blk .unsigned;3223 if (struct_field_ty.zigTypeTag() != .Int) break :blk .unsigned;
...@@ -3426,8 +3286,39 @@ fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -3426,8 +3286,39 @@ fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void {
3426}3286}
34273287
3428/// Result is always a register.3288/// Result is always a register.
3429fn genBinMathOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs: Air.Inst.Ref) !MCValue {3289fn genBinOp(
3290 self: *Self,
3291 inst: Air.Inst.Index,
3292 op_lhs: Air.Inst.Ref,
3293 op_rhs: Air.Inst.Ref,
3294) !MCValue {
3295 const tag = self.air.instructions.items(.tag)[inst];
3296 const is_commutative: bool = switch (tag) {
3297 .add,
3298 .addwrap,
3299 .add_with_overflow,
3300 .bool_or,
3301 .bit_or,
3302 .bool_and,
3303 .bit_and,
3304 .xor,
3305 .not,
3306 => true,
3307
3308 .sub,
3309 .subwrap,
3310 .sub_with_overflow,
3311 .mul,
3312 .shl,
3313 .shr,
3314 .ptr_add,
3315 .ptr_sub,
3316 => false,
3317
3318 else => unreachable,
3319 };
3430 const dst_ty = self.air.typeOf(op_lhs);3320 const dst_ty = self.air.typeOf(op_lhs);
3321 const src_ty = self.air.typeOf(op_rhs);
34313322
3432 const lhs = try self.resolveInst(op_lhs);3323 const lhs = try self.resolveInst(op_lhs);
3433 const lhs_lock: ?RegisterLock = switch (lhs) {3324 const lhs_lock: ?RegisterLock = switch (lhs) {
...@@ -3448,7 +3339,7 @@ fn genBinMathOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs:...@@ -3448,7 +3339,7 @@ fn genBinMathOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs:
3448 if (self.reuseOperand(inst, op_lhs, 0, lhs) and lhs.isRegister()) {3339 if (self.reuseOperand(inst, op_lhs, 0, lhs) and lhs.isRegister()) {
3449 break :blk lhs;3340 break :blk lhs;
3450 }3341 }
3451 if (self.reuseOperand(inst, op_rhs, 1, rhs) and rhs.isRegister()) {3342 if (is_commutative and self.reuseOperand(inst, op_rhs, 1, rhs) and rhs.isRegister()) {
3452 flipped = true;3343 flipped = true;
3453 break :blk rhs;3344 break :blk rhs;
3454 }3345 }
...@@ -3463,7 +3354,7 @@ fn genBinMathOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs:...@@ -3463,7 +3354,7 @@ fn genBinMathOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs:
3463 const src_mcv: MCValue = blk: {3354 const src_mcv: MCValue = blk: {
3464 const mcv = if (flipped) lhs else rhs;3355 const mcv = if (flipped) lhs else rhs;
3465 if (mcv.isRegister() or mcv.isMemory()) break :blk mcv;3356 if (mcv.isRegister() or mcv.isMemory()) break :blk mcv;
3466 break :blk MCValue{ .register = try self.copyToTmpRegister(dst_ty, mcv) };3357 break :blk MCValue{ .register = try self.copyToTmpRegister(src_ty, mcv) };
3467 };3358 };
3468 const src_mcv_lock: ?RegisterLock = switch (src_mcv) {3359 const src_mcv_lock: ?RegisterLock = switch (src_mcv) {
3469 .register => |reg| self.register_manager.lockReg(reg),3360 .register => |reg| self.register_manager.lockReg(reg),
...@@ -3471,18 +3362,39 @@ fn genBinMathOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs:...@@ -3471,18 +3362,39 @@ fn genBinMathOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs:
3471 };3362 };
3472 defer if (src_mcv_lock) |lock| self.register_manager.unlockReg(lock);3363 defer if (src_mcv_lock) |lock| self.register_manager.unlockReg(lock);
34733364
3474 const tag = self.air.instructions.items(.tag)[inst];
3475 switch (tag) {3365 switch (tag) {
3476 .add, .addwrap, .add_with_overflow => try self.genBinMathOpMir(.add, dst_ty, dst_mcv, src_mcv),3366 .add,
3477 .bool_or, .bit_or => try self.genBinMathOpMir(.@"or", dst_ty, dst_mcv, src_mcv),3367 .addwrap,
3478 .bool_and, .bit_and => try self.genBinMathOpMir(.@"and", dst_ty, dst_mcv, src_mcv),3368 .add_with_overflow,
3479 .xor, .not => try self.genBinMathOpMir(.xor, dst_ty, dst_mcv, src_mcv),3369 => try self.genBinOpMir(.add, dst_ty, dst_mcv, src_mcv),
3370
3371 .sub,
3372 .subwrap,
3373 .sub_with_overflow,
3374 => try self.genBinOpMir(.sub, dst_ty, dst_mcv, src_mcv),
3375
3376 .ptr_add,
3377 .ptr_sub,
3378 => {
3379 const mir_tag: Mir.Inst.Tag = switch (tag) {
3380 .ptr_add => .add,
3381 .ptr_sub => .sub,
3382 else => unreachable,
3383 };
3384 const elem_size = dst_ty.elemType2().abiSize(self.target.*);
3385 try self.genIntMulComplexOpMir(src_ty, src_mcv, .{ .immediate = elem_size });
3386 try self.genBinOpMir(mir_tag, dst_ty, dst_mcv, src_mcv);
3387 },
3388
3389 .bool_or, .bit_or => try self.genBinOpMir(.@"or", dst_ty, dst_mcv, src_mcv),
3390 .bool_and, .bit_and => try self.genBinOpMir(.@"and", dst_ty, dst_mcv, src_mcv),
3391 .xor, .not => try self.genBinOpMir(.xor, dst_ty, dst_mcv, src_mcv),
3480 else => unreachable,3392 else => unreachable,
3481 }3393 }
3482 return dst_mcv;3394 return dst_mcv;
3483}3395}
34843396
3485fn genBinMathOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !void {3397fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !void {
3486 const abi_size = @intCast(u32, dst_ty.abiSize(self.target.*));3398 const abi_size = @intCast(u32, dst_ty.abiSize(self.target.*));
3487 switch (dst_mcv) {3399 switch (dst_mcv) {
3488 .none => unreachable,3400 .none => unreachable,
...@@ -3504,7 +3416,7 @@ fn genBinMathOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MC...@@ -3504,7 +3416,7 @@ fn genBinMathOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MC
3504 defer if (dst_reg_lock) |lock| self.register_manager.unlockReg(lock);3416 defer if (dst_reg_lock) |lock| self.register_manager.unlockReg(lock);
35053417
3506 const reg = try self.copyToTmpRegister(dst_ty, src_mcv);3418 const reg = try self.copyToTmpRegister(dst_ty, src_mcv);
3507 return self.genBinMathOpMir(mir_tag, dst_ty, dst_mcv, .{ .register = reg });3419 return self.genBinOpMir(mir_tag, dst_ty, dst_mcv, .{ .register = reg });
3508 },3420 },
3509 .register => |src_reg| {3421 .register => |src_reg| {
3510 _ = try self.addInst(.{3422 _ = try self.addInst(.{
...@@ -3536,7 +3448,7 @@ fn genBinMathOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MC...@@ -3536,7 +3448,7 @@ fn genBinMathOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MC
3536 defer if (dst_reg_lock) |lock| self.register_manager.unlockReg(lock);3448 defer if (dst_reg_lock) |lock| self.register_manager.unlockReg(lock);
35373449
3538 const reg = try self.copyToTmpRegister(dst_ty, src_mcv);3450 const reg = try self.copyToTmpRegister(dst_ty, src_mcv);
3539 return self.genBinMathOpMir(mir_tag, dst_ty, dst_mcv, .{ .register = reg });3451 return self.genBinOpMir(mir_tag, dst_ty, dst_mcv, .{ .register = reg });
3540 },3452 },
3541 .stack_offset => |off| {3453 .stack_offset => |off| {
3542 if (off > math.maxInt(i32)) {3454 if (off > math.maxInt(i32)) {
...@@ -3637,7 +3549,7 @@ fn genBinMathOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MC...@@ -3637,7 +3549,7 @@ fn genBinMathOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MC
36373549
3638/// Performs multi-operand integer multiplication between dst_mcv and src_mcv, storing the result in dst_mcv.3550/// Performs multi-operand integer multiplication between dst_mcv and src_mcv, storing the result in dst_mcv.
3639/// Does not support byte-size operands.3551/// Does not support byte-size operands.
3640fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !void {3552fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError!void {
3641 const abi_size = @intCast(u32, dst_ty.abiSize(self.target.*));3553 const abi_size = @intCast(u32, dst_ty.abiSize(self.target.*));
3642 switch (dst_mcv) {3554 switch (dst_mcv) {
3643 .none => unreachable,3555 .none => unreachable,
...@@ -3733,11 +3645,17 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M...@@ -3733,11 +3645,17 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
3733 .data = undefined,3645 .data = undefined,
3734 });3646 });
3735 // copy dst_reg back out3647 // copy dst_reg back out
3736 return self.genSetStack(dst_ty, off, MCValue{ .register = dst_reg }, .{});3648 return self.genSetStack(dst_ty, off, .{ .register = dst_reg }, .{});
3737 },3649 },
3738 .immediate => |imm| {3650 .immediate => {
3739 _ = imm;3651 // copy dst to a register
3740 return self.fail("TODO implement x86 multiply source immediate", .{});3652 const dst_reg = try self.copyToTmpRegister(dst_ty, dst_mcv);
3653 const dst_reg_lock = self.register_manager.lockRegAssumeUnused(dst_reg);
3654 defer self.register_manager.unlockReg(dst_reg_lock);
3655
3656 try self.genIntMulComplexOpMir(dst_ty, .{ .register = dst_reg }, src_mcv);
3657
3658 return self.genSetStack(dst_ty, off, .{ .register = dst_reg }, .{});
3741 },3659 },
3742 .memory, .stack_offset => {3660 .memory, .stack_offset => {
3743 return self.fail("TODO implement x86 multiply source memory", .{});3661 return self.fail("TODO implement x86 multiply source memory", .{});
...@@ -4213,7 +4131,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {...@@ -4213,7 +4131,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
4213 // This instruction supports only signed 32-bit immediates at most.4131 // This instruction supports only signed 32-bit immediates at most.
4214 const src_mcv = try self.limitImmediateType(bin_op.rhs, i32);4132 const src_mcv = try self.limitImmediateType(bin_op.rhs, i32);
42154133
4216 try self.genBinMathOpMir(.cmp, ty, dst_mcv, src_mcv);4134 try self.genBinOpMir(.cmp, ty, dst_mcv, src_mcv);
4217 break :result switch (signedness) {4135 break :result switch (signedness) {
4218 .signed => MCValue{ .compare_flags_signed = op },4136 .signed => MCValue{ .compare_flags_signed = op },
4219 .unsigned => MCValue{ .compare_flags_unsigned = op },4137 .unsigned => MCValue{ .compare_flags_unsigned = op },
...@@ -4606,7 +4524,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, ty: Type, operand: MCValue) !MCValu...@@ -4606,7 +4524,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, ty: Type, operand: MCValue) !MCValu
4606 break :blk if (payload_ty.hasRuntimeBits()) Type.bool else ty;4524 break :blk if (payload_ty.hasRuntimeBits()) Type.bool else ty;
4607 } else ty;4525 } else ty;
46084526
4609 try self.genBinMathOpMir(.cmp, cmp_ty, operand, MCValue{ .immediate = 0 });4527 try self.genBinOpMir(.cmp, cmp_ty, operand, MCValue{ .immediate = 0 });
46104528
4611 return MCValue{ .compare_flags_unsigned = .eq };4529 return MCValue{ .compare_flags_unsigned = .eq };
4612}4530}
...@@ -4629,13 +4547,13 @@ fn isErr(self: *Self, inst: Air.Inst.Index, ty: Type, operand: MCValue) !MCValue...@@ -4629,13 +4547,13 @@ fn isErr(self: *Self, inst: Air.Inst.Index, ty: Type, operand: MCValue) !MCValue
46294547
4630 if (!payload_type.hasRuntimeBits()) {4548 if (!payload_type.hasRuntimeBits()) {
4631 if (err_type.abiSize(self.target.*) <= 8) {4549 if (err_type.abiSize(self.target.*) <= 8) {
4632 try self.genBinMathOpMir(.cmp, err_type, operand, MCValue{ .immediate = 0 });4550 try self.genBinOpMir(.cmp, err_type, operand, MCValue{ .immediate = 0 });
4633 return MCValue{ .compare_flags_unsigned = .gt };4551 return MCValue{ .compare_flags_unsigned = .gt };
4634 } else {4552 } else {
4635 return self.fail("TODO isErr for errors with size larger than register size", .{});4553 return self.fail("TODO isErr for errors with size larger than register size", .{});
4636 }4554 }
4637 } else {4555 } else {
4638 try self.genBinMathOpMir(.cmp, err_type, operand, MCValue{ .immediate = 0 });4556 try self.genBinOpMir(.cmp, err_type, operand, MCValue{ .immediate = 0 });
4639 return MCValue{ .compare_flags_unsigned = .gt };4557 return MCValue{ .compare_flags_unsigned = .gt };
4640 }4558 }
4641}4559}
...@@ -5053,21 +4971,6 @@ fn airBr(self: *Self, inst: Air.Inst.Index) !void {...@@ -5053,21 +4971,6 @@ fn airBr(self: *Self, inst: Air.Inst.Index) !void {
5053 return self.finishAir(inst, .dead, .{ branch.operand, .none, .none });4971 return self.finishAir(inst, .dead, .{ branch.operand, .none, .none });
5054}4972}
50554973
5056fn airBoolOp(self: *Self, inst: Air.Inst.Index) !void {
5057 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
5058 const air_tags = self.air.instructions.items(.tag);
5059 const result: MCValue = if (self.liveness.isUnused(inst))
5060 .dead
5061 else switch (air_tags[inst]) {
5062 // lhs AND rhs
5063 .bool_and => try self.genBinMathOp(inst, bin_op.lhs, bin_op.rhs),
5064 // lhs OR rhs
5065 .bool_or => try self.genBinMathOp(inst, bin_op.lhs, bin_op.rhs),
5066 else => unreachable, // Not a boolean operation
5067 };
5068 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
5069}
5070
5071fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void {4974fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void {
5072 const block_data = self.blocks.getPtr(block).?;4975 const block_data = self.blocks.getPtr(block).?;
50734976
...@@ -5844,7 +5747,7 @@ fn genInlineMemset(...@@ -5844,7 +5747,7 @@ fn genInlineMemset(
5844 defer self.register_manager.unlockReg(addr_reg_lock);5747 defer self.register_manager.unlockReg(addr_reg_lock);
58455748
5846 try self.genSetReg(Type.usize, .rax, len);5749 try self.genSetReg(Type.usize, .rax, len);
5847 try self.genBinMathOpMir(.sub, Type.usize, .{ .register = .rax }, .{ .immediate = 1 });5750 try self.genBinOpMir(.sub, Type.usize, .{ .register = .rax }, .{ .immediate = 1 });
58485751
5849 // loop:5752 // loop:
5850 // cmp rax, -15753 // cmp rax, -1
...@@ -6963,10 +6866,10 @@ fn truncateRegister(self: *Self, ty: Type, reg: Register) !void {...@@ -6963,10 +6866,10 @@ fn truncateRegister(self: *Self, ty: Type, reg: Register) !void {
6963 const shift = @intCast(u6, max_reg_bit_width - int_info.bits);6866 const shift = @intCast(u6, max_reg_bit_width - int_info.bits);
6964 const mask = (~@as(u64, 0)) >> shift;6867 const mask = (~@as(u64, 0)) >> shift;
6965 if (int_info.bits <= 32) {6868 if (int_info.bits <= 32) {
6966 try self.genBinMathOpMir(.@"and", Type.usize, .{ .register = reg }, .{ .immediate = mask });6869 try self.genBinOpMir(.@"and", Type.usize, .{ .register = reg }, .{ .immediate = mask });
6967 } else {6870 } else {
6968 const tmp_reg = try self.copyToTmpRegister(Type.usize, .{ .immediate = mask });6871 const tmp_reg = try self.copyToTmpRegister(Type.usize, .{ .immediate = mask });
6969 try self.genBinMathOpMir(.@"and", Type.usize, .{ .register = reg }, .{ .register = tmp_reg });6872 try self.genBinOpMir(.@"and", Type.usize, .{ .register = reg }, .{ .register = tmp_reg });
6970 }6873 }
6971 },6874 },
6972 }6875 }