Skip to content

Commit e1a2cad

Browse files
committed
More unsigned goodness
1 parent f26e8bc commit e1a2cad

File tree

1 file changed

+36
-31
lines changed
  • src/libraries/System.Collections/src/System/Collections

1 file changed

+36
-31
lines changed

src/libraries/System.Collections/src/System/Collections/BitArray.cs

Lines changed: 36 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,11 @@ public BitArray(byte[] bytes)
117117
private static readonly Vector128<byte> s_bitMask128 = BitConverter.IsLittleEndian ?
118118
Vector128.Create(0x80402010_08040201).AsByte() :
119119
Vector128.Create(0x01020408_10204080).AsByte();
120+
121+
private const uint Vector128ByteCount = 16;
122+
private const uint Vector128IntCount = 4;
123+
private const uint Vector256ByteCount = 32;
124+
private const uint Vector256IntCount = 8;
120125
public unsafe BitArray(bool[] values)
121126
{
122127
if (values == null)
@@ -144,12 +149,12 @@ public unsafe BitArray(bool[] values)
144149
Vector256<byte> zero = Vector256<byte>.Zero;
145150
fixed (bool* ptr = values)
146151
{
147-
for (; (i + Vector256<byte>.Count) <= values.Length; i += (uint)Vector256<byte>.Count)
152+
for (; (i + Vector256ByteCount) <= (uint)values.Length; i += Vector256ByteCount)
148153
{
149154
Vector256<byte> vector = Avx.LoadVector256((byte*)ptr + i);
150155
Vector256<byte> isFalse = Avx2.CompareEqual(vector, zero);
151156
int result = Avx2.MoveMask(isFalse);
152-
m_array[i / 32] = ~result;
157+
m_array[i / 32u] = ~result;
153158
}
154159
}
155160
}
@@ -159,7 +164,7 @@ public unsafe BitArray(bool[] values)
159164
Vector128<byte> zero = Vector128<byte>.Zero;
160165
fixed (bool* ptr = values)
161166
{
162-
for (; (i + Vector128<byte>.Count * 2) <= values.Length; i += (uint)Vector128<byte>.Count * 2)
167+
for (; (i + Vector128ByteCount * 2u) <= (uint)values.Length; i += Vector128ByteCount * 2u)
163168
{
164169
Vector128<byte> lowerVector = Sse2.LoadVector128((byte*)ptr + i);
165170
Vector128<byte> lowerIsFalse = Sse2.CompareEqual(lowerVector, zero);
@@ -169,7 +174,7 @@ public unsafe BitArray(bool[] values)
169174
Vector128<byte> upperIsFalse = Sse2.CompareEqual(upperVector, zero);
170175
int upperPackedIsFalse = Sse2.MoveMask(upperIsFalse);
171176

172-
m_array[i / 32] = ~((upperPackedIsFalse << 16) | lowerPackedIsFalse);
177+
m_array[i / 32u] = ~((upperPackedIsFalse << 16) | lowerPackedIsFalse);
173178
}
174179
}
175180
}
@@ -181,7 +186,7 @@ public unsafe BitArray(bool[] values)
181186
Vector128<byte> zero = Vector128<byte>.Zero;
182187
fixed (bool* ptr = values)
183188
{
184-
for (; (i + Vector128<byte>.Count * 2) <= values.Length; i += (uint)Vector128<byte>.Count * 2)
189+
for (; (i + Vector128ByteCount * 2u) <= (uint)values.Length; i += Vector128ByteCount * 2u)
185190
{
186191
// Same logic as SSE2 path, however we lack MoveMask (equivalent) instruction
187192
// As a workaround, mask out the relevant bit after comparison
@@ -207,13 +212,13 @@ public unsafe BitArray(bool[] values)
207212
{
208213
result = BinaryPrimitives.ReverseEndianness(result);
209214
}
210-
m_array[i / 32] = ~result;
215+
m_array[i / 32u] = ~result;
211216
}
212217
}
213218
}
214219

215220
LessThan32:
216-
for (; i < values.Length; i++)
221+
for (; i < (uint)values.Length; i++)
217222
{
218223
if (values[i])
219224
{
@@ -379,7 +384,7 @@ public unsafe BitArray And(BitArray value)
379384
fixed (int* leftPtr = thisArray)
380385
fixed (int* rightPtr = valueArray)
381386
{
382-
for (; i < count - (Vector256<int>.Count - 1); i += (uint)Vector256<int>.Count)
387+
for (; i < (uint)count - (Vector256IntCount - 1u); i += Vector256IntCount)
383388
{
384389
Vector256<int> leftVec = Avx.LoadVector256(leftPtr + i);
385390
Vector256<int> rightVec = Avx.LoadVector256(rightPtr + i);
@@ -392,7 +397,7 @@ public unsafe BitArray And(BitArray value)
392397
fixed (int* leftPtr = thisArray)
393398
fixed (int* rightPtr = valueArray)
394399
{
395-
for (; i < count - (Vector128<int>.Count - 1); i += (uint)Vector128<int>.Count)
400+
for (; i < (uint)count - (Vector128IntCount - 1u); i += Vector128IntCount)
396401
{
397402
Vector128<int> leftVec = Sse2.LoadVector128(leftPtr + i);
398403
Vector128<int> rightVec = Sse2.LoadVector128(rightPtr + i);
@@ -405,7 +410,7 @@ public unsafe BitArray And(BitArray value)
405410
fixed (int* leftPtr = thisArray)
406411
fixed (int* rightPtr = valueArray)
407412
{
408-
for (; i < count - (Vector128<int>.Count - 1); i += (uint)Vector128<int>.Count)
413+
for (; i < (uint)count - (Vector128IntCount - 1u); i += Vector128IntCount)
409414
{
410415
Vector128<int> leftVec = AdvSimd.LoadVector128(leftPtr + i);
411416
Vector128<int> rightVec = AdvSimd.LoadVector128(rightPtr + i);
@@ -414,7 +419,7 @@ public unsafe BitArray And(BitArray value)
414419
}
415420
}
416421

417-
for (; i < count; i++)
422+
for (; i < (uint)count; i++)
418423
thisArray[i] &= valueArray[i];
419424

420425
Done:
@@ -465,7 +470,7 @@ public unsafe BitArray Or(BitArray value)
465470
fixed (int* leftPtr = thisArray)
466471
fixed (int* rightPtr = valueArray)
467472
{
468-
for (; i < count - (Vector256<int>.Count - 1); i += (uint)Vector256<int>.Count)
473+
for (; i < (uint)count - (Vector256IntCount - 1u); i += Vector256IntCount)
469474
{
470475
Vector256<int> leftVec = Avx.LoadVector256(leftPtr + i);
471476
Vector256<int> rightVec = Avx.LoadVector256(rightPtr + i);
@@ -478,7 +483,7 @@ public unsafe BitArray Or(BitArray value)
478483
fixed (int* leftPtr = thisArray)
479484
fixed (int* rightPtr = valueArray)
480485
{
481-
for (; i < count - (Vector128<int>.Count - 1); i += (uint)Vector128<int>.Count)
486+
for (; i < (uint)count - (Vector128IntCount - 1u); i += Vector128IntCount)
482487
{
483488
Vector128<int> leftVec = Sse2.LoadVector128(leftPtr + i);
484489
Vector128<int> rightVec = Sse2.LoadVector128(rightPtr + i);
@@ -491,7 +496,7 @@ public unsafe BitArray Or(BitArray value)
491496
fixed (int* leftPtr = thisArray)
492497
fixed (int* rightPtr = valueArray)
493498
{
494-
for (; i < count - (Vector128<int>.Count - 1); i += (uint)Vector128<int>.Count)
499+
for (; i < (uint)count - (Vector128IntCount - 1u); i += Vector128IntCount)
495500
{
496501
Vector128<int> leftVec = AdvSimd.LoadVector128(leftPtr + i);
497502
Vector128<int> rightVec = AdvSimd.LoadVector128(rightPtr + i);
@@ -500,7 +505,7 @@ public unsafe BitArray Or(BitArray value)
500505
}
501506
}
502507

503-
for (; i < count; i++)
508+
for (; i < (uint)count; i++)
504509
thisArray[i] |= valueArray[i];
505510

506511
Done:
@@ -551,7 +556,7 @@ public unsafe BitArray Xor(BitArray value)
551556
fixed (int* leftPtr = m_array)
552557
fixed (int* rightPtr = value.m_array)
553558
{
554-
for (; i < count - (Vector256<int>.Count - 1); i += (uint)Vector256<int>.Count)
559+
for (; i < (uint)count - (Vector256IntCount - 1u); i += Vector256IntCount)
555560
{
556561
Vector256<int> leftVec = Avx.LoadVector256(leftPtr + i);
557562
Vector256<int> rightVec = Avx.LoadVector256(rightPtr + i);
@@ -564,7 +569,7 @@ public unsafe BitArray Xor(BitArray value)
564569
fixed (int* leftPtr = thisArray)
565570
fixed (int* rightPtr = valueArray)
566571
{
567-
for (; i < count - (Vector128<int>.Count - 1); i += (uint)Vector128<int>.Count)
572+
for (; i < (uint)count - (Vector128IntCount - 1u); i += Vector128IntCount)
568573
{
569574
Vector128<int> leftVec = Sse2.LoadVector128(leftPtr + i);
570575
Vector128<int> rightVec = Sse2.LoadVector128(rightPtr + i);
@@ -577,7 +582,7 @@ public unsafe BitArray Xor(BitArray value)
577582
fixed (int* leftPtr = thisArray)
578583
fixed (int* rightPtr = valueArray)
579584
{
580-
for (; i < count - (Vector128<int>.Count - 1); i += (uint)Vector128<int>.Count)
585+
for (; i < (uint)count - (Vector128IntCount - 1u); i += Vector128IntCount)
581586
{
582587
Vector128<int> leftVec = AdvSimd.LoadVector128(leftPtr + i);
583588
Vector128<int> rightVec = AdvSimd.LoadVector128(rightPtr + i);
@@ -586,7 +591,7 @@ public unsafe BitArray Xor(BitArray value)
586591
}
587592
}
588593

589-
for (; i < count; i++)
594+
for (; i < (uint)count; i++)
590595
thisArray[i] ^= valueArray[i];
591596

592597
Done:
@@ -629,7 +634,7 @@ public unsafe BitArray Not()
629634
Vector256<int> ones = Vector256.Create(-1);
630635
fixed (int* ptr = thisArray)
631636
{
632-
for (; i < count - (Vector256<int>.Count - 1); i += (uint)Vector256<int>.Count)
637+
for (; i < (uint)count - (Vector256IntCount - 1u); i += Vector256IntCount)
633638
{
634639
Vector256<int> vec = Avx.LoadVector256(ptr + i);
635640
Avx.Store(ptr + i, Avx2.Xor(vec, ones));
@@ -641,7 +646,7 @@ public unsafe BitArray Not()
641646
Vector128<int> ones = Vector128.Create(-1);
642647
fixed (int* ptr = thisArray)
643648
{
644-
for (; i < count - (Vector128<int>.Count - 1); i += (uint)Vector128<int>.Count)
649+
for (; i < (uint)count - (Vector128IntCount - 1u); i += Vector128IntCount)
645650
{
646651
Vector128<int> vec = Sse2.LoadVector128(ptr + i);
647652
Sse2.Store(ptr + i, Sse2.Xor(vec, ones));
@@ -652,15 +657,15 @@ public unsafe BitArray Not()
652657
{
653658
fixed (int* leftPtr = thisArray)
654659
{
655-
for (; i < count - (Vector128<int>.Count - 1); i += (uint)Vector128<int>.Count)
660+
for (; i < (uint)count - (Vector128IntCount - 1u); i += Vector128IntCount)
656661
{
657662
Vector128<int> leftVec = AdvSimd.LoadVector128(leftPtr + i);
658663
AdvSimd.Store(leftPtr + i, AdvSimd.Not(leftVec));
659664
}
660665
}
661666
}
662667

663-
for (; i < count; i++)
668+
for (; i < (uint)count; i++)
664669
thisArray[i] = ~thisArray[i];
665670

666671
Done:
@@ -935,9 +940,9 @@ public unsafe void CopyTo(Array array, int index)
935940

936941
fixed (bool* destination = &boolArray[index])
937942
{
938-
for (; (i + Vector256<byte>.Count) <= m_length; i += (uint)Vector256<byte>.Count)
943+
for (; (i + Vector256ByteCount) <= (uint)m_length; i += Vector256ByteCount)
939944
{
940-
int bits = m_array[i / BitsPerInt32];
945+
int bits = m_array[i / (uint)BitsPerInt32];
941946
Vector256<int> scalar = Vector256.Create(bits);
942947
Vector256<byte> shuffled = Avx2.Shuffle(scalar.AsByte(), shuffleMask);
943948
Vector256<byte> extracted = Avx2.And(shuffled, bitMask);
@@ -957,9 +962,9 @@ public unsafe void CopyTo(Array array, int index)
957962

958963
fixed (bool* destination = &boolArray[index])
959964
{
960-
for (; (i + Vector128<byte>.Count * 2) <= m_length; i += (uint)Vector128<byte>.Count * 2)
965+
for (; (i + Vector128ByteCount * 2u) <= (uint)m_length; i += Vector128ByteCount * 2u)
961966
{
962-
int bits = m_array[i / BitsPerInt32];
967+
int bits = m_array[i / (uint)BitsPerInt32];
963968
Vector128<int> scalar = Vector128.CreateScalarUnsafe(bits);
964969

965970
Vector128<byte> shuffledLower = Ssse3.Shuffle(scalar.AsByte(), lowerShuffleMask);
@@ -979,9 +984,9 @@ public unsafe void CopyTo(Array array, int index)
979984
Vector128<byte> ones = Vector128.Create((byte)1);
980985
fixed (bool* destination = &boolArray[index])
981986
{
982-
for (; (i + Vector128<byte>.Count * 2) <= m_length; i += (uint)Vector128<byte>.Count * 2)
987+
for (; (i + Vector128ByteCount * 2u) <= (uint)m_length; i += Vector128ByteCount * 2u)
983988
{
984-
int bits = m_array[i / BitsPerInt32];
989+
int bits = m_array[i / (uint)BitsPerInt32];
985990
// Same logic as SSSE3 path, except we do not have Shuffle instruction.
986991
// (TableVectorLookup could be an alternative - dotnet/runtime#1277)
987992
// Instead we use chained ZIP1/2 instructions:
@@ -1015,10 +1020,10 @@ public unsafe void CopyTo(Array array, int index)
10151020
}
10161021

10171022
LessThan32:
1018-
for (; i < m_length; i++)
1023+
for (; i < (uint)m_length; i++)
10191024
{
10201025
int elementIndex = Div32Rem((int)i, out int extraBits);
1021-
boolArray[index + i] = ((m_array[elementIndex] >> extraBits) & 0x00000001) != 0;
1026+
boolArray[(uint)index + i] = ((m_array[elementIndex] >> extraBits) & 0x00000001) != 0;
10221027
}
10231028
}
10241029
else

0 commit comments

Comments
 (0)