[pypy-commit] pypy s390x-backend: regalloc has now one more pair, SPP is now r12 (was r11)
plan_rich
pypy.commits at gmail.com
Tue Feb 16 08:27:01 EST 2016
Author: Richard Plangger <planrichi at gmail.com>
Branch: s390x-backend
Changeset: r82279:9a63f13fcdbd
Date: 2016-02-16 13:01 +0100
http://bitbucket.org/pypy/pypy/changeset/9a63f13fcdbd/
Log: regalloc has now one more pair, SPP is now r12 (was r11) rewritten
regalloc pairs. it is now simpler and easier to understand.
diff --git a/rpython/jit/backend/zarch/assembler.py b/rpython/jit/backend/zarch/assembler.py
--- a/rpython/jit/backend/zarch/assembler.py
+++ b/rpython/jit/backend/zarch/assembler.py
@@ -180,7 +180,7 @@
mc.push_std_frame()
RCS2 = r.r10
- RCS3 = r.r12
+ RCS3 = r.r11
# r10,r11,r12,r2,f0 -> makes exactly 4 words + 8 byte
extra_stack_size = 4 * WORD + 8
@@ -330,7 +330,7 @@
mc.LGR(r.r3, r.SCRATCH2)
RCS2 = r.r10
- RCS3 = r.r12
+ RCS3 = r.r11
self._store_and_reset_exception(mc, RCS2, RCS3)
@@ -387,7 +387,7 @@
come.
"""
# signature of these cond_call_slowpath functions:
- # * on entry, r12 contains the function to call
+ # * on entry, r11 contains the function to call
# * r2, r3, r4, r5 contain arguments for the call
# * r0 is the gcmap
# * the old value of these regs must already be stored in the jitframe
@@ -400,7 +400,7 @@
mc.store_link()
mc.push_std_frame()
- # copy registers to the frame, with the exception of r2 to r5 and r12,
+ # copy registers to the frame, with the exception of r2 to r5 and r11,
# because these have already been saved by the caller. Note that
# this is not symmetrical: these 5 registers are saved by the caller
# but restored here at the end of this function.
@@ -413,13 +413,13 @@
reg is not r.r3 and
reg is not r.r4 and
reg is not r.r5 and
- reg is not r.r12]
+ reg is not r.r11]
self._push_core_regs_to_jitframe(mc, regs)
if supports_floats:
self._push_fp_regs_to_jitframe(mc)
# allocate a stack frame!
- mc.raw_call(r.r12)
+ mc.raw_call(r.r11)
# Finish
self._reload_frame_if_necessary(mc)
diff --git a/rpython/jit/backend/zarch/codebuilder.py b/rpython/jit/backend/zarch/codebuilder.py
--- a/rpython/jit/backend/zarch/codebuilder.py
+++ b/rpython/jit/backend/zarch/codebuilder.py
@@ -195,9 +195,9 @@
def sync(self):
self.BCR_rr(0xf,0)
- def raw_call(self, call_reg=r.RETURN):
+ def raw_call(self, call_reg=r.r14):
"""Emit a call to the address stored in the register 'call_reg',
- which must be either RAW_CALL_REG or r12. This is a regular C
+ which must be either RAW_CALL_REG or r11. This is a regular C
function pointer, which means on big-endian that it is actually
the address of a three-words descriptor.
"""
diff --git a/rpython/jit/backend/zarch/opassembler.py b/rpython/jit/backend/zarch/opassembler.py
--- a/rpython/jit/backend/zarch/opassembler.py
+++ b/rpython/jit/backend/zarch/opassembler.py
@@ -367,7 +367,7 @@
def _find_nearby_operation(self, regalloc, delta):
return regalloc.operations[regalloc.rm.position + delta]
- _COND_CALL_SAVE_REGS = [r.r12, r.r2, r.r3, r.r4, r.r5]
+ _COND_CALL_SAVE_REGS = [r.r11, r.r2, r.r3, r.r4, r.r5]
def emit_cond_call(self, op, arglocs, regalloc):
fcond = self.guard_success_cc
@@ -378,7 +378,7 @@
jmp_adr = self.mc.get_relative_pos()
self.mc.reserve_cond_jump() # patched later to a relative branch
- # save away r2, r3, r4, r5, r12 into the jitframe
+ # save away r2, r3, r4, r5, r11 into the jitframe
should_be_saved = [
reg for reg in self._regalloc.rm.reg_bindings.itervalues()
if reg in self._COND_CALL_SAVE_REGS]
@@ -388,9 +388,9 @@
self.load_gcmap(self.mc, r.SCRATCH2, regalloc.get_gcmap())
#
# load the 0-to-4 arguments into these registers, with the address of
- # the function to call into r12
+ # the function to call into r11
remap_frame_layout(self, arglocs,
- [r.r12, r.r2, r.r3, r.r4, r.r5][:len(arglocs)],
+ [r.r11, r.r2, r.r3, r.r4, r.r5][:len(arglocs)],
r.SCRATCH)
#
# figure out which variant of cond_call_slowpath to call, and call it
diff --git a/rpython/jit/backend/zarch/regalloc.py b/rpython/jit/backend/zarch/regalloc.py
--- a/rpython/jit/backend/zarch/regalloc.py
+++ b/rpython/jit/backend/zarch/regalloc.py
@@ -171,24 +171,29 @@
self.temp_boxes.append(box)
return reg
- def ensure_even_odd_pair(self, var, bindvar, bind_first=True,
+ def ensure_even_odd_pair(self, origvar, bindvar, bind_first=True,
must_exist=True, load_loc_odd=True,
move_regs=True):
""" Allocates two registers that can be used by the instruction.
- var: is the original register holding the value
+ origvar: is the original register holding the value
bindvar: is the variable that will be bound
(= self.reg_bindings[bindvar] = new register)
bind_first: the even register will be bound to bindvar,
if bind_first == False: the odd register will
be bound
"""
- self._check_type(var)
- prev_loc = self.loc(var, must_exist=must_exist)
+ self._check_type(origvar)
+ prev_loc = self.loc(origvar, must_exist=must_exist)
var2 = TempVar()
+ if bindvar is None:
+ bindvar = TempVar()
if bind_first:
loc, loc2 = self.force_allocate_reg_pair(bindvar, var2, self.temp_boxes)
else:
loc, loc2 = self.force_allocate_reg_pair(var2, bindvar, self.temp_boxes)
+ if isinstance(bindvar, TempVar):
+ self.temp_boxes.append(bindvar)
+
self.temp_boxes.append(var2)
assert loc.is_even() and loc2.is_odd()
if move_regs and prev_loc is not loc2:
@@ -198,148 +203,115 @@
self.assembler.regalloc_mov(prev_loc, loc)
return loc, loc2
- def force_allocate_reg_pair(self, var, var2, forbidden_vars=[], selected_reg=None):
- """ Forcibly allocate a register for the new variable var.
- var will have an even register (var2 will have an odd register).
+ def force_allocate_reg_pair(self, even_var, odd_var, forbidden_vars):
+ """ Forcibly allocate a register for the new variable even_var.
+ even_var will have an even register (odd_var, you guessed it,
+ will have an odd register).
"""
- self._check_type(var)
- self._check_type(var2)
- if isinstance(var, TempVar):
- self.longevity[var] = (self.position, self.position)
- if isinstance(var2, TempVar):
- self.longevity[var2] = (self.position, self.position)
+ self._check_type(even_var)
+ self._check_type(odd_var)
+ if isinstance(even_var, TempVar):
+ self.longevity[even_var] = (self.position, self.position)
+ if isinstance(odd_var, TempVar):
+ self.longevity[odd_var] = (self.position, self.position)
+
+ # this function steps through the following:
+ # 1) maybe there is an even/odd pair that is always
+ # free, then allocate them!
+ # 2) try to just spill one variable in either the even
+ # or the odd reg
+ # 3) spill two variables
+
+ # start in 1)
+ SPILL_EVEN = 0
+ SPILL_ODD = 1
even, odd = None, None
- REGS = r.registers
+ candidates = []
i = len(self.free_regs)-1
- candidates = {}
while i >= 0:
even = self.free_regs[i]
if even.is_even():
# found an even registers that is actually free
- odd = REGS[even.value+1]
- if odd not in r.MANAGED_REGS:
- # makes no sense to use this register!
- i -= 1
- continue
+ odd = r.registers[even.value+1]
if odd not in self.free_regs:
# sadly odd is not free, but for spilling
# we found a candidate
- candidates[odd] = True
+ candidates.append((even, odd, SPILL_ODD))
i -= 1
continue
- assert var not in self.reg_bindings
- assert var2 not in self.reg_bindings
- self.reg_bindings[var] = even
- self.reg_bindings[var2] = odd
- del self.free_regs[i]
- i = self.free_regs.index(odd)
- del self.free_regs[i]
- assert even.is_even() and odd.is_odd()
+ # even is free and so is odd! allocate these
+ # two registers
+ assert even_var not in self.reg_bindings
+ assert odd_var not in self.reg_bindings
+ self.reg_bindings[even_var] = even
+ self.reg_bindings[odd_var] = odd
+ self.free_regs = [fr for fr in self.free_regs \
+ if fr is not even and \
+ fr is not odd]
return even, odd
else:
# an odd free register, maybe the even one is
# a candidate?
odd = even
- even = REGS[odd.value-1]
- if even not in r.MANAGED_REGS:
- # makes no sense to use this register!
- i -= 1
- continue
+ even = r.registers[odd.value-1]
if even not in self.free_regs:
# yes even might be a candidate
# this means that odd is free, but not even
- candidates[even] = True
+ candidates.append((even, odd, SPILL_EVEN))
i -= 1
- if len(candidates) != 0:
- cur_max_age = -1
- candidate = None
- # pseudo step to find best spilling candidate
- # similar to _pick_variable_to_spill, but tailored
- # to take the even/odd register allocation in consideration
- for next in self.reg_bindings:
- if next in forbidden_vars:
- continue
- reg = self.reg_bindings[next]
- if reg in candidates:
- reg2 = None
- if reg.is_even():
- reg2 = REGS[reg.value+1]
- else:
- reg2 = REGS[reg.value-1]
- if reg2 not in r.MANAGED_REGS:
- continue
- max_age = self.longevity[next][1]
- if cur_max_age < max_age:
- cur_max_age = max_age
- candidate = next
- if candidate is not None:
- # well, we got away with a single spill :)
- reg = self.reg_bindings[candidate]
- self._sync_var(candidate)
- del self.reg_bindings[candidate]
- if reg.is_even():
- assert var is not candidate
- self.reg_bindings[var] = reg
- rmfree = REGS[reg.value+1]
- self.reg_bindings[var2] = rmfree
- self.free_regs = [fr for fr in self.free_regs if fr is not rmfree]
- return reg, rmfree
- else:
- assert var2 is not candidate
- self.reg_bindings[var2] = reg
- rmfree = REGS[reg.value-1]
- self.reg_bindings[var] = rmfree
- self.free_regs = [fr for fr in self.free_regs if fr is not rmfree]
- return rmfree, reg
+ reverse_mapping = {}
+ for v, reg in self.reg_bindings.items():
+ reverse_mapping[reg] = v
+
+ # needs to spill one variable
+ for even, odd, which_to_spill in candidates:
+ # no heuristic, pick the first
+ if which_to_spill == SPILL_EVEN:
+ orig_var_even = reverse_mapping[even]
+ if orig_var_even in forbidden_vars:
+ continue # duh!
+ self._sync_var(orig_var_even)
+ del self.reg_bindings[orig_var_even]
+ elif which_to_spill == SPILL_ODD:
+ orig_var_odd = reverse_mapping[odd]
+ if orig_var_odd in forbidden_vars:
+ continue # duh!
+ self._sync_var(orig_var_odd)
+ del self.reg_bindings[orig_var_odd]
+
+ # well, we got away with a single spill :)
+ self.free_regs = [fr for fr in self.free_regs \
+ if fr is not even and \
+ fr is not odd]
+ self.reg_bindings[even_var] = even
+ self.reg_bindings[odd_var] = odd
+ return even, odd
# there is no candidate pair that only would
# require one spill, thus we need to spill two!
# this is a rare case!
- reverse_mapping = {}
- for v, reg in self.reg_bindings.items():
- reverse_mapping[reg] = v
- # always take the first
- for i, reg in enumerate(r.MANAGED_REGS):
- if i % 2 == 1:
+ for even, odd in r.MANAGED_REG_PAIRS:
+ orig_var_even = reverse_mapping[even]
+ orig_var_odd = reverse_mapping[odd]
+ if orig_var_even in forbidden_vars or \
+ orig_var_odd in forbidden_vars:
continue
- if i+1 < len(r.MANAGED_REGS):
- reg2 = r.MANAGED_REGS[i+1]
- assert reg.is_even() and reg2.is_odd()
- ovar = reverse_mapping.get(reg,None)
- if ovar is None:
- continue
- if ovar in forbidden_vars:
- continue
- ovar2 = reverse_mapping.get(reg2, None)
- if ovar2 is not None and ovar2 in forbidden_vars:
- # blocked, try other register pair
- continue
- even = reg
- odd = reg2
- self._sync_var(ovar)
- self._sync_var(ovar2)
- del self.reg_bindings[ovar]
- if ovar2 is not None:
- del self.reg_bindings[ovar2]
- # both are not added to free_regs! no need to do so
- self.reg_bindings[var] = even
- self.reg_bindings[var2] = odd
- break
+
+ self._sync_var(orig_var_even)
+ del self.reg_bindings[orig_var_even]
+ self._sync_var(orig_var_odd)
+ del self.reg_bindings[orig_var_odd]
+
+ self.reg_bindings[even_var] = even
+ self.reg_bindings[odd_var] = odd
+ break
else:
# no break! this is bad. really bad
raise NoVariableToSpill()
- reverse_mapping = None
-
return even, odd
- def force_result_in_even_reg(self, result_v, loc, forbidden_vars=[]):
- pass
-
- def force_result_in_odd_reg(self, result_v, loc, forbidden_vars=[]):
- pass
-
class ZARCHFrameManager(FrameManager):
def __init__(self, base_ofs):
FrameManager.__init__(self)
@@ -990,11 +962,9 @@
# args: base, start, len, scale_start, scale_len
itemsize, ofs, _ = unpack_arraydescr(op.getdescr())
startindex_loc = self.ensure_reg_or_16bit_imm(op.getarg(1))
- tempvar = TempInt()
ofs_loc = self.ensure_reg_or_16bit_imm(ConstInt(ofs))
- base_loc, length_loc = self.rm.ensure_even_odd_pair(op.getarg(0), tempvar,
+ base_loc, length_loc = self.rm.ensure_even_odd_pair(op.getarg(0), None,
bind_first=True, must_exist=False, load_loc_odd=False)
- self.rm.temp_boxes.append(tempvar)
length_box = op.getarg(2)
ll = self.rm.loc(length_box)
@@ -1145,13 +1115,11 @@
src_len: when entering the assembler, src_ofs_loc's value is contained
in src_len register.
"""
- src_tmp = TempVar()
src_ptr_loc, _ = \
self.rm.ensure_even_odd_pair(op.getarg(0),
- src_tmp, bind_first=True,
+ None, bind_first=True,
must_exist=False, load_loc_odd=False)
src_ofs_loc = self.ensure_reg_or_any_imm(op.getarg(2))
- self.rm.temp_boxes.append(src_tmp)
dst_ptr_loc = self.ensure_reg(op.getarg(1))
dst_ofs_loc = self.ensure_reg_or_any_imm(op.getarg(3))
length_loc = self.ensure_reg_or_any_imm(op.getarg(4))
diff --git a/rpython/jit/backend/zarch/registers.py b/rpython/jit/backend/zarch/registers.py
--- a/rpython/jit/backend/zarch/registers.py
+++ b/rpython/jit/backend/zarch/registers.py
@@ -7,17 +7,18 @@
[r0,r1,r2,r3,r4,r5,r6,r7,r8,
r9,r10,r11,r12,r13,r14,r15] = registers
-MANAGED_REGS = [r2,r3,r4,r5,r6,r7,r8,r9,r10,r12] # keep this list sorted (asc)!
+MANAGED_REGS = [r2,r3,r4,r5,r6,r7,r8,r9,r10,r11] # keep this list sorted (asc)!
+MANAGED_REG_PAIRS = [(r2,r3), (r4,r5), (r6,r7), (r8,r9), (r10,r11)]
VOLATILES = [r2,r3,r4,r5,r6]
SP = r15
RETURN = r14
POOL = r13
-SPP = r11
+SPP = r12
SCRATCH = r1
SCRATCH2 = r0
GPR_RETURN = r2
RES = r2
-RSZ = r12 # do not use a volatile register
+RSZ = r11 # do not use a volatile register
[f0,f1,f2,f3,f4,f5,f6,f7,f8,
f9,f10,f11,f12,f13,f14,f15] = fpregisters
More information about the pypy-commit
mailing list