#include <errno.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
int main(int argc, char **argv)
uint64_t v = 0;
double o;
if (argc != 2) {
fprintf(stderr, "usage: %s quantity\n", argv[0]);
return 1;
}
v = strtoull(argv[1], NULL, 0);
if (errno == EINVAL || errno == ERANGE) {
perror("strtoull");
return 1;
}
__asm__(
"xxbrd %0, %1\n"
:"=f"(o)
:"f"(*(double *)&v)
);
fprintf(stderr, "0x%lx\n", *(uint64_t *)&o);
return 0;
}
% gcc -o xxbrd xxbrd.c
% ./xxbrd 0x123456789abcdef
0xefcdab8967452301There's an IBM web page somewhere with three(?) alternatives for using VSX, one of which is just using SSE intrinsics -- I don't know how well that works -- and another is a library that's now in Fedora, whose name I forget.
That said, it's obviously not competitive with AVX2 or, presumably SVE, unless you can win on parallelization (or plain clock speed, which you probably can't).
For instance, does it work any better than my C implementation? https://github.com/Sentido-Labs/cedro/blob/master/src/cedro....
Maybe the compiler already compiles that to an optimal SIMD version, I don’t know. That’s what I would like to find out. And if the VSX instructions are not a good fit for this task, which instructions would be needed? Can I come up with a combination of logic gates that does that? Maybe not, there might be no way of implementing any significant part of the algorithm without branches or look up tables.
The thing is that I need to start somewhere, and for that classichasclass’ example is exactly what I need.
A better way would be to explicitly use the newer mtvsrd (mtfprd) and mfvsrd (mffprd) instructions and avoid the spill. So here's a revision 2.
#include <errno.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
int main(int argc, char **argv) {
uint64_t v = 0;
if (argc != 2) {
fprintf(stderr, "usage: %s quantity\n", argv[0]);
return 1;
}
v = strtoull(argv[1], NULL, 0);
if (errno == EINVAL || errno == ERANGE) {
perror("strtoull");
return 1;
}
__asm__(
"mtfprd %1, %0\n"
"xxbrd %1, %1\n"
"mffprd %1, %0\n"
:"=r"(v)
:"r"(v)
);
fprintf(stdout, "0x%lx\n", v);
return 0;
}
If v is already in a register, then it can just stay there.
Do you know of some minimal example of calling VSX instructions from C?
Ideally just one .c file and one Makefile or README with the exact GCC command to compile it, plus a pointer to documentation describing each instruction. I’ve seen assembler inserted into C source code with GCC, but I’ve never done it and I assume there are some non-obvious details to take into account.