Browse Source

Avoid unnecessary casts for bitshifts.

pull/863/head
Daniel Grunwald 8 years ago
parent
commit
9e38bcea5f
  1. 19
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  2. 17
      ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs

19
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -654,13 +654,24 @@ namespace ICSharpCode.Decompiler.CSharp @@ -654,13 +654,24 @@ namespace ICSharpCode.Decompiler.CSharp
var left = Translate(inst.Left);
var right = Translate(inst.Right);
Sign sign = inst.Sign;
if (left.Type.IsSmallIntegerType() && sign != Sign.Unsigned
&& left.Type.Kind != TypeKind.Enum && inst.ResultType == StackType.I4) {
// With small integer types, C# will promote to int and perform signed shifts.
// We thus don't need any casts in this case.
} else {
// Insert cast to target type.
if (sign == Sign.None) {
// if we don't need a specific sign, prefer keeping that of the input:
sign = left.Type.GetSign();
}
IType targetType;
if (inst.ResultType == StackType.I4)
targetType = compilation.FindType(inst.Sign == Sign.Unsigned ? KnownTypeCode.UInt32 : KnownTypeCode.Int32);
targetType = compilation.FindType(sign == Sign.Unsigned ? KnownTypeCode.UInt32 : KnownTypeCode.Int32);
else
targetType = compilation.FindType(inst.Sign == Sign.Unsigned ? KnownTypeCode.UInt64 : KnownTypeCode.Int64);
targetType = compilation.FindType(sign == Sign.Unsigned ? KnownTypeCode.UInt64 : KnownTypeCode.Int64);
left = left.ConvertTo(targetType, this);
}
// Shift operators in C# always expect type 'int' on the right-hand-side
right = right.ConvertTo(compilation.FindType(KnownTypeCode.Int32), this);
@ -670,7 +681,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -670,7 +681,7 @@ namespace ICSharpCode.Decompiler.CSharp
if (inst.ResultType == StackType.I) {
// C# doesn't have shift operators for IntPtr, so we first shifted a long/ulong,
// and now have to case back down to IntPtr/UIntPtr:
result = result.ConvertTo(compilation.FindType(inst.Sign == Sign.Unsigned ? KnownTypeCode.UIntPtr : KnownTypeCode.IntPtr), this);
result = result.ConvertTo(compilation.FindType(sign == Sign.Unsigned ? KnownTypeCode.UIntPtr : KnownTypeCode.IntPtr), this);
}
return result;
}

17
ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs

@ -277,5 +277,22 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -277,5 +277,22 @@ namespace ICSharpCode.Decompiler.IL.Transforms
inst.ReplaceWith(new StLoc(v, new IfInstruction(new LogicNot(inst.Condition), value2, value1)));
}
}
protected internal override void VisitBinaryNumericInstruction(BinaryNumericInstruction inst)
{
base.VisitBinaryNumericInstruction(inst);
switch (inst.Operator) {
case BinaryNumericOperator.ShiftLeft:
case BinaryNumericOperator.ShiftRight:
if (inst.Right.MatchBinaryNumericInstruction(BinaryNumericOperator.BitAnd, out var lhs, out var rhs)
&& rhs.MatchLdcI4(inst.ResultType == StackType.I8 ? 63 : 31))
{
// a << (b & 31) => a << b
context.Step("Combine bit.and into shift", inst);
inst.Right = lhs;
}
break;
}
}
}
}

Loading…
Cancel
Save