From 8c440f42a89e8c9869927ab818eda9d8a74361c6 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sat, 19 Oct 2024 23:31:10 +0200 Subject: [PATCH] Fix #2166: Unnecessary uint casts/conversions for certain bitwise operations --- .../TestCases/ILPretty/Issue1922.cs | 2 +- .../Pretty/CompoundAssignmentTest.cs | 12 ++-- .../TestCases/Pretty/ConstantsTests.cs | 68 +++++++++++-------- .../TestCases/Pretty/TypeAnalysisTests.cs | 2 +- .../CSharp/ExpressionBuilder.cs | 30 +++----- 5 files changed, 58 insertions(+), 56 deletions(-) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1922.cs b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1922.cs index ff7f5db0c..e9dcadb03 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1922.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1922.cs @@ -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) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.cs index 34275f252..b0cb624b6 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.cs +++ b/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) { 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 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 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; diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ConstantsTests.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ConstantsTests.cs index 5df746cc0..7bada4206 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ConstantsTests.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ConstantsTests.cs @@ -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 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 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 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 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 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 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 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 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 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 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 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 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 _) { diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.cs index 7cd3368e6..d85bd2a04 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.cs @@ -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); } } diff --git a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs index 0f629f38e..635d32871 100644 --- a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs @@ -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 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 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 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 right = ConvertConstantValue( right.ResolveResult, allowImplicitConversion: false, - ShouldDisplayAsHex(value, right.Type, inst) + ShouldDisplayAsHex(value, right.Type) ).WithILInstruction(right.ILInstructions); } }