[pypy-svn] r36502 - pypy/branch/i386-regalloc/pypy/jit/codegen/i386
arigo at codespeak.net
arigo at codespeak.net
Thu Jan 11 16:40:04 CET 2007
Author: arigo
Date: Thu Jan 11 16:40:03 2007
New Revision: 36502
Modified:
pypy/branch/i386-regalloc/pypy/jit/codegen/i386/rgenop.py
Log:
Progress on keep condition codes in the processor's condition codes.
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 Thu Jan 11 16:40:03 2007
@@ -2,15 +2,25 @@
from pypy.rpython.lltypesystem import lltype, llmemory
from pypy.jit.codegen.model import AbstractRGenOp, GenLabel, GenBuilder
from pypy.jit.codegen.model import GenVar, GenConst, CodeGenSwitch
+from pypy.objspace.std.multimethod import FailedToImplement
from pypy.jit.codegen.i386.ri386 import *
+from pypy.jit.codegen.i386.ri386setup import Conditions
from pypy.jit.codegen.i386 import conftest
WORD = 4 # bytes
+RK_NO_RESULT = 0
+RK_WORD = 1
+RK_CC = 2
+
class Operation(GenVar):
- def allocate_registers(self, allocator):
+ clobbers_cc = True
+ result_kind = RK_WORD
+ cc_result = -1
+
+ def allocate(self, allocator):
pass
def generate(self, allocator):
raise NotImplementedError
@@ -18,7 +28,7 @@
class Op1(Operation):
def __init__(self, x):
self.x = x
- def allocate_registers(self, allocator):
+ def allocate(self, allocator):
allocator.using(self.x)
def generate(self, allocator):
try:
@@ -30,13 +40,46 @@
allocator.store_back_location(loc, op)
class OpSameAs(Op1):
- emit = staticmethod(lambda mc, x: None)
+ clobbers_cc = False
+ def generate(self, allocator):
+ try:
+ dstop = allocator.get_operand(self)
+ except KeyError:
+ return # result not used
+ srcop = self.get_operand(self.x)
+ if srcop != dstop:
+ try:
+ self.mc.MOV(dstop, srcop)
+ except FailedToImplement:
+ self.mc.MOV(ecx, srcop)
+ self.mc.MOV(dstop, ecx)
+ return dstop
+
+class OpCompare1(Op1):
+ result_kind = RK_CC
+ def generate(self, allocator):
+ srcop = allocator.get_operand(self.x)
+ dstop = allocator.get_operand(self.y)
+ mc = allocator.mc
+ # XXX optimize the case CMP(immed, reg-or-modrm)
+ try:
+ mc.CMP(srcop, dstop)
+ except FailedToImplement:
+ mc.MOV(ecx, srcop)
+ mc.CMP(ecx, dstop)
+
+class OpIntIsTrue(OpCompare1):
+ opname = 'int_is_true'
+ cc_result = I386CodeBuilder.JNE
+ @staticmethod
+ def emit(mc, x):
+ mc.CMP(x, imm8(0))
class Op2(Operation):
def __init__(self, x, y):
self.x = x
self.y = y
- def allocate_registers(self, allocator):
+ def allocate(self, allocator):
allocator.using(self.x)
allocator.using(self.y)
def generate(self, allocator):
@@ -57,26 +100,37 @@
opname = 'int_sub'
emit = staticmethod(I386CodeBuilder.SUB)
-class OpIntGt(Op2):
+class OpCompare2(Op2):
+ result_kind = RK_CC
+ def generate(self, allocator):
+ srcop = allocator.get_operand(self.x)
+ dstop = allocator.get_operand(self.y)
+ mc = allocator.mc
+ # XXX optimize the case CMP(immed, reg-or-modrm)
+ try:
+ mc.CMP(srcop, dstop)
+ except FailedToImplement:
+ mc.MOV(ecx, srcop)
+ mc.CMP(ecx, dstop)
+
+class OpIntGt(OpCompare2):
opname = 'int_gt'
- @staticmethod
- def emit(mc, x, y):
- mc.CMP(x, y)
- mc.SETG(cl)
- mc.MOVZX(x, cl)
+ cc_result = Conditions['G']
class JumpIfFalse(Operation):
+ clobbers_cc = False
+ result_kind = RK_NO_RESULT
def __init__(self, gv_condition, targetbuilder):
+ assert 0 <= gv_condition.cc_result < INSN_JMP
self.gv_condition = gv_condition
self.targetbuilder = targetbuilder
- def allocate_registers(self, allocator):
- allocator.using(self.gv_condition)
+ def allocate(self, allocator):
+ allocator.using_cc(self.gv_condition)
def generate(self, allocator):
- op = allocator.get_operand(self.gv_condition)
+ cc = cond_negate(self.gv_condition.cc_result)
mc = allocator.mc
- mc.CMP(op, imm8(0))
targetbuilder = self.targetbuilder
- targetbuilder.set_coming_from(mc, insn=I386CodeBuilder.JE)
+ targetbuilder.set_coming_from(mc, insncond=cc)
targetbuilder.inputoperands = [allocator.get_operand(gv)
for gv in targetbuilder.inputargs_gv]
@@ -157,7 +211,19 @@
OPCLASSES2 = setup_opclasses(Op2)
del setup_opclasses
-OPCLASSES1['int_is_true'] = None
+def setup_conditions():
+ result = [None] * 16
+ for key, value in Conditions.items():
+ result[value] = getattr(I386CodeBuilder, 'J'+key)
+ return result
+EMIT_CONDITION = setup_conditions()
+INSN_JMP = len(EMIT_CONDITION)
+EMIT_CONDITION.append(I386CodeBuilder.JMP)
+del setup_conditions
+
+def cond_negate(cond):
+ assert 0 <= cond < INSN_JMP
+ return cond ^ 1
class StackOpCache:
@@ -221,13 +287,44 @@
self.nextloc += 1
self.var2loc[v] = loc
+ def creating_cc(self, v):
+ if self.need_var_in_cc is v:
+ # common case: v is a compare operation whose result is precisely
+ # what we need to be in the CC
+ self.need_var_in_cc = None
+
+ def save_cc(self):
+ # we need a value to be in the CC, but we see a clobbering
+ # operation, so we copy the original CC-creating operation down
+ # past the clobbering operation
+ v = self.need_var_in_cc
+ self.operations.insert(self.operationindex, v)
+ self.need_var_in_cc = None
+
+ def using_cc(self, v):
+ assert not v.is_const
+ if self.need_var_in_cc is not None:
+ self.save_cc()
+ self.need_var_in_cc = v
+
def allocate_locations(self, operations):
# assign locations to gvars
self.operations = operations
+ self.need_var_in_cc = None
+ self.operationindex = len(operations)
for i in range(len(operations)-1, -1, -1):
v = operations[i]
- self.creating(v)
- v.allocate_registers(self)
+ kind = v.result_kind
+ if kind == RK_WORD:
+ self.creating(v)
+ elif kind == RK_CC:
+ self.creating_cc(v)
+ if self.need_var_in_cc is not None and v.clobbers_cc:
+ self.save_cc()
+ v.allocate(self)
+ self.operationindex = i
+ if self.need_var_in_cc is not None:
+ self.save_cc()
def force_var_operands(self, force_vars, force_operands, at_start):
force_loc2operand = self.force_loc2operand
@@ -358,10 +455,11 @@
self.rgenop.close_mc(mc)
self.start_writing()
- def set_coming_from(self, mc, insn=I386CodeBuilder.JMP):
- self.coming_from_insn = insn
+ def set_coming_from(self, mc, insncond=INSN_JMP):
+ self.coming_from_cond = insncond
self.coming_from = mc.tell()
- insn(mc, rel32(0))
+ insnemit = EMIT_CONDITION[insncond]
+ insnemit(mc, rel32(0))
def start_mc(self):
mc = self.rgenop.open_mc()
@@ -371,7 +469,7 @@
targetaddr = mc.tell()
end = start + 6 # XXX hard-coded, enough for JMP and Jcond
oldmc = self.rgenop.InMemoryCodeBuilder(start, end)
- insn = self.coming_from_insn
+ insn = EMIT_CONDITION[self.coming_from_cond]
insn(oldmc, rel32(targetaddr))
oldmc.done()
self.coming_from = 0
@@ -379,6 +477,9 @@
def jump_if_false(self, gv_condition, args_for_jump_gv):
newbuilder = Builder(self.rgenop, list(args_for_jump_gv), None)
+ if gv_condition.cc_result < 0:
+ gv_condition = OpIntIsTrue(gv_condition)
+ self.operations.append(gv_condition)
self.operations.append(JumpIfFalse(gv_condition, newbuilder))
return newbuilder
More information about the Pypy-commit
mailing list