| ... | @@ -26596,6 +26596,9 @@ fn airLoopSwitchBr(self: *CodeGen, inst: Air.Inst.Index) !void { | ... | @@ -26596,6 +26596,9 @@ fn airLoopSwitchBr(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 26596 | if (switch_br.operand.toIndex()) |op_inst| try self.processDeath(op_inst); | 26596 | if (switch_br.operand.toIndex()) |op_inst| try self.processDeath(op_inst); |
| 26597 | } | 26597 | } |
| 26598 | | 26598 | |
| | 26599 | // Ensure a register is available for dispatch. |
| | 26600 | if (!mat_cond.isRegister()) _ = try self.register_manager.allocReg(null, abi.RegisterClass.gp); |
| | 26601 | |
| 26599 | self.scope_generation += 1; | 26602 | self.scope_generation += 1; |
| 26600 | const state = try self.saveState(); | 26603 | const state = try self.saveState(); |
| 26601 | | 26604 | |
| ... | @@ -26618,47 +26621,63 @@ fn airSwitchDispatch(self: *CodeGen, inst: Air.Inst.Index) !void { | ... | @@ -26618,47 +26621,63 @@ fn airSwitchDispatch(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 26618 | | 26621 | |
| 26619 | const block_ty = self.typeOfIndex(br.block_inst); | 26622 | const block_ty = self.typeOfIndex(br.block_inst); |
| 26620 | const loop_data = self.loops.getPtr(br.block_inst).?; | 26623 | const loop_data = self.loops.getPtr(br.block_inst).?; |
| 26621 | if (self.loop_switches.getPtr(br.block_inst)) |table| { | 26624 | const block_tracking = self.inst_tracking.getPtr(br.block_inst).?; |
| 26622 | // Process operand death so that it is properly accounted for in the State below. | 26625 | { |
| 26623 | const condition_dies = self.liveness.operandDies(inst, 0); | 26626 | try self.getValue(block_tracking.short, null); |
| 26624 | | 26627 | const src_mcv = try self.resolveInst(br.operand); |
| 26625 | try self.restoreState(loop_data.state, &.{}, .{ | 26628 | |
| 26626 | .emit_instructions = true, | 26629 | if (self.reuseOperandAdvanced(inst, br.operand, 0, src_mcv, br.block_inst)) { |
| 26627 | .update_tracking = false, | 26630 | try self.getValue(block_tracking.short, br.block_inst); |
| 26628 | .resurrect = false, | 26631 | // .long = .none to avoid merging operand and block result stack frames. |
| 26629 | .close_scope = false, | 26632 | const current_tracking: InstTracking = .{ .long = .none, .short = src_mcv }; |
| 26630 | }); | 26633 | try current_tracking.materializeUnsafe(self, br.block_inst, block_tracking.*); |
| | 26634 | for (current_tracking.getRegs()) |src_reg| self.register_manager.freeReg(src_reg); |
| | 26635 | } else { |
| | 26636 | try self.getValue(block_tracking.short, br.block_inst); |
| | 26637 | try self.genCopy(block_ty, block_tracking.short, try self.resolveInst(br.operand), .{}); |
| | 26638 | } |
| | 26639 | } |
| 26631 | | 26640 | |
| | 26641 | // Process operand death so that it is properly accounted for in the State below. |
| | 26642 | if (self.liveness.operandDies(inst, 0)) { |
| | 26643 | if (br.operand.toIndex()) |op_inst| try self.processDeath(op_inst); |
| | 26644 | } |
| | 26645 | |
| | 26646 | try self.restoreState(loop_data.state, &.{}, .{ |
| | 26647 | .emit_instructions = true, |
| | 26648 | .update_tracking = false, |
| | 26649 | .resurrect = false, |
| | 26650 | .close_scope = false, |
| | 26651 | }); |
| | 26652 | |
| | 26653 | if (self.loop_switches.getPtr(br.block_inst)) |table| { |
| 26632 | const condition_ty = self.typeOf(br.operand); | 26654 | const condition_ty = self.typeOf(br.operand); |
| 26633 | const condition = try self.resolveInst(br.operand); | 26655 | const condition_mcv = block_tracking.short; |
| 26634 | const condition_index = if (condition_dies and condition.isModifiable()) condition else condition_index: { | | |
| 26635 | const condition_index = try self.allocTempRegOrMem(condition_ty, true); | | |
| 26636 | try self.genCopy(condition_ty, condition_index, condition, .{}); | | |
| 26637 | break :condition_index condition_index; | | |
| 26638 | }; | | |
| 26639 | try self.spillEflagsIfOccupied(); | 26656 | try self.spillEflagsIfOccupied(); |
| 26640 | if (table.min.orderAgainstZero(self.pt.zcu).compare(.neq)) try self.genBinOpMir( | 26657 | if (table.min.orderAgainstZero(self.pt.zcu).compare(.neq)) try self.genBinOpMir( |
| 26641 | .{ ._, .sub }, | 26658 | .{ ._, .sub }, |
| 26642 | condition_ty, | 26659 | condition_ty, |
| 26643 | condition_index, | 26660 | condition_mcv, |
| 26644 | .{ .air_ref = Air.internedToRef(table.min.toIntern()) }, | 26661 | .{ .air_ref = Air.internedToRef(table.min.toIntern()) }, |
| 26645 | ); | 26662 | ); |
| 26646 | switch (table.else_relocs) { | 26663 | switch (table.else_relocs) { |
| 26647 | .@"unreachable" => {}, | 26664 | .@"unreachable" => {}, |
| 26648 | .forward => |*else_relocs| { | 26665 | .forward => |*else_relocs| { |
| 26649 | try self.genBinOpMir(.{ ._, .cmp }, condition_ty, condition_index, .{ .immediate = table.len - 1 }); | 26666 | try self.genBinOpMir(.{ ._, .cmp }, condition_ty, condition_mcv, .{ .immediate = table.len - 1 }); |
| 26650 | try else_relocs.append(self.gpa, try self.asmJccReloc(.a, undefined)); | 26667 | try else_relocs.append(self.gpa, try self.asmJccReloc(.a, undefined)); |
| 26651 | }, | 26668 | }, |
| 26652 | .backward => |else_reloc| { | 26669 | .backward => |else_reloc| { |
| 26653 | try self.genBinOpMir(.{ ._, .cmp }, condition_ty, condition_index, .{ .immediate = table.len - 1 }); | 26670 | try self.genBinOpMir(.{ ._, .cmp }, condition_ty, condition_mcv, .{ .immediate = table.len - 1 }); |
| 26654 | _ = try self.asmJccReloc(.a, else_reloc); | 26671 | _ = try self.asmJccReloc(.a, else_reloc); |
| 26655 | }, | 26672 | }, |
| 26656 | } | 26673 | } |
| 26657 | { | 26674 | { |
| 26658 | const condition_index_reg = if (condition_index.isRegister()) | 26675 | const condition_index_reg = if (condition_mcv.isRegister()) condition_mcv.getReg().? else cond: { |
| 26659 | condition_index.getReg().? | 26676 | const condition_index_reg = |
| 26660 | else | 26677 | RegisterManager.regAtTrackedIndex(@intCast(loop_data.state.free_registers.findFirstSet().?)); |
| 26661 | try self.copyToTmpRegister(.usize, condition_index); | 26678 | try self.genSetReg(condition_index_reg, condition_ty, condition_mcv, .{}); |
| | 26679 | break :cond condition_index_reg; |
| | 26680 | }; |
| 26662 | const condition_index_lock = self.register_manager.lockReg(condition_index_reg); | 26681 | const condition_index_lock = self.register_manager.lockReg(condition_index_reg); |
| 26663 | defer if (condition_index_lock) |lock| self.register_manager.unlockReg(lock); | 26682 | defer if (condition_index_lock) |lock| self.register_manager.unlockReg(lock); |
| 26664 | try self.truncateRegister(condition_ty, condition_index_reg); | 26683 | try self.truncateRegister(condition_ty, condition_index_reg); |
| ... | @@ -26677,38 +26696,6 @@ fn airSwitchDispatch(self: *CodeGen, inst: Air.Inst.Index) !void { | ... | @@ -26677,38 +26696,6 @@ fn airSwitchDispatch(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 26677 | return self.finishAir(inst, .none, .{ br.operand, .none, .none }); | 26696 | return self.finishAir(inst, .none, .{ br.operand, .none, .none }); |
| 26678 | } | 26697 | } |
| 26679 | | 26698 | |
| 26680 | const block_tracking = self.inst_tracking.getPtr(br.block_inst).?; | | |
| 26681 | done: { | | |
| 26682 | try self.getValue(block_tracking.short, null); | | |
| 26683 | const src_mcv = try self.resolveInst(br.operand); | | |
| 26684 | | | |
| 26685 | if (self.reuseOperandAdvanced(inst, br.operand, 0, src_mcv, br.block_inst)) { | | |
| 26686 | try self.getValue(block_tracking.short, br.block_inst); | | |
| 26687 | // .long = .none to avoid merging operand and block result stack frames. | | |
| 26688 | const current_tracking: InstTracking = .{ .long = .none, .short = src_mcv }; | | |
| 26689 | try current_tracking.materializeUnsafe(self, br.block_inst, block_tracking.*); | | |
| 26690 | for (current_tracking.getRegs()) |src_reg| self.register_manager.freeReg(src_reg); | | |
| 26691 | break :done; | | |
| 26692 | } | | |
| 26693 | | | |
| 26694 | try self.getValue(block_tracking.short, br.block_inst); | | |
| 26695 | const dst_mcv = block_tracking.short; | | |
| 26696 | try self.genCopy(block_ty, dst_mcv, try self.resolveInst(br.operand), .{}); | | |
| 26697 | break :done; | | |
| 26698 | } | | |
| 26699 | | | |
| 26700 | // Process operand death so that it is properly accounted for in the State below. | | |
| 26701 | if (self.liveness.operandDies(inst, 0)) { | | |
| 26702 | if (br.operand.toIndex()) |op_inst| try self.processDeath(op_inst); | | |
| 26703 | } | | |
| 26704 | | | |
| 26705 | try self.restoreState(loop_data.state, &.{}, .{ | | |
| 26706 | .emit_instructions = true, | | |
| 26707 | .update_tracking = false, | | |
| 26708 | .resurrect = false, | | |
| 26709 | .close_scope = false, | | |
| 26710 | }); | | |
| 26711 | | | |
| 26712 | // Emit a jump with a relocation. It will be patched up after the block ends. | 26699 | // Emit a jump with a relocation. It will be patched up after the block ends. |
| 26713 | // Leave the jump offset undefined | 26700 | // Leave the jump offset undefined |
| 26714 | _ = try self.asmJmpReloc(loop_data.target); | 26701 | _ = try self.asmJmpReloc(loop_data.target); |