News for hackers. Stuff that matters.

dougall

Hi, author here. My version definitely shouldn't be faster unless something very weird is going on with the runtime (though I think with the benefit of hindsight some further optimisation of it is possible). I have never seen a good use for this, aside from as a proof that it is possible, but I can imagine it coming up if, say, you wanted to write an exploit for an esoteric programming language runtime.

If you still maintain this code and want to optimise it, I don't think you should need a full powers-of-two table, just having log(n) powers of two should do in a pattern like:

  if (v > 2**1024) { v *= 2**-1024; e += 1024; }
  if (v > 2**512) { v *= 2**-512; e += 512; }
  ...
That's a straightforward memory saving and also leaves v normalised, so gives you your fraction bits with a single multiplication or division. This is a little less simple than I'm making it look, because in reality you end up moving v to near the subnormal range, or having to use a different code path if v < 1 vs if v >= 2 or something. But otherwise, yeah, the code looks good.
Re:Linux on Apple Silicon with Alyssa Rosenzweig [audio] on Friday November 01, 2024 @07:22PM (#42022536)
It's fun :)
Re:Bit-twiddling abstract addition with unknown bits on Wednesday June 05, 2024 @09:41AM (#40584640)
Yeah, exactly this.

To try to make it more "concrete", compilers tend to end up processing an absurd mess of code, that does things that superficially look silly, due to extensive inlining.

The code above is entirely plausible for C code checking the alignment of a total size, where "a" and "b" are the sizes of two parts, both calculated by a multiplication that ensures their evenness.

Another realistic examples are flags-fields, where each bit represents a boolean. For example, the compiler should be able to optimise:

    flags |= 0x100;
    if (!(flags & 0x100)) { ... }
Addition might factor in either as a substitution for bitwise-OR or bitwise-XOR where the author has prior knowledge that the two are equivalent (and assumes it will lead to better code generation), as part of SWAR (simd-within-a-word) code, or in cases where integer fields are packed alongside flags (e.g. a refcount and a couple of flags, or a string-length and some flags).

If this seems rare and unusual, that's cool – in general it is. But these strategies are very heavily used in performance-critical code, where using multiple variables would cause a measurable slowdown, so it makes sense that compilers care about optimising this kind of thing.

Re:Bit-twiddling abstract addition with unknown bits on Wednesday June 05, 2024 @12:56AM (#40581514)
Author here - I believe this 2020 post resurfaced as known-bits optimisation was recently added to PyPy (Python implementation using a JIT compiler), which this thread discusses:

https://mastodon.social/@cfbolz/112557672421317765

It includes discussion of where this kind of optimisation helps (not most "normal" Python code, but some code like emulators with lots of bitwise operations is ~30% faster), links to LLVM and Linux kernel implementations, and some related blog posts and papers. (I believe the Linux eBPF people came up with all of the ideas here before I did, though I wasn't aware of it at the time - it's easy to forget the Linux kernel has an optimising compiler in it.)

I'm not sure if that's what you mean by context - happy to answer questions.

Re:A64 SIMD Instruction List: SVE Instructions on Thursday October 05, 2023 @12:21AM (#37774880)
Awesome! I'm always happy to hear people are interested in SVE :)

(And yeah, creating technical documentation that a large company should have created themselves has somehow become a hobby of mine.)

Re:A64 SIMD Instruction List: SVE Instructions on Tuesday October 03, 2023 @05:20AM (#37749578)
Heh, I'd have called it the Arm SIMD Instruction List, but Arm have been aggressively enforcing the Arm trademark [1], so I settled for A64 (the official name for the instruction set [2]).

[1] https://www.theregister.com/2023/08/31/a_star_star_domains/

[2] https://developer.arm.com/Architectures/A64%20Instruction%20...

Re:A64 SIMD Instruction List: SVE Instructions on Tuesday October 03, 2023 @01:51AM (#37748381)
I hope it's useful, though I think most people care about the "Advanced SIMD" (Neon) instructions, which I'd also like to do. I started with SVE because I wasn't already familiar with it, so it was a more interesting project.

(For anyone unfamiliar, SVE is supported only on extremely recent ARM CPUs, and Apple CPUs do not yet support it, whereas AdvSIMD is available on all ARMv8-A CPUs.)

Re:What is gained and lost with 63-bit integers? (2014) on Saturday August 12, 2023 @07:43AM (#37099186)
It is a trade off, but a lot of processors have free offsets from loads, so pointer chasing is almost always free.

On ARM, "ldr x0, [x1]" just becomes "ldur x0, [x1, #-1]" - same size, same performance (at least on the Apple M1). If you have an array in a structure "add x0, x1, #16 ; ldr x0, [x0, x2, lsl #3]" becomes "add x0, x1, #15 ; ldr x0, [x0, x2, lsl #3]".

The only place I can think of penalties are pointers directly to arrays: "ldr x0, [x0, x1, lsl #3]" becomes "sub x0, x0, #1 ; ldr x0, [x0, x1, lsl #3]". Or loads from large offsets - ldur can only reach 256 bytes, whereas the aligned ldr can reach 32760 bytes. In either case the penalty is only one SUB operation.

Re:What is gained and lost with 63-bit integers? (2014) on Saturday August 12, 2023 @07:06AM (#37098956)
The tag bit can be inverted.

V8 uses 1 for pointers, 0 for integers - you're usually loading from constant offsets from pointers anyway, so that mostly folds away nicely. Then:

x + y is translated to CPU instructions x + y

x * y is translated to CPU instructions (x >> 1) * y

x / y is translated to CPU instructions (((x >> 1) / (y >> 1)) << 1)

x lsl y is translated to CPU instructions (x << (y >> 1))

Re:Downfall Attacks on Tuesday August 08, 2023 @09:01PM (#37057511)
Yeah... I don't know if you saw Rodrigo Branco's damning "The Microarchitectures That I Saw And The Ones That I Hope To One Day See":

https://www.youtube.com/watch?v=WlcQrx7VK00 https://hardwear.io/usa-2023/presentation/the-microarchitect...

But it definitely seems to be a culture/disclosure problem.

(Also, hi - hope things are going well! We miss you on Mastodon)

Browsers use multiple processes for security and reliability, not as an alternative to multi-threading. They extensively use multi-threading for performance (as does a lot of other modern software).
Re:Having non-x86 machines makes your life harder on Wednesday June 21, 2023 @05:38AM (#36416407)
With Rosetta 2, it's been amazing. But yeah, Linux doesn't have Rosetta 2. Depending on what you're doing, everything works already, but it definitely can make life harder.
Yeah – ARM specifically added EOR3 and BCAX instructions to accelerate SHA-3 hashes, both of which can be handled by VPTERNLOGD.
Is there a reason you call out Discord and not GitHub?
Good point, it's likely that a high-power in-order chip could go faster. Do you know of any examples of high-power in-order cores I could compare to?
Alas, security generally isn't so important.

How many times have you been hacked by a side-channel exploit? (Or people you know? Or any publicly documented case?) Are you going to use a computer that runs at 1/10th the speed to mitigate that risk going forwards?

Keep in mind that a ton of non-side-channel exploits are caught in the wild every year, so your slow new computer isn't really secure, it's just not vulnerable to these specific attacks.

(For 1/10th: the Cortex-A55 in the following chart is the only "in-order" CPU: https://images.anandtech.com/doci/17102/SPECint2017_575px.pn... - though arguably even it isn't completely non-speculative, and it definitely has branch-prediction, but it's at least a reasonable ballpark.)

Nice!

Sorry if this comment is overly pedantic, I just enjoy having an excuse to talk about assembly.

It's worth noting that 0x80000000 would pass this "is zero" check. (I think this is probably a legal compiler optimisation because signed integer overflow is undefined, but I'm not 100% sure either way.)

Using a jump is also a bit risky - slightly better if it's predictable, much worse if it's unpredictable.

As far as size, this is 5 bytes on 32-bit x86 (as stated), 6 bytes on 64-bit x86, but can be 8 bytes if different registers are used:

    4501C0            add r8d,r8d
    7503              jnz 0x8
    41FFC0            inc r8d
(And, unlike the ARM code, you'd need an additional mov instruction if you wanted to preserve the input value.)

It feels like an ADC-based variant might be possible on x86 too - CMP and ADC are also x86 instructions. The problem is that ARM and x86 invert the value of the carry flag on subtraction (and comparison), so it doesn't translate directly, and I can't immediately see how to fix it up without using more instructions.

Though it'd be preferable to do:

    cmp wzr, w19      // set the carry flag if w19 is zero
    adc w8, w19, w19  // w8 = w19 + w19 + carry
Really? Is there case law to this effect?

These things happen, and have value, but I wouldn't have considered them as "given as a quid pro quo" or "mutual promises".

It's a huge issue, but multi-threading only helps with latency, not energy.
Then do that. It's not a video codec. The problem is computation power is increasing much more slowly than bandwidth, and is likely to continue to. 8K PNGs (by my napkin calculations) already take around 1 second of CPU time to decode. There are other solutions, and certainly better options today, but it's plausible that in the next 10-15 years, this will become the best option for fast-loading, high-resolution, 2D images. (Or texture data for 3D graphics. Or 360, I guess - not sure why that'd be different.)
Thanks! It's a tiny contribution compared to Alyssa and Lina's development and reverse engineering work, but it's been very educational and rewarding work so far :)
My personal answer: It's good hardware. I like good hardware, so I'm pro-competition. Doing the work makes the hardware documented, for anyone to understand (mainly developers, but also Apple's competitors). Having more developers on ARM also makes ARM more competitive, and helps to break the x86 duopoly on single-core performance.

It's a gift to users and developers, not Apple. I like arm64 a lot more than RISC-V, and find their documentation better. And there aren't yet RISC-V CPUs that have competitive single-core performance.

Re:ARM64 Linux Workstation on Saturday March 04, 2023 @01:28AM (#35018719)
Yeah, looks like Intel desktops are currently ~10% ahead of Mac laptops in single-threaded performance:

https://browser.geekbench.com/processors/intel-core-i9-13900...

https://browser.geekbench.com/macs/macbook-pro-16-inch-2023-...

(Admittedly the Mac Studio is slower, since it was released ~360 days ago - probably not the best time to buy one, but who knows when they'll update it.)

The author states the desire is to match the architecture of the servers they deploy software to, which seems reasonable - depending on the software, it can be very useful to be able to run/debug the same binaries locally.

Re:ARM64 Linux Workstation on Friday March 03, 2023 @08:04PM (#35017071)
Feature support: https://github.com/AsahiLinux/docs/wiki/Feature-Support

Asahi is still in Alpha. Expect things to be a bit rough.

Re:ARM64 Linux Workstation on Friday March 03, 2023 @05:54PM (#35016144)
That toot is about upstream Linux 6.2, not Asahi Linux. If you run Asahi Linux (as in the blog post) you get decent (but not complete) legwork-free hardware support. Detailed breakdown here: https://github.com/AsahiLinux/docs/wiki/Feature-Support
Every time there's an indirect branch (including a return) there's a chance that they will be inspected. The "unused flags" optimisation does remove most of them, in a way that gets it right 100% of the time (excluding signals/interrupts inspecting state at random points, and possible bugs), but the pattern "an add or subtract or compare followed by an indirect branch or return" is still very common.

(I haven't looked at Linux Rosetta 2, other than to note the parity-flag computation coincidentally showing up in a screenshot posted to Twitter, so I'm not sure exactly how often they do the manual computation, but I'm guessing it's anywhere flags are used, in which case the unused-flags optimisation could be extended further by tracking AF and PF separately to the usual flags, which is roughly your suggestion.)

You could still remove the vast majority of the remaining computations with some heuristics that work well, but then you've gone from 100% correct to 99.9% correct, which is nice to avoid when you have the option.

I've only messed around in user-space, so I'm not sure how it's enabled. But if I were to guess, it might be bit 4 ("Enable APFLG") of ACTLR_EL1 ("(ARM standard-not-standard)"): https://github.com/AsahiLinux/docs/wiki/HW:ARM-System-Regist...

Older »