') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); Atomic memory operations · Issue #43 · tetsuo-cpp/warpforth · GitHub
Skip to content

Atomic memory operations #43

Description

@tetsuo-cpp

Summary

Add atomic memory operation words for safe concurrent updates from multiple threads.

Words to implement

Integer atomics

WordStack effectMLIR opDescription
ATOMIC+( n addr -- )memref.atomic_rmw addiAtomic add (i64)
ATOMIC-MAX( n addr -- )memref.atomic_rmw maxsAtomic signed max (i64)
ATOMIC-MIN( n addr -- )memref.atomic_rmw minsAtomic signed min (i64)
ATOMIC-AND( n addr -- )memref.atomic_rmw andiAtomic bitwise AND
ATOMIC-OR( n addr -- )memref.atomic_rmw oriAtomic bitwise OR
ATOMIC-XOR( n addr -- )memref.atomic_rmw xoriAtomic bitwise XOR
ATOMIC-XCHG( n addr -- old )memref.atomic_rmw assignAtomic exchange, returns old value
ATOMIC-CAS( expected new addr -- old )memref.generic_atomic_rmwCompare-and-swap, returns old value

Float atomics

WordStack effectMLIR opDescription
ATOMIC-F+( f addr -- )memref.atomic_rmw addfAtomic float add
ATOMIC-FMAX( f addr -- )memref.atomic_rmw maximumfAtomic float max
ATOMIC-FMIN( f addr -- )memref.atomic_rmw minimumfAtomic float min

Motivation

  • Multi-block reductions: When a reduction spans more than one thread block, the output must be accumulated atomically (e.g., ATOMIC-F+ for partial sums, ATOMIC-FMAX for global max).
  • Histogram / scatter patterns: Common GPU patterns where multiple threads update the same output location.
  • Lock-free data structures: ATOMIC-CAS enables lock-free algorithms.
  • Flash attention: Multi-block flash attention variants need atomic output accumulation.

Implementation notes

  • Integer atomics: straightforward mapping to memref.atomic_rmw with the appropriate arith::AtomicRMWKind.
  • Float atomics: values are i64 bit patterns on the stack, so bitcast to f64 before the atomic op. The address computation follows the same pattern as ! / F!.
  • ATOMIC-CAS is more complex: needs memref.generic_atomic_rmw with a comparison body, or lower directly to an LLVM cmpxchg.
  • NVVM has native support for all of these via PTX atom.* instructions.
  • Consider starting with just ATOMIC+ and ATOMIC-F+ as the minimum viable set.

Files to modify

  1. include/warpforth/Dialect/Forth/ForthOps.td — Define new ops
  2. lib/Translation/ForthToMLIR/ForthToMLIR.cpp — Parse words
  3. lib/Conversion/ForthToMemRef/ForthToMemRef.cpp — Add conversion patterns
  4. test/Translation/Forth/ — Parser tests
  5. test/Conversion/ForthToMemRef/ — Conversion tests

Priority

Medium — needed for multi-block reductions and scatter patterns. Not required for single-block kernels.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions