public override void Run(IRContext context) { var longRightShiftVar = new IRRegisterVariable(IRPrimitive.U64, "mergeVar"); var shiftAmountA = new IRRegisterVariable(IRPrimitive.S32, "a"); var shiftAmountB = new IRRegisterVariable(IRPrimitive.S32, "b"); var shiftAmountNew = new IRRegisterVariable(IRPrimitive.U64, "c"); var longRightShiftTemplate = longRightShiftVar.Cast(IRPrimitive.U32).ShiftRightLogical(shiftAmountA) | longRightShiftVar.ShiftRightLogical(32).Cast(IRPrimitive.U32).ShiftLeft(shiftAmountB); var longRightShiftSubst = longRightShiftVar.ShiftRightLogical(shiftAmountNew).Cast(IRPrimitive.U32); foreach (var basicBlock in context.Function.BasicBlocks) { foreach (var instruction in basicBlock.Instructions) { instruction.Substitute(longRightShiftTemplate, longRightShiftSubst, mapping => { var shiftA = mapping[shiftAmountA] as IRConstant <int>; var shiftB = mapping[shiftAmountB] as IRConstant <int>; if (shiftA is null || shiftB is null) { return(false); } if (shiftA.Value <= 0 || shiftA.Value >= 32) { return(false); } if (shiftB.Value != 32 - shiftA.Value) { return(false); } mapping[shiftAmountNew] = (ulong)shiftA.Value; return(true); });
public override void Run(IRContext context) { var s64ExprMergeVar = new IRRegisterVariable(IRPrimitive.S64, "mergeVar"); var s64ExprMergeTemplate = s64ExprMergeVar.Cast(IRPrimitive.U32).Cast(IRPrimitive.U64) | s64ExprMergeVar.ShiftRightLogical(32).Cast(IRPrimitive.U32).Cast(IRPrimitive.U64).ShiftLeft(32); var s64ExprMergeSubst = s64ExprMergeVar.Cast(IRPrimitive.U64); foreach (var basicBlock in context.Function.BasicBlocks) { foreach (var instruction in basicBlock.Instructions) { instruction.Substitute(s64ExprMergeTemplate, s64ExprMergeSubst); } } }
public override void Run(IRContext context) { var x = new IRRegisterVariable(IRPrimitive.U32, "x"); var magicVal = new IRRegisterVariable(IRPrimitive.U32, "magicVal"); var shiftVal = new IRRegisterVariable(IRPrimitive.S32, "shiftVal"); var divisor = new IRRegisterVariable(IRPrimitive.S32, "divisor"); var subst = (x.Cast(IRPrimitive.S32) / divisor).Cast(IRPrimitive.U32); //Signed, division by two foreach (var basicBlock in context.Function.BasicBlocks) { foreach (var instruction in basicBlock.Instructions) { instruction.Substitute((x + x.ShiftRightLogical(31)).ShiftRightArithmetic(1), (x.Cast(IRPrimitive.S32) / 2).Cast(IRPrimitive.U32)); } } //Signed, no shift, positive constant var template = (magicVal.Cast(IRPrimitive.S32).Cast(IRPrimitive.S64) * x.Cast(IRPrimitive.S32).Cast(IRPrimitive.S64)).ShiftRightLogical(32) .Cast(IRPrimitive.U32) + x.ShiftRightLogical(31); foreach (var basicBlock in context.Function.BasicBlocks) { foreach (var instruction in basicBlock.Instructions) { instruction.Substitute(template, subst, mapping => { var magic = mapping[magicVal] as IRConstant <uint>; if (magic is null) { return(false); } int magicSigned = (int)magic.Value; float divisorVal = (float)(1ul << 32) / magicSigned; if (divisorVal != (float)Math.Round(divisorVal)) { return(false); } mapping[divisor] = (int)divisorVal; return(true); }); } } //Signed, shift, positive constant template = x.ShiftRightLogical(31) + (magicVal.Cast(IRPrimitive.S32).Cast(IRPrimitive.S64) * x.Cast(IRPrimitive.S32).Cast(IRPrimitive.S64)).ShiftRightLogical(32) .Cast(IRPrimitive.U32).ShiftRightArithmetic(shiftVal); foreach (var basicBlock in context.Function.BasicBlocks) { foreach (var instruction in basicBlock.Instructions) { instruction.Substitute(template, subst, mapping => { var magic = mapping[magicVal] as IRConstant <uint>; var shift = mapping[shiftVal] as IRConstant <int>; if (magic is null || shift is null) { return(false); } int magicSigned = (int)magic.Value; float divisorVal = (float)(1ul << 32 << shift.Value) / magicSigned; if (divisorVal != (float)Math.Round(divisorVal)) { return(false); } mapping[divisor] = (int)divisorVal; return(true); });