def FunOptBasic(fun: ir.Fun, opt_stats: Dict[str, int], allow_conv_conversion: bool): opt_stats["merge_move"] += reaching_defs.FunMergeMoveWithSrcDef(fun) opt_stats["canonicalized"] += canonicalize.FunCanonicalize(fun) opt_stats["strength_red"] += lowering.FunStrengthReduction(fun) opt_stats["empty_bbls"] = cfg.FunRemoveEmptyBbls(fun) opt_stats["unreachable_bbls"] = cfg.FunRemoveUnreachableBbls(fun) reaching_defs.FunComputeReachingDefs(fun) reaching_defs.FunCheckReachingDefs(fun) opt_stats["reg_prop"] = reaching_defs.FunPropagateRegs(fun) opt_stats["const_prop"] += reaching_defs.FunPropagateConsts(fun) opt_stats["const_fold"] += reaching_defs.FunConstantFold( fun, allow_conv_conversion) opt_stats["canonicalized"] += canonicalize.FunCanonicalize(fun) opt_stats["strength_red"] += lowering.FunStrengthReduction(fun) opt_stats["ls_st_simplify"] += reaching_defs.FunLoadStoreSimplify(fun) opt_stats["move_elim"] += lowering.FunMoveElimination(fun) liveness.FunComputeLivenessInfo(fun) opt_stats["useless"] = liveness.FunRemoveUselessInstructions(fun) reg_stats.FunComputeRegStatsExceptLAC(fun) reg_stats.FunComputeRegStatsLAC(fun) opt_stats["dropped_regs"] += reg_stats.FunDropUnreferencedRegs(fun) opt_stats["separated_regs"] += reg_stats.FunSeparateLocalRegUsage(fun)
def FunCfgInit(fun: ir.Fun, unit: ir.Unit): cfg.FunSplitBbls(fun) cfg.FunInitCFG(fun) cfg.FunRemoveUnconditionalBranches(fun) cfg.FunRemoveEmptyBbls(fun) sanity.FunCheck(fun, unit, check_cfg=True, check_push_pop=True, check_fallthroughs=False)
def testD(self): code = io.StringIO(r""" .fun arm_syscall_write SIGNATURE [S32] = [S32 A32 U32] .fun putchar NORMAL [] = [U32] .fun writeln NORMAL [] = [A32 U32] # live_out: ['r0', 'r1'] .reg S32 [$r0_S32 dummy] .reg U32 [$r0_U32 $r1_U32 $r2_U32 len] .reg A32 [$r0_A32 $r1_A32 buf] .bbl start mov buf $r0_A32@r0 # 0 mov len $r1_U32@r1 # 1 mov $r2_U32@r2 len # 2 mov $r1_A32@r1 buf # 3 mov $r0_S32@r0 1 # 4 syscall arm_syscall_write 4:U32 # 5 mov dummy $r0_S32@r0 # 6 mov $r0_U32@r0 10 # 7 bsr putchar # 8 ret # 9 """) cpu_regs = {"r0": ir.CpuReg("r0", 0), "r1": ir.CpuReg("r1", 1), "r2": ir.CpuReg("r2", 2)} unit = serialize.UnitParseFromAsm(code, cpu_regs=cpu_regs) fun = unit.fun_syms["arm_syscall_write"] fun.cpu_live_out = {cpu_regs["r0"]} fun.cpu_live_in = {cpu_regs["r0"], cpu_regs["r1"], cpu_regs["r2"]} fun = unit.fun_syms["putchar"] fun.cpu_live_in = {cpu_regs["r0"]} fun = unit.fun_syms["writeln"] cfg.FunSplitBbls(fun) cfg.FunInitCFG(fun) cfg.FunRemoveUnconditionalBranches(fun) cfg.FunRemoveEmptyBbls(fun) liveness.FunComputeLivenessInfo(fun) ranges = liveness.BblGetLiveRanges(fun.bbls[0], fun, fun.bbls[0].live_out, False) ranges.sort() print("TestD") for lr in ranges: print(lr) self.assertEqual(ranges, [ liveness.LiveRange(liveness.BEFORE_BBL, 0, fun.reg_syms["$r0_A32"], 1), liveness.LiveRange(liveness.BEFORE_BBL, 1, fun.reg_syms["$r1_U32"], 1), liveness.LiveRange(0, 3, fun.reg_syms["buf"], 1), liveness.LiveRange(1, 2, fun.reg_syms["len"], 1), liveness.LiveRange(2, 5, fun.reg_syms["$r2_U32"], 0), liveness.LiveRange(3, 5, fun.reg_syms["$r1_A32"], 0), liveness.LiveRange(4, 5, fun.reg_syms["$r0_S32"], 0), liveness.LiveRange(5, 6, fun.reg_syms["$r0_S32"], 1), liveness.LiveRange(6, liveness.NO_USE, fun.reg_syms["dummy"], 0), liveness.LiveRange(7, 8, fun.reg_syms["$r0_U32"], 0), ])
def testE(self): code = io.StringIO(r""" .fun test NORMAL [F32 F32 F32 F32] = [F32 F32] .reg F32 [a b add sub mul div $s0_F32 $s1_F32 $s2_F32 $s3_F32] .bbl start mov a $s0_F32@s0 mov b $s1_F32@s1 add add a b sub sub a b mul mul a b div div a b mov $s3_F32@s3 div mov $s2_F32@s2 mul mov $s1_F32@s1 sub mov $s0_F32@s0 add ret """) cpu_regs = { "s0": ir.CpuReg("s0", 0), "s1": ir.CpuReg("s1", 1), "s2": ir.CpuReg("s2", 2), "s3": ir.CpuReg("s3", 2) } unit = serialize.UnitParseFromAsm(code, cpu_regs=cpu_regs) fun = unit.fun_syms["test"] fun.cpu_live_out = { cpu_regs["s0"], cpu_regs["s1"], cpu_regs["s2"], cpu_regs["s3"] } fun.cpu_live_in = {cpu_regs["s0"], cpu_regs["s1"]} cfg.FunSplitBblsAtTerminators(fun) cfg.FunInitCFG(fun) cfg.FunRemoveUnconditionalBranches(fun) cfg.FunRemoveEmptyBbls(fun) liveness.FunComputeLivenessInfo(fun) ranges = liveness.BblGetLiveRanges(fun.bbls[0], fun, fun.bbls[0].live_out) ranges.sort() print("TestE") for lr in ranges: print(lr)
def testD(self): code = io.StringIO(r""" .fun arm_syscall_write SIGNATURE [S32] = [S32 A32 U32] .fun putchar NORMAL [] = [U32] .fun writeln NORMAL [] = [A32 U32] # live_out: ['r0', 'r1'] .reg S32 [$r0_S32 dummy] .reg U32 [$r0_U32 $r1_U32 $r2_U32 len] .reg A32 [$r0_A32 $r1_A32 buf] .bbl start mov buf $r0_A32@r0 # 0 mov len $r1_U32@r1 # 1 mov $r2_U32@r2 len # 2 mov $r1_A32@r1 buf # 3 mov $r0_S32@r0 1 # 4 syscall arm_syscall_write 4:U32 # 5 mov dummy $r0_S32@r0 # 6 mov $r0_U32@r0 10 # 7 bsr putchar # 8 ret # 9 """) cpu_regs = { "r0": ir.CpuReg("r0", 0), "r1": ir.CpuReg("r1", 1), "r2": ir.CpuReg("r2", 2) } unit = serialize.UnitParseFromAsm(code, cpu_regs=cpu_regs) fun = unit.fun_syms["arm_syscall_write"] fun.cpu_live_out = {cpu_regs["r0"]} fun.cpu_live_in = {cpu_regs["r0"], cpu_regs["r1"], cpu_regs["r2"]} fun = unit.fun_syms["putchar"] fun.cpu_live_in = {cpu_regs["r0"]} fun = unit.fun_syms["writeln"] cfg.FunSplitBblsAtTerminators(fun) cfg.FunInitCFG(fun) cfg.FunRemoveUnconditionalBranches(fun) cfg.FunRemoveEmptyBbls(fun) liveness.FunComputeLivenessInfo(fun) ranges = liveness.BblGetLiveRanges(fun.bbls[0], fun, fun.bbls[0].live_out) ranges.sort() print("TestD") for lr in ranges: print(lr) lr_r0 = liveness.LiveRange(liveness.BEFORE_BBL, 0, fun.reg_syms["$r0_A32"], 1) lr_r1 = liveness.LiveRange(liveness.BEFORE_BBL, 1, fun.reg_syms["$r1_U32"], 1) lr_buf = liveness.LiveRange(0, 3, fun.reg_syms["buf"], 1) lr_len = liveness.LiveRange(1, 2, fun.reg_syms["len"], 1) lr_r0_2 = liveness.LiveRange(5, 6, fun.reg_syms["$r0_S32"], 1) expected = [ lr_r0, lr_r1, liveness.LiveRange(0, 0, reg=ir.REG_INVALID, num_uses=1, uses=[lr_r0]), lr_buf, liveness.LiveRange(1, 1, reg=ir.REG_INVALID, num_uses=1, uses=[lr_r1]), lr_len, liveness.LiveRange(2, 2, reg=ir.REG_INVALID, num_uses=1, uses=[lr_len]), liveness.LiveRange(2, 5, fun.reg_syms["$r2_U32"], 0), liveness.LiveRange(3, 3, reg=ir.REG_INVALID, num_uses=1, uses=[lr_buf]), liveness.LiveRange(3, 5, fun.reg_syms["$r1_A32"], 0), liveness.LiveRange(4, 5, fun.reg_syms["$r0_S32"], 0), lr_r0_2, liveness.LiveRange(6, 6, reg=ir.REG_INVALID, num_uses=1, uses=[lr_r0_2]), liveness.LiveRange(6, liveness.NO_USE, fun.reg_syms["dummy"], 0), liveness.LiveRange(7, 8, fun.reg_syms["$r0_U32"], 0), ] # self.assertSequenceEqual(ranges, expected) # this does not work because of the uses field self.assertEqual(len(ranges), len(expected)) for a, b in zip(): self.assertEqual(a, b)