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. 28
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

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

@ -4,7 +4,7 @@
{ {
public static long fnWorks(int x, int y) 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) 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
public static void UintBitAndTest(uint p, CustomClass c, CustomStruct2 s) public static void UintBitAndTest(uint p, CustomClass c, CustomStruct2 s)
{ {
uint num = 0u; uint num = 0u;
p &= 5u; p &= 5;
num &= 5u; num &= 5;
Use(ref num); Use(ref num);
uintField &= 5u; uintField &= 5u;
UintProp &= 5u; UintProp &= 5u;
@ -2970,8 +2970,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static void UintBitOrTest(uint p, CustomClass c, CustomStruct2 s) public static void UintBitOrTest(uint p, CustomClass c, CustomStruct2 s)
{ {
uint num = 0u; uint num = 0u;
p |= 5u; p |= 5;
num |= 5u; num |= 5;
Use(ref num); Use(ref num);
uintField |= 5u; uintField |= 5u;
UintProp |= 5u; UintProp |= 5u;
@ -2997,8 +2997,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public static void UintBitXorTest(uint p, CustomClass c, CustomStruct2 s) public static void UintBitXorTest(uint p, CustomClass c, CustomStruct2 s)
{ {
uint num = 0u; uint num = 0u;
p ^= 5u; p ^= 5;
num ^= 5u; num ^= 5;
Use(ref num); Use(ref num);
uintField ^= 5u; uintField ^= 5u;
UintProp ^= 5u; UintProp ^= 5u;

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

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

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

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

28
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

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

Loading…
Cancel
Save