3 ms·
CPUs handle excessively large shifts in implementation defined ways. Some return 0. Some trap. x86 masks the right hand side with & 63 (for a 64-bit shift) s
by ksherlock 3y ago
CPUs handle excessively large shifts in implementation defined ways. Some return 0. Some trap. x86 masks the right hand side with & 63 (for a 64-bit shift) so shifting by 65 is equivalent to shifting by 1.
In C and C++ it's undefined behavior (Really it should be implementation defined)
- dzaima 3y agoAnother different shift implementation is in ARM NEON, where, for a non-constant shift amount, there's only a shift-left, and that with a negative shift amount gets you right shift; thus, were it forced to choose only one behavior, either scalar or vector shifts would get worse.
- Const-me 3y agoInteresting, thanks. BTW, I fixed like that: uint64_t mask = -( missingLanes < 8 ); mask >>= missingLanes * 8; I only care about the AMD64 because the surrounding code uses AVX2 intrinsics, i.e. my new version is hopefully good enough. I’ve tried conditional operator to not rely on these details, however VC++ failed to generate fast code from them. It emit branches, and that code is kinda performance critical.
- sweetjuly 3y agoRISC-V is even more fun where they shift based on shamt[4:0] (or [5:0] in XLEN=64 mode). So, if you do something like: li t0, 128 li t1, 1 sll t2, t1, t0 You'll get t2 := 1 since t0[5:0] == 6'b0 (i.e. no shift). It's a very sensible solution IMO if you don't have trapping arithmetic since you don't have to do anything special to handle illegal shifts, it just works.