Author: Carl Friedrich Bolz-Tereick <cfb...@gmx.de> Branch: regalloc-playground Changeset: r92233:f68f729a80cf Date: 2017-08-23 18:33 +0200 http://bitbucket.org/pypy/pypy/changeset/f68f729a80cf/
Log: use the regular spill heuristics to chose the variables to spill before a call diff --git a/rpython/jit/backend/llsupport/regalloc.py b/rpython/jit/backend/llsupport/regalloc.py --- a/rpython/jit/backend/llsupport/regalloc.py +++ b/rpython/jit/backend/llsupport/regalloc.py @@ -418,20 +418,24 @@ return loc def _pick_variable_to_spill(self, v, forbidden_vars, selected_reg=None, - need_lower_byte=False): + need_lower_byte=False, vars=None): + # YYY v is unused, remove + # try to spill a variable that has no further real usages, ie that only # appears in failargs or in a jump # if that doesn't exist, spill the variable that has a real_usage that # is the furthest away from the current position # YYY check for fixed variable usages + if vars is None: + vars = self.reg_bindings.keys() cur_max_use_distance = -1 position = self.position candidate = None cur_max_age_failargs = -1 candidate_from_failargs = None - for next in self.reg_bindings: + for next in vars: reg = self.reg_bindings[next] if next in forbidden_vars: continue @@ -696,46 +700,31 @@ else: # this is a register like eax/rax, which needs either # spilling or moving. - move_or_spill.append((v, max_age)) + move_or_spill.append(v) if len(move_or_spill) > 0: - while len(self.free_regs) > 0: - # YYY here we need to use the new information to pick stuff - new_reg = self.free_regs.pop() - if new_reg in self.save_around_call_regs: - new_free_regs.append(new_reg) # not this register... - continue - # This 'new_reg' is suitable for moving a candidate to. - # Pick the one with the smallest max_age. (This - # is one step of a naive sorting algo, slow in theory, - # but the list should always be very small so it - # doesn't matter.) - best_i = 0 - smallest_max_age = move_or_spill[0][1] - for i in range(1, len(move_or_spill)): - max_age = move_or_spill[i][1] - if max_age < smallest_max_age: - best_i = i - smallest_max_age = max_age - v, max_age = move_or_spill.pop(best_i) - # move from 'reg' to 'new_reg' + free_regs = [reg for reg in self.free_regs + if reg not in self.save_around_call_regs] + # chose which to spill using the usual spill heuristics + while len(move_or_spill) > len(free_regs): + v = self._pick_variable_to_spill(None, [], vars=move_or_spill) + self._bc_spill(v, new_free_regs) + move_or_spill.remove(v) + assert len(move_or_spill) <= len(free_regs) + for v in move_or_spill: + # search next good reg + new_reg = None + while True: + new_reg = self.free_regs.pop() + if new_reg in self.save_around_call_regs: + new_free_regs.append(new_reg) # not this register... + continue + break + assert new_reg is not None # must succeed reg = self.reg_bindings[v] - if not we_are_translated(): - if move_or_spill: - assert max_age <= min([_a for _, _a in move_or_spill]) - assert reg in save_sublist - assert reg in self.save_around_call_regs - assert new_reg not in self.save_around_call_regs self.assembler.regalloc_mov(reg, new_reg) self.reg_bindings[v] = new_reg # change the binding new_free_regs.append(reg) - # - if len(move_or_spill) == 0: - break - else: - # no more free registers to move to, spill the rest - for v, max_age in move_or_spill: - self._bc_spill(v, new_free_regs) # re-add registers in 'new_free_regs', but in reverse order, # so that the last ones (added just above, from diff --git a/rpython/jit/backend/llsupport/test/test_regalloc.py b/rpython/jit/backend/llsupport/test/test_regalloc.py --- a/rpython/jit/backend/llsupport/test/test_regalloc.py +++ b/rpython/jit/backend/llsupport/test/test_regalloc.py @@ -617,6 +617,7 @@ assembler=asm) for b in boxes[:-1]: rm.force_allocate_reg(b) + rm.position = 0 rm.before_call() assert len(rm.reg_bindings) == 2 assert fm.get_frame_depth() == 2 @@ -1236,3 +1237,35 @@ ('guard_false', r0, []) ] + def test_call_spill_furthest_use(self): + # here, i2 should be spilled, because its use is farther away + ops = ''' + [i0, i1, i2, i3, i4, i5, i6] + i8 = call_i(ConstClass(f2ptr), i0, i1, descr=f2_calldescr) + escape_i(i3) + escape_i(i2) + guard_false(i8) [i2, i3, i4, i5, i6] + ''' + emitted = self.allocate(ops, [r1, r2, r0, r3, r4, r5, r6]) + fp0 = FakeFramePos(0, INT) + assert emitted == [ + ('move', fp0, r0), + ('move', r7, r3), + ('call_i', r0, [r1, r2]), + ('escape_i', r1, [r7]), + ('escape_i', r1, [fp0]), + ('guard_false', r0, [fp0, r7, r4, r5, r6]) + ] + + def test_call_spill(self): + py.test.skip("also messy") + # i0 dies, i1 is the argument, the other fight for caller-saved regs + # all_regs = [r0, r1, r2, r3, r4, r5, r6, r7] + # save_around_call_regs = [r0, r1, r2, r3] + ops = ''' + [i0, i1, i2, i3, i4, i5, i6] + i8 = call_i(ConstClass(f2ptr), i1, i0, descr=f2_calldescr) + guard_false(i8) [i2, i3, i4, i5, i6] + ''' + emitted = self.allocate(ops, [r5, r1, r0, r2, r3, r6, r7]) + assert emitted == ["???"] _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit