Author: Richard Plangger <[email protected]>
Branch: s390x-backend
Changeset: r80634:5a93f832d42a
Date: 2015-11-11 15:46 +0100
http://bitbucket.org/pypy/pypy/changeset/5a93f832d42a/
Log: implemented int_mul, int_floordiv, uint_floordiv and int_mod added
test case to ensure the correct register allocation (e.g. division
takes a pair of even odd registers) not yet all cases covered for
pair allocation
diff --git a/rpython/jit/backend/zarch/helper/regalloc.py
b/rpython/jit/backend/zarch/helper/regalloc.py
--- a/rpython/jit/backend/zarch/helper/regalloc.py
+++ b/rpython/jit/backend/zarch/helper/regalloc.py
@@ -41,18 +41,18 @@
def prepare_int_div(self, op):
a0 = op.getarg(0)
a1 = op.getarg(1)
- lr,lq = self.ensure_even_odd_pair(a0)
+ lr,lq = self.rm.ensure_even_odd_pair(a0, bind_first=False)
l1 = self.ensure_reg(a1)
- self.force_result_in_odd_reg(op, a0)
+ self.rm.force_result_in_reg(op, a0)
self.free_op_vars()
return [lr, lq, l1]
def prepare_int_mod(self, op):
a0 = op.getarg(0)
a1 = op.getarg(1)
- lr,lq = self.ensure_even_odd_pair(a0)
+ lr,lq = self.rm.ensure_even_odd_pair(a0, bind_first=True)
l1 = self.ensure_reg(a1)
- self.force_result_in_even_reg(op, a0)
+ self.rm.force_result_in_reg(op, a0)
self.free_op_vars()
return [lr, lq, l1]
diff --git a/rpython/jit/backend/zarch/instruction_builder.py
b/rpython/jit/backend/zarch/instruction_builder.py
--- a/rpython/jit/backend/zarch/instruction_builder.py
+++ b/rpython/jit/backend/zarch/instruction_builder.py
@@ -185,7 +185,7 @@
self.writechar(opcode)
byte = (reg_or_mask & 0xf) << 4 | (ord(halfopcode) & 0xf)
self.writechar(chr(byte))
- if br or mnemonic == 'LARL':
+ if br:
imm32 = imm32 >> 1
# half word boundary, addressing bytes
self.write_i32(imm32 & BIT_MASK_32)
@@ -350,7 +350,7 @@
for i,arg in enumerate(unrolling_iterable(func._arguments_)):
if arg == '-':
newargs[i] = 0
- elif arg == 'r' or arg == 'r/m' or arg == 'f':
+ elif arg == 'r' or arg == 'r/m' or arg == 'f' or arg == 'eo':
newargs[i] = args[i].value
elif arg.startswith('i') or arg.startswith('u') or
arg.startswith('h'):
newargs[i] = args[i].value
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
@@ -19,8 +19,8 @@
def emit_int_mul(self, op, arglocs, regalloc):
l0, l1 = arglocs
if l1.is_imm():
- self.mc.MSFI(l0, l1)
- if l1.is_in_pool():
+ self.mc.MSGFI(l0, l1)
+ elif l1.is_in_pool():
self.mc.MSG(l0, l1)
else:
self.mc.MSGR(l0, l1)
@@ -29,7 +29,7 @@
lr, lq, l1 = arglocs # lr == remainer, lq == quotient
# when entering the function lr contains the dividend
# after this operation either lr or lq is used further
- assert not l1.is_imm() , "imm divider not supported"
+ assert l1.is_in_pool() or not l1.is_imm() , "imm divider not supported"
# remainer is always a even register r0, r2, ... , r14
assert lr.is_even()
assert lq.is_odd()
@@ -38,18 +38,32 @@
else:
self.mc.DSGR(lr, l1)
- def emit_int_ufloordiv(self, op, arglocs, regalloc):
+ def emit_uint_floordiv(self, op, arglocs, regalloc):
lr, lq, l1 = arglocs # lr == remainer, lq == quotient
# when entering the function lr contains the dividend
# after this operation either lr or lq is used further
- assert not l1.is_imm() , "imm divider not supported"
+ assert l1.is_in_pool() or not l1.is_imm() , "imm divider not supported"
+ # remainer is always a even register r0, r2, ... , r14
+ assert lr.is_even()
+ assert lq.is_odd()
+ self.mc.XGR(lr, lr)
+ if l1.is_in_pool():
+ self.mc.DLG(lr, l1)
+ else:
+ self.mc.DLGR(lr, l1)
+
+ def emit_int_mod(self, op, arglocs, regalloc):
+ lr, lq, l1 = arglocs # lr == remainer, lq == quotient
+ # when entering the function lr contains the dividend
+ # after this operation either lr or lq is used further
+ assert l1.is_in_pool() or not l1.is_imm() , "imm divider not supported"
# remainer is always a even register r0, r2, ... , r14
assert lr.is_even()
assert lq.is_odd()
if l1.is_in_pool():
- self.mc.DLG(lr, l1)
+ self.mc.DSG(lr, l1)
else:
- self.mc.DLGR(lr, l1)
+ self.mc.DSGR(lr, l1)
def emit_int_sub(self, op, arglocs, regalloc):
l0, l1 = arglocs
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
@@ -135,27 +135,73 @@
self.temp_boxes.append(box)
return reg
- def ensure_even_odd_pair(self, var):
- self.rm.ensure__check_type(var)
+ def ensure_even_odd_pair(self, var, bind_first=True):
+ self._check_type(var)
prev_loc = self.loc(var, must_exist=True)
+ var2 = TempVar()
+ self.temp_boxes.append(var2)
if prev_loc is self.frame_reg:
return prev_loc
- if not prev_loc.is_even():
- # we need to move it ...
- pass
- loc = self.force_allocate_reg(v, forbidden_vars, selected_reg,
- need_lower_byte=need_lower_byte)
- if prev_loc is not loc:
- self.assembler.regalloc_mov(prev_loc, loc)
+ if bind_first:
+ loc, loc2 = self.force_allocate_reg_pair(var, var2,
self.temp_boxes)
+ else:
+ loc, loc2 = self.force_allocate_reg_pair(var2, var,
self.temp_boxes)
+ assert loc.is_even() and loc2.is_odd()
+ if prev_loc is not loc2:
+ # TODO is this true for each op?
+ # works for division -> if not parametrize
+ self.assembler.regalloc_mov(prev_loc, loc2)
+ return loc, loc2
+
+ def force_allocate_reg_pair(self, var, var2, forbidden_vars=[],
selected_reg=None):
+ """ Forcibly allocate a register for the new variable v.
+ It must not be used so far. If we don't have a free register,
+ spill some other variable, according to algorithm described in
+ '_pick_variable_to_spill'.
+
+ Will not spill a variable from 'forbidden_vars'.
+ """
+ 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)
+ even, odd = None, None
+ REGS = r.registers
+ i = len(self.free_regs)-1
+ while i >= 0:
+ even = self.free_regs[i]
+ if even.is_even():
+ odd = REGS[even.value+1]
+ print even, "is even", odd
+ if odd not in self.free_regs:
+ print odd, "is NOT free"
+ continue
+ print odd, "is free"
+ 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]
+ return even, odd
+ i += 1
+
+ import pdb; pdb.set_trace()
+ xxx
+ loc = self._spill_var(v, forbidden_vars, selected_reg,
+ need_lower_byte=need_lower_byte)
+ prev_loc = self.reg_bindings.get(v, None)
+ if prev_loc is not None:
+ self.free_regs.append(prev_loc)
+ self.reg_bindings[v] = loc
return loc
def force_result_in_even_reg(self, result_v, loc, forbidden_vars=[]):
- xxx
pass
def force_result_in_odd_reg(self, result_v, loc, forbidden_vars=[]):
- xxx
pass
@@ -490,9 +536,9 @@
prepare_int_add = helper.prepare_int_add
prepare_int_sub = helper.prepare_int_sub
prepare_int_mul = helper.prepare_int_mul
- prepare_int_floordiv = helper.prepare_div
- prepare_uint_floordiv = helper.prepare_div
- prepare_int_mod = helper.prepare_mod
+ prepare_int_floordiv = helper.prepare_int_div
+ prepare_uint_floordiv = helper.prepare_int_div
+ prepare_int_mod = helper.prepare_int_mod
prepare_int_le = helper.prepare_cmp_op
prepare_int_lt = helper.prepare_cmp_op
diff --git a/rpython/jit/backend/zarch/test/test_runner.py
b/rpython/jit/backend/zarch/test/test_runner.py
--- a/rpython/jit/backend/zarch/test/test_runner.py
+++ b/rpython/jit/backend/zarch/test/test_runner.py
@@ -24,10 +24,18 @@
cpu.setup_once()
return cpu
- @py.test.parametrize('input,opcode,result',
- [30,'i1 = int_mul(i0, 2)',60]
- )
- def test_int_arithmetic_and_logic(self, input, opcode, result):
+ @py.test.mark.parametrize('value,opcode,result',
+ [ (30,'i1 = int_mul(i0, 2)',60),
+ (30,'i1 = int_floordiv(i0, 2)',15),
+ (2**31,'i1 = int_floordiv(i0, 15)',2**31//15),
+ (0,'i1 = int_floordiv(i0, 1)', 0),
+ (1,'i1 = int_floordiv(i0, 1)', 1),
+ (0,'i1 = uint_floordiv(i0, 1)', 0),
+ (1,'i1 = uint_floordiv(i0, 1)', 1),
+ (30,'i1 = int_mod(i0, 2)', 0),
+ (1,'i1 = int_mod(i0, 2)', 1),
+ ])
+ def test_int_arithmetic_and_logic(self, value, opcode, result):
loop = parse("""
[i0]
{opcode}
@@ -35,7 +43,7 @@
""".format(opcode=opcode),namespace={"faildescr": BasicFinalDescr(1)})
looptoken = JitCellToken()
self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken)
- deadframe = self.cpu.execute_token(looptoken, input)
+ deadframe = self.cpu.execute_token(looptoken, value)
fail = self.cpu.get_latest_descr(deadframe)
res = self.cpu.get_int_value(deadframe, 0)
assert res == result
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit