Mercurial > lcfOS
diff python/transform.py @ 253:74c6a20302d5
Added better logging
author | Windel Bouwman |
---|---|
date | Wed, 31 Jul 2013 17:57:03 +0200 |
parents | c4370696ccc7 |
children | 7416c923a02a |
line wrap: on
line diff
--- a/python/transform.py Tue Jul 30 17:57:46 2013 +0200 +++ b/python/transform.py Wed Jul 31 17:57:03 2013 +0200 @@ -2,20 +2,24 @@ Transformation to optimize IR-code """ +import logging from ir import * # Standard passes: class FunctionPass: - def run(self, ir): - """ Main entry point for the pass """ - self.prepare() - for f in ir.Functions: - self.onFunction(f) - def onFunction(self, f): - """ Override this virtual method """ - raise NotImplementedError() - def prepare(self): - pass + def run(self, ir): + """ Main entry point for the pass """ + logging.info('Running pass {}'.format(type(self))) + self.prepare() + for f in ir.Functions: + self.onFunction(f) + + def onFunction(self, f): + """ Override this virtual method """ + raise NotImplementedError() + + def prepare(self): + pass class BasicBlockPass(FunctionPass): @@ -64,13 +68,15 @@ self.constMap[i.result] = vr i.removeDef(i.result) i2 = ImmLoad(i.result, vr) - print('Replacing', i) + logging.debug('Replacing {}'.format(i)) i.Parent.replaceInstruction(i, i2) class DeadCodeDeleter(BasicBlockPass): def onBasicBlock(self, bb): def instructionUsed(ins): + if not type(ins) in [ImmLoad, BinaryOperator]: + return True if len(ins.defs) == 0: # In case this instruction does not define any # variables, assume it is usefull. @@ -96,6 +102,7 @@ if i.value in constMap: t_new = constMap[i.value] t_old = i.target + logging.debug('Replacing {} with {}'.format(t_old, t_new)) for ui in t_old.used_by: ui.replaceValue(t_old, t_new) to_remove.append(i) @@ -104,137 +111,37 @@ elif isinstance(i, BinaryOperator): k = (i.value1, i.operation, i.value2) if k in constMap: - print('Duplicate binop!', i) t_old = i.result t_new = constMap[k] + logging.debug('Replacing {} with {}'.format(t_old, t_new)) for ui in t_old.used_by: ui.replaceValue(t_old, t_new) to_remove.append(i) else: constMap[k] = i.result for i in to_remove: - print('removing ', i) + logging.debug('removing {}'.format(i)) bb.removeInstruction(i) - - class CleanPass(FunctionPass): def onFunction(self, f): bbs = list(f.BasicBlocks) for bb in bbs: - # TODO: determine check for 'empty' - - # If a block only contains a branch, it can be removed: - if len(bb.Instructions) == 1 and type(bb.LastInstruction) is Branch: - # This block is empty. - # find predecessors of this block and replace this block reference with the jumped reference. - ins = bb.LastInstruction - preds = bb.Predecessors - if bb in preds: + # If a block only contains a branch, it can be removed: + if len(bb.Instructions) == 1 and type(bb.LastInstruction) is Branch: + # This block is empty. + # find predecessors of this block and replace this block reference with the jumped reference. + ins = bb.LastInstruction + preds = bb.Predecessors + if bb in preds: # Do not remove if preceeded by itself pass - else: + else: for pred in bb.Predecessors: pred.LastInstruction.changeTarget(bb, ins.target) f.removeBasicBlock(bb) -def isAllocPromotable(allocinst): - # Check if alloc value is only used by load and store operations. - assert type(allocinst) is Alloc - for use in allocinst.value.used_by: - if not type(use) in [Load, Store]: - # TODO: check volatile - return False - otherUse = True - return True -class Mem2RegPromotor(FunctionPass): - def promoteSingleBlock(self, ai): - print('Single block:', ai) - v = ai.value - bb = ai.Block - - # Replace all loads with the value: - loads = [i for i in v.used_by if isinstance(i, Load)] - stores = [i for i in v.used_by if isinstance(i, Store)] - stores.sort(key=lambda s: s.Position) - stores.reverse() - print(stores) - - for load in loads: - idx = load.Position - # Search upwards: - for store in stores: - if store.Position < load.Position: - break - #print('replace {} with {}'.format(load, store.value)) - for use_ins in load.value.used_by: - use_ins.replaceValue(load.value, store.value) - assert not load.value.Used - print('removing {}'.format(load)) - bb.removeInstruction(load) - - # Remove store instructions: - for store in stores: - sv = store.value - print('removing {}'.format(store)) - bb.removeInstruction(store) - #assert sv.Used - - # Remove alloca instruction: - assert not ai.value.Used, ai.value.used_by - bb.removeInstruction(ai) - - - - def promote(self, ai): - # Find load operations and replace them with assignments - v = ai.value - if len(ai.value.UsedInBlocks) == 1: - self.promoteSingleBlock(ai) - return - - loads = [i for i in v.used_by if isinstance(i, Load)] - stores = [i for i in v.used_by if isinstance(i, Store)] - - # Each store instruction can be removed (later). - # Instead of storing the value, we use it - # where the load would have been! - replMap = {} - for store in stores: - replMap[store] = store.value - - # for each load, track back what the defining store - # was. - for load in loads: - print(load) - - def onFunction(self, f): - # TODO - for bb in f.BasicBlocks: - allocs = [i for i in bb.Instructions if isinstance(i, Alloc)] - for i in allocs: - print(i, isAllocPromotable(i)) - if isAllocPromotable(i): - self.promote(i) - -def optimize(ir): - cf = ConstantFolder() - dcd = DeadCodeDeleter() - m2r = Mem2RegPromotor() - clr = CleanPass() - cse = CommonSubexpressionElimination() - ir.check() - cf.run(ir) - dcd.run(ir) - ir.check() - clr.run(ir) - ir.check() - m2r.run(ir) - ir.check() - cse.run(ir) - ir.check() -