| ... | @@ -953,15 +953,6 @@ fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register { | ... | @@ -953,15 +953,6 @@ fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register { |
| 953 | return reg; | 953 | return reg; |
| 954 | } | 954 | } |
| 955 | | 955 | |
| 956 | /// Allocates a new register and copies `mcv` into it. | | |
| 957 | /// `reg_owner` is the instruction that gets associated with the register in the register table. | | |
| 958 | /// This can have a side effect of spilling instructions to the stack to free up a register. | | |
| 959 | fn copyToNewRegister(self: *Self, reg_owner: Air.Inst.Index, mcv: MCValue) !MCValue { | | |
| 960 | const reg = try self.register_manager.allocReg(reg_owner, gp); | | |
| 961 | try self.genSetReg(self.air.typeOfIndex(reg_owner), reg, mcv); | | |
| 962 | return MCValue{ .register = reg }; | | |
| 963 | } | | |
| 964 | | | |
| 965 | fn airAlloc(self: *Self, inst: Air.Inst.Index) !void { | 956 | fn airAlloc(self: *Self, inst: Air.Inst.Index) !void { |
| 966 | const stack_offset = try self.allocMemPtr(inst); | 957 | const stack_offset = try self.allocMemPtr(inst); |
| 967 | return self.finishAir(inst, .{ .ptr_stack_offset = stack_offset }, .{ .none, .none, .none }); | 958 | return self.finishAir(inst, .{ .ptr_stack_offset = stack_offset }, .{ .none, .none, .none }); |
| ... | @@ -2185,6 +2176,9 @@ fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_ind | ... | @@ -2185,6 +2176,9 @@ fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_ind |
| 2185 | .stack_offset => |off| { | 2176 | .stack_offset => |off| { |
| 2186 | log.debug("%{d} => stack offset {d} (reused)", .{ inst, off }); | 2177 | log.debug("%{d} => stack offset {d} (reused)", .{ inst, off }); |
| 2187 | }, | 2178 | }, |
| | 2179 | .cpsr_flags => { |
| | 2180 | log.debug("%{d} => cpsr_flags (reused)", .{inst}); |
| | 2181 | }, |
| 2188 | else => return false, | 2182 | else => return false, |
| 2189 | } | 2183 | } |
| 2190 | | 2184 | |
| ... | @@ -2487,7 +2481,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2487,7 +2481,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2487 | else => unreachable, | 2481 | else => unreachable, |
| 2488 | }; | 2482 | }; |
| 2489 | | 2483 | |
| 2490 | if (self.liveness.operandDies(inst, 0)) { | 2484 | if (self.reuseOperand(inst, operand, 0, field)) { |
| 2491 | break :result field; | 2485 | break :result field; |
| 2492 | } else { | 2486 | } else { |
| 2493 | // Copy to new register | 2487 | // Copy to new register |
| ... | @@ -2511,6 +2505,41 @@ fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2511,6 +2505,41 @@ fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 2511 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); | 2505 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 2512 | } | 2506 | } |
| 2513 | | 2507 | |
| | 2508 | /// Allocates a new register. If Inst in non-null, additionally tracks |
| | 2509 | /// this register and the corresponding int and removes all previous |
| | 2510 | /// tracking. Does not do the actual moving (that is handled by |
| | 2511 | /// genSetReg). |
| | 2512 | fn prepareNewRegForMoving( |
| | 2513 | self: *Self, |
| | 2514 | track_inst: ?Air.Inst.Index, |
| | 2515 | register_class: RegisterManager.RegisterBitSet, |
| | 2516 | mcv: MCValue, |
| | 2517 | ) !Register { |
| | 2518 | const branch = &self.branch_stack.items[self.branch_stack.items.len - 1]; |
| | 2519 | const reg = try self.register_manager.allocReg(track_inst, register_class); |
| | 2520 | |
| | 2521 | if (track_inst) |inst| { |
| | 2522 | // Overwrite the MCValue associated with this inst |
| | 2523 | branch.inst_table.putAssumeCapacity(inst, .{ .register = reg }); |
| | 2524 | |
| | 2525 | // If the previous MCValue occupied some space we track, we |
| | 2526 | // need to make sure it is marked as free now. |
| | 2527 | switch (mcv) { |
| | 2528 | .cpsr_flags => { |
| | 2529 | assert(self.cpsr_flags_inst.? == inst); |
| | 2530 | self.cpsr_flags_inst = null; |
| | 2531 | }, |
| | 2532 | .register => |prev_reg| { |
| | 2533 | assert(!self.register_manager.isRegFree(prev_reg)); |
| | 2534 | self.register_manager.freeReg(prev_reg); |
| | 2535 | }, |
| | 2536 | else => {}, |
| | 2537 | } |
| | 2538 | } |
| | 2539 | |
| | 2540 | return reg; |
| | 2541 | } |
| | 2542 | |
| 2514 | /// Don't call this function directly. Use binOp instead. | 2543 | /// Don't call this function directly. Use binOp instead. |
| 2515 | /// | 2544 | /// |
| 2516 | /// Calling this function signals an intention to generate a Mir | 2545 | /// Calling this function signals an intention to generate a Mir |
| ... | @@ -2537,18 +2566,12 @@ fn binOpRegister( | ... | @@ -2537,18 +2566,12 @@ fn binOpRegister( |
| 2537 | null; | 2566 | null; |
| 2538 | defer if (lhs_lock) |reg| self.register_manager.unlockReg(reg); | 2567 | defer if (lhs_lock) |reg| self.register_manager.unlockReg(reg); |
| 2539 | | 2568 | |
| 2540 | const branch = &self.branch_stack.items[self.branch_stack.items.len - 1]; | | |
| 2541 | | | |
| 2542 | const lhs_reg = if (lhs_is_register) lhs.register else blk: { | 2569 | const lhs_reg = if (lhs_is_register) lhs.register else blk: { |
| 2543 | const track_inst: ?Air.Inst.Index = if (metadata) |md| inst: { | 2570 | const track_inst: ?Air.Inst.Index = if (metadata) |md| inst: { |
| 2544 | break :inst Air.refToIndex(md.lhs).?; | 2571 | break :inst Air.refToIndex(md.lhs).?; |
| 2545 | } else null; | 2572 | } else null; |
| 2546 | | 2573 | |
| 2547 | const reg = try self.register_manager.allocReg(track_inst, gp); | 2574 | break :blk try self.prepareNewRegForMoving(track_inst, gp, lhs); |
| 2548 | | | |
| 2549 | if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg }); | | |
| 2550 | | | |
| 2551 | break :blk reg; | | |
| 2552 | }; | 2575 | }; |
| 2553 | const new_lhs_lock = self.register_manager.lockReg(lhs_reg); | 2576 | const new_lhs_lock = self.register_manager.lockReg(lhs_reg); |
| 2554 | defer if (new_lhs_lock) |reg| self.register_manager.unlockReg(reg); | 2577 | defer if (new_lhs_lock) |reg| self.register_manager.unlockReg(reg); |
| ... | @@ -2558,11 +2581,7 @@ fn binOpRegister( | ... | @@ -2558,11 +2581,7 @@ fn binOpRegister( |
| 2558 | break :inst Air.refToIndex(md.rhs).?; | 2581 | break :inst Air.refToIndex(md.rhs).?; |
| 2559 | } else null; | 2582 | } else null; |
| 2560 | | 2583 | |
| 2561 | const reg = try self.register_manager.allocReg(track_inst, gp); | 2584 | break :blk try self.prepareNewRegForMoving(track_inst, gp, rhs); |
| 2562 | | | |
| 2563 | if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg }); | | |
| 2564 | | | |
| 2565 | break :blk reg; | | |
| 2566 | }; | 2585 | }; |
| 2567 | const new_rhs_lock = self.register_manager.lockReg(rhs_reg); | 2586 | const new_rhs_lock = self.register_manager.lockReg(rhs_reg); |
| 2568 | defer if (new_rhs_lock) |reg| self.register_manager.unlockReg(reg); | 2587 | defer if (new_rhs_lock) |reg| self.register_manager.unlockReg(reg); |
| ... | @@ -2652,8 +2671,6 @@ fn binOpImmediate( | ... | @@ -2652,8 +2671,6 @@ fn binOpImmediate( |
| 2652 | null; | 2671 | null; |
| 2653 | defer if (lhs_lock) |reg| self.register_manager.unlockReg(reg); | 2672 | defer if (lhs_lock) |reg| self.register_manager.unlockReg(reg); |
| 2654 | | 2673 | |
| 2655 | const branch = &self.branch_stack.items[self.branch_stack.items.len - 1]; | | |
| 2656 | | | |
| 2657 | const lhs_reg = if (lhs_is_register) lhs.register else blk: { | 2674 | const lhs_reg = if (lhs_is_register) lhs.register else blk: { |
| 2658 | const track_inst: ?Air.Inst.Index = if (metadata) |md| inst: { | 2675 | const track_inst: ?Air.Inst.Index = if (metadata) |md| inst: { |
| 2659 | break :inst Air.refToIndex( | 2676 | break :inst Air.refToIndex( |
| ... | @@ -2661,11 +2678,7 @@ fn binOpImmediate( | ... | @@ -2661,11 +2678,7 @@ fn binOpImmediate( |
| 2661 | ).?; | 2678 | ).?; |
| 2662 | } else null; | 2679 | } else null; |
| 2663 | | 2680 | |
| 2664 | const reg = try self.register_manager.allocReg(track_inst, gp); | 2681 | break :blk try self.prepareNewRegForMoving(track_inst, gp, lhs); |
| 2665 | | | |
| 2666 | if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg }); | | |
| 2667 | | | |
| 2668 | break :blk reg; | | |
| 2669 | }; | 2682 | }; |
| 2670 | const new_lhs_lock = self.register_manager.lockReg(lhs_reg); | 2683 | const new_lhs_lock = self.register_manager.lockReg(lhs_reg); |
| 2671 | defer if (new_lhs_lock) |reg| self.register_manager.unlockReg(reg); | 2684 | defer if (new_lhs_lock) |reg| self.register_manager.unlockReg(reg); |
| ... | @@ -3444,7 +3457,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. | ... | @@ -3444,7 +3457,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. |
| 3444 | if (RegisterManager.indexOfRegIntoTracked(reg) == null) { | 3457 | if (RegisterManager.indexOfRegIntoTracked(reg) == null) { |
| 3445 | // Save function return value into a tracked register | 3458 | // Save function return value into a tracked register |
| 3446 | log.debug("airCall: copying {} as it is not tracked", .{reg}); | 3459 | log.debug("airCall: copying {} as it is not tracked", .{reg}); |
| 3447 | break :result try self.copyToNewRegister(inst, info.return_value); | 3460 | const new_reg = try self.copyToTmpRegister(fn_ty.fnReturnType(), info.return_value); |
| | 3461 | break :result MCValue{ .register = new_reg }; |
| 3448 | } | 3462 | } |
| 3449 | }, | 3463 | }, |
| 3450 | else => {}, | 3464 | else => {}, |
| ... | @@ -4124,7 +4138,7 @@ fn airSwitch(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4124,7 +4138,7 @@ fn airSwitch(self: *Self, inst: Air.Inst.Index) !void { |
| 4124 | var case_i: u32 = 0; | 4138 | var case_i: u32 = 0; |
| 4125 | while (case_i < switch_br.data.cases_len) : (case_i += 1) { | 4139 | while (case_i < switch_br.data.cases_len) : (case_i += 1) { |
| 4126 | const case = self.air.extraData(Air.SwitchBr.Case, extra_index); | 4140 | const case = self.air.extraData(Air.SwitchBr.Case, extra_index); |
| 4127 | const items = @bitCast([]const Air.Inst.Ref, self.air.extra[case.end..][0..case.data.items_len]); | 4141 | const items = @ptrCast([]const Air.Inst.Ref, self.air.extra[case.end..][0..case.data.items_len]); |
| 4128 | assert(items.len > 0); | 4142 | assert(items.len > 0); |
| 4129 | const case_body = self.air.extra[case.end + items.len ..][0..case.data.body_len]; | 4143 | const case_body = self.air.extra[case.end + items.len ..][0..case.data.body_len]; |
| 4130 | extra_index = case.end + items.len + case_body.len; | 4144 | extra_index = case.end + items.len + case_body.len; |