aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
diff options
context:
space:
mode:
authorLRFLEW <LRFLEW@aol.com>2024-04-19 11:58:18 -0500
committerGitHub <noreply@github.com>2024-04-19 18:58:18 +0200
commit41e696291c64fe19629e14887ed1ed9b9c2271f0 (patch)
tree31e6d20d8a09c712ce1a0f26cc62c4340b8371b9 /llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
parent82c320ca59744b5082ef6e45dab6bab20cbd0795 (diff)
downloadllvm-41e696291c64fe19629e14887ed1ed9b9c2271f0.zip
llvm-41e696291c64fe19629e14887ed1ed9b9c2271f0.tar.gz
llvm-41e696291c64fe19629e14887ed1ed9b9c2271f0.tar.bz2
linear_congruential_engine: add using more precision to prevent overflow (#81583)
This PR is a followup to #81080. This PR makes two major changes to how the LCG operation is computed: The first is that I added an additional case where `ax + c` might overflow the intermediate variable, but `ax` by itself won't. In this case, it's much better to use `(ax mod m) + c mod m` than the previous behavior of falling back to Schrage's algorithm. The addition modulo is done in the same way as when using Schrage's algorithm (i.e. `x += c - (x >= m - c)*m`), but the multiplication modulo is calculated directly, which is faster. The second is that I added handling for the case where the `ax` intermediate might overflow, but Schrage's algorithm doesn't apply (i.e. r > q). In this case, the only real option is to increase the precision of the intermediate values. The good news is that - for `x`, `a`, and `c` being n-bit values - `ax + c` will never overflow a 2n-bit intermediary, meaning this promotion can only happen once, and will always be able to use the simplest implementation. This is already the case for 16-bit LCGs, as libcxx chooses to compute them with 32-bit intermediate values. For 32-bit LCGs, I simply added code similar to the 16-bit case to use the existing 64-bit implementations. Lastly, for 64-bit LCGs, I wrote a case that calculates it using `unsigned __int128` if it is available to use. While this implementation covers a *lot* of the missing cases from #81080, this still won't compile **every** possible `linear_congruential_engine`. Specifically, if `a`, `c`, and `m` are chosen such that it needs 128-bit integers, but the platform doesn't support `__int128` (eg. 32-bit x86), then it will fail to compile. However, this is a fairly rare case to see actually used, and libcxx would be in good company with this, as [libstdc++ also fails to compile under these circumstances](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87744). Fixing **this** gap would require even **more** work of further complexity, so that would probably be best handled by a different PR (I'll put more details on what that PR would entail in a comment).
Diffstat (limited to 'llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp')
0 files changed, 0 insertions, 0 deletions