Ripwire Opt Remarks logo

Ripwire Opt Remarks

OrganizationPopular
redhat-et
ripwire-opt-remarks

Triage clang optimization remarks (-Rpass, -Rpass-missed, opt-record YAML) while editing ripwire's OWN C++: 'loop not vectorized', 'will not be inlined' — worth a diff, or is LTO/PGO the real fix? Contributor-only: about compiling this tool, never about running it.

Overview

Publisherredhat-et
Repositoryripwire
Skill nameripwire-opt-remarks
Stars
2.2K
Forks
141
Bundled files
Instructions only
LicenseApache-2.0
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • Self-contained

    Everything the model needs lives in the instructions — no extra files to sync.

  • Open source

    Published by redhat-et on GitHub. Read the source before you install it.

Installation

Install the Ripwire Opt Remarks AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/redhat-et/ripwire.git /tmp/ripwire
mkdir -p .claude/skills
cp -r /tmp/ripwire/skills/ripwire-opt-remarks .claude/skills/ripwire-opt-remarks
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Ripwire Opt Remarks in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Ripwire Opt Remarks on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Ripwire Opt Remarks is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

Triaging clang optimization remarks in this repo

Nearest neighbours: • A measured slow operation, any codebase → ripwire-perf-target. Do that FIRST; remarks are the second question, not the first. • Maintenance risk / complexity in a subsystem → ripwire-fresh-eyes. Different axis entirely.

Full record of the pass this skill came from, with every number: docs/OPTREMARKS.md.

The one rule

A remark is an observation, not a defect. Clang is reporting a decision, usually the right one. The pass that produced this skill read ~1.1 M remarks over src/. Zero of them justified a source edit. Two justified a BUILD change (LTO, then PGO), and the best-looking source-level candidate was implemented, verified to do exactly what the remark asked, measured, and reverted. Budget your attention accordingly: on this codebase, the answer to a remark is far more often a compiler flag than a diff.

Step 0 — profile first, or you will optimize a millisecond

bash
cmake -S . -B build_prof -DRIPWIRE_PROFILE=ON && cmake --build build_prof -j 6
./build_prof/ripwire . --no-cache 2>&1 >/dev/null | sed -n '/hottest scopes/,/PROF_TSV/p'

On this codebase the answer is stable and counterintuitive: PageRank is ~1 ms of a ~2.7 s cold CPU profile, the build-model sorts are ~1.7 ms, and ~29% sits in two phases now living in src/ingest_sidecap.h (captureTagsFacts, captureSideFacts) that spend it calling tree-sitter. So a remark in src/pagerank.cpp, src/infra/sortutil.h or src/infra/radixSort.inl is dismissible on arithmetic before you read it. Re-derive this table if you touch the pipeline; do not trust this paragraph forever.

Step 1 — collect

bash
scripts/optremarks.sh --passes 'inline|loop-vectorize|slp-vectorizer|licm|gvn|.*unswitch|loop-idiom'
python3 scripts/optremarks.py --hot --top 40

--hot narrows to a literal list (HOT_FILES) rather than a heuristic, so what the report calls "hot" stays reviewable. That list once went stale silently — the ingest split moved the hot phases into src/ingest_*.h sections of the same TU, every listed path still existed, and --hot quietly fell to 0.2% coverage of that TU. test/optremarkshotcheck.sh now gates the list against the tree (docs/OPTREMARKS.md §8). If you split or rename a hot file, run that gate: it will tell you which files you now owe a decision on, and COLD_FILES is where a deliberate exclusion goes, with its reason.

Never in build/ — CMake refuses it by name, because build/ripwire is the binary every gate and bench number is measured against. Never with a build type: RIPWIRE_ARCH_FLAGS is already -O2, and Release would define NDEBUG and blind the degrade-path gates. Run wide once to learn which classes fire (src/main.cpp unfiltered exceeds 800 MB of YAML), then narrow.

Step 2 — the remark classes, and what each one is worth here

Real signal

Missed inline NoDefinition, callee in another TU that you own the build of. Meaning: the definition is not visible, full stop — not a cost-model opinion. Confirmed here: 831 of 1,437 distinct NoDefinition sites in the ingest translation unit name a tree-sitter C accessor (ts_node_child_by_field_name, ts_node_is_null, ts_node_type, …), each a two-line function compiled into a separate C object, inside the phases that are ~29% of a cold run. Fix pattern: make the definition available — link-time optimization, not a source edit. Measured: -DRIPWIRE_LTO=ON, four interleaved A/Bs (9/21/21/31 runs per arm) → cold 1–6% faster, warm 0–3%, every cold statistic in every run favouring LTO; output byte-identical, build time +2.6×. Now the default (-DRIPWIRE_LTO=OFF for a fast edit loop). Note the shape of that claim: four runs put the cold median anywhere from −0.8% to −5.9%, so the honest number is the range and the unanimous direction, not the best run. Tell it from noise: if the callee is libc (fopen, fread, stat) the same remark is worthless — inlining a syscall wrapper saves nothing. The class is only interesting when the callee is tiny and yours to build.

Missed gvn LoadClobbered … clobbered by call, in bulk, in one function. Meaning: fires per load per pass; 90,971 of them in this record. Useless individually. Fix pattern: there isn't one for a single site. Its value is aggregate — a dense cluster in one function means that function is call-bound, and that is how the NoDefinition finding above was located. Read it as a heat map, never as a work item.

Restated algorithm — dismiss as a class

loop-vectorize early-exit family: TooManyUncountableEarlyExits, PotentiallyFaultingEarlyExitLoop, CantComputeNumberOfIterations, UnsupportedUncountableLoop, LoopContainsUnsupportedSwitch, WritesInEarlyExitLoop. Confirmed here: hundreds, concentrated in src/docparse.h, src/arch.h, src/lexical.h, src/graph.h, src/infra/radixSort.inl:402. Every one is a scanner that breaks on a delimiter. A loop whose trip count depends on the bytes it is reading is uncountable by construction. There is nothing to fix without changing the algorithm.

Missed inline NeverInline naming __clang_call_terminate. 275 in the hot set. The exception-landing-pad helper; noinline is deliberate and it never runs on a hot path. Filter first, every time.

Missed loop-vectorize MissedDetails. Always paired with an Analysis row that gives the actual reason. Read the Analysis row; the Missed row carries no information of its own.

Missed gvn LoadClobbered … in favor of store … clobbered by store on a histogram. Confirmed here: src/infra/radixSort.inl:411-413, the 4×-unrolled counting loop — the compiler cannot prove digit0 != digit1, so each ++hist[pass][d] reloads. Real, and it has a textbook fix (private per-lane histograms, summed after). Dismissed on the profile, not on the analysis: the sorts are 1.7 ms. Note the shape — "the remark is right and the fix is known and it still is not worth doing" is a legitimate, common verdict.

Real but not worth it — the calibration case

Missed licm LoadWithLoopInvariantAddressInvalidated + gvn LoadClobbered on an address-escaped struct in a call-heavy loop. Confirmed here: src/ingest_sidecap.h:1428, for( uint16_t ci = 0; ci < match.capture_count; ++ci ) over match.captures[ci]. match had its address taken by ts_query_cursor_next_match, so every accessor call in the body clobbers it: the trip count and the capture base were reloaded on every iteration, inside the single hottest own-code loop in the tool. Fix pattern (the textbook one): hoist to locals before the loop — const uint16_t captureCount = match.capture_count; const TSQueryCapture* const captures = match.captures; What happened: the remark moved exactly as predicted (from the inner loop's line to the hoist's line — the load became per-match instead of per-capture). The wall clock did not:

baselinehoisted
run 1, cold median166.6 ms165.6 ms (−0.6%)
run 2, arms swapped243.7 ms257.6 ms (+5.7%)

Direction flips between runs ⇒ noise. Reverted. The reason: the reload sits immediately beside an opaque call that costs orders of magnitude more. This is the most useful entry in this file — if you are about to hoist a load out of a loop whose body calls into another translation unit, expect this outcome and measure before you commit to the diff.

Missed inline TooCostly on libc++ (basic_string::push_back, vector::push_back, unordered_dense::table::…). The cost model declining to inline into a large caller. Occasionally worth chasing; every hot-set instance here was in src/docparse.h (document extraction, off the default path) or one-shot setup in buildGraph. Dismissed on location, not on principle — check where yours is before you copy this verdict.

The cost-model classes have a wholesale answer

inline/TooCostly and loop-vectorize/VectorizationNotBeneficial are the same complaint: the cost model is guessing at hotness with no data. Chasing them one site at a time is nearly always a loss — but you can just give the cost model the data.

Confirmed here: scripts/pgobuild.sh (-DRIPWIRE_PGO=generate → train → llvm-profdata merge-DRIPWIRE_PGO=use, on top of -DRIPWIRE_LTO=ON). Measured cold 14–25% faster than a non-LTO build (6–16% over the LTO default), warm 5–10% — several times LTO's own effect — with the largest gain on a corpus that appears in no training run, which is what rules out train-on-test. Output byte-identical, determinism gate green. The lesson to carry: when a whole remark CLASS is the cost model rather than a fact about your code, look for a build-level answer before you rewrite a single loop. And where it will NOT help: the cold path gained 2–3× more than the warm one, because cold is a branchy call-heavy walk over tree-sitter's parse tree while warm runs mostly in structures already hand-tuned for cache locality under G2 (the CSR triple, the SoA symbol tables, dynamic_map's B+tree, the radix sorts). A profile has little to discover in code whose layout is already the optimization — so expect cost-model remarks in G2-shaped code to stay dismissed even after PGO.

Step 3 — the measurement a fix has to survive

A remark that does not move a measured number does not justify a diff. On this codebase that bar is harder than it sounds: a cold run is ~160 ms and run-to-run spread is wide.

bash
# interleaved A/B — A,B,A,B,… so thermal drift and background load hit both arms equally.
# Report median AND min, >= ~20 runs per arm, and REPEAT THE WHOLE A/B at least twice.

Two failure modes this bar exists for, both hit during the pass that wrote this file:

  • A single non-interleaved run would have "proved" the D2 hoist below. Its first A/B said −0.6%; swapping the arms said +5.7%.
  • Repeating the A/B is what keeps a real win honest, too. The LTO finding's four runs put the cold median at −3.9%, −4.6%, −0.8% and −5.9%. Quoting the best one would be a fabricated precision; what is actually established is a range plus a direction that never flipped.

bench/perfgate.sh (median of 5, cold + warm; ledger mode since 2026-08-08 — it prints the medians and appends them to bench/PROFILE.md, no pass/fail against a budget) is the committed harness for the whole-pipeline number; use RIPWIRE_BIN= to point it at each arm and read the two printed medians off stdout. For a change inside one phase, -DRIPWIRE_PROFILE=ON gives per-phase medians that a 160 ms wall clock cannot resolve.

Then, before you keep it:

bash
./build/ripwire <dir> >a; ./build/ripwire <dir> >b; diff -q a b     # determinism is a contract
python3 test/pargates.py . ./build/ripwire -j 6

Never answer a vectorization remark with -ffast-math / -ffp-contract changes. src/pagerank.cpp is compiled -fno-fast-math on purpose — the reduction must not reassociate — and anything that makes output depend on optimization level is a bug even when the ranking still looks right.

Anti-patterns this pass actually hit

  • Triaging the wide record. size-info, asm-printer, prologepilog, stack-frame-layout, regalloc and hotcoldsplit are per-function-per-pass bookkeeping. They are most of the volume and none of the signal. Narrow with --passes after the first look.
  • Reading third_party/ remarks. The vendored tree-sitter core and sixteen grammars are C you do not own. scripts/optremarks.py drops them (and toolchain headers) by default; keep it that way.
  • Believing a remark about a loop you never profiled. src/lexical.h's BM25 loops looked like the best remaining candidate until the --for profile showed lexicalScores at 0.886 ms of a 95 ms run — and the scanField re-tokenizer the LICM remarks point at does not execute at all on a warm cache.
  • Publishing a one-run A/B. See the table in Step 2. Swap the arms and run it again.

Frequently asked questions

What does the Ripwire Opt Remarks AI skill do?

Triage clang optimization remarks (-Rpass, -Rpass-missed, opt-record YAML) while editing ripwire's OWN C++: 'loop not vectorized', 'will not be inlined' — worth a diff, or is LTO/PGO the real fix? Contributor-only: about compiling this tool, never about running it.

Why use Ripwire Opt Remarks on TypingMind?

Because you install it once and use it with any model. Ripwire Opt Remarks is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Ripwire Opt Remarks in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/redhat-et/ripwire/tree/main/skills/ripwire-opt-remarks. TypingMind reads its SKILL.md and installs it as a skill you can enable per chat.

Which AI models can use Ripwire Opt Remarks?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Ripwire Opt Remarks?

As many as you like. As long as a model supports skills, you can use Ripwire Opt Remarks with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Ripwire Opt Remarks AI skill free?

Yes. It is published on GitHub by redhat-et under the Apache-2.0 license. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇