Skip to main content

migraphx-simplify

Review the changed MIGraphX code for reuse, simplification, efficiency, altitude, safety, and comment quality, then apply the fixes. Quality only — it does not hunt for correctness bugs; use /code-review for that.

Informações da origem

Repositório
ROCm/AMDMIGraphX
Última atividade na origem
11 de outubro de 2026 às 14:54
Idioma detectado do SKILL.md
inglês
Estrelas
338
Forks
161

Opções de instalação

Por padrão, está selecionado o prompt que primeiro revisa a origem. Você pode mudar para um comando direto ou baixar uma cópia local.

Revise os arquivos de origem

Leia o SKILL.md e os arquivos complementares exibidos pelo SkillsMP antes de decidir se vai instalar.

Exibindo SKILL.md

SKILL.md
Instruções da origem · Visualização somente leitura
name
migraphx-simplify
description
Review the changed MIGraphX code for reuse, simplification, efficiency, altitude, safety, and comment quality, then apply the fixes. Quality only — it does not hunt for correctness bugs; use /code-review for that.
allowed-tools
Bash(git diff:*), Bash(git status:*), Bash(git merge-base:*), Bash(git log:*), Bash(git rev-parse:*), Bash(git branch:*), Bash(git fetch:*), Bash(grep:*), Bash(find:*), Read, Edit, Write, Agent
# migraphx-simplify: Code Review and Cleanup You are improving the quality of the changed code, not hunting for bugs. Review it for **reuse, simplification, efficiency, altitude, safety, and comment quality**, then fix what you find. Do not look for correctness bugs — that is what `/code-review` is for. ## Phase 0 — Gather the diff Determine the set of changed code under review, then hand the same diff to every agent so they all see identical context. The base must be the **up-to-date remote** integration branch — use `origin/develop`, **not** the local `develop` ref. The local `develop` is frequently stale (behind origin by several already-merged PRs), and feature branches often merge `develop` in repeatedly. Diffing against a stale local `develop` silently pulls already-merged upstream PRs into the diff, so you end up reviewing and editing files that aren't this branch's work at all. 1. Resolve the base ref. Prefer `origin/develop`; if it doesn't resolve, fall back in order to `origin/main`, `origin/master`, then a local `develop` / `main` / `master` — but never default to a local branch when a remote-tracking ref exists. Optionally `git fetch origin develop` first if the network is available and you suspect `origin/develop` itself is stale. ```bash git rev-parse --abbrev-ref HEAD git rev-parse --verify --quiet origin/develop # confirm the base resolves ``` Use the resolved ref as `<base>` below. 2. Produce the combined diff of committed-on-this-branch **and** uncommitted working-tree changes versus the merge base: ```bash git merge-base HEAD <base> git diff $(git merge-base HEAD <base>) ``` 3. Sanity-check the scope **before** launching agents. List the changed files and confirm they look like *this* branch's work: ```bash git diff --stat $(git merge-base HEAD <base>) HEAD ``` If the list contains files you don't expect — unrelated ops, whole subsystems, or infra you didn't touch — the base is almost certainly wrong. A tell-tale sign is that HEAD is a `Merge branch 'develop' into <feature>` commit (its develop-side parent `HEAD^2` is usually the correct base). Confirm a suspect commit is upstream (and therefore out of scope) before trusting the diff: ```bash git merge-base --is-ancestor <commit-sha> <base> # exit 0 => upstream, exclude it ``` Re-resolve `<base>` (e.g. to `HEAD^2`) until the file list matches only the branch's own changes. 4. If the diff against the base is empty (e.g. you are already on the base branch), fall back to the working-tree changes alone: ```bash git diff HEAD git status --short ``` 5. List the changed files and note which are GPU kernel headers (under `src/targets/gpu/kernels/`) versus general host C++ — the kernel-specific bullets below only apply to kernel files. If there are no changes at all, stop and report that there is nothing to review. ## Phase 1 — Review (6 cleanup agents in parallel) Launch **6 independent review agents via the Agent tool, all in a single message** so they run concurrently (use `subagent_type: general-purpose`; they need Grep/Read to inspect the surrounding codebase). Give each agent the full diff from Phase 0, the list of changed files, and the one review angle below that is its responsibility. Tell every agent: assume all tools work — do not test them or make exploratory calls without a purpose. Each agent returns its findings as a list, where each finding has `file`, `line`, a one-line `summary`, and the concrete cost (what is duplicated, wasted, unsafe, misleading, or harder to maintain) plus the concrete fix (name the helper, the simpler form, or the safe abstraction to use instead). Report only findings inside the changed code; do not flag pre-existing issues. ### 1. Reuse Flag new code that re-implements something the codebase or standard library already provides. Grep shared/utility modules and files adjacent to the change before concluding something is new, and name the existing helper to call instead. - Flag any new function that duplicates existing functionality - Suggest the existing function to use instead. - Flag any inline logic that could use an existing utility — hand-rolled string manipulation, manual path handling, custom environment checks, ad-hoc type guards, and similar patterns are common candidates. - Copy-paste with slight variation: near-duplicate code blocks that should be unified with a shared abstraction - Raw loops that should be STL `<algorithm>` or MIGraphX `<migraphx/algorithm.hpp>` algorithms (`transform_if`, `transform_accumulate`, `group_by`, `group_unique`, `adjacent_for_each`, etc.). `std::for_each` is not an acceptable substitute for a real algorithm, but a raw loop is the *least* preferred form: never rewrite a `std::for_each` into a raw `for` loop. If it is a side-effecting fold with no clean algorithm (e.g. folding `hash_combine` into a seed), leave it alone. - A `contiguous` inserted before `reshape` — `reshape` already copies and handles non-standard input layouts, so the extra op is redundant. - Pair/tuple member access (`auto r = f(); r.first`) where a structured binding `auto [a, b] = f();` fits; when a C++17 lambda needs the binding, use an init-capture (`[&, &x = x]`) rather than avoiding the binding. - Manually written lexicographical comparisons — use `std::tie` or `std::lexicographical_compare` instead. - Manual offset / stride / index math with mod and division — use the `migraphx::shape` methods for offsets, strides, and indexing instead. - Open-coded instruction traversal where a matcher from `src/matcher.hpp` would do. - C acquire/release handling that should use `MIGRAPHX_MANAGE_PTR`. - Duplicated literals or magic numbers where a named constant or existing enum already exists. - A new helper that duplicates one already living elsewhere — name the existing function. - **Not** a duplicate: a bespoke test stub operator (e.g. `view_pass_op` in `test/gpu/hipgraphify.cpp`) that a `basic_ops` stub could replace behaviorally. Check which branch of the predicate under test each one drives (no `compute` → not context-free, versus context-free + aliasing); if they differ, swapping them silently changes what the test covers. - (kernel files) Hand-rolled utilities that already exist: `migraphx::array`, `tensor_view`, `vec<T, N>` for vector types, `repeat_c` for unrolling loops, `uninitialized_buffer` for shared LDS, the `index` class for thread/block indices, and `local_stride` / `global_stride` / `local_wave_stride` for strided loops. ### 2. Simplification Flag unnecessary complexity the diff adds — code that could do the same job in a simpler, smaller, or flatter form. Name the simpler form that does the same job. - Avoid redundant or unnecessary casts. - Redundant or derivable state; intermediate variables that can be used directly. - Copy-paste with slight variation that should be factored or parameterized. - Deep nesting that an early return or restructuring would flatten. - Dead code left behind by the change. **Not** dead code: a shared kernel utility (e.g. `partial` in `kernels/functional.hpp`) whose last caller this diff removed — the kernel functional library is kept as a toolkit, so only remove helpers the change itself introduced. - Premature abstraction — a helper used only once. - Classes masquerading as functions — a stateless struct with one public method *instantiated as an object* should be a free function. A `static` member function that happens to use no member state is **not** this: it is scoped to its class on purpose, so leave it where it is. - Locally-called named lambdas (`auto used_outside = [&](...) {...};` followed by a call) — a function in disguise with hidden captures. Convert to a `static` free function taking its captures as parameters, or inline a single use. Lambdas *passed* to an algorithm or callback are fine. - Static helpers that each take 5+ parameters to marshal shared state after a function was split — replace with a (nested) struct holding that state in value members, with methods that add to it; keep `context&` and other external state as method parameters. - Config / builder structs around what should be 1–2 function arguments; factory functions that only call a constructor. - Multiple wrapper layers with no distinct responsibility per layer — collapse them. - Future-proofing: single-value enums, one-alternative `variant`, always-present `optional` returns, hooks/callbacks with no second caller. - Unnecessary arithmetic (`+0`, `*1`). - Defensive checks at internal boundaries and speculative error handling for conditions that cannot occur given caller guarantees — remove them. (This is distinct from assertions that document assumptions, which belong to the safety pass.) An `assert` at an exported function's boundary that a later internal helper re-asserts is **not** a duplicate: each layer documents its own contract, so keep both. - Backwards-compat shims that aren't needed: renamed `_unused` parameters, re-exports of removed types. - Unrequested refactors bundled into the change — flag them for separation. - A one-line layout predicate (e.g. `is_nhwc(const shape&)`) added to a widely included core header such as `permutation.hpp` — inline the stride check at each site with a comment instead; narrow GPU/conv helpers do not belong in core headers. - (kernel files) `::value` used to read an integral constant — it converts implicitly; pass the `integral_constant` through and capture it with `auto`. In **tests**, `::value` is read on purpose to check the stored constant: keep it and add a `cppcheck-suppress migraphx-AvoidNestedValue`. - (kernel files) Do **not** flag `if constexpr` special cases that look redundant with the generic path (e.g. `arg_c` for `N == 0`): kernel headers are JIT-compiled at runtime and those branches cut template instantiations. If one lacks a comment saying so, add the one-line comment rather than removing the branch. - (kernel files) Do **not** merge per-kernel JIT raw-string source templates into a shared `${...}` shell; the explicit per-kernel template is the preferred form. - (kernel files) `static_cast<T&&>(x)` is a move, not a redundant cast — keep it and suppress `migraphx-RedundantCast`; do not introduce a `move()` helper. ### 3. Efficiency Flag wasted work the diff introduces — computation, memory, or build cost that a cheaper form avoids without changing behavior. Name the cheaper alternative. - Redundant computation or repeated I/O that could be hoisted or cached. - Independent operations run sequentially that could be combined. - Blocking or expensive work added to startup or a hot path. - Copies where a reference or view suffices; unnecessary `auto&&`. - Unused `std::move` and unused casts. - Over-broad `#include`s where a forward declaration or a narrower header would do. - A non-template helper defined inline in a header — it drags its includes into every consumer. Declare it in the header (with the target's export macro) and move the body to the `.cpp`; only templates and trivial accessors stay inline. ### 4. Altitude Check that each change is implemented at the right depth, not as a fragile bandaid, and that it is written generically rather than tied to one concrete type. Special cases layered on shared infrastructure signal the fix isn't deep enough — prefer generalizing the underlying mechanism. - Special cases added on top of shared infrastructure where generalizing the mechanism would be cleaner than another branch. - Type-specific code that should be generic — write reusable, type-independent code using templates and STL algorithms rather than duplicating per type. - Open-coded traversal where a matcher-based rewrite expresses the transform at the right level. - Hand-rolled polymorphism via inheritance where MIGraphX's type erasure (implement the interface, no base class) fits. - Leaky abstractions - exposing internal details that should be encapsulated, or breaking existing abstraction boundaries ### 5. Safety Flag places where the diff gives up safety it could keep for free — unchecked assumptions, raw memory and pointer handling, and unsafe type or bit manipulation. Do **not** recommend adding defensive checks at internal boundaries or speculative error handling; assertions that document an invariant are different and are encouraged. - Silent assumptions (a size matches, an index is in range, a pointer is non-null, a shape is packed/standard) — add an `assert` / MIGraphX assertion that documents and checks the invariant. - Manual buffers or raw C arrays — use `std::vector` / `std::array`; in kernels use `migraphx::array`. - Raw `new` / `delete` — use `std::make_unique` / `std::make_shared`; use `MIGRAPHX_MANAGE_PTR` for C-style acquire/release resources. - Raw pointer arithmetic — use iterators, range-based access, or `tensor_view`; in kernels prefer `tensor_view` / iterators over raw pointers and the `index` class over raw `threadIdx` / `blockIdx`. - Manual offset / index math that can run out of bounds — compute via `migraphx::shape` (host) or `tensor_view` / `shape` / `index` (kernels); slice a `tensor_view` / `shape` for tiling rather than hand-computing offsets, and use `uninitialized_buffer` for shared LDS. - Unsafe casts — `const_cast` (especially to bypass API design), C-style casts, and `reinterpret_cast` that bypass the type system; fix by declaring the correct type at the source. - Bit-twiddling and low-level bit manipulation written inline — encapsulate it behind a well-named utility function and prefer `std::bitset`. ### 6. Comments Check that comments in the diff are correct, clear, and relevant, and remove comment slop. Quote the current comment and give the corrected / shortened replacement, or recommend deletion. - Correct — the comment matches what the code actually does; flag stale comments left after the code changed and comments describing the wrong behavior. - Clear — flag confusing, ambiguous, or misleading wording; rewrite to state the non-obvious *why* (a constraint, workaround, or invariant) in one to three lines. A rewrite must not grow the comment: drop parentheticals, cross-references, and enumerated consequences unless they are load-bearing. - Relevant — flag comments that discuss unrelated components, files, or code not present in the change. - Tombstones — flag `// removed ...` / "this used to ..." comments that describe history instead of the current code. - Slop — delete redundant comments describing *what* obvious code does (`// increment i`, `// return result`). - Banners — collapse multi-line docstrings / banner comments on trivial functions to one short line at most. ## Phase 2 — Apply the fixes Wait for all six agents to complete. Dedup findings that point at the same line or mechanism (the angles overlap by design — e.g. reuse and safety may both flag a raw pointer that should be a `tensor_view`). Fix each remaining finding directly in the working tree with Edit. Skip any finding whose fix would: - change intended behavior, - require changes well outside the reviewed diff, or - that you judge to be a false positive — note the skip rather than arguing with it. Do not modify tests to match changed output; if a fix breaks a test, the fix is wrong. Finish with a brief summary grouped by angle: what was fixed (with `file:line`) and what was skipped and why — or confirm the code was already clean.
Ver no GitHub