authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-09-02 17:19:14+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-09-07 22:42:56+02:00
logb9c31a8703fdd8297673aa65a1bdefd56cd13b77
tree583448db567d37f7615c8359cb6facdfe513b3b0
parentc0e288c78248870bf9881b25ff8354c67753bbe2

x86_64: refactor cond_br with canonicaliseBranches helper


1 files changed, 2 insertions(+), 64 deletions(-)

src/arch/x86_64/CodeGen.zig+2-64
...@@ -4736,9 +4736,6 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {...@@ -4736,9 +4736,6 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
4736 // that we can use all the code emitting abstractions. This is why at the bottom we4736 // that we can use all the code emitting abstractions. This is why at the bottom we
4737 // assert that parent_branch.free_registers equals the saved_then_branch.free_registers4737 // assert that parent_branch.free_registers equals the saved_then_branch.free_registers
4738 // rather than assigning it.4738 // rather than assigning it.
4739 const parent_branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
4740 try parent_branch.inst_table.ensureUnusedCapacity(self.gpa, else_branch.inst_table.count());
4741
4742 log.debug("Upper branches:", .{});4739 log.debug("Upper branches:", .{});
4743 for (self.branch_stack.items) |bs| {4740 for (self.branch_stack.items) |bs| {
4744 log.debug("{}", .{bs.fmtDebug()});4741 log.debug("{}", .{bs.fmtDebug()});
...@@ -4747,67 +4744,8 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {...@@ -4747,67 +4744,8 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
4747 log.debug("Then branch: {}", .{then_branch.fmtDebug()});4744 log.debug("Then branch: {}", .{then_branch.fmtDebug()});
4748 log.debug("Else branch: {}", .{else_branch.fmtDebug()});4745 log.debug("Else branch: {}", .{else_branch.fmtDebug()});
47494746
4750 const else_slice = else_branch.inst_table.entries.slice();4747 const parent_branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
4751 const else_keys = else_slice.items(.key);4748 try self.canonicaliseBranches(parent_branch, &then_branch, &else_branch);
4752 const else_values = else_slice.items(.value);
4753 for (else_keys) |else_key, else_idx| {
4754 const else_value = else_values[else_idx];
4755 const canon_mcv = if (then_branch.inst_table.fetchSwapRemove(else_key)) |then_entry| blk: {
4756 // The instruction's MCValue is overridden in both branches.
4757 parent_branch.inst_table.putAssumeCapacity(else_key, then_entry.value);
4758 if (else_value == .dead) {
4759 assert(then_entry.value == .dead);
4760 continue;
4761 }
4762 break :blk then_entry.value;
4763 } else blk: {
4764 if (else_value == .dead)
4765 continue;
4766 // The instruction is only overridden in the else branch.
4767 var i: usize = self.branch_stack.items.len - 1;
4768 while (true) {
4769 i -= 1; // If this overflows, the question is: why wasn't the instruction marked dead?
4770 if (self.branch_stack.items[i].inst_table.get(else_key)) |mcv| {
4771 assert(mcv != .dead);
4772 break :blk mcv;
4773 }
4774 }
4775 };
4776 log.debug("consolidating else_entry {d} {}=>{}", .{ else_key, else_value, canon_mcv });
4777 // TODO make sure the destination stack offset / register does not already have something
4778 // going on there.
4779 try self.setRegOrMem(self.air.typeOfIndex(else_key), canon_mcv, else_value);
4780 // TODO track the new register / stack allocation
4781 }
4782 try parent_branch.inst_table.ensureUnusedCapacity(self.gpa, then_branch.inst_table.count());
4783 const then_slice = then_branch.inst_table.entries.slice();
4784 const then_keys = then_slice.items(.key);
4785 const then_values = then_slice.items(.value);
4786 for (then_keys) |then_key, then_idx| {
4787 const then_value = then_values[then_idx];
4788 // We already deleted the items from this table that matched the else_branch.
4789 // So these are all instructions that are only overridden in the then branch.
4790 parent_branch.inst_table.putAssumeCapacity(then_key, then_value);
4791 log.debug("then_value = {}", .{then_value});
4792 if (then_value == .dead)
4793 continue;
4794 const parent_mcv = blk: {
4795 log.debug("{d}", .{self.branch_stack.items.len});
4796 var i: usize = self.branch_stack.items.len - 1;
4797 while (true) {
4798 i -= 1;
4799 if (self.branch_stack.items[i].inst_table.get(then_key)) |mcv| {
4800 assert(mcv != .dead);
4801 break :blk mcv;
4802 }
4803 }
4804 };
4805 log.debug("consolidating then_entry {d} {}=>{}", .{ then_key, parent_mcv, then_value });
4806 // TODO make sure the destination stack offset / register does not already have something
4807 // going on there.
4808 try self.setRegOrMem(self.air.typeOfIndex(then_key), parent_mcv, then_value);
4809 // TODO track the new register / stack allocation
4810 }
48114749
4812 // We already took care of pl_op.operand earlier, so we're going4750 // We already took care of pl_op.operand earlier, so we're going
4813 // to pass .none here4751 // to pass .none here