Mercurial > lcfOS
changeset 177:460db5669efa
Added clean pass for IR
author | Windel Bouwman |
---|---|
date | Mon, 22 Apr 2013 23:54:54 +0200 |
parents | 5fd02aa38b42 |
children | c694ec551f34 |
files | python/c3/codegenerator.py python/ir/basicblock.py python/ir/function.py python/ir/instruction.py python/ir/module.py python/testir.py python/transform.py python/x86.py |
diffstat | 8 files changed, 113 insertions(+), 6 deletions(-) [+] |
line wrap: on
line diff
--- a/python/c3/codegenerator.py Sat Apr 20 12:00:51 2013 +0200 +++ b/python/c3/codegenerator.py Mon Apr 22 23:54:54 2013 +0200 @@ -124,15 +124,17 @@ if type(expr) is astnodes.Binop: ra = self.genExprCode(expr.a) rb = self.genExprCode(expr.b) - tmp = self.builder.newTmp() - ops = ['+', '-', '*', '/', 'and', 'or'] + ops = ['+', '-', '*', '/'] if expr.op in ops: + tmpnames = {'+':'addtmp', '-':'subtmp', '*': 'multmp', '/':'divtmp'} + tmp = self.builder.newTmp(tmpnames[expr.op]) op = expr.op ins = ir.BinaryOperator(tmp, op, ra, rb) self.builder.addIns(ins) return tmp else: print('Unknown {0}'.format(expr)) + tmp = self.builder.newTmp() # TODO return tmp elif type(expr) is astnodes.Constant:
--- a/python/ir/basicblock.py Sat Apr 20 12:00:51 2013 +0200 +++ b/python/ir/basicblock.py Mon Apr 22 23:54:54 2013 +0200 @@ -41,10 +41,15 @@ def getSuccessors(self): if not self.Empty: i = self.LastInstruction + print(i) return i.Targets return [] Successors = property(getSuccessors) def getPredecessors(self): - return [] + preds = [] + for bb in self.parent.BasicBlocks: + if self in bb.Successors: + preds.append(bb) + return preds Predecessors = property(getPredecessors)
--- a/python/ir/function.py Sat Apr 20 12:00:51 2013 +0200 +++ b/python/ir/function.py Mon Apr 22 23:54:54 2013 +0200 @@ -9,6 +9,10 @@ return 'Function {0}'.format(self.name) def addBB(self, bb): self.bbs.append(bb) + bb.parent = self + def removeBasicBlock(self, bb): + self.bbs.remove(bb) + bb.parent = None def getBBs(self): return self.bbs BasicBlocks = property(getBBs)
--- a/python/ir/instruction.py Sat Apr 20 12:00:51 2013 +0200 +++ b/python/ir/instruction.py Mon Apr 22 23:54:54 2013 +0200 @@ -43,9 +43,13 @@ def setParent(self, p): self.parent = p Parent = property(getParent, setParent) + +class Terminator(Instruction): @property def Targets(self): return self.getTargets() + def changeTarget(self, tfrom, tto): + pass # Function calling: class Call(Instruction): @@ -69,7 +73,7 @@ args = ','.join([str(arg) for arg in self.arguments]) return pfx + '{0}({1})'.format(self.callee.name, args) -class Return(Instruction): +class Return(Terminator): def __init__(self, value=None): super().__init__() self.value = value @@ -143,7 +147,7 @@ return '[{0}] = {1}'.format(self.location, self.value) # Branching: -class Branch(Instruction): +class Branch(Terminator): def __init__(self, target): super().__init__() assert type(target) is BasicBlock @@ -152,8 +156,11 @@ return 'BRANCH {0}'.format(self.target) def getTargets(self): return [self.target] + def changeTarget(self, tfrom, tto): + if tfrom is self.target: + self.target = tto -class ConditionalBranch(Instruction): +class ConditionalBranch(Terminator): def __init__(self, a, cond, b, lab1, lab2): super().__init__() self.a = a @@ -171,6 +178,11 @@ return 'IF {0} {1} {2} THEN {3} ELSE {4}'.format(self.a, self.cond, self.b, self.lab1, self.lab2) def getTargets(self): return [self.lab1, self.lab2] + def changeTarget(self, tfrom, tto): + if tfrom is self.lab1: + self.lab1 = tto + if tfrom is self.lab2: + self.lab2 = tto class PhiNode(Instruction): def __init__(self):
--- a/python/ir/module.py Sat Apr 20 12:00:51 2013 +0200 +++ b/python/ir/module.py Mon Apr 22 23:54:54 2013 +0200 @@ -45,6 +45,11 @@ outf.write('{0} [shape=note label="{1}"];\n'.format(id(bb), contents)) for successor in bb.Successors: outf.write('"{0}" -> "{1}"\n'.format(id(bb), id(successor))) + # Draw dags if any: + if hasattr(bb, 'dag'): + outf.write('{0} -> {1}\n'.format(id(bb), id(bb.dag))) + bb.dag.dumpgv(outf) + outf.write('"{0}" -> "{1}" [label="entry"]\n'.format(id(f), id(f.entry))) outf.write('}\n')
--- a/python/testir.py Sat Apr 20 12:00:51 2013 +0200 +++ b/python/testir.py Mon Apr 22 23:54:54 2013 +0200 @@ -34,6 +34,8 @@ // return y - 33; //} + res = res + (x + 2 * y) + (x + 2 * y) + (2*8) + (2*8); + if (x > 13) { while (y > 1337) @@ -57,10 +59,14 @@ cf = transform.ConstantFolder() dcd = transform.DeadCodeDeleter() m2r = transform.Mem2RegPromotor() + clr = transform.CleanPass() ir.check() cf.run(ir) dcd.run(ir) + clr.run(ir) m2r.run(ir) + for bb in ir.BasicBlocks: + bb.dag = x86.Dag(bb) #ir.dump() # Dump a graphiz file:
--- a/python/transform.py Sat Apr 20 12:00:51 2013 +0200 +++ b/python/transform.py Mon Apr 22 23:54:54 2013 +0200 @@ -77,6 +77,21 @@ otherUse = True return True +class CleanPass(FunctionPass): + def onFunction(self, f): + bbs = list(f.BasicBlocks) + for bb in bbs: + # TODO: determine check for 'empty' + if len(bb.Instructions) == 1: + # This block is empty. + # find predecessors of this block and replace this block reference with the jumped reference. + ins = bb.LastInstruction + if type(ins) is Branch: + print(ins, bb.Predecessors) + for pred in bb.Predecessors: + pred.LastInstruction.changeTarget(bb, ins.target) + f.removeBasicBlock(bb) + class Mem2RegPromotor(FunctionPass): def onFunction(self, f): # TODO
--- a/python/x86.py Sat Apr 20 12:00:51 2013 +0200 +++ b/python/x86.py Mon Apr 22 23:54:54 2013 +0200 @@ -2,6 +2,63 @@ import ir import registerallocator +# Instruction selection with DAG (Directed Acyclic Graph) +class DagLeaf: + def __init__(self, v): + self.v = v + +class DagNode: + def __init__(self, name): + self.name = name + self.children = [] + def __repr__(self): + return str(self.name) + +class Dag: + def __init__(self, bb): + self.mapping = {} + self.buildFromBB(bb) + def buildFromBB(self, bb): + for ins in bb.Instructions: + if type(ins) is ir.BinaryOperator: + if not ins.value1 in self.mapping: + self.mapping[ins.value1] = DagNode(ins.value1) + if not ins.value2 in self.mapping: + self.mapping[ins.value2] = DagNode(ins.value2) + # look for op with left and right operand the same: + N = None + lnode = self.mapping[ins.value1] + rnode = self.mapping[ins.value2] + for node in self.mapping.values(): + if node.name == ins.operation: + if node.children[0] == lnode and node.children[1] == rnode: + N = node + break + if not N: + # Create a node. + N = DagNode(ins.operation) + N.children.append(lnode) + N.children.append(rnode) + self.mapping[ins.result] = N + else: + pass + def dumpgv(self, outf): + outf.write('subgraph {0} {{\n'.format(id(self))) + for node in self.mapping.values(): + outf.write('{0} [label="{1}"];\n'.format(id(node), node.name)) + for c in node.children: + outf.write('{0} -> {1};\n'.format(id(node), id(c))) + outf.write('label="dag"}\n') + +def insSelect(mod): + """ Create DAG from ir-code """ + for bb in mod.BasicBlocks: + print(bb) + dag = Dag(bb) + print(dag.mapping) + bb.dag = dag + +# x86 specific: class AsmLabel: def __init__(self, lab): self.lab = lab @@ -34,6 +91,7 @@ def genBin(self, ir): self.asm = [] # Allocate registers: + insSelect(ir) ra = registerallocator.RegisterAllocator() # TODO: do not register allocate on intermediate code: ra.registerAllocate(ir, self.regs)