Skip to content

Commit b22d9c7

Browse files
committed
Minor codegen improvements
1 parent 44eb3e2 commit b22d9c7

File tree

2 files changed

+17
-6
lines changed

2 files changed

+17
-6
lines changed

Microsoft.Toolkit.HighPerformance/Extensions/BoolExtensions.cs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,14 @@ public static class BoolExtensions
2323
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2424
public static unsafe byte ToByte(this bool flag)
2525
{
26-
return *(byte*)&flag;
26+
// Whenever we need to take the address of an argument, we make a local copy first.
27+
// This will be removed by the JIT anyway, but it can help produce better codegen and
28+
// remove unwanted stack spills if the caller is using constant arguments. This is
29+
// because taking the address of an argument can interfere with some of the flow
30+
// analysis executed by the JIT, which can in some cases block constant propagation.
31+
bool copy = flag;
32+
33+
return *(byte*)©
2734
}
2835

2936
/// <summary>
@@ -58,7 +65,8 @@ public static unsafe int ToInt(this bool flag)
5865
[MethodImpl(MethodImplOptions.AggressiveInlining)]
5966
public static unsafe int ToBitwiseMask32(this bool flag)
6067
{
61-
byte rangeFlag = *(byte*)&flag;
68+
bool copy = flag;
69+
byte rangeFlag = *(byte*)&copy;
6270
int
6371
negativeFlag = rangeFlag - 1,
6472
mask = ~negativeFlag;
@@ -77,7 +85,8 @@ public static unsafe int ToBitwiseMask32(this bool flag)
7785
[MethodImpl(MethodImplOptions.AggressiveInlining)]
7886
public static unsafe long ToBitwiseMask64(this bool flag)
7987
{
80-
byte rangeFlag = *(byte*)&flag;
88+
bool copy = flag;
89+
byte rangeFlag = *(byte*)&copy;
8190
long
8291
negativeFlag = (long)rangeFlag - 1,
8392
mask = ~negativeFlag;

Microsoft.Toolkit.HighPerformance/Helpers/BitHelper.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -209,8 +209,9 @@ public static unsafe uint SetFlag(uint value, int n, bool flag)
209209
// and perform an OR with the resulting value of the previous
210210
// operation. This will always guaranteed to work, thanks to the
211211
// initial code clearing that bit before setting it again.
212+
bool copy = flag;
212213
uint
213-
flag32 = *(byte*)&flag,
214+
flag32 = *(byte*)&copy,
214215
shift = flag32 << n,
215216
or = and | shift;
216217

@@ -378,8 +379,9 @@ public static unsafe ulong SetFlag(ulong value, int n, bool flag)
378379
ulong
379380
bit = 1ul << n,
380381
not = ~bit,
381-
and = value & not,
382-
flag64 = *(byte*)&flag,
382+
and = value & not;
383+
bool copy = flag;
384+
ulong flag64 = *(byte*)&copy,
383385
shift = flag64 << n,
384386
or = and | shift;
385387

0 commit comments

Comments
 (0)