Browse Source

Fix #2166: Unnecessary uint casts/conversions for certain bitwise operations

pull/3308/head
Siegfried Pammer 7 months ago
parent
commit
8c440f42a8
  1. 2
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1922.cs
  2. 12
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.cs
  3. 68
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/ConstantsTests.cs
  4. 2
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.cs
  5. 30
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

2
ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1922.cs

@ -4,7 +4,7 @@ @@ -4,7 +4,7 @@
{
public static long fnWorks(int x, int y)
{
return (long)(((ulong)y & 0xFFFFFFuL) << 24) | ((long)x & 0xFFFFFFL);
return (long)((((ulong)y & 0xFFFFFFuL) << 24) | ((ulong)x & 0xFFFFFFuL));
}
public static long fnFails(int x, int y)

12
ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.cs

@ -2943,8 +2943,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -2943,8 +2943,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static void UintBitAndTest(uint p, CustomClass c, CustomStruct2 s)
{
uint num = 0u;
p &= 5u;
num &= 5u;
p &= 5;
num &= 5;
Use(ref num);
uintField &= 5u;
UintProp &= 5u;
@ -2970,8 +2970,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -2970,8 +2970,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static void UintBitOrTest(uint p, CustomClass c, CustomStruct2 s)
{
uint num = 0u;
p |= 5u;
num |= 5u;
p |= 5;
num |= 5;
Use(ref num);
uintField |= 5u;
UintProp |= 5u;
@ -2997,8 +2997,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -2997,8 +2997,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static void UintBitXorTest(uint p, CustomClass c, CustomStruct2 s)
{
uint num = 0u;
p ^= 5u;
num ^= 5u;
p ^= 5;
num ^= 5;
Use(ref num);
uintField ^= 5u;
UintProp ^= 5u;

68
ICSharpCode.Decompiler.Tests/TestCases/Pretty/ConstantsTests.cs

@ -83,7 +83,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -83,7 +83,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
ExpectUInt64(a & 7);
ExpectUInt64(a & 0x7FFFFFFF);
ExpectUInt64(a & 0xFFFFFFFFu);
ExpectUInt64(a & 0x7FFFFFFFFFFFFFFFuL);
ExpectUInt64(a & 0x7FFFFFFFFFFFFFFFL);
ExpectUInt64(a & 0xFFFFFFFFFFFFFFFFuL);
}
@ -97,8 +97,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -97,8 +97,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void BitwiseAndWithConstantUInt32(uint a)
{
ExpectUInt32(a & 7u);
ExpectUInt32(a & 0x7FFFFFFFu);
ExpectUInt32(a & 7);
ExpectUInt32(a & 0x7FFFFFFF);
ExpectUInt32(a & 0xFFFFFFFFu);
}
@ -110,9 +110,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -110,9 +110,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void BitwiseAndWithConstantUInt16(ushort a)
{
ExpectUInt16((ushort)(a & 7u));
ExpectUInt16((ushort)(a & 0x7FFFu));
ExpectUInt16((ushort)(a & 0xFFFFu));
ExpectUInt16((ushort)(a & 7));
ExpectUInt16((ushort)(a & 0x7FFF));
ExpectUInt16((ushort)(a & 0xFFFF));
}
public void BitwiseAndWithConstantInt16(short a)
@ -123,9 +123,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -123,9 +123,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void BitwiseAndWithConstantUInt8(byte a)
{
ExpectUInt8((byte)(a & 7u));
ExpectUInt8((byte)(a & 0x7Fu));
ExpectUInt8((byte)(a & 0xFFu));
ExpectUInt8((byte)(a & 7));
ExpectUInt8((byte)(a & 0x7F));
ExpectUInt8((byte)(a & 0xFF));
}
public void BitwiseAndWithConstantInt8(sbyte a)
@ -139,7 +139,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -139,7 +139,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
ExpectUInt64(a | 7);
ExpectUInt64(a | 0x7FFFFFFF);
ExpectUInt64(a | 0xFFFFFFFFu);
ExpectUInt64(a | 0x7FFFFFFFFFFFFFFFuL);
ExpectUInt64(a | 0x7FFFFFFFFFFFFFFFL);
ExpectUInt64(a | 0xFFFFFFFFFFFFFFFFuL);
}
@ -153,8 +153,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -153,8 +153,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void BitwiseOrWithConstantUInt32(uint a)
{
ExpectUInt32(a | 7u);
ExpectUInt32(a | 0x7FFFFFFFu);
ExpectUInt32(a | 7);
ExpectUInt32(a | 0x7FFFFFFF);
ExpectUInt32(a | 0xFFFFFFFFu);
}
@ -166,9 +166,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -166,9 +166,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void BitwiseOrWithConstantUInt16(ushort a)
{
ExpectUInt16((ushort)(a | 7u));
ExpectUInt16((ushort)(a | 0x7FFFu));
ExpectUInt16((ushort)(a | 0xFFFFu));
ExpectUInt16((ushort)(a | 7));
ExpectUInt16((ushort)(a | 0x7FFF));
ExpectUInt16((ushort)(a | 0xFFFF));
}
public void BitwiseOrWithConstantInt16(short a)
@ -179,9 +179,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -179,9 +179,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void BitwiseOrWithConstantUInt8(byte a)
{
ExpectUInt8((byte)(a | 7u));
ExpectUInt8((byte)(a | 0x7Fu));
ExpectUInt8((byte)(a | 0xFFu));
ExpectUInt8((byte)(a | 7));
ExpectUInt8((byte)(a | 0x7F));
ExpectUInt8((byte)(a | 0xFF));
}
public void BitwiseOrWithConstantInt8(sbyte a)
@ -195,7 +195,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -195,7 +195,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
ExpectUInt64(a ^ 7);
ExpectUInt64(a ^ 0x7FFFFFFF);
ExpectUInt64(a ^ 0xFFFFFFFFu);
ExpectUInt64(a ^ 0x7FFFFFFFFFFFFFFFuL);
ExpectUInt64(a ^ 0x7FFFFFFFFFFFFFFFL);
ExpectUInt64(a ^ 0xFFFFFFFFFFFFFFFFuL);
}
@ -209,8 +209,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -209,8 +209,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void BitwiseXorWithConstantUInt32(uint a)
{
ExpectUInt32(a ^ 7u);
ExpectUInt32(a ^ 0x7FFFFFFFu);
ExpectUInt32(a ^ 7);
ExpectUInt32(a ^ 0x7FFFFFFF);
ExpectUInt32(a ^ 0xFFFFFFFFu);
}
@ -222,9 +222,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -222,9 +222,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void BitwiseXorWithConstantUInt16(ushort a)
{
ExpectUInt16((ushort)(a ^ 7u));
ExpectUInt16((ushort)(a ^ 0x7FFFu));
ExpectUInt16((ushort)(a ^ 0xFFFFu));
ExpectUInt16((ushort)(a ^ 7));
ExpectUInt16((ushort)(a ^ 0x7FFF));
ExpectUInt16((ushort)(a ^ 0xFFFF));
}
public void BitwiseXorWithConstantInt16(short a)
@ -235,9 +235,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -235,9 +235,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public void BitwiseXorWithConstantUInt8(byte a)
{
ExpectUInt8((byte)(a ^ 7u));
ExpectUInt8((byte)(a ^ 0x7Fu));
ExpectUInt8((byte)(a ^ 0xFFu));
ExpectUInt8((byte)(a ^ 7));
ExpectUInt8((byte)(a ^ 0x7F));
ExpectUInt8((byte)(a ^ 0xFF));
}
public void BitwiseXorWithConstantInt8(sbyte a)
@ -246,6 +246,20 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -246,6 +246,20 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
ExpectInt8((sbyte)(a ^ 0x7F));
}
public int Issue2166a(int x)
{
if ((x & 0x10) != 0)
{
return 1;
}
return 0;
}
public byte Issue2166b(int x)
{
return (byte)(x & 0x10);
}
private void ExpectUInt64(ulong _)
{

2
ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.cs

@ -44,7 +44,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -44,7 +44,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
return (ushort)((uint64Field & 0xFFFF000000000000uL) >> 48);
}
set {
uint64Field = (uint64Field & 0xFFFFFFFFFFFFuL) | ((ulong)value << 48);
uint64Field = (uint64Field & 0xFFFFFFFFFFFFL) | ((ulong)value << 48);
}
}

30
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -541,8 +541,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -541,8 +541,7 @@ namespace ICSharpCode.Decompiler.CSharp
rr = AdjustConstantToType(rr, context.TypeHint);
return ConvertConstantValue(
rr,
allowImplicitConversion: true,
ShouldDisplayAsHex(inst.Value, rr.Type, inst.Parent)
allowImplicitConversion: true
).WithILInstruction(inst);
}
@ -566,29 +565,17 @@ namespace ICSharpCode.Decompiler.CSharp @@ -566,29 +565,17 @@ namespace ICSharpCode.Decompiler.CSharp
rr = AdjustConstantToType(rr, context.TypeHint);
return ConvertConstantValue(
rr,
allowImplicitConversion: true,
ShouldDisplayAsHex(inst.Value, rr.Type, inst.Parent)
allowImplicitConversion: true
).WithILInstruction(inst);
}
private bool ShouldDisplayAsHex(long value, IType type, ILInstruction parent)
private bool ShouldDisplayAsHex(long value, IType type)
{
if (parent is Conv conv)
parent = conv.Parent;
if (value >= 0 && value <= 9)
return false;
if (value < 0 && type.GetSign() == Sign.Signed)
return false;
switch (parent)
{
case BinaryNumericInstruction bni:
if (bni.Operator == BinaryNumericOperator.BitAnd
|| bni.Operator == BinaryNumericOperator.BitOr
|| bni.Operator == BinaryNumericOperator.BitXor)
return true;
break;
}
return false;
return true;
}
protected internal override TranslatedExpression VisitLdcF4(LdcF4 inst, TranslationContext context)
@ -1525,8 +1512,9 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1525,8 +1512,9 @@ namespace ICSharpCode.Decompiler.CSharp
TranslatedExpression HandleBinaryNumeric(BinaryNumericInstruction inst, BinaryOperatorType op, TranslationContext context)
{
var resolverWithOverflowCheck = resolver.WithCheckForOverflow(inst.CheckForOverflow);
var left = Translate(inst.Left, op.IsBitwise() ? context.TypeHint : null);
var right = Translate(inst.Right, op.IsBitwise() ? context.TypeHint : null);
bool propagateTypeHint = op.IsBitwise() && inst.LeftInputType != inst.RightInputType;
var left = Translate(inst.Left, propagateTypeHint ? context.TypeHint : null);
var right = Translate(inst.Right, propagateTypeHint ? context.TypeHint : null);
if (inst.UnderlyingResultType == StackType.Ref)
{
@ -1613,7 +1601,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1613,7 +1601,7 @@ namespace ICSharpCode.Decompiler.CSharp
left = ConvertConstantValue(
left.ResolveResult,
allowImplicitConversion: false,
ShouldDisplayAsHex(value, left.Type, inst)
ShouldDisplayAsHex(value, left.Type)
).WithILInstruction(left.ILInstructions);
}
if (right.ResolveResult.ConstantValue != null)
@ -1623,7 +1611,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1623,7 +1611,7 @@ namespace ICSharpCode.Decompiler.CSharp
right = ConvertConstantValue(
right.ResolveResult,
allowImplicitConversion: false,
ShouldDisplayAsHex(value, right.Type, inst)
ShouldDisplayAsHex(value, right.Type)
).WithILInstruction(right.ILInstructions);
}
}

Loading…
Cancel
Save