Skip to content

[Cross-platform] Bug fix for #39646 regarding downsizing of division operation

J. Gareth "Kit" Moreton requested to merge CuriousKit/optimisations:i39646 into main

Summary

This merge request fixes the issue raised over at #39646 (closed) where a nested division operation inside a bitwise AND operation was incorrectly truncated and caused incorrect results if the numerator was greater than or equal to 2^32.

System

  • Processor architecture: x86_64, AArch64

What is the current bug behavior?

With an expression of the form Result := (Input div 100000000) and $FF, with Input of type QWord and Result of type SmallInt, the division would produce an incorrect quotient if Input was >= 2^32 due to the compiler truncating the operands to a LongWord.

What is the behavior after applying this patch?

Results from nested DIV and MOD operations inside bitwise AND operations should now be correct.

Additional Notes

  • See #39646 (closed) for more information.
  • The root of this bug was the special handling of bitwise AND operations when it comes to using internal typecasting to downsize integer operations, specifically the nested docheckremoveinttypeconvs in the checkremovebiginttypeconvs subroutine, in the ncnv unit. If any of the operands in the AND node was expanded at an earlier stage, the compiler tries to shrink them down again. Nested DIV and MOD operations, much like SHR nodes already, are exempt from this process.
  • From the above, the bug only appears to fully manifest in situations where the fast division algorithm is implemented on 64-bit platforms, where divisions by a constant are converted into a high multiplication and bit shift. As a result, this bug also gets triggered on AArch64.
Edited by J. Gareth "Kit" Moreton

Merge request reports