Live data from Hacker News

The 8-Byte Two-Step

zinascii.com

31–34 of 34 posts

Re: The 8-Byte Two-Step

#31
post #30

Earlier quoted context omitted.

>In general, you might be better off always using long unless there is a specific reason not to I don't agree. That's trading off useful cache for almost invisible micro optimizations. As a general rule, it's always better to use the smallest size possible.

I phrase it as "might be" since I realize it's controversial, but I think that rule is outdated. Yes, having a large static array would be a fine specific reason to use the smallest size possible. But what would be the benefit when you are dealing with the argument to a function in an example like this? Most of the time the argument starts in a register, is passed in a register, and returned in a register. Using a sm…

One argument? Sure, probably no difference. When you start using longs as local variables and arguments, even if they're all in registers in one function, if you call other functions inside they are going to be pushed on the stack. It all adds up and suddenly you're getting L1 cache misses.

Anyway, unnecessary conversions mostly go away when you use link time optimizations (fwhole-program or flto in gcc).

Re: The 8-Byte Two-Step

#32
post #30

Earlier quoted context omitted.

I phrase it as "might be" since I realize it's controversial, but I think that rule is outdated. Yes, having a large static array would be a fine specific reason to use the smallest size possible. But what would be the benefit when you are dealing with the argument to a function in an example like this? Most of the time the argument starts in a register, is passed in a register, and returned in a register. Using a sm…

One argument? Sure, probably no difference. When you start using longs as local variables and arguments, even if they're all in registers in one function, if you call other functions inside they are going to be pushed on the stack. It all adds up and suddenly you're getting L1 cache misses. Anyway, unnecessary conversions mostly go away when you use link time optimizations (fwhole-program or flto in gcc).

A reasonable argument, although not one I seem to run up against, perhaps because I'm rarely concerned about high performance when writing functions with that many layers of subcalls.

By contrast, when trying to optimize inner loops, I frequently encounter cases where the front-end limitation of 4 micro-ops per cycle is a limiting factor, and getting rid of any extraneous instruction is a speedup. And rather than worrying about a deep stack causing L1 data misses, I'm more concerned with missing L1 instruction cache, or with the extra micro-ops causing me to miss the ~1000 slot decoded micro-op cache.

These concerns are clearly at opposite ends of the performance spectrum, and which should dominate probably depends on the problem at hand.

(I glanced at your comment history. Welcome to HN! You have good insights. Please stick around.)

Re: The 8-Byte Two-Step

#33
post #26

Earlier quoted context omitted.

I wrote a little post up to show: https://gist.github.com/superjamie/72f7bf3b6a22371d24f7

Great short intro! One other useful thing I'd add is that you don't have to have the register window open to see the contents of registers --- they can also be printed like other variables while you are in 'layout asm'. Or you can use 'layout split' which shows both source and assembly. For example, "p/t $rax" will print the contents of %rax. Printing the floating point registers can be a little awkward, since they a…

One thing I like about the register view is the highlighting on register change.

This is great when an instruction changes a register beyond a basic MOV/ADD/SUB.

Using register view ended up being the "lightbulb" moment which helped me understand how stack frames are built.

Re: The 8-Byte Two-Step

#34
post #4

Holy shit, mind blown. I've done this before, but usually take modulo 8 rather than bitwise-and negative 7 as the final step.

Same, I'd write it out using modulo and would assume the compiler would figure it out. void *p = x; p += 7; p -= (p%8); Now that I've written it out I suppose it's not any clearer than the mask method: void *p = x; p += 7; p &= ~7;

[deleted]
Post reply on HN