authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-05-10 09:04:39+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-05-10 09:04:39+02:00
logaf3ecd04b4377db7104a2d37d462f0f4b3e3db84
treed29259d4bec5c023630e7d2be289c835d129069c
parent252c5a2339820d15bc7a063cdd68cc65b49ed413

x64: make genBinOp operate on MCValues directly


1 files changed, 84 insertions(+), 54 deletions(-)

src/arch/x86_64/CodeGen.zig+84-54
......@@ -1089,8 +1089,15 @@ fn airBoolToInt(self: *Self, inst: Air.Inst.Index) !void {
10891089
10901090fn airNot(self: *Self, inst: Air.Inst.Index) !void {
10911091 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1092 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1093 const operand = try self.resolveInst(ty_op.operand);
1092
1093 if (self.liveness.isUnused(inst)) {
1094 return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none });
1095 }
1096
1097 const operand_ty = self.air.typeOf(ty_op.operand);
1098 const operand = try self.resolveInst(ty_op.operand);
1099
1100 const result: MCValue = result: {
10941101 switch (operand) {
10951102 .dead => unreachable,
10961103 .unreach => unreachable,
......@@ -1122,7 +1129,28 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {
11221129 },
11231130 else => {},
11241131 }
1125 break :result try self.genBinOp(.not, inst, ty_op.operand, .bool_true);
1132
1133 const operand_lock: ?RegisterLock = switch (operand) {
1134 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
1135 else => null,
1136 };
1137 defer if (operand_lock) |lock| self.register_manager.unlockReg(lock);
1138
1139 const dst_mcv: MCValue = blk: {
1140 if (self.reuseOperand(inst, ty_op.operand, 0, operand) and operand.isRegister()) {
1141 break :blk operand;
1142 }
1143 break :blk try self.copyToRegisterWithInstTracking(inst, operand_ty, operand);
1144 };
1145 const dst_mcv_lock: ?RegisterLock = switch (dst_mcv) {
1146 .register => |reg| self.register_manager.lockReg(reg),
1147 else => null,
1148 };
1149 defer if (dst_mcv_lock) |lock| self.register_manager.unlockReg(lock);
1150
1151 try self.genBinOpMir(.xor, operand_ty, dst_mcv, .{ .immediate = 1 });
1152
1153 break :result dst_mcv;
11261154 };
11271155 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
11281156}
......@@ -1214,7 +1242,13 @@ fn airBinOp(self: *Self, inst: Air.Inst.Index) !void {
12141242 }
12151243
12161244 const tag = self.air.instructions.items(.tag)[inst];
1217 const result = try self.genBinOp(tag, inst, bin_op.lhs, bin_op.rhs);
1245 const lhs = try self.resolveInst(bin_op.lhs);
1246 const rhs = try self.resolveInst(bin_op.rhs);
1247 const lhs_ty = self.air.typeOf(bin_op.lhs);
1248 const rhs_ty = self.air.typeOf(bin_op.rhs);
1249
1250 const result = try self.genBinOp(tag, inst, lhs, rhs, lhs_ty, rhs_ty);
1251
12181252 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
12191253}
12201254
......@@ -1263,7 +1297,10 @@ fn airAddWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
12631297 try self.spillCompareFlagsIfOccupied();
12641298 self.compare_flags_inst = inst;
12651299
1266 const partial = try self.genBinOp(.add, inst, bin_op.lhs, bin_op.rhs);
1300 const lhs = try self.resolveInst(bin_op.lhs);
1301 const rhs = try self.resolveInst(bin_op.rhs);
1302
1303 const partial = try self.genBinOp(.add, null, lhs, rhs, ty, ty);
12671304 const result: MCValue = switch (int_info.signedness) {
12681305 .signed => .{ .register_overflow_signed = partial.register },
12691306 .unsigned => .{ .register_overflow_unsigned = partial.register },
......@@ -1295,7 +1332,10 @@ fn airSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
12951332 try self.spillCompareFlagsIfOccupied();
12961333 self.compare_flags_inst = inst;
12971334
1298 const partial = try self.genBinOp(.sub, inst, bin_op.lhs, bin_op.rhs);
1335 const lhs = try self.resolveInst(bin_op.lhs);
1336 const rhs = try self.resolveInst(bin_op.rhs);
1337
1338 const partial = try self.genBinOp(.sub, null, lhs, rhs, ty, ty);
12991339 const result: MCValue = switch (int_info.signedness) {
13001340 .signed => .{ .register_overflow_signed = partial.register },
13011341 .unsigned => .{ .register_overflow_unsigned = partial.register },
......@@ -1330,9 +1370,12 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
13301370
13311371 try self.spillCompareFlagsIfOccupied();
13321372
1373 const lhs = try self.resolveInst(bin_op.lhs);
1374 const rhs = try self.resolveInst(bin_op.rhs);
1375
13331376 if (math.isPowerOfTwo(int_info.bits)) {
13341377 self.compare_flags_inst = inst;
1335 const partial = try self.genBinOp(.mul, inst, bin_op.lhs, bin_op.rhs);
1378 const partial = try self.genBinOp(.mul, null, lhs, rhs, ty, ty);
13361379 break :result switch (int_info.signedness) {
13371380 .signed => MCValue{ .register_overflow_signed = partial.register },
13381381 .unsigned => MCValue{ .register_overflow_unsigned = partial.register },
......@@ -1344,9 +1387,6 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
13441387 const dst_reg: Register = dst_reg: {
13451388 switch (int_info.signedness) {
13461389 .signed => {
1347 const lhs = try self.resolveInst(bin_op.lhs);
1348 const rhs = try self.resolveInst(bin_op.rhs);
1349
13501390 const rhs_lock: ?RegisterLock = switch (rhs) {
13511391 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
13521392 else => null,
......@@ -1375,7 +1415,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
13751415 break :dst_reg dst_reg;
13761416 },
13771417 .unsigned => {
1378 const dst_mcv = try self.genBinOp(.mul, null, bin_op.lhs, bin_op.rhs);
1418 const dst_mcv = try self.genBinOp(.mul, null, lhs, rhs, ty, ty);
13791419 break :dst_reg dst_mcv.register;
13801420 },
13811421 }
......@@ -3137,8 +3177,10 @@ fn genBinOp(
31373177 self: *Self,
31383178 tag: Air.Inst.Tag,
31393179 maybe_inst: ?Air.Inst.Index,
3140 op_lhs: Air.Inst.Ref,
3141 op_rhs: Air.Inst.Ref,
3180 lhs: MCValue,
3181 rhs: MCValue,
3182 lhs_ty: Type,
3183 rhs_ty: Type,
31423184) !MCValue {
31433185 const is_commutative: bool = switch (tag) {
31443186 .add,
......@@ -3148,7 +3190,6 @@ fn genBinOp(
31483190 .bool_and,
31493191 .bit_and,
31503192 .xor,
3151 .not,
31523193 => true,
31533194
31543195 .sub,
......@@ -3169,14 +3210,12 @@ fn genBinOp(
31693210
31703211 else => unreachable,
31713212 };
3172 const dst_ty = self.air.typeOf(op_lhs);
3173 const src_ty = self.air.typeOf(op_rhs);
31743213
3175 if (dst_ty.zigTypeTag() == .Vector or dst_ty.zigTypeTag() == .Float) {
3176 return self.fail("TODO implement genBinOp for {}", .{dst_ty.fmtDebug()});
3214 if (lhs_ty.zigTypeTag() == .Vector or lhs_ty.zigTypeTag() == .Float) {
3215 return self.fail("TODO implement genBinOp for {}", .{lhs_ty.fmtDebug()});
31773216 }
3178 if (dst_ty.abiSize(self.target.*) > 8) {
3179 return self.fail("TODO implement genBinOp for {}", .{dst_ty.fmtDebug()});
3217 if (lhs_ty.abiSize(self.target.*) > 8) {
3218 return self.fail("TODO implement genBinOp for {}", .{lhs_ty.fmtDebug()});
31803219 }
31813220
31823221 switch (tag) {
......@@ -3191,24 +3230,21 @@ fn genBinOp(
31913230 self.register_manager.unlockReg(reg);
31923231 };
31933232
3194 const lhs = try self.resolveInst(op_lhs);
3195 const rhs = try self.resolveInst(op_rhs);
3196
3197 const int_info = dst_ty.intInfo(self.target.*);
3233 const int_info = lhs_ty.intInfo(self.target.*);
31983234 try self.genIntMulDivOpMir(switch (int_info.signedness) {
31993235 .signed => .imul,
32003236 .unsigned => .mul,
3201 }, dst_ty, int_info.signedness, lhs, rhs);
3237 }, lhs_ty, int_info.signedness, lhs, rhs);
32023238
32033239 return switch (int_info.signedness) {
32043240 .signed => MCValue{ .register = .rax },
3205 .unsigned => MCValue{ .register = registerAlias(.rax, @intCast(u32, dst_ty.abiSize(self.target.*))) },
3241 .unsigned => MCValue{ .register = registerAlias(.rax, @intCast(u32, lhs_ty.abiSize(self.target.*))) },
32063242 };
32073243 },
32083244 .mod,
32093245 .rem,
32103246 => {
3211 const int_info = dst_ty.intInfo(self.target.*);
3247 const int_info = lhs_ty.intInfo(self.target.*);
32123248 const track_inst_rdx: ?Air.Inst.Index = switch (tag) {
32133249 .mod => if (int_info.signedness == .unsigned) maybe_inst else null,
32143250 .rem => maybe_inst,
......@@ -3223,27 +3259,24 @@ fn genBinOp(
32233259 self.register_manager.unlockReg(reg);
32243260 };
32253261
3226 const lhs = try self.resolveInst(op_lhs);
3227 const rhs = try self.resolveInst(op_rhs);
3228
32293262 switch (int_info.signedness) {
32303263 .signed => {
32313264 switch (tag) {
32323265 .rem => {
3233 try self.genIntMulDivOpMir(.idiv, dst_ty, .signed, lhs, rhs);
3266 try self.genIntMulDivOpMir(.idiv, lhs_ty, .signed, lhs, rhs);
32343267 return MCValue{ .register = .rdx };
32353268 },
32363269 .mod => {
3237 const div_floor = try self.genInlineIntDivFloor(dst_ty, lhs, rhs);
3238 try self.genIntMulComplexOpMir(dst_ty, div_floor, rhs);
3270 const div_floor = try self.genInlineIntDivFloor(lhs_ty, lhs, rhs);
3271 try self.genIntMulComplexOpMir(lhs_ty, div_floor, rhs);
32393272 const div_floor_lock = self.register_manager.lockReg(div_floor.register);
32403273 defer if (div_floor_lock) |lock| self.register_manager.unlockReg(lock);
32413274
32423275 const result: MCValue = if (maybe_inst) |inst|
3243 try self.copyToRegisterWithInstTracking(inst, dst_ty, lhs)
3276 try self.copyToRegisterWithInstTracking(inst, lhs_ty, lhs)
32443277 else
3245 MCValue{ .register = try self.copyToTmpRegister(dst_ty, lhs) };
3246 try self.genBinOpMir(.sub, dst_ty, result, div_floor);
3278 MCValue{ .register = try self.copyToTmpRegister(lhs_ty, lhs) };
3279 try self.genBinOpMir(.sub, lhs_ty, result, div_floor);
32473280
32483281 return result;
32493282 },
......@@ -3251,7 +3284,7 @@ fn genBinOp(
32513284 }
32523285 },
32533286 .unsigned => {
3254 try self.genIntMulDivOpMir(.div, dst_ty, .unsigned, lhs, rhs);
3287 try self.genIntMulDivOpMir(.div, lhs_ty, .unsigned, lhs, rhs);
32553288 return MCValue{ .register = .rdx };
32563289 },
32573290 }
......@@ -3259,14 +3292,12 @@ fn genBinOp(
32593292 else => {},
32603293 }
32613294
3262 const lhs = try self.resolveInst(op_lhs);
32633295 const lhs_lock: ?RegisterLock = switch (lhs) {
32643296 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
32653297 else => null,
32663298 };
32673299 defer if (lhs_lock) |lock| self.register_manager.unlockReg(lock);
32683300
3269 const rhs = try self.resolveInst(op_rhs);
32703301 const rhs_lock: ?RegisterLock = switch (rhs) {
32713302 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
32723303 else => null,
......@@ -3276,16 +3307,17 @@ fn genBinOp(
32763307 var flipped: bool = false;
32773308 const dst_mcv: MCValue = blk: {
32783309 if (maybe_inst) |inst| {
3279 if (self.reuseOperand(inst, op_lhs, 0, lhs) and lhs.isRegister()) {
3310 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
3311 if (self.reuseOperand(inst, bin_op.lhs, 0, lhs) and lhs.isRegister()) {
32803312 break :blk lhs;
32813313 }
3282 if (is_commutative and self.reuseOperand(inst, op_rhs, 1, rhs) and rhs.isRegister()) {
3314 if (is_commutative and self.reuseOperand(inst, bin_op.rhs, 1, rhs) and rhs.isRegister()) {
32833315 flipped = true;
32843316 break :blk rhs;
32853317 }
3286 break :blk try self.copyToRegisterWithInstTracking(inst, dst_ty, lhs);
3318 break :blk try self.copyToRegisterWithInstTracking(inst, lhs_ty, lhs);
32873319 }
3288 break :blk MCValue{ .register = try self.copyToTmpRegister(dst_ty, lhs) };
3320 break :blk MCValue{ .register = try self.copyToTmpRegister(lhs_ty, lhs) };
32893321 };
32903322 const dst_mcv_lock: ?RegisterLock = switch (dst_mcv) {
32913323 .register => |reg| self.register_manager.lockReg(reg),
......@@ -3296,7 +3328,7 @@ fn genBinOp(
32963328 const src_mcv: MCValue = blk: {
32973329 const mcv = if (flipped) lhs else rhs;
32983330 if (mcv.isRegister() or mcv.isMemory()) break :blk mcv;
3299 break :blk MCValue{ .register = try self.copyToTmpRegister(src_ty, mcv) };
3331 break :blk MCValue{ .register = try self.copyToTmpRegister(rhs_ty, mcv) };
33003332 };
33013333 const src_mcv_lock: ?RegisterLock = switch (src_mcv) {
33023334 .register => |reg| self.register_manager.lockReg(reg),
......@@ -3307,11 +3339,11 @@ fn genBinOp(
33073339 switch (tag) {
33083340 .add,
33093341 .addwrap,
3310 => try self.genBinOpMir(.add, dst_ty, dst_mcv, src_mcv),
3342 => try self.genBinOpMir(.add, lhs_ty, dst_mcv, src_mcv),
33113343
33123344 .sub,
33133345 .subwrap,
3314 => try self.genBinOpMir(.sub, dst_ty, dst_mcv, src_mcv),
3346 => try self.genBinOpMir(.sub, lhs_ty, dst_mcv, src_mcv),
33153347
33163348 .ptr_add,
33173349 .ptr_sub,
......@@ -3321,22 +3353,20 @@ fn genBinOp(
33213353 .ptr_sub => .sub,
33223354 else => unreachable,
33233355 };
3324 const elem_size = dst_ty.elemType2().abiSize(self.target.*);
3325 try self.genIntMulComplexOpMir(src_ty, src_mcv, .{ .immediate = elem_size });
3326 try self.genBinOpMir(mir_tag, dst_ty, dst_mcv, src_mcv);
3356 const elem_size = lhs_ty.elemType2().abiSize(self.target.*);
3357 try self.genIntMulComplexOpMir(rhs_ty, src_mcv, .{ .immediate = elem_size });
3358 try self.genBinOpMir(mir_tag, lhs_ty, dst_mcv, src_mcv);
33273359 },
33283360
33293361 .bool_or,
33303362 .bit_or,
3331 => try self.genBinOpMir(.@"or", dst_ty, dst_mcv, src_mcv),
3363 => try self.genBinOpMir(.@"or", lhs_ty, dst_mcv, src_mcv),
33323364
33333365 .bool_and,
33343366 .bit_and,
3335 => try self.genBinOpMir(.@"and", dst_ty, dst_mcv, src_mcv),
3367 => try self.genBinOpMir(.@"and", lhs_ty, dst_mcv, src_mcv),
33363368
3337 .xor,
3338 .not,
3339 => try self.genBinOpMir(.xor, dst_ty, dst_mcv, src_mcv),
3369 .xor => try self.genBinOpMir(.xor, lhs_ty, dst_mcv, src_mcv),
33403370
33413371 else => unreachable,
33423372 }