Implement cent/ucent - #23575
Conversation
DMD perf check
|
e11d659 to
08340ba
Compare
|
Mir, Mir-random, Phobos have got code that has been silently "supporting" (u)cent that is now erroring. |
d596b2c to
feaf0a2
Compare
|
This is ready for a first pass over it @WalterBright, we can talk more at meeting about it. |
| @@ -0,0 +1,173 @@ | |||
| # Plan: Implement `cent` and `ucent` (128-bit integers) in dmd | |||
There was a problem hiding this comment.
Intentionally, learning things to give @LightBender data points for PhobosV3.
|
|
||
| #pragma once | ||
|
|
||
| #include <cstdint> |
There was a problem hiding this comment.
Include dsystem.h, not system headers in frontend code.
| #include <cstdint> | ||
|
|
||
| // Mirrors dmd.common.int128.Cent | ||
| struct alignas(16) Cent |
There was a problem hiding this comment.
FYI this is not common code, so it's location is only a bit odd for that reason alone.
Other backends implement they own versions/library of double-int (and wide-int for N-sized integers), so maybe better to move to root library, along with overloads of all operators.
See longdouble as an example.
Though not really a problem. As downstreams can just move this file (and int128.d) to the bin and implement their own version that wraps their own backend type irrespective of where it is placed.
There was a problem hiding this comment.
I did not add dmd.common.int128.
Also, common is just root but with some -betterC stuff, like attributes that were added. It's something that Andrei worked on years ago but didn't get very far with.
| static IntegerExp literal(); | ||
| }; | ||
|
|
||
| class BigIntegerExp final : public Expression |
There was a problem hiding this comment.
No to introducing a new integer expression. Instead adapt the existing IntegerExp. 99% of the time it'll still use the fast path and do arithmetic on value.lo directly only (ensuring that hi is always 0)
You can still keep around the helpers like isCentType below to keep the double and single int paths separate. At the same time you'll save on a lot of duplication.
There was a problem hiding this comment.
I have some concerns with that, which is why I did not do it that way.
- Memory usage, from other experiments that @rainers has been doing the increase would be noticeable
- In practice its operating on sinteger_t's; and integer_t, I suspect that this would have a lot more effect than you may realize. So there will be duplication regardless.
- It'll scale to 256bit without hurting the smaller sizes (however they are not needed atm).
There was a problem hiding this comment.
There'll be no growth in memory. It'll just be extended as needed, we already do this for general arrays.
union {
dinteger_t _value;
Cent* _widevalue;
}
And we can get away with gating on the Type for now when reading the value as it's only cent to support.
To future proof for _BitInt or if D opts to have it's own N-sized integers, we'll have to give up the existing implementation and layout anyway (can store length in a ushort). The pervasiveness of assuming dinteger_t == 64 bits everywhere needs to be ejected from the compiler. Attempts to mitigate by not unifying all internal integer representations will just make things worse in the long run.
There was a problem hiding this comment.
I've checked Expression, and there's even enough padding room to put in the length of a variable-sized integer here.
dmd/compiler/src/dmd/expression.d
Line 129 in 9703ff2
Obviously, just store a ushort with a generic name and then derived expressions can use it for whatever they like. Possibly even to move their bitfields into Expression itself to reduce even more memory.
| import core.stdc.stdio; | ||
| import dmd.arraytypes; | ||
| import dmd.astenums; | ||
| import dmd.common.int128 : Cent, add, sub, mul, div, udiv, divmod, udivmod, and, or, xor, com, neg, shl, shr, sar, lt, le, ult, ule, tst, MinusOne; |
There was a problem hiding this comment.
| import dmd.common.int128 : Cent, add, sub, mul, div, udiv, divmod, udivmod, and, or, xor, com, neg, shl, shr, sar, lt, le, ult, ule, tst, MinusOne; | |
| import dmd.common.int128; |
Selectively importing the entire library is too jarring.
Either import the entire module at top-level, or selectively import as-needed at function-level.
|
(merge conflicts) |
|
While I can't comment on the code itself, I do see a number of holes in the tests.
|
For this we can thank DeepSeek v4 flash.