Skip to content

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
...
  • 2 commits
  • 4 files changed
  • 0 commit comments
  • 1 contributor
View
6 ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs
@@ -42,6 +42,7 @@ public enum ILAstOptimizationStep
SimplifyTernaryOperator,
SimplifyNullCoalescing,
JoinBasicBlocks,
+ SimplifyShiftOperators,
TransformDecimalCtorToConstant,
SimplifyLdObjAndStObj,
SimplifyCustomShortCircuit,
@@ -131,7 +132,10 @@ public void Optimize(DecompilerContext context, ILBlock method, ILAstOptimizatio
if (abortBeforeStep == ILAstOptimizationStep.JoinBasicBlocks) return;
modified |= block.RunOptimization(new SimpleControlFlow(context, method).JoinBasicBlocks);
-
+
+ if (abortBeforeStep == ILAstOptimizationStep.SimplifyShiftOperators) return;
+ modified |= block.RunOptimization(SimplifyShiftOperators);
+
if (abortBeforeStep == ILAstOptimizationStep.TransformDecimalCtorToConstant) return;
modified |= block.RunOptimization(TransformDecimalCtorToConstant);
modified |= block.RunOptimization(SimplifyLdcI4ConvI8);
View
35 ICSharpCode.Decompiler/ILAst/PeepholeTransform.cs
@@ -868,5 +868,40 @@ bool HandleStringFixing(ILVariable pinnedVar, List<ILNode> body, ref int pos, re
return false;
}
#endregion
+
+ #region SimplifyShiftOperators
+ static bool SimplifyShiftOperators(List<ILNode> body, ILExpression expr, int pos)
+ {
+ // C# compiles "a << b" to "a << (b & 31)", so we will remove the "& 31" if possible.
+ bool modified = false;
+ SimplifyShiftOperators(expr, ref modified);
+ return modified;
+ }
+
+ static void SimplifyShiftOperators(ILExpression expr, ref bool modified)
+ {
+ for (int i = 0; i < expr.Arguments.Count; i++)
+ SimplifyShiftOperators(expr.Arguments[i], ref modified);
+ if (expr.Code != ILCode.Shl && expr.Code != ILCode.Shr && expr.Code != ILCode.Shr_Un)
+ return;
+ var a = expr.Arguments[1];
+ if (a.Code != ILCode.And || a.Arguments[1].Code != ILCode.Ldc_I4 || expr.InferredType == null)
+ return;
+ int mask;
+ switch (expr.InferredType.MetadataType) {
+ case MetadataType.Int32:
+ case MetadataType.UInt32: mask = 31; break;
+ case MetadataType.Int64:
+ case MetadataType.UInt64: mask = 63; break;
+ default: return;
+ }
+ if ((int)a.Arguments[1].Operand != mask) return;
+ var res = a.Arguments[0];
+ res.ILRanges.AddRange(a.ILRanges);
+ res.ILRanges.AddRange(a.Arguments[1].ILRanges);
+ expr.Arguments[1] = res;
+ modified = true;
+ }
+ #endregion
}
}
View
34 ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs
@@ -526,9 +526,36 @@ TypeReference DoInferTypeForExpression(ILExpression expr, TypeReference expected
return NumericPromotion(InferTypeForExpression(expr.Arguments[0], null));
case ILCode.Shr:
case ILCode.Shr_Un:
- if (forceInferChildren)
- InferTypeForExpression(expr.Arguments[1], typeSystem.Int32);
- return NumericPromotion(InferTypeForExpression(expr.Arguments[0], null));
+ {
+ if (forceInferChildren)
+ InferTypeForExpression(expr.Arguments[1], typeSystem.Int32);
+ TypeReference type = NumericPromotion(InferTypeForExpression(expr.Arguments[0], null));
+ TypeReference expectedInputType = null;
+ switch (type.MetadataType) {
+ case MetadataType.Int32:
+ if (expr.Code == ILCode.Shr_Un)
+ expectedInputType = typeSystem.UInt32;
+ break;
+ case MetadataType.UInt32:
+ if (expr.Code == ILCode.Shr)
+ expectedInputType = typeSystem.Int32;
+ break;
+ case MetadataType.Int64:
+ if (expr.Code == ILCode.Shr_Un)
+ expectedInputType = typeSystem.UInt64;
+ break;
+ case MetadataType.UInt64:
+ if (expr.Code == ILCode.Shr)
+ expectedInputType = typeSystem.UInt64;
+ break;
+ }
+ if (expectedInputType != null) {
+ InferTypeForExpression(expr.Arguments[0], expectedInputType);
+ return expectedInputType;
+ } else {
+ return type;
+ }
+ }
case ILCode.CompoundAssignment:
{
TypeReference varType = InferTypeForExpression(expr.Arguments[0].Arguments[0], null);
@@ -1097,7 +1124,6 @@ static bool OperandFitsInType(TypeReference type, int num)
return char.MinValue <= num && num <= char.MaxValue;
case MetadataType.UInt16:
return ushort.MinValue <= num && num <= ushort.MaxValue;
- break;
default:
return true;
}
View
60 ICSharpCode.Decompiler/Tests/TypeAnalysisTests.cs
@@ -25,9 +25,45 @@ public byte SubtractFrom256(byte b)
return (byte)(256 - (int)b);
}
- public int GetHashCode(long num)
+ #region Shift
+ public int LShiftInteger(int num1, int num2)
{
- return (int)num ^ (int)(num >> 32);
+ return num1 << num2;
+ }
+
+ public uint LShiftUnsignedInteger(uint num1, uint num2)
+ {
+ return num1 << (int)num2;
+ }
+
+ public long LShiftLong(long num1, long num2)
+ {
+ return num1 << (int)num2;
+ }
+
+ public ulong LShiftUnsignedLong(ulong num1, ulong num2)
+ {
+ return num1 << (int)num2;
+ }
+
+ public int RShiftInteger(int num1, int num2)
+ {
+ return num1 >> num2;
+ }
+
+ public uint RShiftUnsignedInteger(uint num1, int num2)
+ {
+ return num1 >> num2;
+ }
+
+ public long RShiftLong(long num1, long num2)
+ {
+ return num1 >> (int)num2;
+ }
+
+ public ulong RShiftUnsignedLong(ulong num1, ulong num2)
+ {
+ return num1 >> (int)num2;
}
public int ShiftByte(byte num)
@@ -40,7 +76,12 @@ public int RShiftByte(byte num)
return num >> 8;
}
- public int RShiftByteWithSignExtension(byte num)
+ public uint RShiftByteWithZeroExtension(byte num)
+ {
+ return (uint)num >> 8;
+ }
+
+ public int RShiftByteAsSByte(byte num)
{
return (sbyte)num >> 8;
}
@@ -50,8 +91,19 @@ public int RShiftSByte(sbyte num)
return num >> 8;
}
- public int RShiftSByteWithZeroExtension(sbyte num)
+ public uint RShiftSByteWithZeroExtension(sbyte num)
+ {
+ return (uint)num >> 8;
+ }
+
+ public int RShiftSByteAsByte(sbyte num)
{
return (byte)num >> 8;
}
+ #endregion
+
+ public int GetHashCode(long num)
+ {
+ return (int)num ^ (int)(num >> 32);
+ }
}

No commit comments for this range

Something went wrong with that request. Please try again.