[pypy-svn] r36607 - pypy/branch/i386-regalloc/pypy/jit/codegen/i386
arigo at codespeak.net
arigo at codespeak.net
Fri Jan 12 19:05:09 CET 2007
Author: arigo
Date: Fri Jan 12 19:04:55 2007
New Revision: 36607
Modified:
pypy/branch/i386-regalloc/pypy/jit/codegen/i386/rgenop.py
Log:
Fix the generation of binary operations. Try hard to generate the
smallest possible amount of MOVs around each operation individually.
Maybe possibly even succeed in doing so.
Modified: pypy/branch/i386-regalloc/pypy/jit/codegen/i386/rgenop.py
==============================================================================
--- pypy/branch/i386-regalloc/pypy/jit/codegen/i386/rgenop.py (original)
+++ pypy/branch/i386-regalloc/pypy/jit/codegen/i386/rgenop.py Fri Jan 12 19:04:55 2007
@@ -39,7 +39,6 @@
return # simple operation whose result is not used anyway
op = allocator.load_location_with(loc, self.x)
self.emit(allocator.mc, op)
- allocator.store_back_location(loc, op)
class OpSameAs(Op1):
clobbers_cc = False
@@ -78,6 +77,7 @@
mc.CMP(x, imm8(0))
class Op2(Operation):
+ commutative = False
def __init__(self, x, y):
self.x = x
self.y = y
@@ -86,22 +86,66 @@
allocator.using(self.y)
def generate(self, allocator):
try:
- loc = allocator.var2loc[self]
+ dstop = allocator.get_operand(self)
except KeyError:
return # simple operation whose result is not used anyway
- op1 = allocator.load_location_with(loc, self.x)
+ op1 = allocator.get_operand(self.x)
op2 = allocator.get_operand(self.y)
- self.emit(allocator.mc, op1, op2)
- allocator.store_back_location(loc, op1)
+ # now all of dstop, op1 and op2 may alias each other and be in
+ # a register or in the stack... finding a correct and encodable
+ # combination of instructions is loads of fun
+ mc = allocator.mc
+ if dstop == op1:
+ case = 1 # optimize for this common case
+ elif self.commutative and dstop == op2:
+ op1, op2 = op2, op1
+ case = 1
+ elif isinstance(dstop, REG):
+ if dstop != op2:
+ # REG = OPERATION(op1, op2) with op2 != REG
+ case = 2
+ else:
+ # REG = OPERATION(op1, REG)
+ case = 3
+ elif isinstance(op1, REG) and isinstance(op2, REG):
+ # STACK = OPERATION(REG, REG)
+ case = 2
+ else:
+ case = 3
+ # this is a separator line but a blank line doesn't look nice here
+ if case == 1:
+ # dstop == op1
+ try:
+ self.emit(mc, op1, op2)
+ except FailedToImplement: # emit(STACK, STACK) combination
+ mc.MOV(ecx, op2)
+ self.emit(mc, op1, ecx)
+ elif case == 2:
+ # this case works for:
+ # * REG = OPERATION(op1, op2) with op2 != REG
+ # * STACK = OPERATION(REG, REG)
+ mc.MOV(dstop, op1)
+ self.emit(mc, dstop, op2)
+ else:
+ # most general case
+ mc.MOV(ecx, op1)
+ self.emit(mc, ecx, op2)
+ mc.MOV(dstop, ecx)
class OpIntAdd(Op2):
opname = 'int_add'
emit = staticmethod(I386CodeBuilder.ADD)
+ commutative = True
class OpIntSub(Op2):
opname = 'int_sub'
emit = staticmethod(I386CodeBuilder.SUB)
+class OpIntMul(Op2):
+ opname = 'int_mul'
+ emit = staticmethod(I386CodeBuilder.IMUL)
+ commutative = True
+
class OpCompare2(Op2):
result_kind = RK_CC
def generate(self, allocator):
@@ -409,18 +453,11 @@
def load_location_with(self, loc, gv_source):
dstop = self.operands[loc]
- if not isinstance(dstop, REG):
- dstop = ecx
srcop = self.get_operand(gv_source)
if srcop != dstop:
self.mc.MOV(dstop, srcop)
return dstop
- def store_back_location(self, loc, operand):
- dstop = self.operands[loc]
- if operand != dstop:
- self.mc.MOV(dstop, operand)
-
def generate_initial_moves(self):
initial_moves = self.initial_moves
# first make sure that the reserved stack frame is big enough
@@ -433,6 +470,7 @@
if last_n >= 0:
self.mc.LEA(esp, stack_op(last_n))
# XXX naive algo for now
+ # XXX at least remove moves that don't move anything!
for loc, srcoperand in initial_moves:
self.mc.PUSH(srcoperand)
initial_moves.reverse()
@@ -523,6 +561,14 @@
self.operations.append(JumpIf(gv_condition, newbuilder, negate=False))
return newbuilder
+ def finish_and_goto(self, outputargs_gv, targetlbl):
+ operands = targetlbl.inputoperands
+ if operands is None:
+ raise NotImplementedError
+ mc = self.generate_block_code(outputargs_gv, outputargs_gv, operands)
+ mc.JMP(rel32(targetlbl.targetaddr))
+ self.rgenop.close_mc(mc)
+
def finish_and_return(self, sigtoken, gv_returnvar):
mc = self.generate_block_code([gv_returnvar], [gv_returnvar], [eax])
# --- epilogue ---
More information about the Pypy-commit
mailing list