igneum/proto-opencl/intel_rotr.h
igneum-labs 5bd64245d0 OpenCL worker: on an Intel platform rotr_var is rewritten to the shift form before the build (the Intel rotate fold, the Arc B580 bisect of 7 October 2026)
Intel's compiler turns rotate(x, (0u - n) & 31u) into a rotate LEFT by n: lane 0's register trace on the B580 diverged
at instruction 6 of iteration 0 (rotr) and nowhere before, in both exchange modes, with every other family and the
dataset kernels bit-exact. proto-opencl/intel_rotr.h rewrites the one helper line when the device's vendor or
platform string holds Intel (host.c's buildProgram and the prepare path), no other vendor sees a change, no pack or
consensus text moves. proto-opencl/test_intel_rotr.c (the pre-push gate runs it) feeds the line through the rewrite
under Intel, AMD and NVIDIA strings and asserts the outputs.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
(cherry picked from commit 26e135a362718a68a842da59080b43e93afd9dc2)
2026-10-07 11:23:55 +00:00

40 lines
2.4 KiB
C

/* intel_rotr.h: the Intel rotate fold (7 October 2026, the Arc B580 register-trace bisect, docs/plans/intel-arc.md
* section 7). Intel's OpenCL compiler turns the pack's `rotr_var(x, n) = rotate(x, (0u - n) & 31u)` into a rotate LEFT
* by n (the negation dropped), so every variable right-rotate of every program came out wrong on the Arc while every
* other family and the dataset kernels were bit-exact (lane 0's trace diverged at instruction 6 of iteration 0, rotr,
* and nowhere before; job run-ia-arc-trace-20261007-b). On an Intel platform the worker rewrites that one helper line
* to the shift form the CPU interpreter and the family probe compute, before clCreateProgramWithSource; the text is
* otherwise untouched and no other vendor sees a change. Shared by host.c and test_intel_rotr.c (the gate's test). */
#ifndef IGNEUM_INTEL_ROTR_H
#define IGNEUM_INTEL_ROTR_H
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
static const char* IGNEUM_ROTR_BUILTIN = "static inline uint rotr_var(uint x, uint n) { return rotate(x, (0u - n) & 31u); }";
static const char* IGNEUM_ROTR_SHIFTS = "static inline uint rotr_var(uint x, uint n) { n &= 31u; return (x >> n) | (x << ((32u - n) & 31u)); }";
/* Returns the source to build: the original pointer when nothing applies, else a new buffer (the caller frees it when
* `*patched` is set) with the one line replaced and `*srcLen` updated. `vendor` and `platform` are the device's
* CL_DEVICE_VENDOR and the platform name; only a string holding "Intel" is rewritten. `quiet` suppresses the line. */
static char* igneum_intel_rotr_patch(const char* vendor, const char* platform, const char* src, size_t* srcLen, int* patched, int quiet) {
const char* at;
char* out;
size_t a = strlen(IGNEUM_ROTR_BUILTIN), b = strlen(IGNEUM_ROTR_SHIFTS), pre;
*patched = 0;
if (!((vendor && strstr(vendor, "Intel")) || (platform && strstr(platform, "Intel")))) return (char*)src;
at = strstr(src, IGNEUM_ROTR_BUILTIN);
if (!at) return (char*)src;
pre = (size_t)(at - src);
out = (char*)malloc(*srcLen - a + b + 1);
if (!out) return (char*)src;
memcpy(out, src, pre);
memcpy(out + pre, IGNEUM_ROTR_SHIFTS, b);
memcpy(out + pre + b, at + a, *srcLen - pre - a);
out[*srcLen - a + b] = 0;
*srcLen = *srcLen - a + b;
*patched = 1;
if (!quiet) printf("intel: rotr_var rewritten to the shift form before the build (the rotate fold of 7 October 2026)\n");
return out;
}
#endif