@@ -363,10 +363,20 @@ public bool TallyDist(int distance, int length)
363363 [ MethodImpl ( InliningOptions . ShortMethod ) ]
364364 public static short BitReverse ( int toReverse )
365365 {
366- DebugGuard . MustBeLessThan ( toReverse & 0xF , Bit4Reverse . Length , nameof ( toReverse ) ) ;
367- DebugGuard . MustBeLessThan ( ( toReverse >> 4 ) & 0xF , Bit4Reverse . Length , nameof ( toReverse ) ) ;
368- DebugGuard . MustBeLessThan ( ( toReverse >> 8 ) & 0xF , Bit4Reverse . Length , nameof ( toReverse ) ) ;
369- DebugGuard . MustBeLessThan ( toReverse >> 12 , Bit4Reverse . Length , nameof ( toReverse ) ) ;
366+ /* Use unsafe offsetting and manually validate the input index to reduce the
367+ * total number of conditional branches. There are two main cases to test here:
368+ * 1. In the first 3, the input value (or some combination of it) is combined
369+ * with & 0xF, which results in a maximum value of 0xF no matter what the
370+ * input value was. That is 15, which is always in range for the target span.
371+ * As a result, no input validation is needed at all in this case.
372+ * 2. There are two cases where the input value might cause an invalid access:
373+ * when it is either negative, or greater than 15 << 12. We can test both
374+ * conditions in a single pass by casting the input value to uint, and checking
375+ * whether that value is lower than 15 << 12. If it was a negative value (2-complement),
376+ * the test will fail as the uint cast will result in a much larger value.
377+ * If the value was simply too high, the test will fail as expected.
378+ * Doing this reduces the total number of index checks from 4 down to just 1. */
379+ Guard . MustBeLessThanOrEqualTo < uint > ( ( uint ) toReverse , 15 << 12 , nameof ( toReverse ) ) ;
370380
371381 ref byte bit4ReverseRef = ref MemoryMarshal . GetReference ( Bit4Reverse ) ;
372382
0 commit comments