5 ms·
32-bit ARM assembly language provided conditional execution for most instructions. This was dropped in the 64-bit instruction set. (https://en.wikipedia.org/wik
by tom_mellior 6y ago
32-bit ARM assembly language provided conditional execution for most instructions. This was dropped in the 64-bit instruction set. (https://en.wikipedia.org/wiki/Predication_(computer_architecture) https://en.wikipedia.org/wiki/Predication_(computer_architec..., https://en.wikipedia.org/wiki/ARM_architecture#64-bit https://en.wikipedia.org/wiki/ARM_architecture#64-bit) I imagine the architects had a clear picture of the advantages and disadvantages, and made a very well-informed decision. I guess that part of the reason might have been that it's not clear when compilers should emit predicated code instead of branches.
Also, you can get something very similar even for scalar code as long as your machine has a conditional move operation, which they all have:
/* true path */
a = ...
b = ...
true_result = ...
/* false path */
x = ...
y = ...
false_result = ...
/* final result */
result = (condition ? true_result : false_result)
This works if the two "branches" have no side effects (memory writes, function calls) and cannot raise exceptions. Again, it's very difficult to estimate for compilers (and humans) if it will pay off to run both computations rather than branch.
The trade-offs for vectorization are different from scalar code since vectorizing a loop by a factor N gives a huge win, and even if you waste some time doing some redundant computations, you still have a reasonable chance of being faster than scalar.
- ncmncm 6y agoYou can get close to the performance of a cmov instruction by generating a pair of all-1s and all-0s values: a=c, b=c-1, and a result z=a&x|b&y. Gcc will not under any circumstances produce two cmov instructions in a basic block, so that is your only alternative without dropping to asm. Clang is happy to produce two adjacent cmov instructions. Usually your ALUs are not otherwise so engaged as to make the number of operations involved costly.
- ncmncm 6y agoI should add that Clang is happy to turn c&x|(c-1)&y into cmov.
- deleted 6y ago[deleted]
- tom_mellior 6y agoI don't get this. If c can be 0 or 1, then a can be 0 or 1, so it can be all-0s but not all-1s. b can be -1 or 0, so that part is fine. Can you show actual C or C++ code for a function like this: int select(int x, int y, bool condition) { ... }
- ncmncm 6y agoSorry, brain freeze. See https://news.ycombinator.com/item?id=23237663 https://news.ycombinator.com/item?id=23237663 The bitwise thing is correctly -c&x|(c-1)&y.
- tom_mellior 6y agoOh, yes, I should have realized that -c is enough to transform from 0/1 to 0/-1. Thanks!