def PhaseLegalization(fun: ir.Fun, unit: ir.Unit, _opt_stats: Dict[str, int], fout): """ Does a lot of the heavily lifting so that the instruction selector can remain simple and table driven. * lift almost all regs to 32bit width * rewrite Ins that cannot be expanded * rewrite immediates that cannot be expanded except stack offsets which are dealt with in another pass TODO: missing is a function to change calling signature so that """ lowering.FunRegWidthWidening(fun, o.DK.U8, o.DK.U32) lowering.FunRegWidthWidening(fun, o.DK.S8, o.DK.S32) lowering.FunRegWidthWidening(fun, o.DK.S16, o.DK.S32) lowering.FunRegWidthWidening(fun, o.DK.U16, o.DK.U32) fun.cpu_live_in = regs.GetCpuRegsForSignature(fun.input_types) fun.cpu_live_out = regs.GetCpuRegsForSignature(fun.output_types) if fun.kind is not o.FUN_KIND.NORMAL: return # ARM has no mod instruction lowering.FunEliminateRem(fun) # ARM has not support for these addressing modes lowering.FunEliminateStkLoadStoreWithRegOffset(fun, base_kind=o.DK.A32, offset_kind=o.DK.S32) # No floating point immediates lowering.FunMoveImmediatesToMemory(fun, unit, o.DK.F32) lowering.FunMoveImmediatesToMemory(fun, unit, o.DK.F64) # also handles ld_mem from two transformations above lowering.FunEliminateMemLoadStore(fun, base_kind=o.DK.A32, offset_kind=o.DK.S32) canonicalize.FunCanonicalize(fun) # TODO: add a cfg linearization pass to improve control flow optimize.FunCfgExit( fun, unit) # not this may affect immediates as it flips branches # Handle most overflowing immediates. # This excludes immediates related to stack offsets which have not been determined yet lowering.FunEliminateImmediateStores(fun) # handles st_stk immediates _FunRewriteOutOfBoundsImmediates(fun) # hack: some of the code expansion templates need a scratch reg # we do not want to reserve registers for this globally, so instead # we inject some nop instructions that reserve a register that we # use as a scratch for the instruction immediately following the nop isel_tab.FunAddNop1ForCodeSel(fun) sanity.FunCheck(fun, None)
def PhaseLegalization(fun: ir.Fun, unit: ir.Unit, _opt_stats: Dict[str, int], fout): """ Does a lot of the heavily lifting so that the instruction selector can remain simple and table driven. * lift almost all regs to 32bit width * rewrite Ins that cannot be expanded * rewrite immediates that cannot be expanded except stack offsets which are dealt with in another pass TODO: missing is a function to change calling signature so that """ lowering.FunRegWidthWidening(fun, o.DK.U8, o.DK.U32) lowering.FunRegWidthWidening(fun, o.DK.S8, o.DK.S32) lowering.FunRegWidthWidening(fun, o.DK.S16, o.DK.S32) lowering.FunRegWidthWidening(fun, o.DK.U16, o.DK.U32) fun.cpu_live_in = regs.PushPopInterface.GetCpuRegsForInSignature(fun.input_types) fun.cpu_live_out = regs.PushPopInterface.GetCpuRegsForOutSignature(fun.output_types) if fun.kind is not o.FUN_KIND.NORMAL: return # Getting rid of the pusharg/poparg now relieves us form having to pay to attention to the # invariant that pushargs/popargs must be adjacent. lowering.FunPushargConversion(fun, regs.PushPopInterface) lowering.FunPopargConversion(fun, regs.PushPopInterface) # ARM has no mod instruction lowering.FunEliminateRem(fun) # A64 has not support for these addressing modes lowering.FunEliminateStkLoadStoreWithRegOffset(fun, base_kind=o.DK.A64, offset_kind=o.DK.S32) # we cannot load/store directly from mem so expand the instruction to simpler # sequences lowering.FunEliminateMemLoadStore(fun, base_kind=o.DK.A64, offset_kind=o.DK.S32) canonicalize.FunCanonicalize(fun) # TODO: add a cfg linearization pass to improve control flow optimize.FunCfgExit(fun, unit) # not this may affect immediates as it flips branches # Handle most overflowing immediates. # This excludes immediates related to stack offsets which have not been determined yet _FunRewriteOutOfBoundsImmediates(fun, unit) sanity.FunCheck(fun, None)
def PhaseLegalization(fun: ir.Fun, unit: ir.Unit, _opt_stats: Dict[str, int], fout): """ Does a lot of the heavily lifting so that the instruction selector can remain simple and table driven. * lift almost all regs to 32bit width * rewrite Ins that cannot be expanded * rewrite immediates that cannot be expanded except stack offsets which are dealt with in another pass TODO: missing is a function to change calling signature so that """ fun.cpu_live_in = regs.PushPopInterface.GetCpuRegsForInSignature( fun.input_types) fun.cpu_live_out = regs.PushPopInterface.GetCpuRegsForOutSignature( fun.output_types) if fun.kind is not o.FUN_KIND.NORMAL: return # Getting rid of the pusharg/poparg now relieves us form having to pay to attention to the # invariant that pushargs/popargs must be adjacent. lowering.FunPushargConversion(fun, regs.PushPopInterface) lowering.FunPopargConversion(fun, regs.PushPopInterface) # We did not bother with this addressing mode # TODO: we like can avoid this by adding more cases to isel_tab.py lowering.FunEliminateStkLoadStoreWithRegOffset(fun, base_kind=o.DK.A64, offset_kind=o.DK.S32) # TODO: switch this to a WithRegOffset flavor lowering.FunEliminateMemLoadStore(fun, base_kind=o.DK.A64, offset_kind=o.DK.S32) lowering.FunEliminateCopySign(fun) # TODO: support a few special cases in the isel, e.g. cmpXX a 0, 1, x, y lowering.FunEliminateCmp(fun) canonicalize.FunCanonicalize(fun) # TODO: add a cfg linearization pass to improve control flow optimize.FunCfgExit( fun, unit) # not this may affect immediates as it flips branches # Handle most overflowing immediates. # This excludes immediates related to stack offsets which have not been determined yet _FunRewriteOutOfBoundsImmediates(fun, unit) # mul/div/rem need special treatment _FunRewriteDivRem(fun) _FunRewriteIntoAABForm(fun, unit) # Recompute Everything (TODO: make this more selective to reduce work) reg_stats.FunComputeRegStatsExceptLAC(fun) reg_stats.FunDropUnreferencedRegs(fun) liveness.FunComputeLivenessInfo(fun) reg_stats.FunComputeRegStatsLAC(fun) reg_stats.FunSeparateLocalRegUsage( fun ) # this has special hacks to avoid undoing _FunRewriteIntoAABForm() # DumpRegStats(fun, local_reg_stats) # if fun.name == "fibonacci": DumpFun("end of legal", fun) # if fun.name == "write_s": exit(1) sanity.FunCheck(fun, None)
def PhaseLegalization(fun: ir.Fun, unit: ir.Unit, _opt_stats: Dict[str, int], fout): """ Does a lot of the heavily lifting so that the instruction selector can remain simple and table driven. * lift almost all regs to 32bit width * rewrite Ins that cannot be expanded * rewrite immediates that cannot be expanded (stack offsets which are not known yet are ignored and we rely on being able to select all (reasonable) stack offsets) TODO: missing is a function to change calling signature so that """ # shifts on A32 are saturating but Cwerg requires (mod <bitwidth>) lowering.FunLimitShiftAmounts(fun, 32) # lift everything to 32 bit lowering.FunRegWidthWidening(fun, o.DK.U8, o.DK.U32) lowering.FunRegWidthWidening(fun, o.DK.S8, o.DK.S32) lowering.FunRegWidthWidening(fun, o.DK.S16, o.DK.S32) lowering.FunRegWidthWidening(fun, o.DK.U16, o.DK.U32) fun.cpu_live_in = regs.PushPopInterface.GetCpuRegsForInSignature( fun.input_types) fun.cpu_live_out = regs.PushPopInterface.GetCpuRegsForOutSignature( fun.output_types) if fun.kind is not o.FUN_KIND.NORMAL: return # replaces pusharg and poparg instructions and replace them with moves # The moves will use pre-allocated regs (the once use for argument/result passing) # We eliminate pusharg/poparg early because out immediate elimination code may # introduce addtional instructions which make it difficult to perserve the invariant # that all poparg/pusharg related to a call be adjecent. lowering.FunPushargConversion(fun, regs.PushPopInterface) lowering.FunPopargConversion(fun, regs.PushPopInterface) # ARM has no mod instruction lowering.FunEliminateRem(fun) # A32 has not support for these addressing modes. # They will be rewritten using lea.stk lowering.FunEliminateStkLoadStoreWithRegOffset(fun, base_kind=o.DK.A32, offset_kind=o.DK.S32) # we cannot load/store directly from mem so expand the instruction to simpler # sequences lowering.FunEliminateMemLoadStore(fun, base_kind=o.DK.A32, offset_kind=o.DK.S32) canonicalize.FunCanonicalize(fun) # TODO: add a cfg linearization pass to improve control flow optimize.FunCfgExit( fun, unit) # not this may affect immediates as it flips branches # Handle most overflowing immediates. _FunRewriteOutOfBoundsImmediates(fun, unit) # hack: some of the code expansion templates need a scratch reg # we do not want to reserve registers for this globally, so instead # we inject some nop instructions that reserve a register that we # use as a scratch for the instruction immediately following the nop isel_tab.FunAddNop1ForCodeSel(fun) sanity.FunCheck(fun, None)