3 ms·
What I’d like to do is a quick proof-of-concept to see whether whatever instructions are available in my CPU can be leveraged for UTF-8 en-/decoding. For insta
by AlbertoGP 5y ago
What I’d like to do is a quick proof-of-concept to see whether whatever instructions are available in my CPU can be leveraged for UTF-8 en-/decoding.
For instance, does it work any better than my C implementation? https://github.com/Sentido-Labs/cedro/blob/master/src/cedro.c#L139 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.
- classichasclass 5y agoJust keep in mind that the FPRs and vector registers are now aliased together (in VMX-only CPUs this wasn't necessarily the case). What is particularly stupid about my example is that it may have to spill to memory to move the uint64_t (a GPR) into the VSX register (an FPR) and then move it back because PowerPC famously had no direct GPR-FPR moves for quite a while. Since I didn't specify -mcpu=power8 (or higher), gcc doesn't issue the new instructions and I'm not sure it would know how to. 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.