Papers
Topics
Authors
Recent
Search
2000 character limit reached

Semantic Guided Adaptive Patching

Updated 5 July 2026
  • The paper introduces a framework that uses semantic patches as high-level refactoring recipes to adapt HPC codes while preserving original application logic.
  • It details a selective, replayable transformation process guided by AST, CFG, and type information to enable context-sensitive optimizations.
  • The approach separates application logic from performance edits, fostering maintainability, debuggability, and scalable GPU migrations.

Searching arXiv for the cited papers and closely related semantic patching work. I’ll look up the two specified arXiv papers and a small amount of adjacent work on semantic patching. Semantic Guided Adaptive Patching is the idea of using Coccinelle SmPL rules as high-level, semantics-aware refactoring recipes for HPC codes. In the formulation advanced for HPC-oriented refactorings, transformations are guided by program semantics—specifically AST, CFG, and type information—can be applied selectively, can be parameterized, and can be replayed or adapted over time as hardware targets or optimization goals change. The central separation is between application semantics in the base code and performance-portability transformations in semantic patches, with the explicit goal of preserving intelligibility, longevity, and debuggability while enabling scriptable and possibly parametric code evolution for GPUs and other HPC platforms (Martone et al., 26 Mar 2025).

1. Conceptual definition and scope

Semantic Guided Adaptive Patching treats HPC-oriented refactoring as a semantic-patching problem rather than as a sequence of manual source edits. The maintained codebase remains a clear CPU-oriented implementation of the scientific or application logic, while performance specialists maintain separate semantic patches that inject, remove, or modify performance-related constructs. The workflow explicitly supports writing terse application code, deferring circumstantial performance edits to separate semantic patches, preserving intelligibility, longevity, and debuggability of the original code, and enabling HPC-oriented evolution in a scriptable and possibly parametric manner (Martone et al., 26 Mar 2025).

This organization is motivated by recurring properties of scientific software. Scientific and HPC codes are often large, old, and hand-tuned for CPUs, while contemporary targets require transformations of memory layout, loop structure, intrinsics, kernel launches, programming model directives, compiler pragmas, and API calls. The approach therefore emphasizes refactorings that are replayable, selective, and reversible. The paper characterizes these as “transitory” or “on-demand” changes and even “replayable refactorings,” meaning that the program is not permanently rewritten so much as equipped with patch recipes that can be re-applied when needed.

A plausible implication is that the “adaptive” qualifier does not denote runtime adaptation; rather, it denotes context-sensitive, parameter-driven source transformation. In the cited formulation, adaptivity arises from semantic matching, rule dependencies, scripting hooks, and selective application over chosen functions, loops, kernels, attributes, or pragmas.

2. Formal substrate: semantic patches in Coccinelle

A semantic patch is defined as a change specification written like a unified diff, with removed (-) and added (+) lines, but unlike a traditional text patch, it is matched against the program’s AST, CFG, and type information through metavariables. Matching therefore respects full language syntax, operator precedence, complete identifiers rather than substrings, and control-flow structure, including loops and branches (Martone et al., 26 Mar 2025).

The paper gives a concise contrast:

  • POSIX patch: text-level change
  • Coccinelle semantic patch: semantics-aware change specification over AST/CFG with metavariables

The role of metavariables is central because it makes rules generic and reusable across a code base. The listed categories include:

  • type T;
  • identifier f;
  • expression x,y,z;
  • statement A,B,C,D;
  • parameter list PL;
  • pragmainfo pi;
  • fresh identifier f512 = "avx512_"##f;

These constructs let a patch refer to arbitrary code fragments while preserving syntactic correctness. Rule dependency further extends expressiveness: later rules can depend on previous rules, as in @ah depends on rl@, and can reuse metavariables from earlier matches. This allows multi-step transformations in which one rule identifies a target and another performs the edit only if the earlier match succeeded.

The paper also emphasizes scripting hooks such as @initialize:python@, @script:python ...@, and @finalize. Those hooks make the patch system adaptive and programmable, not merely declarative. In the documented use cases, scripts are used for translating APIs through dictionaries, generating fresh names, constructing pragma strings, building lambda wrappers, and conditional editing.

3. Adaptive mechanisms and replayable transformation workflows

The “semantic-guided adaptive patching” idea is most visible where a patch is not only a static transformation rule but can be selective, parameter-driven, conditional on context, combined with scripting, and composed across multiple steps (Martone et al., 26 Mar 2025). This is the operational content of adaptivity in the approach.

Selective application is explicit. Patches can target only some functions, only some loops, only some kernels, only specific attributes or pragmas, or only code matched by naming conventions. That granularity is important in HPC settings because ports and optimizations are rarely uniform across an entire code base. Some kernels may be prepared for offload, some may require instrumentation, and others may need temporary workarounds or architecture-specific variants.

Replayability is equally central. The same semantic patch can be applied across many similar code regions, different experimental variants can coexist without maintaining many branches, and transformations can be systematically replayed on demand. This differs from a one-time source migration: the semantic patch becomes a maintained artifact that documents the transformation and can be re-executed when the source evolves or when a new target architecture is introduced.

This suggests a layered maintenance model in which domain scientists preserve the readable base code while HPC specialists curate a patch library. The source remains close to the scientific model, debug builds remain closer to the original behavior and do not get obscured by layers of inline wrappers or macro trickery, and performance-oriented edits remain externalized as semantically constrained rules.

4. Representative transformation classes in HPC and GPU migration

The paper sketches a series of self-contained use cases that collectively define the practical envelope of Semantic Guided Adaptive Patching. They range from localized annotation insertion to multi-stage API migration and architecture-specific specialization (Martone et al., 26 Mar 2025).

One simple class is adding or removing instrumentation markers. The LIKWID example inserts headers and wraps selected OpenMP regions:

1
2
3
4
5
6
7
8
9
10
11
12
13
@@
@@
#include <omp.h>
+ #include <likwid-marker.h>

@@
@@
#pragma omp ...
{
+ LIKWID_MARKER_START(__func__);
...
+ LIKWID_MARKER_STOP(__func__);
}

This demonstrates selective insertion around chosen regions and the use of compiler-provided metadata such as __func__.

A second class is introduction of target-specific function variants. For OpenMP declare variant, Coccinelle can detect candidate functions by name pattern, clone them automatically, create fresh names, add compiler-directed variant pragmas, and then specialize each clone in subsequent semantic patches:

1
2
3
4
5
6
7
8
9
10
11
12
13
@@
type T;
identifier f =~ "kernel";
parameter list PL;
statement list SL;
fresh identifier f512 = "avx512_"##f;
fresh identifier f10 = "avx10_"##f;
@@
+ T f512 (PL) { SL }
+ T f10 (PL) { SL }
+#pragma omp declare variant(v512_f) match(device={isa{"core-avx512"})
+#pragma omp declare variant(v10_f)  match(device={isa{"core-avx10"})
T f (PL) { SL }

A related mechanism is GCC/Clang function multiversioning through attributes such as __attribute__((target("default"))) and __attribute__((target("avx512"))). The documented workflow creates duplicated function bodies, tags them with attributes, and later matches on attribute values to apply architecture-specific changes.

The cleanup direction is also covered. The paper describes removal of obsolete specializations or code bloat, including rules that remove AVX512 and AVX2 specializations and then remove the remaining default attribute once variants are gone. This matters because optimization experiments often leave residual specialization scaffolding that must later be removed consistently.

The treatment of explicit loop unrolling is more structurally demanding. The paper presents both a simpler rule matching repeated indexed statements and a more careful multi-rule version that first normalizes index expressions and then checks whether the statements truly become identical. The important point is that semantic patches can reason about repeated structure, index offsets, and loop form rather than merely replacing text.

For data-layout-oriented rewriting, the paper gives an example that transforms array access syntax toward multidimensional indexing forms:

1
2
3
4
5
6
@tomultiindex@
symbol a;
expression x,y,z;
@@
- a[x][y][z]
+ a[x, y, z]

The paper positions this as representative of broad data-layout rewrites relevant to GPU-friendly layouts, vectorizable layouts, or abstractions such as mdspan.

CUDA-to-HIP migration is presented as a concrete API translation case. Function translation is implemented through a dictionary plus scripts, with examples including curand_uniform_double to rocrand_uniform_double and __half to rocblas_half. Kernel launch syntax is handled by a syntax-sensitive rule:

1
2
3
4
5
6
7
@@
identifier k;
expression b,t,x,y;
expression list el;
@@
- k<<<b,t,x,y>>>(el)
+ hipLaunchKernelGGL(k,b,t,x,y,el)

Directive-based migration is illustrated by a translation sketch for pragmas such as OpenACC to OpenMP using pragmainfo and a Python translator. The paper notes that Coccinelle handles whitespace and line continuations more robustly than ad hoc scripts.

The most elaborate example concerns Kokkos-style lambda-based parallel kernels and similar APIs in RAJA, SYCL, and ISO C++ parallel algorithms. The described workflow inserts Kokkos headers, identifies loops to transform, uses Python to turn a loop body into a lambda string, and substitutes that into parallel_for or parallel_reduce. The paper notes that this currently relies on a workaround because lambda manipulation is not fully supported yet in Coccinelle.

5. Comparative position relative to other patching and refactoring methods

The paper distinguishes Semantic Guided Adaptive Patching from manual refactoring, plain diff patches, preprocessor-heavy solutions, LLVM/ROSE-style transformation APIs, and ML/chatbot code assistants (Martone et al., 26 Mar 2025).

Compared with manual refactoring, the advantage claimed is scale and consistency. Manual editing is feasible for a few isolated sites, but not for thousands of repeated transformations, evolving codebases, multiple architecture-specific versions, or reversible experimentation. By encoding the transformation once and applying it across the code base, semantic patches reduce repetitive editing and preserve consistency.

Compared with plain diff patches, the distinction is semantic robustness. Traditional patches operate at line or text level and are fragile under formatting changes, partial identifier overlap, precedence-sensitive expressions, multi-line structure, or context-dependent matching. Coccinelle instead matches syntax trees, understands control flow, binds metavariables, and preserves structure.

Compared with preprocessor-heavy solutions, the stated concern is clarity and debuggability. Heavy use of macros can damage clarity and increase bug risk. Semantic patches externalize complexity rather than embedding it in the source through macro layers, which the paper identifies as particularly important for HPC debuggability.

Compared with LLVM or ROSE, the difference is one of expression and ergonomics. The paper suggests that those systems require programming in C++ and often matching at a lower, more exact grammar level, which can be more verbose and less convenient for broad refactoring tasks than SmPL’s declarative rule style.

Compared with ML or chatbot-based code assistants, the contrast is explicit: no machine learning, no opaque model, more control, and explainable and auditable transformation behavior. This does not imply that statistical systems are unusable in HPC refactoring; rather, the cited framing emphasizes that semantic patches remain inspectable transformation artifacts.

6. Limits, adjacent domains, and broader significance

The documented approach is source-level and presupposes editable C or C++ code to which semantic patches can be applied. An adjacent but distinct problem arises when source code or the original toolchain is unavailable. In that setting, SCRIBE addresses static binary patching by decompiling target functions, repairing syntactic and semantic inaccuracies, selectively recompiling the target functions, and placing the recompiled function back into the original binary through binary-aware recompilation and patching (Dai et al., 4 May 2026).

The distinction is methodologically significant. Semantic Guided Adaptive Patching, as described for Coccinelle, assumes that the original readable codebase remains the locus of scientific meaning and that transformations should be maintained as separate, reusable refactoring rules. SCRIBE, by contrast, begins from binaries and seeks to recover a source-level patching workflow even when the original source code and build environment are unavailable. A plausible implication is that both lines of work promote source-level reasoning over low-level editing, but they operate on different artifacts and with different correctness constraints.

Within its own domain, the broader significance claimed for Semantic Guided Adaptive Patching is that HPC refactoring should be treated as a layered, semantic, scriptable evolution process. Scientists write and preserve the readable base code; performance experts maintain transformation recipes; the recipes can target GPUs, vector ISAs, runtime libraries, or compiler-specific fixes; and the transformations can be replayed, adapted, or removed over time. For GPU migration in particular, this is presented as attractive because such migrations often require many localized syntactic changes, large-scale repeated edits, architecture-specific variants, and careful preservation of behavior and debuggability.

This suggests that the term denotes more than a particular set of SmPL idioms. It names a maintenance strategy in which semantic patches become first-class, versioned artifacts for performance portability. In that reading, the essential technical contribution is the separation of application logic from refactoring logic, with semantic matching and scripting providing the adaptive mechanism by which that separation remains practical at scale.

Topic to Video (Beta)

No one has generated a video about this topic yet.

Whiteboard

No one has generated a whiteboard explanation for this topic yet.

Follow Topic

Get notified by email when new papers are published related to Semantic Guided Adaptive Patching.