extremum-shapeRunning minimum/maximum the kernel just missed
Reported by --explain after a verdict.
mettle explain extremum-shape
if (a[i] > best) { best = a[i]; } is a shape the compiler vectorizes: it reads the diamond as the operator it is and emits vmaxps/vmaxpd (or vpmaxsd for int32), seeding every lane with the accumulator's incoming value. So the branch is not what stopped this loop. Something else did:
The counter does not start at 0. A scan seeded from
a[0]and run fromi = 1is outside the kernel, which treats the loop's bound as an element count from the base. Start at 0 and seed the accumulator with a sentinel instead.The elements are not float32, float64 or int32. Those are the lane widths the extremum kernel carries, and the width it reads is the ELEMENT's. A uint8 or int16 array stays scalar however the accumulator is declared, so widening
bestalone moves nothing; widen the array. uint32 is refused because vpmaxsd compares signed.The elements are narrower than the accumulator.
(int32)bytes[i]widens per element; the kernel's lanes are the element width. This is a gap, not a problem with the loop.The body also stores. Then it is a clamp, not a reduction. See
mettle explain clamp-store.
Related
- call-in-bodyThe loop body calls a function
- extern-call-in-bodyThe loop body calls an external function
- indirect-callThe loop body calls through a function pointer
- alloc-in-bodyThe loop body allocates
- inline-asmThe loop body contains inline assembly
- control-flowThe loop body branches
- early-exitThe loop can leave before its trip count
- int16-elements16-bit integer elements have no kernel