Author: Richard Plangger <planri...@gmail.com> 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 pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit