Author: Lukas Diekmann <lukas.diekm...@uni-duesseldorf.de> Branch: Changeset: r50311:6acad4874739 Date: 2011-12-08 17:47 +0100 http://bitbucket.org/pypy/pypy/changeset/6acad4874739/
Log: merge diff --git a/pypy/jit/backend/llsupport/regalloc.py b/pypy/jit/backend/llsupport/regalloc.py --- a/pypy/jit/backend/llsupport/regalloc.py +++ b/pypy/jit/backend/llsupport/regalloc.py @@ -23,9 +23,12 @@ return self.frame_bindings.get(box, None) def loc(self, box): - res = self.get(box) - if res is not None: - return res + try: + return self.frame_bindings[box] + except KeyError: + return self.get_new_loc(box) + + def get_new_loc(self, box): size = self.frame_size(box.type) self.frame_depth += ((-self.frame_depth) & (size-1)) # ^^^ frame_depth is rounded up to a multiple of 'size', assuming @@ -67,8 +70,17 @@ self.position = -1 self.frame_manager = frame_manager self.assembler = assembler + self.hint_frame_locations = {} # {Box: StackLoc} + self.freed_frame_locations = {} # {StackLoc: None} + + def is_still_alive(self, v): + # Check if 'v' is alive at the current position. + # Return False if the last usage is strictly before. + return self.longevity[v][1] >= self.position def stays_alive(self, v): + # Check if 'v' stays alive after the current position. + # Return False if the last usage is before or at position. return self.longevity[v][1] > self.position def next_instruction(self, incr=1): @@ -84,11 +96,16 @@ point for all variables that might be in registers. """ self._check_type(v) - if isinstance(v, Const) or v not in self.reg_bindings: + if isinstance(v, Const): return if v not in self.longevity or self.longevity[v][1] <= self.position: - self.free_regs.append(self.reg_bindings[v]) - del self.reg_bindings[v] + if v in self.reg_bindings: + self.free_regs.append(self.reg_bindings[v]) + del self.reg_bindings[v] + if self.frame_manager is not None: + if v in self.frame_manager.frame_bindings: + loc = self.frame_manager.frame_bindings[v] + self.freed_frame_locations[loc] = None def possibly_free_vars(self, vars): """ Same as 'possibly_free_var', but for all v in vars. @@ -160,6 +177,23 @@ self.reg_bindings[v] = loc return loc + def _frame_loc(self, v): + # first check if it's already in the frame_manager + try: + return self.frame_manager.frame_bindings[v] + except KeyError: + pass + # check if we have a hint for this box + if v in self.hint_frame_locations: + # if we do, check that the hinted location is known to be free + loc = self.hint_frame_locations[v] + if loc in self.freed_frame_locations: + del self.freed_frame_locations[loc] + self.frame_manager.frame_bindings[v] = loc + return loc + # no valid hint. make up a new free location + return self.frame_manager.get_new_loc(v) + def _spill_var(self, v, forbidden_vars, selected_reg, need_lower_byte=False): v_to_spill = self._pick_variable_to_spill(v, forbidden_vars, @@ -167,7 +201,7 @@ loc = self.reg_bindings[v_to_spill] del self.reg_bindings[v_to_spill] if self.frame_manager.get(v_to_spill) is None: - newloc = self.frame_manager.loc(v_to_spill) + newloc = self._frame_loc(v_to_spill) self.assembler.regalloc_mov(loc, newloc) return loc @@ -244,7 +278,7 @@ except KeyError: if box in self.bindings_to_frame_reg: return self.frame_reg - return self.frame_manager.loc(box) + return self._frame_loc(box) def return_constant(self, v, forbidden_vars=[], selected_reg=None): """ Return the location of the constant v. If 'selected_reg' is @@ -292,7 +326,7 @@ self.reg_bindings[v] = loc self.assembler.regalloc_mov(prev_loc, loc) else: - loc = self.frame_manager.loc(v) + loc = self._frame_loc(v) self.assembler.regalloc_mov(prev_loc, loc) def force_result_in_reg(self, result_v, v, forbidden_vars=[]): @@ -311,7 +345,7 @@ self.reg_bindings[result_v] = loc return loc if v not in self.reg_bindings: - prev_loc = self.frame_manager.loc(v) + prev_loc = self._frame_loc(v) loc = self.force_allocate_reg(v, forbidden_vars) self.assembler.regalloc_mov(prev_loc, loc) assert v in self.reg_bindings @@ -331,7 +365,7 @@ def _sync_var(self, v): if not self.frame_manager.get(v): reg = self.reg_bindings[v] - to = self.frame_manager.loc(v) + to = self._frame_loc(v) self.assembler.regalloc_mov(reg, to) # otherwise it's clean diff --git a/pypy/jit/backend/llsupport/test/test_regalloc.py b/pypy/jit/backend/llsupport/test/test_regalloc.py --- a/pypy/jit/backend/llsupport/test/test_regalloc.py +++ b/pypy/jit/backend/llsupport/test/test_regalloc.py @@ -348,3 +348,50 @@ spilled2 = rm.force_allocate_reg(b5) assert spilled2 is loc rm._check_invariants() + + + def test_hint_frame_locations_1(self): + b0, b1 = newboxes(0, 1) + longevity = {b0: (0, 1), b1: (0, 1)} + fm = TFrameManager() + asm = MockAsm() + rm = RegisterManager(longevity, frame_manager=fm, assembler=asm) + rm.hint_frame_locations[b0] = "some_stack_loc" + rm.freed_frame_locations["some_stack_loc"] = None + rm.force_allocate_reg(b0) + rm.force_allocate_reg(b1) + rm.force_spill_var(b0) + rm.force_spill_var(b1) + assert rm.loc(b0) == "some_stack_loc" + assert isinstance(rm.loc(b1), FakeFramePos) + rm._check_invariants() + + def test_hint_frame_locations_2(self): + b0, b1, b2 = newboxes(0, 1, 2) + longevity = {b0: (0, 1), b1: (0, 2), b2: (0, 2)} + fm = TFrameManager() + asm = MockAsm() + rm = RegisterManager(longevity, frame_manager=fm, assembler=asm) + rm.force_allocate_reg(b0) + rm.force_allocate_reg(b1) + rm.force_allocate_reg(b2) + rm.force_spill_var(b0) + loc = rm.loc(b0) + assert isinstance(loc, FakeFramePos) + rm.position = 1 + assert loc not in rm.freed_frame_locations + rm.possibly_free_var(b0) + assert loc in rm.freed_frame_locations + # + rm.hint_frame_locations[b1] = loc + rm.force_spill_var(b1) + loc1 = rm.loc(b1) + assert loc1 is loc + assert rm.freed_frame_locations == {} + # + rm.hint_frame_locations[b2] = loc + rm.force_spill_var(b2) + loc2 = rm.loc(b2) + assert loc2 is not loc1 # because it's not in freed_frame_locations + # + rm._check_invariants() diff --git a/pypy/jit/backend/x86/assembler.py b/pypy/jit/backend/x86/assembler.py --- a/pypy/jit/backend/x86/assembler.py +++ b/pypy/jit/backend/x86/assembler.py @@ -690,6 +690,7 @@ def _assemble(self, regalloc, operations): self._regalloc = regalloc + regalloc.compute_hint_frame_locations(operations) regalloc.walk_operations(operations) if we_are_translated() or self.cpu.dont_keepalive_stuff: self._regalloc = None # else keep it around for debugging diff --git a/pypy/jit/backend/x86/regalloc.py b/pypy/jit/backend/x86/regalloc.py --- a/pypy/jit/backend/x86/regalloc.py +++ b/pypy/jit/backend/x86/regalloc.py @@ -1318,6 +1318,29 @@ self.rm.possibly_free_var(tmpbox_low) self.rm.possibly_free_var(tmpbox_high) + def compute_hint_frame_locations(self, operations): + # optimization only: fill in the 'hint_frame_locations' dictionary + # of rm and xrm based on the JUMP at the end of the loop, by looking + # at where we would like the boxes to be after the jump. + op = operations[-1] + if op.getopnum() != rop.JUMP: + return + descr = op.getdescr() + assert isinstance(descr, LoopToken) + nonfloatlocs, floatlocs = self.assembler.target_arglocs(descr) + for i in range(op.numargs()): + box = op.getarg(i) + if isinstance(box, Box): + loc = nonfloatlocs[i] + if isinstance(loc, StackLoc): + assert box.type != FLOAT + self.rm.hint_frame_locations[box] = loc + else: + loc = floatlocs[i] + if isinstance(loc, StackLoc): + assert box.type == FLOAT + self.xrm.hint_frame_locations[box] = loc + def consider_jump(self, op): assembler = self.assembler assert self.jump_target_descr is None _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit