[pypy-commit] pypy regalloc-playground: chose the fixed register if it is available
cfbolz
pypy.commits at gmail.com
Tue Aug 22 15:21:33 EDT 2017
Author: Carl Friedrich Bolz <cfbolz at gmx.de>
Branch: regalloc-playground
Changeset: r92211:bb3d99077725
Date: 2017-08-22 21:07 +0200
http://bitbucket.org/pypy/pypy/changeset/bb3d99077725/
Log: chose the fixed register if it is available
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
@@ -381,24 +381,27 @@
loc = self.reg_bindings.get(v, None)
if loc is not None and loc not in self.no_lower_byte_regs:
return loc
- for i in range(len(self.free_regs) - 1, -1, -1):
- reg = self.free_regs[i]
- if reg not in self.no_lower_byte_regs:
- if loc is not None:
- self.free_regs[i] = loc
- else:
- del self.free_regs[i]
- self.reg_bindings[v] = reg
- return reg
- return None
+ free_regs = [reg for reg in self.free_regs
+ if reg not in self.no_lower_byte_regs]
+ newloc = self.longevity.try_pick_free_reg(
+ self.position, v, free_regs)
+ if newloc is None:
+ return None
+ self.free_regs.remove(newloc)
+ if loc is not None:
+ self.free_regs.append(loc)
+ self.reg_bindings[v] = newloc
+ return newloc
try:
return self.reg_bindings[v]
except KeyError:
- # YYY here we should chose the free variable a bit more carefully
- if self.free_regs:
- loc = self.free_regs.pop()
- self.reg_bindings[v] = loc
- return loc
+ loc = self.longevity.try_pick_free_reg(
+ self.position, v, self.free_regs)
+ if loc is None:
+ return None
+ self.reg_bindings[v] = loc
+ self.free_regs.remove(loc)
+ return loc
def _spill_var(self, v, forbidden_vars, selected_reg,
need_lower_byte=False):
@@ -421,6 +424,8 @@
# 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
+
cur_max_use_distance = -1
position = self.position
candidate = None
@@ -579,9 +584,9 @@
if v not in self.reg_bindings:
# v not in a register. allocate one for result_v and move v there
prev_loc = self.frame_manager.loc(v)
- loc = self.force_allocate_reg(v, forbidden_vars)
+ loc = self.force_allocate_reg(result_v, forbidden_vars)
self.assembler.regalloc_mov(prev_loc, loc)
- assert v in self.reg_bindings
+ return loc
if self.longevity[v].last_usage > self.position:
# we need to find a new place for variable v and
# store result in the same place
@@ -865,6 +870,14 @@
self.fixed_positions.append((position, reg))
return res
+ def find_fixed_register(self, opindex):
+ # XXX could use binary search
+ if self.fixed_positions is None:
+ return None
+ for (index, reg) in self.fixed_positions:
+ if opindex <= index:
+ return reg
+
def _check_invariants(self):
assert self.definition_pos <= self.last_usage
if self.real_usages is not None:
@@ -928,9 +941,11 @@
fixed registers. Find the register that is free the longest. Return a
tuple (reg, free_until_pos). """
free_until_pos = {}
- max_free_pos = -1
+ max_free_pos = position
best_reg = None
- for reg in free_regs:
+ # reverse for compatibility with old code
+ for i in range(len(free_regs) - 1, -1, -1):
+ reg = free_regs[i]
fixed_reg_pos = self.fixed_register_use.get(reg, None)
if fixed_reg_pos is None:
return reg, sys.maxint
@@ -941,6 +956,26 @@
max_free_pos = free_until_pos
return best_reg, max_free_pos
+ def try_pick_free_reg(self, position, v, free_regs):
+ if not free_regs:
+ return None
+ longevityvar = self[v]
+ reg = longevityvar.find_fixed_register(position)
+ if reg is not None and reg in free_regs:
+ return reg
+ return free_regs[-1]
+ # more advanced stuff below, needs tests
+
+
+
+ loc, free_until = self.longevity.longest_free_reg(
+ self.position, free_regs)
+ if loc is None:
+ return None
+ # YYY could check whether it's best to spill v here, but hard
+ # to do in the current system
+ return loc
+
def __contains__(self, var):
return var in self.longevity
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
@@ -56,6 +56,12 @@
class RegisterManager(BaseRegMan):
all_regs = regs
+
+ def __init__(self, longevity, frame_manager=None, assembler=None):
+ if isinstance(longevity, dict):
+ longevity = LifetimeManager(longevity)
+ BaseRegMan.__init__(self, longevity, frame_manager, assembler)
+
def convert_to_imm(self, v):
return v
@@ -840,6 +846,7 @@
# note: we need to make a copy of inputargs because possibly_free_vars
# is also used on op args, which is a non-resizable list
self.possibly_free_vars(list(inputargs))
+ self._add_fixed_registers()
return operations
def _prepare(self, inputargs, operations, allgcrefs):
@@ -916,6 +923,16 @@
emit((opname, locs))
return self.assembler.emitted
+ def _add_fixed_registers(self):
+ for i, op in enumerate(self.operations):
+ if rop.is_call(op.getopnum()):
+ # calling convention!
+ arglist = op.getarglist()[1:]
+ for arg, reg in zip(arglist + [None] * (3 - len(arglist)), [r1, r2, r3]):
+ self.longevity.fixed_register(i, reg, arg)
+ self.longevity.fixed_register(i, r0, op)
+
+
CPU = getcpuclass()
class TestFullRegallocFakeCPU(object):
# XXX copy-paste from test_regalloc_integration
@@ -1006,9 +1023,8 @@
emitted = self.allocate(ops)
fp0 = FakeFramePos(0, INT)
assert emitted == [
- ("move", r0, fp0),
- ("int_mul", r0, [2]),
- ("move", r1, r0),
+ ("move", r1, fp0),
+ ("int_mul", r1, [2]),
("call_i", r0, [r1]),
("guard_false", r0, []),
]
More information about the pypy-commit
mailing list