<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Hacker News: dzaima</title><link>https://news.ycombinator.com/user?id=dzaima</link><description>Hacker News RSS</description><docs>https://hnrss.org/</docs><generator>hnrss v2.1.1</generator><lastBuildDate>Mon, 24 Aug 2026 05:27:10 +0000</lastBuildDate><atom:link href="https://hnrss.org/user?id=dzaima" rel="self" type="application/rss+xml"></atom:link><item><title><![CDATA[New comment by dzaima in "RISC-V: They Should Have Known Better"]]></title><description><![CDATA[
<p>That is quite a good bit more evenly-spread (the "..." is 5159 instrs).<p>Wonder what's up with bit 21; if whatever uses it so much is repositionable (and not an aarch64-specific thing), could save like 2KB on x86-64 via putting it in the low 8 bits instead.</p>
]]></description><pubDate>Sun, 16 Aug 2026 12:48:18 +0000</pubDate><link>https://news.ycombinator.com/item?id=49319554</link><dc:creator>dzaima</dc:creator><comments>https://news.ycombinator.com/item?id=49319554</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49319554</guid></item><item><title><![CDATA[New comment by dzaima in "RISC-V: They Should Have Known Better"]]></title><description><![CDATA[
<p>Some stats on an aarch64 binary of my current main project (1.6MB .text, 6600 symbols as per whatever "nm the-binary | wc -l" includes, from "objdump -d the-binary"):<p><pre><code>    19546 /tbn?z/
    18029 /tbn?z.*, #0x0/  (but this includes boolean checks)
      224 /tbn?z.*, #0x1f/ (i.e. 32-bit x<0)
     1139 /tbn?z.*, #0x3f/ (i.e. 64-bit x<0)
      154 other immediates
</code></pre>
Said project doesn't do fixed bitfields much (there are some, but a chunk of those test multiple bits) so unsurprisingly not much. (I could imagine that the kernel has significantly more, but it's an edge-case (though perhaps an important one) of being basically massive amounts of fixed configurable glue)</p>
]]></description><pubDate>Sun, 16 Aug 2026 10:44:17 +0000</pubDate><link>https://news.ycombinator.com/item?id=49318815</link><dc:creator>dzaima</dc:creator><comments>https://news.ycombinator.com/item?id=49318815</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49318815</guid></item><item><title><![CDATA[New comment by dzaima in "RISC-V: They Should Have Known Better"]]></title><description><![CDATA[
<p>Both clang and gcc do actually generate TBZ/TBNZ for checking a bool: <a href="https://godbolt.org/z/K6evhaxGT" rel="nofollow">https://godbolt.org/z/K6evhaxGT</a></p>
]]></description><pubDate>Sun, 16 Aug 2026 06:16:57 +0000</pubDate><link>https://news.ycombinator.com/item?id=49317356</link><dc:creator>dzaima</dc:creator><comments>https://news.ycombinator.com/item?id=49317356</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49317356</guid></item><item><title><![CDATA[New comment by dzaima in "RISC-V: They Should Have Known Better"]]></title><description><![CDATA[
<p>Some more:<p>> The spec says that bit must be zero, and yet no encoding uses the space opened up by that bit being one.<p>The spec says "the code points with shamt[5]=1 are designated for custom extensions.", so the space is specifically reserved for custom vendor extensions.<p>So, if I wanted to add a custom "dzaima.c.clear_top_n_bits rd, imm5" instruction, that's space I could safely put it in, knowing that no future standard instruction will be added there that I may regret overlapping. So while that space goes unused in the standard, its existence helps with the overlapping encoding problem!<p>> For I-type instructions, bit 1 [...], bit 11<p>Of course, that's cherry-picking two of the 25% of bits that have multiple positions they come from, and specifically 11 as it's the worst one. Full stats:<p><pre><code>    1 position: 24 bits: (everything that's not listed below)
    2 positions: 7 bits: 0, 1, 2, 3, 4, 12, 20
    3 positions: 1 bits: 11 (the single worst case)
</code></pre>
So that's like 9 muxes for merging all immediates to the same place (or less of course if the different encodings' immediates go to different places), the rest is just wires.<p>Obligatory note is that some of the funkiness is to place the sign-extended bit in the same bit position, so some saved muxes from that.<p>Now, I am a "software person who's never written verilog", but I highly doubt a 3:1 mux is as cheap as a 2:1 mux in silicon, so even if you always need to merge in the sign bit, reducing the number of cases is still beneficial.<p>Compressed does make it a ton more ugly though (combining both 32-bit and 16-bit instruction encodings, placing the 16-bit ones in the low 16 bits):<p><pre><code>    1 position: 13 bits
    2 positions: 7 bits: 10, 13, 14, 15, 16, 17, 20
    3 positions: 4 bits: 3, 4, 9, 12
    4 positions: 5 bits: 0, 1, 2, 5, 11
    5 positions: 3 bits: 6, 7, 8
</code></pre>
looking at aarch64 on <a href="https://asmjit.com/asmgrid/" rel="nofollow">https://asmjit.com/asmgrid/</a>:<p><pre><code>    tbz Xt, #imm, #relS*4   imm:1|0110110|imm:5 |    relS:14 |Rt
    lsl Xd, Xn, #n            1   1010011|01|immr:6|imms:6|Rn|Rd
</code></pre>
Fun! (lsl being a subset of the bitfield extract instrs is neat; tbz's similar-functionality 6-bit field is just entirely-differently placed though. Also.. using the Rd slot for an input-only Rt? that's one thing RISC-V doesn't do, even across compressed and 32-bit instrs!)</p>
]]></description><pubDate>Sat, 15 Aug 2026 21:56:18 +0000</pubDate><link>https://news.ycombinator.com/item?id=49314686</link><dc:creator>dzaima</dc:creator><comments>https://news.ycombinator.com/item?id=49314686</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49314686</guid></item><item><title><![CDATA[New comment by dzaima in "RISC-V: They Should Have Known Better"]]></title><description><![CDATA[
<p>Random minor-ish notes:<p>- A big problem with extension detection RISC-V has is that there's no central authority mandating vendors to not overlap things (obviously, given RISC-V being an open standard), so basic bitmasks for supported extensions is generally rather problematic (and of course even if you collected a standardized bitmask of all extensions from all vendors, it'd grow quite massive quite quickly); you'd at least want some grouping/marking by vendor, if not full extension strings. That said, it would be nice to at the very least have some standard in-memory blob format if nothing else, that you could query from any OS/libc. (which maybe somewhat-exists to some extent with a C API meant for libc, but as-is still doesn't attempt to figure out vendor extensions).<p>- many, if not the vast majority, of aarch64 TBZ/TBNZ are probably branching on a boolean; something RISC-V can also of course do in one instruction. Generally, comparing instruction frequencies across ISAs is messy if not approximately meaningless due to different sorts of things existing for solving the same tasks.<p>- "Having this happen means that instead of a clearly-understandable crash you get ... well ... anything." - RISC-V will do you one better - it doesn't even guarantee a crash when an instruction isn't defined at all! Overlapping extensions is definitely messy for disassembly, sure, but that's also just basically unavoidable as long as RISC-V is open (see my first point). (perhaps there could've been stricter rules for reserved-for-standard encodings than reserved-for-vendor ones? of course still doesn't help vendor encodings, nor non-compliant vendors)</p>
]]></description><pubDate>Fri, 14 Aug 2026 22:09:47 +0000</pubDate><link>https://news.ycombinator.com/item?id=49305195</link><dc:creator>dzaima</dc:creator><comments>https://news.ycombinator.com/item?id=49305195</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49305195</guid></item><item><title><![CDATA[New comment by dzaima in "Moving integer division to floating-point is trivial"]]></title><description><![CDATA[
<p>Float divides are still pretty expensive; 8-10 cycles of latency on modern hardware, integer divides being 8-20 cycles. (on Apple M1 both are 8-10 cycles; int div is much worse on older x86 hw)<p>Integer multiply is also pretty universally 3 cycles of latency, i.e. basically the same as float multiply (or even add!).<p>What float div definitely has over int div is throughput, as float div comes in vectorized versions on x86 & ARM, and it usually is actually parallelized.<p>On top of generally fp div generally having higher throughput (M1 gets down to 1 instr/cycle! though int div isn't bad either at 0.5 instrs/cycle; x86 numbers are messy but even 32-bit int div is never better than f64 div, though they're close; also an annoying aspect is that x86 division instrs actually always take a 128-bit divisor, though hopefully a sign-/zero-extended 64-bit value skips the extra work)</p>
]]></description><pubDate>Fri, 14 Aug 2026 20:33:45 +0000</pubDate><link>https://news.ycombinator.com/item?id=49304218</link><dc:creator>dzaima</dc:creator><comments>https://news.ycombinator.com/item?id=49304218</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49304218</guid></item><item><title><![CDATA[New comment by dzaima in "Faster floating point math with Rust's new API"]]></title><description><![CDATA[
<p>> Sure, and that's basically what I was wondering about with respect to "can't define it" being shorthand for something else<p>Eh, I'd say it's still the same thing; can't define a sanitizer for it if what you define isn't a sanitizer. Depends on a specific definition of "sanitizer" though.<p>> At least making your own isn't horrendously difficult.<p>In C++ perhaps, but impossible in C. (and there are still some funky edge-cases where multiplying two `uint16_t`s can overflow due to implicit promotion to signed int; C's _BitInt solves at least that)<p>Clang does actually have experimental support for these - <a href="https://clang.llvm.org/docs/OverflowBehaviorTypes.html" rel="nofollow">https://clang.llvm.org/docs/OverflowBehaviorTypes.html</a></p>
]]></description><pubDate>Fri, 14 Aug 2026 14:25:04 +0000</pubDate><link>https://news.ycombinator.com/item?id=49299136</link><dc:creator>dzaima</dc:creator><comments>https://news.ycombinator.com/item?id=49299136</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49299136</guid></item><item><title><![CDATA[New comment by dzaima in "Faster floating point math with Rust's new API"]]></title><description><![CDATA[
<p>> it's still a counterexample for "you can't define it because it means sanitizers can't warn for it"<p>Sure, technically you can write a sanitizer for anything. It just becomes less a "sanitizer" you can always recommend everyone everywhere use, and more of just a heuristic thing that only really works if you design your code for its arbitrary desires.<p>> and in the cases where it actually is intentional you can suppress the check.<p>imo it'd be nice to have separate types for wrapping and non-wrapping integers for that, so that you have actual language-level semantics and an easy way to mix things (e.g. wrapping arith for hashing, mixed with non-wrapping arith for loop index or whatever) instead of suppressions.</p>
]]></description><pubDate>Tue, 11 Aug 2026 21:49:43 +0000</pubDate><link>https://news.ycombinator.com/item?id=49264982</link><dc:creator>dzaima</dc:creator><comments>https://news.ycombinator.com/item?id=49264982</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49264982</guid></item><item><title><![CDATA[New comment by dzaima in "Faster floating point math with Rust's new API"]]></title><description><![CDATA[
<p>> -fsanitize=unsigned-integer-overflow<p>Of course, -fsanitize=unsigned-integer-overflow isn't enabled by default, and few people use it (github code search gives 6K results for that, compared to 175K for "-fsanitize=undefined"; which to be fair is a lot higher than I expected, but still not a lot).<p>> Makes me wonder whether "sanitizers can't flag defined behavior" is meant to be shorthand for some more nuanced position<p>And signed overflow checking would have to be off-by-default too, if people were allowed to start relying on it. It'd be less "false positive rate too high", more "it disallows you to use a genuine language feature that is actually useful", defeating the point of defining signed overflow in the first place.<p>(imo defining signed overflow specifically for reducing attack surface from exploitable UB is a mostly-separate discussion, which should not affect core language semantics, and certainly not what users would be suggested to do)</p>
]]></description><pubDate>Tue, 11 Aug 2026 20:36:41 +0000</pubDate><link>https://news.ycombinator.com/item?id=49264107</link><dc:creator>dzaima</dc:creator><comments>https://news.ycombinator.com/item?id=49264107</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49264107</guid></item><item><title><![CDATA[New comment by dzaima in "Faster floating point math with Rust's new API"]]></title><description><![CDATA[
<p>C23 specifies that signed integers must be two's complement, but still leaves signed arithmetic overflow as undefined behavior.</p>
]]></description><pubDate>Tue, 11 Aug 2026 13:01:05 +0000</pubDate><link>https://news.ycombinator.com/item?id=49257610</link><dc:creator>dzaima</dc:creator><comments>https://news.ycombinator.com/item?id=49257610</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49257610</guid></item><item><title><![CDATA[New comment by dzaima in "Branchless Rust: Making a Filter 4x Faster by Removing an If"]]></title><description><![CDATA[
<p>There's no autovectorization there; scalar f64-s just are always stored in xmm registers. And the bounds check is still there.</p>
]]></description><pubDate>Thu, 06 Aug 2026 18:41:06 +0000</pubDate><link>https://news.ycombinator.com/item?id=49200601</link><dc:creator>dzaima</dc:creator><comments>https://news.ycombinator.com/item?id=49200601</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49200601</guid></item><item><title><![CDATA[New comment by dzaima in "Branchless Rust: Making a Filter 4x Faster by Removing an If"]]></title><description><![CDATA[
<p>Compress patterns aren't recognized by any open-source compiler autovectorizer as far as I'm aware of. (I think intel's proprietary C/C++ compiler can?)</p>
]]></description><pubDate>Thu, 06 Aug 2026 18:38:52 +0000</pubDate><link>https://news.ycombinator.com/item?id=49200576</link><dc:creator>dzaima</dc:creator><comments>https://news.ycombinator.com/item?id=49200576</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49200576</guid></item><item><title><![CDATA[New comment by dzaima in "Nvidia’s Vera Whitepaper Has a Thread Loose"]]></title><description><![CDATA[
<p>aarch64 has a CPU mode, DIT (Data Independent Timing), specifically for allowing software to request all fancy value prediction stuff to be disabled for the duration of processing of sensitive data.<p>(doesn't help when the attack target is general-purpose/user-controlled code leaking things, but if you're relying on a process not leaking memory plainly available to it without full careful control of what the process runs, you've already been fully-SOL on that for decades and nothing has nor will nor can change about that)</p>
]]></description><pubDate>Thu, 06 Aug 2026 10:09:17 +0000</pubDate><link>https://news.ycombinator.com/item?id=49194721</link><dc:creator>dzaima</dc:creator><comments>https://news.ycombinator.com/item?id=49194721</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49194721</guid></item><item><title><![CDATA[New comment by dzaima in "JEP 401: Value Objects (Preview) merged to OpenJDK master"]]></title><description><![CDATA[
<p>While I agree with the comment being overly-praise-y, this is complexity that any multithreaded language with mutability and reasonable sanity/safety desires (but without intrusive compile-time rules a la Rust) has; others just might pretend some of the options don't exist / aren't desirable. (..and value objects, as landed in the PR, doesn't yet have tearable objects)</p>
]]></description><pubDate>Fri, 31 Jul 2026 13:19:09 +0000</pubDate><link>https://news.ycombinator.com/item?id=49122779</link><dc:creator>dzaima</dc:creator><comments>https://news.ycombinator.com/item?id=49122779</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49122779</guid></item><item><title><![CDATA[New comment by dzaima in "Zig's Incremental Compilation Internals"]]></title><description><![CDATA[
<p>A quick test (C, clang) gives me that a binary depending on 1000 shared libraries, each containing a single function returning an integer, with a main function summing up the results of all those functions, takes ~270ms to run from the dynamic linker overhead. So you'd definitely want a good chunk below thousands.<p>(a process with 100 shared libraries takes 6ms to run, which is a lot better (0.9ms for 1 library, for reference), but, especially with in-place patching skipping work on unchanged values, static linking still has a good shot at beating dynamic linking, especially if you run the binary multiple times)<p>Incremental compilation generally already depends on its stored intermediate data not getting corrupted, and the final binary need not be any differently handled in that aspect.</p>
]]></description><pubDate>Tue, 28 Jul 2026 18:39:33 +0000</pubDate><link>https://news.ycombinator.com/item?id=49088119</link><dc:creator>dzaima</dc:creator><comments>https://news.ycombinator.com/item?id=49088119</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49088119</guid></item><item><title><![CDATA[New comment by dzaima in "SIMD for Collision"]]></title><description><![CDATA[
<p>Unaligned loads/stores aren't <i>super</i> bad; if still within a cacheline, there's zero penalty, and on crossing cachelines it's alike two ops (except page crossing, which is more bad).<p>So, for 32B loads/stores and 64B cachelines, it's 1.5x more L1 cache ops (as half of the ops will cross a cacheline); perhaps bad if you're L1-cache-throughput-bound, but less so if you're at L2+ as the extra work sits in L1.</p>
]]></description><pubDate>Sat, 25 Jul 2026 23:32:58 +0000</pubDate><link>https://news.ycombinator.com/item?id=49052915</link><dc:creator>dzaima</dc:creator><comments>https://news.ycombinator.com/item?id=49052915</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49052915</guid></item><item><title><![CDATA[New comment by dzaima in "Codeberg: ToU extension to prohibit LLM-extrusions"]]></title><description><![CDATA[
<p>Where I eat doesn't have a "WC" sign, walls separating it from public areas, and a toilet present. Codebergs private repos have a clear "private" label, infrastructure for making them, acknowledgement and rules for it in ToS, and they are kept private.<p>Anyway, originally I didn't quite agree with fs111 on straight up calling your post misinformation, but I guess it is indeed your intent to completely ignore facts and just say random garbage.</p>
]]></description><pubDate>Thu, 23 Jul 2026 08:57:48 +0000</pubDate><link>https://news.ycombinator.com/item?id=49018682</link><dc:creator>dzaima</dc:creator><comments>https://news.ycombinator.com/item?id=49018682</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49018682</guid></item><item><title><![CDATA[New comment by dzaima in "Codeberg: ToU extension to prohibit LLM-extrusions"]]></title><description><![CDATA[
<p>...in what way whatsoever is this "They dont allow private repos"?<p>The size limit is........a size limit, something every host should have; there's one for public codeberg repos too.<p>And while there are restrictions on what private repos are allowed, there are also restrictions on what public repos are allowed too, and it's extremely clear that neither requirement is equivalent to "they don't allow [public / private] repos".<p>My reading of that section is that, besides the size limit, the rules on private repos are, to an extent, <i>less</i> strict than of public repos; anyone who falls under your second quoted sentence couldn't have any public repos either, by the nature of public repos needing to be FOSS.</p>
]]></description><pubDate>Wed, 22 Jul 2026 11:53:45 +0000</pubDate><link>https://news.ycombinator.com/item?id=49005284</link><dc:creator>dzaima</dc:creator><comments>https://news.ycombinator.com/item?id=49005284</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=49005284</guid></item><item><title><![CDATA[New comment by dzaima in "Two Case Studies of NaN"]]></title><description><![CDATA[
<p>> For example any such function can be marked with __attribute__((pure)) in compilers like gcc and clang.<p><a href="https://gcc.gnu.org/onlinedocs/gcc/Common-Attributes.html" rel="nofollow">https://gcc.gnu.org/onlinedocs/gcc/Common-Attributes.html</a> states:<p>> However, functions declared with the pure attribute can safely [...] in a way that does not affect [...] or the observable state of the program<p>So an exception-aware FP op cannot be __attribute__((pure)) in a program that may read the FP status later, or has trapping on FP exceptions enabled.<p>This is obvious from the fact that gcc & clang will entirely delete a call to a pure function if the result isn't used, thereby making potential FP traps not happen, or accrued exceptions not mutated.<p>(also traps on exceptions would make FP ops clearly not pure by the definition in functional programming too)<p>> If exceptions were enabled only for a part of the program, then the rest of the program can still generate special values and you need to test for them everywhere. So you get the worst of both choices, a complex program that can be crashed by an error.<p>Would be perfectly fine if combined with separate NaNful and NaNless types; design the language s.t. exception handling state must always be (or is automatically set to) the necessary one, and you never get NaNs in the NaNless types.</p>
]]></description><pubDate>Fri, 17 Jul 2026 12:21:20 +0000</pubDate><link>https://news.ycombinator.com/item?id=48946493</link><dc:creator>dzaima</dc:creator><comments>https://news.ycombinator.com/item?id=48946493</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=48946493</guid></item><item><title><![CDATA[New comment by dzaima in "Two Case Studies of NaN"]]></title><description><![CDATA[
<p>> Floating-point operations are stateful in any CPU made during the last 40 years.<p>But sane programming languages entirely hide that (to the same extent that they hide integer flags and registers in general), at the very least by default; and in such sane languages, programmers do not need to be aware of any of this mess.<p>e.g. C's requirement of "#pragma STDC FENV_ACCESS ON" for non-default FP status, and lack thereof in 99.99% of code; C spec even explicitly notes:<p>> With these conventions, a programmer can safely assume default floating-point control modes (or be unaware of them). The responsibilities associated with accessing the floating-point environment fall on the programmer or program that does so explicitly.<p>(never mind basically every other language, which don't even allow anything other than round-nearest-ties-even + no-exceptions)<p>> Enabling some or all kinds of FP exceptions has absolutely no influence on auto-vectorization. It also has no influence on speed, in well-designed CPUs.<p>If you want to have deterministic semantics (i.e. want to be a sane language), it absolutely does; it means that, in `a+b; x[i];`, the `x[i]` load <i>must not happen</i> if `a+b` results in a trap. So you cannot ever execute the next loop iteration before being sure the previous doesn't trap. Entirely forbidding autovectorization.<p>If you want to still have autovectorization, you'd need to have some washy semantics of like "the trap of an fp op can be delayed to an arbitrarily-later point in time, up to [insert some messy ambiguous incomplete attempt at establishing some limit to this]", which, besides making basic code non-deterministic (yikes! we don't need <i>more</i> of that in the world), will make proving compiler optimization correctness extra-messy.<p>Non-trapping exceptions (i.e. accruing) would be simpler to preserve through vectorization (allowing reordering up to reading the status, which is explicit in code), but you're back to allowing observable NaNs and making programmers insert manual checks. (and even then, you'd run into issues if you wanted to vectorize the tail of a loop on architectures without maskable FP SIMD ops)<p>(and, of course, unrelated to any of this, giving the programmer control over FP status means compilers are massively-restricted on optimizing code - can't DCE float ops, can't insert new FP ops even if it would be beneficial, etc)</p>
]]></description><pubDate>Fri, 17 Jul 2026 12:07:34 +0000</pubDate><link>https://news.ycombinator.com/item?id=48946359</link><dc:creator>dzaima</dc:creator><comments>https://news.ycombinator.com/item?id=48946359</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=48946359</guid></item></channel></rss>