Пример #1
0
def _RunLinearScan(bbl: ir.Bbl, fun: ir.Fun, live_ranges: List[liveness.LiveRange], allow_spilling,
                   gpr_regs_lac: int, gpr_regs_not_lac: int,
                   flt_regs_lac: int,
                   flt_regs_not_lac: int):
    pool = CpuRegPool(fun, bbl, allow_spilling,
                      gpr_regs_lac, gpr_regs_not_lac, flt_regs_lac, flt_regs_not_lac)
    for lr in live_ranges:
        # since we are operating on a BBL we cannot change LiveRanges
        # extending beyond the BBL.
        # reg_kinds_fixed (e.g. Machine) regs are assumed to be
        # pre-allocated and will not change

        if liveness.LiveRangeFlag.PRE_ALLOC in lr.flags:
            assert lr.cpu_reg is not ir.CPU_REG_INVALID and lr.cpu_reg is not ir.CPU_REG_SPILL

            pool.add_reserved_range(lr)
        else:
            lr.cpu_reg = ir.CPU_REG_INVALID

    # print (f"{pool}")
    # print(f"\nPY {bbl.name}")
    # for lr in live_ranges:
    #    print(f"{lr}")

    # print ("\n".join(serialize.BblRenderToAsm(bbl)))
    n = [0]

    def logger(lr, message):
        m = f"{n[0]} {lr} {message}"
        n[0] += 1
        print(m)

    reg_alloc.RegisterAssignerLinearScan(live_ranges, pool, None)
Пример #2
0
    def testSimple(self):

        code = io.StringIO(r"""
.fun main NORMAL [U32 U32 U32 U32] = [U32 U32 U32 U32]

.bbl start
    poparg w:U32 
    poparg x:U32 
    poparg y:U32 
    poparg z:U32 
    
    pusharg z
    pusharg y
    pusharg x
    pusharg w
    ret
        """)

        unit = serialize.UnitParseFromAsm(code, False)
        fun = unit.fun_syms["main"]
        bbl = fun.bbls[0]

        DumpBbl(bbl)

        live_ranges = BblGetLiveRanges(bbl, fun, {}, True)
        live_ranges.sort()

        pool = TestRegPool(MakeGenericCpuRegs(4))
        reg_alloc.RegisterAssignerLinearScan(live_ranges, pool)
        for n, lr in enumerate(live_ranges):
            # print (lr)
            if not lr.uses:
                assert lr.cpu_reg.no == n, f"unexpected reg {lr}"

        live_ranges = BblGetLiveRanges(bbl, fun, {}, True)
        live_ranges.sort()
        pool = TestRegPool(MakeGenericCpuRegs(3))
        reg_alloc.RegisterAssignerLinearScan(live_ranges, pool)
        for n, lr in enumerate(live_ranges):
            # print (lr)
            if not lr.uses:
                if n <= 2:
                    assert lr.cpu_reg.no == n
                else:
                    assert lr.cpu_reg == ir.CPU_REG_SPILL, f"unexpected reg {lr}"
Пример #3
0
    def testBacktrack(self):
        # this is a good example for linear scan producing pretty bad assignments
        code = io.StringIO(r"""
.fun main NORMAL [U32 U32 U32 U32] = [U32 U32 U32 U32]

.bbl start
    poparg w:U32 
    poparg x:U32 
    poparg y:U32 
    poparg z:U32 
    
    mov a:U32 1
    mov b:U32 2
    mov c:U32 3
    mov d:U32 4
    
    cmpeq e:U32 a b c d
    
    pusharg z
    pusharg y
    pusharg x
    pusharg w
    ret
        """)

        unit = serialize.UnitParseFromAsm(code, False)
        fun = unit.fun_syms["main"]
        bbl = fun.bbls[0]

        _DumpBblWithLineNumbers(bbl)

        live_ranges = liveness.BblGetLiveRanges(bbl, fun, set(), True)
        live_ranges.sort()

        pool = TestRegPool(MakeGenericCpuRegs(4))
        reg_alloc.RegisterAssignerLinearScan(live_ranges, pool)
        for n, lr in enumerate(live_ranges):
            # print (lr)
            if not lr.uses:
                if n <= 3:
                    assert lr.cpu_reg.no == n
                else:
                    assert lr.cpu_reg is ir.CPU_REG_SPILL, f"unexpected reg {lr}"

        live_ranges = liveness.BblGetLiveRanges(bbl, fun, set(), True)
        live_ranges.sort()
        pool = TestRegPool(MakeGenericCpuRegs(8))
        reg_alloc.RegisterAssignerLinearScanFancy(live_ranges, pool, False)
        for n, lr in enumerate(live_ranges):
            # print (lr)
            assert lr.cpu_reg != ir.CPU_REG_SPILL, f"unexpected reg {lr}"
Пример #4
0
def FunComputeBblRegUsageStats(
        fun: ir.Fun, reg_kind_map: Dict[o.DK,
                                        o.DK]) -> Dict[REG_KIND_LAC, int]:
    """
    Computes maximum number of register needed for locals across all Bbls

    Requires liveness
    """
    pool = BblRegUsageStatsRegPool(reg_kind_map)
    for bbl in fun.bbls:
        live_ranges = liveness.BblGetLiveRanges(bbl, fun, bbl.live_out, True)
        # we do not want re-use of regs that are not coming from the pool
        for lr in live_ranges:
            if LiveRangeShouldBeIgnored(lr, reg_kind_map):
                lr.flags |= liveness.LiveRangeFlag.IGNORE
        reg_alloc.RegisterAssignerLinearScan(live_ranges, pool)
    return pool.usage()
Пример #5
0
def FunComputeBblRegUsageStats(
        fun: ir.Fun, reg_kind_map: Dict[o.DK, int]) -> Dict[REG_KIND_LAC, int]:
    """
    Computes maximum number of register needed for locals across all Bbls

    Requires liveness.
    """
    pool = BblRegUsageStatsRegPool(reg_kind_map)
    for bbl in fun.bbls:
        live_ranges = liveness.BblGetLiveRanges(bbl, fun, bbl.live_out)
        live_ranges.sort()
        if TRACE_REG_ALLOC:
            print("@" * 60)
            print("\n".join(serialize.BblRenderToAsm(bbl)))
            for lr in live_ranges:
                print(lr)
        # we do not want re-use of regs that are not coming from the pool
        for lr in live_ranges:
            if LiveRangeShouldBeIgnored(lr, reg_kind_map):
                lr.flags |= liveness.LiveRangeFlag.IGNORE
        reg_alloc.RegisterAssignerLinearScan(live_ranges, pool)
    return pool.usage()