def FunSpillRegs(fun: ir.Fun, offset_kind: o.DK, regs: List[ir.Reg]) -> int: reg_to_stk: Dict[ir.Reg, ir.Stk] = {} for reg in regs: size = ir.OffsetConst(reg.kind.bitwidth() // 8) stk = ir.Stk(f"$spill_{reg.name}", size, size) reg_to_stk[reg] = stk fun.AddStk(stk) return ir.FunGenericRewrite(fun, InsSpillRegs, zero_const=ir.Const(offset_kind, 0), reg_to_stk=reg_to_stk)
def testNoChange(self): x = ir.Reg("x", o.DK.S32) target = ir.Bbl("target") bbl = ir.Bbl("bbl") bbl.live_out.add(x) bbl.AddIns(ir.Ins(O("poparg"), [x])) bbl.AddIns(ir.Ins(O("blt"), [target, ir.OffsetConst(1), x])) DumpBbl(bbl) live_ranges = liveness.BblGetLiveRanges(bbl, None, bbl.live_out, False) live_ranges.sort() lr_cross_bbl = [lr for lr in live_ranges if lr.is_cross_bbl()] lr_lac = [lr for lr in live_ranges if liveness.LiveRangeFlag.LAC in lr.flags] assert len(live_ranges) == 1 assert len(lr_cross_bbl) == 1 assert len(lr_lac) == 0, f"{lr_lac}"
def _CombinedOffset(ins: ir.Ins, base_ins: ir.Ins) -> Tuple[Any, Any]: """Returns the combine offset, where it was defined and its original type The second is relevant if the offset is a Reg and allows us to check that Reg's content is still available at the location using the combined offset. """ off_pos = 1 if ins.opcode is o.ST else 2 offset1 = ins.operands[off_pos] if base_ins.opcode is o.MOV: return offset1, ins.operand_defs[off_pos] if base_ins.opcode.kind != o.OPC_KIND.LEA: return None, None offset2 = base_ins.operands[2] if isinstance(offset1, ir.Const) and offset1.IsZero(): return offset2, base_ins.operand_defs[2] if isinstance(offset2, ir.Const) and offset2.IsZero(): return offset1, ins.operand_defs[off_pos] if isinstance(offset1, ir.Const) and isinstance(offset2, ir.Const): return ir.OffsetConst(offset1.value + offset2.value), None return None, None
def AddOffsets(a: ir.Const, b: ir.Const) -> ir.Const: return ir.OffsetConst(a.value + b.value)