# Path: backend/ir.py
# class VirtualRegister(object):
# class I32(VirtualRegister):
# class I16(VirtualRegister):
# class I8(VirtualRegister):
# class Pointer(VirtualRegister):
# class ConstantInt(object):
# class ConstantI32(ConstantInt):
# class ConstantI8(ConstantInt):
# class Instruction(object):
# class Binop(Instruction):
# class Unop(Instruction):
# class Call(Instruction):
# class LoadGlobalAddr(Instruction):
# class LoadParamAddr(Instruction):
# class LoadLocalAddr(Instruction):
# class LoadConstant(Instruction):
# class Deref(Instruction):
# class Store(Instruction):
# class Terminator(Instruction):
# class Ret(Terminator):
# class Branch(Terminator):
# class Jmp(Terminator):
# class Phi(Instruction):
# class Move(Instruction):
#     def __init__(self):
#     def isPhysical(self):
#     def __repr__(self):
#     def getSize(self):
#     def getSize(self):
#     def getSize(self):
#     def getSize(self):
#     def getSize(self):
#     def __init__(self,v):
#     def __repr__(self):
#     def __init__(self):
#     def getDagDisplayText(self):
#     def isTerminator(self):
#     def isBranch(self):
#     def swapVar(self,old,new):
#     def swapRead(self,old,new):
#     def swapAssigned(self,old,new):
#     def asm(self):
#     def getSuccessors(self):
#     def setSuccessors(self,new):
#     def swapSuccessor(self,old,new):
#     def getStackSlots(self):
#     def readsMem(self):
#     def writesMem(self):
#     def isMD(self):
#     def isMove(self):
#     def isCall(self):
#     def getClobberedRegisters(self):
#     def getPreClobberedRegisters(self):
#     def __init__(self,op,res,l,r):
#     def getDagDisplayText(self):
#     def __repr__(self):
#     def __init__(self,op,res,arg):
#     def __repr__(self):
#     def __init__(self,label):
#     def __repr__(self):
#     def isCall(self):
#     def readsMem(self):
#     def writesMem(self):
#     def __init__(self,res,sym):
#     def __repr__(self):
#     def __init__(self,res,sym):
#     def __repr__(self):
#     def __init__(self,res,sym):
#     def __repr__(self):
#     def getStackSlots(self):
#     def __init__(self,res,const):
#     def __repr__(self):
#     def __init__(self,out,p):
#     def __repr__(self):
#     def readsMem(self):
#     def __init__(self,p,val):
#     def __repr__(self):
#     def writesMem(self):
#     def isTerminator(self):
#     def getTemplateLookupStr(self):
#     def __init__(self,v=None):
#     def __repr__(self):
#     def __init__(self,v,t,f):
#     def __repr__(self):
#     def __init__(self,dest):
#     def __repr__(self):
#     def __init__(self,lhs,args):
#     def __repr__(self):
#     def __init__(self,l,r):
#     def isMove(self):
#     def __repr__(self):
# 
# Path: vis/irvis.py
# def showFunction(f):
# def renderFunctionToFile(f):


import functionpass
from backend import ir
from vis import irvis


class CopyPropagation(functionpass.FunctionPass):
    
    def runOnFunction(self,f):
        changed = False
        chain = {}
        #irvis.showFunction(f)
        #build a chain of equivalent vars
        
        for block in f:
            idx = 0
            while idx < len(block):
                instr = block[idx]

# Path: backend/ir.py
# class VirtualRegister(object):
# class I32(VirtualRegister):
# class I16(VirtualRegister):
# class I8(VirtualRegister):
# class Pointer(VirtualRegister):
# class ConstantInt(object):
# class ConstantI32(ConstantInt):
# class ConstantI8(ConstantInt):
# class Instruction(object):
# class Binop(Instruction):
# class Unop(Instruction):
# class Call(Instruction):
# class LoadGlobalAddr(Instruction):
# class LoadParamAddr(Instruction):
# class LoadLocalAddr(Instruction):
# class LoadConstant(Instruction):
# class Deref(Instruction):
# class Store(Instruction):
# class Terminator(Instruction):
# class Ret(Terminator):
# class Branch(Terminator):
# class Jmp(Terminator):
# class Phi(Instruction):
# class Move(Instruction):
#     def __init__(self):
#     def isPhysical(self):
#     def __repr__(self):
#     def getSize(self):
#     def getSize(self):
#     def getSize(self):
#     def getSize(self):
#     def getSize(self):
#     def __init__(self,v):
#     def __repr__(self):
#     def __init__(self):
#     def getDagDisplayText(self):
#     def isTerminator(self):
#     def isBranch(self):
#     def swapVar(self,old,new):
#     def swapRead(self,old,new):
#     def swapAssigned(self,old,new):
#     def asm(self):
#     def getSuccessors(self):
#     def setSuccessors(self,new):
#     def swapSuccessor(self,old,new):
#     def getStackSlots(self):
#     def readsMem(self):
#     def writesMem(self):
#     def isMD(self):
#     def isMove(self):
#     def isCall(self):
#     def getClobberedRegisters(self):
#     def getPreClobberedRegisters(self):
#     def __init__(self,op,res,l,r):
#     def getDagDisplayText(self):
#     def __repr__(self):
#     def __init__(self,op,res,arg):
#     def __repr__(self):
#     def __init__(self,label):
#     def __repr__(self):
#     def isCall(self):
#     def readsMem(self):
#     def writesMem(self):
#     def __init__(self,res,sym):
#     def __repr__(self):
#     def __init__(self,res,sym):
#     def __repr__(self):
#     def __init__(self,res,sym):
#     def __repr__(self):
#     def getStackSlots(self):
#     def __init__(self,res,const):
#     def __repr__(self):
#     def __init__(self,out,p):
#     def __repr__(self):
#     def readsMem(self):
#     def __init__(self,p,val):
#     def __repr__(self):
#     def writesMem(self):
#     def isTerminator(self):
#     def getTemplateLookupStr(self):
#     def __init__(self,v=None):
#     def __repr__(self):
#     def __init__(self,v,t,f):
#     def __repr__(self):
#     def __init__(self,dest):
#     def __repr__(self):
#     def __init__(self,lhs,args):
#     def __repr__(self):
#     def __init__(self,l,r):
#     def isMove(self):
#     def __repr__(self):
# 
# Path: vis/irvis.py
# def showFunction(f):
# def renderFunctionToFile(f):


# Path: backend/passes/copypropagation.py
import functionpass
from backend import ir
from vis import irvis



class CopyPropagation(functionpass.FunctionPass):
    
    def runOnFunction(self,f):
        changed = False
        chain = {}
        #irvis.showFunction(f)
        #build a chain of equivalent vars
        
        for block in f:
            idx = 0
            while idx < len(block):
                instr = block[idx]

                if type(instr) in [ir.Move,ir.Phi]: