def METHOD_NAME(self, stmts):
    if len(stmts) == 0:
        return stmts
    def used_e(e):
        res = []
        if isinstance(e, LoopIR.Read):
            res += [e.name]
            for ei in e.idx:
                res += used_e(ei)
        elif isinstance(e, LoopIR.USub):
            res += used_e(e.arg)
        elif isinstance(e, LoopIR.BinOp):
            res += used_e(e.lhs)
            res += used_e(e.rhs)
        elif isinstance(e, LoopIR.BuiltIn):
            for ei in e.args:
                res += used_e(ei)
        elif isinstance(e, (LoopIR.WindowExpr, LoopIR.StrideExpr)):
            res += [e.name]
        return res
    def used_s(s):
        res = []
        if isinstance(s, (LoopIR.Assign, LoopIR.Reduce)):
            res += [s.name]
            res += used_e(s.rhs)
        elif isinstance(s, LoopIR.WriteConfig):
            res += used_e(s.rhs)
        elif isinstance(s, LoopIR.If):
            res += used_e(s.cond)
            for b in s.body:
                res += used_s(b)
            for b in s.orelse:
                res += used_s(b)
        elif isinstance(s, LoopIR.Seq):
            for b in s.body:
                res += used_s(b)
        elif isinstance(s, LoopIR.Alloc):
            res += [s.name]
        elif isinstance(s, LoopIR.Call):
            for e in s.args:
                res += used_e(e)
        elif isinstance(s, LoopIR.WindowStmt):
            res += used_e(s.rhs)
        return res
    body = []
    for b in reversed([self.mem_s(b) for b in stmts]):
        used = used_s(b)
        rm = []
        for (nm, typ, mem) in self.tofree[-1]:
            if nm in used:
                rm += [(nm, typ, mem)]
        for (nm, typ, mem) in rm:
            body += [LoopIR.Free(nm, typ, mem, None, b.srcinfo)]
            self.tofree[-1].remove((nm, typ, mem))
        body += [b]
    return list(reversed(body))