def precolor(node): if classGuard(node, Assign, Phi): sym = extractSymbol(node) if not sym.has_key('precolor'): sym['precolor'] = None elif isinstance(node, Div) and isinstance(node.left, Symbol): node.left['precolor'] = eax elif isinstance(node, Function): # This clause pre-colors function arguments with their position on # the stack relative to the %ebp register. The first argument # starts 8 bytes above the base pointer. Each successive argument is # 4 bytes above that. offset = 8 for sym in node.argSymbols: sym['precolor'] = Mem(offset, 'up', True) #Advance to the next argument offset. offset += 4 elif isinstance(node, Return): # Values are returned from functions in the %eax register. node['precolor'] = eax for child in node: precolor(child)
def eliminateDeadStores(node, klass=0): newChildren = [] if isinstance(node, Class): klass += 1 for child in node: newChildren.append(eliminateDeadStores(child, klass)) node.setChildren(flatten(newChildren)) if isinstance(node, Assign): sym = extractSymbol(node.var) if sym['reads'] == 0 and klass == 0: if classGuard(node.exp, Class, FunctionCall): return node else: return None else: return node elif isinstance(node, Phi) and node.target['reads'] == 0: return None else: return node
def reads(node): if classGuard(node, Assign, Phi): sym = extractSymbol(node) if not sym.has_key('reads'): sym['reads'] = 0 elif isinstance(node, Function): for sym in node.argSymbols: sym['reads'] = 0 elif isinstance(node, Symbol): # This is kind of ugly, but because of Python's scoping rules we can # read from a variable before it is 'in scope.' if node.has_key('reads'): node['reads'] += 1 else: node['reads'] = 1 elif isinstance(node, Subscript) and isinstance(node.symbol, Symbol): # This little hack is here to take care of cases where subscripts are # applied to literal values. After the flatten transformation this # branch will be taken whenever we see a subscript. node.symbol['reads'] += 1 for child in node: reads(child)
def eliminateDeadStores(node, klass = 0): newChildren = [] if isinstance(node, Class): klass += 1 for child in node: newChildren.append(eliminateDeadStores(child, klass)) node.setChildren(flatten(newChildren)) if isinstance(node, Assign): sym = extractSymbol(node.var) if sym['reads'] == 0 and klass == 0: if classGuard(node.exp, Class, FunctionCall): return node else: return None else: return node elif isinstance(node, Phi) and node.target['reads'] == 0: return None else: return node
def spans(node, count=0, alive=None): inc = 1 if isinstance(node, Module): alive = {} # Count the spans over our children. for child in node: subInc = spans(child, count, alive) inc += subInc count += subInc if classGuard(node, Assign, Phi): # Due to SSA form we know this variable isn't already alive. sym = extractSymbol(node) sym['spans-funcall'] = False if sym in node['post-alive']: alive[sym] = count else: sym['span-start'] = sym['span-end'] = count sym['span-length'] = 0 elif isinstance(node, Function): for sym in node.argSymbols: sym['spans-funcall'] = False if sym in node['post-alive']: alive[sym] = count else: sym['span-start'] = sym['span-end'] = count sym['span-length'] = 0 elif isinstance(node, FunctionCall): #Mark functions that span this function call. for sym in node['pre-alive']: if sym in node['post-alive']: sym['spans-funcall'] = True # This is here so we don't change the alive list while we are iterating # through it. deletes = [] # Symbols don't have any pre/post-alive information due to their Singleton # nature. if not classGuard(node, Name, String, Symbol): for sym in alive: if isinstance(node, Function) or sym not in node['post-alive']: sym['span-start'] = alive[sym] sym['span-end'] = count - 1 sym['span-length'] = sym['span-end'] - sym['span-start'] deletes.append(sym) for sym in deletes: del alive[sym] return inc
def spans(node, count = 0, alive = None): inc = 1 if isinstance(node, Module): alive = {} # Count the spans over our children. for child in node: subInc = spans(child, count, alive) inc += subInc count += subInc if classGuard(node, Assign, Phi): # Due to SSA form we know this variable isn't already alive. sym = extractSymbol(node) sym['spans-funcall'] = False if sym in node['post-alive']: alive[sym] = count else: sym['span-start'] = sym['span-end'] = count sym['span-length'] = 0 elif isinstance(node, Function): for sym in node.argSymbols: sym['spans-funcall'] = False if sym in node['post-alive']: alive[sym] = count else: sym['span-start'] = sym['span-end'] = count sym['span-length'] = 0 elif isinstance(node, FunctionCall): #Mark functions that span this function call. for sym in node['pre-alive']: if sym in node['post-alive']: sym['spans-funcall'] = True # This is here so we don't change the alive list while we are iterating # through it. deletes = [] # Symbols don't have any pre/post-alive information due to their Singleton # nature. if not classGuard(node, Name, String, Symbol): for sym in alive: if isinstance(node, Function) or sym not in node['post-alive']: sym['span-start'] = alive[sym] sym['span-end' ] = count - 1 sym['span-length'] = sym['span-end'] - sym['span-start'] deletes.append(sym) for sym in deletes: del alive[sym] return inc
def liveness(node, alive=[]): if isinstance(node, Module): alive = [] if not classGuard(node, Name, String, Symbol): node['pre-alive'] = set(alive) if isinstance(node, Function): for sym in node.argSymbols: #Functions might have arguments that are never read. if sym['reads'] > 0: sym['tmp'] = sym['reads'] alive.append(sym) for child in node: liveness(child, alive) if classGuard(node, Assign, Phi): sym = extractSymbol(node) if not sym.has_key('tmp'): sym['tmp'] = sym['reads'] alive.append(sym) elif isinstance(node, Symbol) or (isinstance(node, Subscript) and isinstance(node.symbol, Symbol)): sym = extractSymbol(node) if sym.has_key('tmp'): sym['tmp'] -= 1 if sym['tmp'] == 0: alive.remove(sym) else: sym['tmp'] = sym['reads'] alive.append(sym) if not classGuard(node, Name, String, Symbol): node['post-alive'] = set(alive)
def weight(node, depth = 0.0): if isinstance(node, Assign): sym = extractSymbol(node) sym['weight'] = 1.0 + (10.0 ** depth) sym['tmp'] = sym['reads'] elif isinstance(node, Symbol): node['weight'] += 1.0 + (10.0 ** depth) node['tmp'] -= 1 if node['tmp'] == 0: node['weight'] = node['weight'] / float(node['span-length']) for child in node: if isinstance(node, BasicBlock): weight(child, depth + 1.0) else: weight(child, depth)
def related(node): if isinstance(node, Assign): sym0 = extractSymbol(node.var) sym0['related'] = set() if not sym0.has_key('phi-related'): sym0['phi-related'] = set() if isinstance(node.exp, Symbol): sym1 = node.exp if not sym1 in node['post-alive']: sym0['related'].add(sym1) elif isinstance(node.exp, BinOp): if isinstance(node.exp.left, Symbol): # Mark the left symbol as related to the target symbol. sym1 = node.exp.left if sym1 not in node['post-alive']: sym0['related'].add(sym1) if classGuard(node.exp, Add, Mul) and isinstance(node.exp.right, Symbol): # Mark the right symbol as related to the target symbol if # this is an Add or Mul node. sym1 = node.exp.right if sym1 not in node['post-alive']: sym0['related'].add(sym1) elif isinstance(node.exp, UnaryOp) and isinstance(node.exp.operand, Symbol): sym1 = node.exp.operand if not sym1 in node['post-alive']: sym0['related'].add(sym1) elif isinstance(node, Function): for sym in node.argSymbols: sym['related'] = set() sym['phi-related'] = set() elif isinstance(node, Phi): fullSet = set() syms = set([node.target] + node.srcs) while len(syms) > 0: sym = syms.pop() if sym.has_key('phi-related'): syms |= sym['phi-related'] - fullSet fullSet.add(sym) for sym in fullSet: if sym.has_key('phi-related'): sym['phi-related'] |= fullSet else: sym['phi-related'] = fullSet for child in node: related(child)