| name | swpp-team-rules |
| description | Rules, conventions, and grading criteria for the SWPP 2026 Spring team compiler project. Use this skill whenever the user is working inside the `swpp202601-teamNN` team repository — writing code, opening or reviewing a pull request, preparing a sprint document, planning an optimization, or asking "what's the rule for X?". Triggers on any mention of the SWPP project, sprints (Sprint 0/1/2/3), the team compiler, PR grading, the target machine / imaginary ISA, the interpreter, benchmarks, the CI image, LLVM passes for this project, Alive2 for this project, or any file under `.clang-format`, `compile.sh`, or CMakeLists.txt in the context of this project. Use it even if the user does not explicitly ask — these rules govern grading, so aligning with them matters on every change. |
SWPP 2026 Spring — Team Compiler Project Rules
This skill encodes the rules and conventions from the course's Project Specification and Target Machine Specification for the 2026 Spring SWPP team project. Anything written here overrides defaults; anything not covered should be looked up in the official PDFs or clarified with the TAs.
What the project is
Each team builds an LLVM-based compiler that reads an LLVM IR program and emits optimized assembly for an imaginary target machine (the "Target Machine" or TM). Team grading is PR-based across three sprints, plus a final competition.
- LLVM: version 22.1.0 (built with the class repo script — do not substitute another version)
- Sprints: Sprint 0 (setup, 4/17–4/23) → Sprint 1 (4/24–5/7) → Sprint 2 (5/8–5/21) → Sprint 3 (5/22–6/4) → Wrap-up (6/5–6/8) → Competition (6/9)
- Repo name: must be
swpp202601-teamNN exactly
When to consult which reference
This SKILL.md covers the rules you need for most day-to-day actions. For deeper material, read the reference file when the task calls for it:
- Opening, reviewing, or grading a PR → read
references/pr-rubric.md for the full 23-point rubric, team-score deduction table, and an example of a "full-credit" PR.
- Writing code that emits assembly, reasoning about costs, planning an optimization → read
references/target-machine-spec.md for the ISA, cost model, 4-Phobia rule, and Heat Memory mechanic.
- Preparing a Planning / Requirements & Specification / Progress Report document or filing it as an Issue → read
references/documents-submission.md for exact titles, filenames, page limits, and the submission calendar.
Do not load a reference file unless the current task actually uses its content — the SKILL.md body is designed to stand alone for common work.
Core rules that apply to every PR
These show up as −1 deductions on the team score or as lost points on the individual rubric, so they matter on every change. Read them once, then let them guide the work.
1. PR scope & shape
A PR should represent one feature / one optimization pass / one analysis pass. That's the unit the course grades. Avoid bundling unrelated changes — it makes the PR harder to review, and reviewers may withhold full credit on the explanation rubric because the "one thing" is unclear.
- Title starts with
[Sprint N] where N is the current sprint number (1, 2, or 3). Variants for special cases:
- Non-functional cleanup (directory restructure, splitting files, no behavior change):
[Sprint N, NFC]
- Reverting a previous PR:
[Sprint N, Revert] on the revert PR, and amend the reverted PR's title to [Sprint N, Reverted]
- Applying the TAs' codebase update:
[Sprint N, Update]
- Line diff ≤ ~500 lines after running
clang-format, excluding comments, whitespace, tests, and non-C++ files (.gitignore, CMakeLists.txt, etc.). If a feature genuinely needs more, split it.
- Every PR must include unit tests for the new behavior (see "Testing" below).
- Every PR must pass CI at merge time. Merging a CI-failing PR costs the team 1 point per PR with no exceptions.
- Squash and merge is the only allowed merge strategy. The PR author (not the reviewer) clicks the squash-merge button. Merging a PR via "Create a merge commit" or "Rebase and merge" costs 1 team point per PR.
- Never push directly to
main. Direct pushes cost 1 team point per incident. The one exception is Sprint 0 skeleton commits, which the spec exempts from PR rules entirely.
2. Reviews
- Each PR needs 2 or more human reviewers. AI / automated reviewers can be wired in but do not count toward the 2-review requirement.
- A review counts as "meaningful" only if it raises a technical point: a correctness concern, an edge case, a test-adequacy question, a performance-evaluation question, or an implementation/design discussion. "LGTM", "Looks good", emoji-only reactions, approvals with no body, or comments only about formatting/wording are insufficient and cost 1 team point per PR.
- Aim to actually read the diff, run it mentally, and ask at least one question that a reviewer would ask if they cared about the code.
3. Personal merge quotas per sprint
- Maximum 6 merged PRs per person per sprint. This caps the amount of code any one student can ship, encouraging spreading work.
- Minimum 2 merged PRs per person per sprint to earn the full 20-point individual score. One PR caps the personal score at 10; zero PRs is 0 points.
- If the team has fewer than 4 active members, the missing teammate's 6-PR quota is redistributable.
- NFC, Revert, and Reverted PRs are exempt from the 6-PR cap and do not count toward the 2-PR minimum (only the normally-graded PRs count toward the minimum).
- Co-authored PRs count as one PR for each listed author.
- Only PRs merged into
main are graded. Feature branches, draft PRs, and closed-without-merge PRs are not graded.
4. What counts as a valid optimization
The course is strict here because the project is about reasoning about programs, not about pattern-matching them:
- Optimizations based on function-name matching are forbidden. E.g., "if the function is named
sort, replace its body" is not allowed.
- Replacing an entire program implementation with pre-written code is forbidden.
- Transformations must come from logical analysis of the IR, not from syntactic matching against specific benchmark patterns.
- Reusing existing LLVM optimization passes is allowed — but each one must come in as its own PR, with its own unit tests, and counts toward the 6-PR cap. Slipping an existing pass in as an "NFC" PR to dodge the cap is penalized.
- Existing LLVM analysis passes may be included and used freely as building blocks — only passes you actually implement count toward the 6-PR cap.
5. Testing
Every optimization / analysis PR must ship with at least 3 unit tests that exercise the new pass specifically.
- For an optimization pass: each unit test is an LLVM IR program with FileCheck comments, validating the output of
opt --<new-opt-pass>.
- For an analysis pass: each unit test is a C++ program that loads an IR file, runs the analysis, and asserts on the result (analysis passes don't mutate IR, so FileCheck isn't enough).
ctest --test-dir build must run all tests. GitHub Actions must run ctest on every PR.
- Also run the full example-program tests from the Benchmarks repo before opening the PR. Both unit tests and example-program tests must pass for full correctness credit. If either one is missing, the Correctness/Unit-Tests rubric item receives 0.
- Alive2 verification is optional but earns a bonus point on the correctness rubric. Apply the course-provided Alive2 patch (
applying-patch.md) so Alive2 understands the project's custom intrinsics, then check the representative transformations. Report Alive2 results in the PR body.
6. PR body content (this is 10 of the 23 rubric points)
A PR's body must explain, clearly:
- Issue description — what problem / missed optimization / inefficiency motivated this PR.
- Implementation / high-level algorithm — how the pass works, as a numbered list or prose. A reviewer should understand the transformation without reading the diff.
- Performance evaluation — numerical results (table/figure) on concrete benchmarks, plus a short analysis of what the numbers mean. The amount of speedup is not graded, but the presence of quantitative evidence is.
- Correctness discussion — unit-test + example-test results, plus reasoning about why the transformation is safe (safety conditions, edge cases, why the conservatism, etc.). Alive2 results go here if used.
Vague claims without evidence lose points even if the code is correct. See references/pr-rubric.md for the full rubric and a worked example.
CI, environment, and tooling
- Development environment: use the course-provided Docker image (Ubuntu 24.04, x86-64). LLVM 22.1.0 lives at
/opt/llvm-22.1.0, Z3 4.16.0 lives at /opt/z3-4.16.0. The image is the authoritative environment — if something works locally but fails in the image, the image wins.
- Inside the container, the default user is root. Do not use
sudo inside the container. Commands like sudo apt install ... will error out; use apt install ... directly.
- CI must pass on every merged PR. Configure GitHub Actions to run
./compile.sh and ctest --test-dir build inside the course Docker image, on every pull_request targeting main.
- Formatter: use the
.clang-format shipped with the skeleton. Line counts in the 500-line cap are measured after formatting. A pre-commit Git hook that runs clang-format is recommended — it prevents review-time formatting churn.
compile.sh and ctest --test-dir build must always work from the repo root. TAs run these after every commit; breaking them silently breaks grading.
AI policy (the course allows AI use, conditionally)
The course permits AI assistance for code, PRs, reviews, and documents, but:
- Students are fully responsible for the correctness and quality of anything submitted. Incorrect or unnatural AI output can be penalized substantially.
- Any PR, review, or document that used AI must disclose it explicitly in the PR/Issue body.
- Do not modify code based only on function-name matching or superficial pattern recognition. The expectation is that the student understands the behavior before changing it.
- AI-only / automated reviewers can exist, but they do not count toward the 2-human-reviewer requirement on a PR.
Practically, when using Claude Code: include a one-line note like "AI-assisted (Claude Code)" in the PR body, and always read the diff end-to-end before merging.
Target machine cheat sheet (just enough for planning)
Full details are in references/target-machine-spec.md. The essentials that shape optimization decisions:
- Single-core CPU, 64-bit memory space, 32 64-bit general registers (
r1..r32) plus sp, plus 16 read-only argument registers (arg1..arg16).
- Calling convention saves all registers automatically. You never need to spill registers across calls.
- Cost model: total cost =
program-wide instruction execution cost + (max heap bytes used) * 1024. Code size does not matter; execution cost and peak heap do.
mul / udiv / sdiv / urem / srem cost 2. If a mul is directly followed by an add or sub, the mul's cost becomes 0 (fuse multiply-add pattern).
eadd / oadd / esub / osub exist for even/odd result optimization: cost 10 when the parity matches the expectation, 20 otherwise. Regular integer arithmetic is worth thinking about in parity terms.
- Branches are expensive, and forward jumps are 50% more expensive than backward ones. Loop back-edges are cheaper than forward skips.
aload (async load) is much cheaper than load if you can hoist it far enough from its use site to cover the resolution latency (36 for stack, 60 for heap).
- Heat Memory: every heap access adds 400 HP to its 8-byte segment (and neighbors, depending on access width). Heat segments cap at 2000 HP. Remaining heat increases access cost by
floor(HP / 10), and every non-access instruction cools by its own cost. Clustering hot memory traffic penalizes itself; interleaving cool instructions between accesses helps.
- 4-Phobia: any instruction involving the constant
4 costs an extra 10. If 4 appears multiple times in the same instruction, the penalty applies once. assert_eq is exempt. When in doubt, avoid 4 — prefer 2+2, 8/2, shifts, or similar rewrites when cost-advantageous.
When planning an optimization, always translate its win into the cost model above. "Faster" is not enough; "replaces N mul+add pairs with fused sequences, saving 2 × N program-wide cost" is the kind of reasoning that earns full credit on the Performance rubric.
Documents to submit during each sprint
Full rules, filenames, and Issue titles are in references/documents-submission.md. The calendar at a glance:
| Due (11:59 pm) | Planning | Req/Spec | Progress |
|---|
| 4/23 (Sprint 0) | ✓ | Sprint 1 | — |
| 5/7 (Sprint 1) | — | Sprint 2 | Sprint 1 |
| 5/21 (Sprint 2) | — | Sprint 3 | Sprint 2 |
| 6/4 (Sprint 3) | — | — | Sprint 3 |
Each document is attached as a PDF file on a GitHub Issue in the team repo — do not paste document contents into the Issue body. Issues edited after the deadline are graded zero.
Common operations, quick reference
Opening a new optimization PR
- Branch from up-to-date
main: git checkout -b opt/<short-name>.
- Implement the pass and unit tests together. Run
clang-format before committing.
- Run
./compile.sh && ctest --test-dir build locally inside the course Docker image to match CI.
- Run the example-program test suite from the Benchmarks repo.
- (Optional but recommended) Run Alive2 on representative transformations.
- Push the branch, open a PR titled
[Sprint N] <feature name>.
- In the PR body, fill in the four sections: Issue description, Implementation / high-level algorithm, Performance evaluation (with a table and a short analysis), Correctness discussion (unit tests + example tests + Alive2 if used).
- Request reviews from at least 2 teammates.
- After approvals and green CI, you (the author) click Squash and merge.
Reviewing a teammate's PR
- Read the PR body first. If the Issue description, implementation, performance evaluation, or correctness section is missing/thin, say so — that feedback directly affects their rubric score, and is more valuable than nit-picking code.
- Read the diff. Ask at least one technical question (correctness, edge cases, test adequacy, design).
- If something's unclear or risky, request changes. If it all checks out, approve with a comment explaining what you verified — not just "LGTM".
Recovering from a mistake
- PR merged that broke CI → open a
[Sprint N, Revert] PR. Edit the original PR title to [Sprint N, Reverted]. The reverted PR is still graded, but the revert isn't.
- Accidentally pushed to
main → that's −1 team score per incident. Revert the commit via a PR.
- Forgot to disclose AI use on a merged PR → add a comment disclosing it as soon as possible.