Пример #1
0
def _BblRemoveUnreachableIns(bbl: ir.Bbl):
    n = 0
    for n, ins in enumerate(bbl.inss):
        if ins.opcode.kind in {o.OPC_KIND.RET, o.OPC_KIND.BRA}:
            break
    if n != len(bbl.inss):
        bbl.inss = bbl.inss[:n + 1]
Пример #2
0
def _BblRemoveUselessInstructions(bbl: ir.Bbl, fun: ir.Fun) -> int:
    live_out = bbl.live_out.copy()
    old_count = len(bbl.inss)
    keep = []
    for ins in reversed(bbl.inss):
        if _InsUpdateLiveness(ins, fun, live_out):
            keep.append(ins)
    bbl.inss = list(reversed(keep))
    return old_count - len(keep)
Пример #3
0
def BblSplit(ins: ir.Ins, orig_bbl: ir.Bbl, fun: ir.Fun, prefix) -> ir.Bbl:
    """Create a new bbl BEFORE orig_bbl containing all the instruction up to and including ins"""
    assert ins.opcode.kind is not o.OPC_KIND.COND_BRA
    ins_pos = orig_bbl.index(ins)
    bbl_pos = fun.bbls.index(orig_bbl)
    count = 1
    while True:
        name = f"{prefix}{count}"
        if name not in fun.bbl_syms:
            break
        count += 1
    new_bbl = ir.Bbl(name)
    for x in orig_bbl.edge_in[:]:
        if x.inss:
            InsMaybePatchNewSuccessor(x.inss[-1], orig_bbl,
                                      new_bbl)  # patch ins/jtb
        x.ReplaceEdgeOut(orig_bbl, new_bbl)
    new_bbl.AddEdgeOut(orig_bbl)
    new_bbl.inss = orig_bbl.inss[:ins_pos + 1]
    orig_bbl.inss = orig_bbl.inss[ins_pos + 1:]
    fun.bbls.insert(bbl_pos, new_bbl)
    fun.bbl_syms[name] = new_bbl
    return new_bbl
Пример #4
0
def _BblMergeMoveWithSrcDef(bbl: ir.Bbl, _fun: ir.Fun) -> int:
    """
    This transformation will make certain MOVs obsolete.

     op x = a b
     [stuff]
     mov y = x

     will become


     op y = a b
     mov x = y
     [stuff]
     [deleted]

    """
    last_def_pos: Dict[ir.Reg, int] = {}
    last_use_pos: Dict[ir.Reg, int] = {}
    inss: List[ir.Ins] = []

    def update_def_use(ins: ir.Ins, pos):
        num_defs = ins.opcode.def_ops_count()
        for n, op in enumerate(ins.operands):
            if not isinstance(op, ir.Reg):
                continue
            if n < num_defs:
                last_def_pos[op] = pos
            else:
                last_use_pos[op] = pos

    def is_suitable_mov(mov: ir.Ins) -> bool:
        ops = mov.operands
        if mov.opcode is not o.MOV or not isinstance(
                ops[1], ir.Reg) or ops[0] == ops[1]:
            return False
        src_def_pos = last_def_pos.get(ops[1], -1)
        if src_def_pos < 0:
            return False
        # avoid inserting MOVs inbetween POPARGs - this could be improved
        if len(inss) > src_def_pos + 1 and inss[src_def_pos +
                                                1].opcode is o.POPARG:
            return False
        # no intervening use of ops[0]
        dst_def_pos = last_def_pos.get(ops[0], -1)
        if dst_def_pos > src_def_pos:
            return False
        dst_use_pos = last_use_pos.get(ops[0], -1)
        if dst_use_pos > src_def_pos:
            return False
        return True

    count = 0
    for ins in bbl.inss:

        if is_suitable_mov(ins):
            count += 1
            dst_reg, src_reg = ins.operands
            src_def_pos = last_def_pos[src_reg]
            ins_src_def = inss[src_def_pos]
            assert ins_src_def.operands[0] == src_reg
            ins_src_def.operands[0] = dst_reg
            last_def_pos[dst_reg] = src_def_pos
            ir.InsSwapOps(ins, 0, 1)
            inss.insert(src_def_pos + 1, ins)
            for pos in range(src_def_pos + 1, len(inss)):
                update_def_use(inss[pos], pos)
        else:
            update_def_use(ins, len(inss))
            inss.append(ins)

    bbl.inss = inss
    return count