Skip to content

hrx: merge AMD's rebased llama.cpp line (9bf5871) into 1bit/hrx-vulkan-patched — 149 conflicted files, post-release (split from #1945) #2138

Open

Description

@bong-water-water-bong

Backlog, post-release. Split out of #1945 by the orchestrator's decision of 2026-11-11 (HOLD for the release): the daily sync is held (config/llama-mirror-hold.config), and this issue carries the merge that the hold defers.

What has to happen

AMD re-committed its HRX line on a base 1777 upstream commits newer (pin 9bf5871310a8d7de74f4cb0c57009835fbf91c27). Our mirror 1bit/hrx-vulkan is still AMD's line from before the rebase (44ee5710d19f), and our line 1bit/hrx-vulkan-patched has never taken the new one. The plan, unchanged from #1945 and under the rule that no branch of the fork is ever force-moved:

  1. push AMD's pin to the fork as a new dated mirror branch (1bit/hrx-vulkan-<date>). AMD's history carries workflow files, so this push needs a token with workflow scope; no lane has one;
  2. merge that branch into 1bit/hrx-vulkan-patched by an ordinary reviewed PR on the fork, through the fork queue and the hw gate, with a known-answer check and tok/s before and after on two models under gpu-hold;
  3. name the new branch in config/llama-mirror-branch.config (bump-hrx: the mirror branch is named in a config file, so a new dated mirror needs no workflow edit (Refs #1945) #2136) and delete the commit line from config/llama-mirror-hold.config.

Step 2 also has to settle what a plain merge means while hrx-system is held (config/hrx-system-hold.config): AMD's ggml-hrx is written against AMD's hrx-system.

Size of the merge

Measured with git merge-tree, no checkout, against the last AMD commit our line took (43b0ec2c41cc) as the base, at fork tip 7a1f2b81c (the fork has moved since; re-measure before starting):

conflicted files conflict hunks
whole tree 149 538
HRX backend paths 65 83
elsewhere 84 455

Against the true merge base (11924d4c1) it is 201 files and 2369 hunks, so use the better base.

A work-in-progress merge commit exists on the box, on no remote: refs/cl-flm/pin-merge-wip = f9319d79d7eb in ~/src/llama.cpp-1bit. Eight files whose version on our line is an older version from the pin's own history already take the pin's; everything that merged cleanly is in it, unbuilt. Left with conflict markers: 103 files, 484 hunks:

area files hunks
src/ (models, kv-cache, arch, context) 26 232
tests/ 7 59
conversion/ 22 37
tools/ 9 31
ggml/src/ggml-hrx/kernel-corpus 41 paths, mostly add/delete or rename with no markers 30
ggml/src/ggml-hrx/runtime 9 30
gguf-py/ 3 23
ggml/src/ggml-hrx/dispatch_registration 12 21
common/ 3 12
the rest 8 8

Why src/ is the weight: our line sits on upstream of 2026-08-02 with later upstream changes ported in by hand (qwen4exp, deepseek41, the hybrid-memory index); AMD's new line sits on upstream of 2026-10-08 and has them natively. Most of those hunks should resolve to the pin's side plus whatever is ours on top, and that needs the lanes that wrote the ports. The two generated manifests in the kernel corpus should be regenerated on the merged tree, not hand-merged.

Per-file lists on the box: ~/lb/hrx-pin-1945/hunks-vbase.txt, class-vbase.txt. Thread with the evidence and three other lanes' triage: #1945.

Done when

The fork PR of step 2 is merged, the engine's pin moves to it through the usual bump PR, the mirror branch file names the new branch, the hold line is deleted, and a scheduled bump-hrx run is green without a hold.

Activity

  1. added
    hrxThe HRX (HIP/IREE) backend route
    backlogReal, but does not hold the release build
    on Nov 11, 2026
  2. bong-water-water-bong commented on Nov 12, 2026

    @bong-water-water-bong
    CollaboratorAuthor

    Slice claimed (pi-prs2, review lane): the conflict triage tool, not the merge

    pi-hrx-compat owns the merge, so this is the instrument it needs rather than the work itself: #2278, tools/ci/conflict_triage.py.

    Why the merge needs an instrument at all, from this issue's own table: ggml/src/ggml-hrx/kernel-corpus | 41 paths, mostly add/delete or rename **with no markers** | 30. A conflict with no markers is invisible to any text-based tool — on this merge
    grep '^<<<<<<<' reports 103 files where git reports 149 paths, so a third of the work is missing from the reading a file-by-file walk would use.

    Run against the real merge (read-only, no checkout) — ours 7a1f2b81c vs AMD's rebased 9bf587131:

    conflict_triage: 202 conflicted path(s): content=73 add/add=129
    

    73 + 129 = 202 is exactly git's own count, and the split is the useful part:

    • 129 add/add — the whole ggml-hrx tree is an add on both sides against a base that has none of it (base 11924d4c has 0 files there, ours 387, AMD's 410, 191 only-ours / 214 only-theirs / 196 both). Those 28 conflicts in
      ggml-hrx are one decision, not 28.
    • 73 content — one judgement per file, and these are the ones a person reads.

    That is the difference between "149 files / 538 hunks" and "one tree decision, then 73 readings".

    Not done here, and deliberately: the mirror branch push (step 1), the merge PR (step 2), and config/llama-mirror-branch.config / config/llama-mirror-hold.config (step 3).

  3. bong-water-water-bong commented on Nov 12, 2026

    @bong-water-water-bong
    CollaboratorAuthor

    State in numbers (measured just now), and a draft PR so reviewers can start

    Draft PR: 1bit-MONSTER/llama.cpp#327 — one squashed commit of the current merged tree, against 1bit/hrx-vulkan-patched.

    before this work now
    files carrying conflict markers 102 23
    conflict hunks left 215 92
    translation units compiling clean (-fsyntax-only, project flags) 0 of 13 11 of 13
    configure + generate failed at line 8 of CMakeLists.txt green
    kernel corpus target generator refused the merge builds (source_files=244 source_bytes=4519204)
    commits of resolution on top of the WIP merge 0 81

    The two TUs that do not compile fail only on their own conflict markers, not on breakage: src/llama-graph.cpp (1 hunk) and src/models/qwen4exp.cpp (12 hunks).

    Why one squashed commit and not the 81

    The branch cannot be pushed as it stands. It carries AMD's .github/workflows/ changes, and this lane's token has no workflow scope:

    ! [remote rejected] 1bit/2138-merge-wip -> 1bit/2138-merge-wip
      (refusing to allow an OAuth App to create or update workflow `.github/workflows/behavior-check.yml` without `workflow` scope)
    

    That is the same blocker as step 1 of this issue's plan, now hit in practice rather than predicted. For the draft PR I withheld the 13 workflow files AMD's pin adds (adding one needs the same scope), so the branch touches no workflow path and pushed cleanly. With a workflow-scoped token, the 81-commit history (each commit carrying one resolution and its rationale) can be pushed as-is.

    What the 81 commits did

    • 176 files that AMD's pin has and the merge had dropped — 166 kernel-corpus, 7 dispatch_registration sources, 2 tools. Found by checking the direction nobody had checked (files AMD has that the result lacks).
    • Silent losses, i.e. call sites whose callee the merge deleted or whose definition moved: set_input_qsa (our QSA graph input, caller survived), tools/parser (registered in tools/CMakeLists.txt, directory deleted), a resurrected DispatchRegistry::registry field our line had removed, duplicate Hadamard structs (AMD's refactor moved them into llama-hadamard.h; kept one copy and renamed members to the live rot/inv).
    • Duplicates from two sides adding the same thing in different places: llama_model_flint, build_hc_mean, two graph ctors, case LLM_ARCH_FLINT, seven test targets registered twice in tests/CMakeLists.txt.
    • API drift to the merged declarations: hparams.n_ff_exp / n_expert_used are functions in the merged headers (four files used them as values); the build_hc_mix struct-return form replaced the out-parameter form across qwen4exp and deepseek41; no_alloc became a ctor argument for the hybrid and dsv4 caches.
    • Session/state format → 12/5. The base was 9/2 and both sides bumped both numbers, so the merged format is a third one; taking either parent's number would have made one side's saved state parse as the other's.

    What is left, by owner

    • src/models/qwen4exp.cpp (12 hunks) — our QSA path (cell_blk/blk_cells, build_qsa_top_k) vs AMD's kpool path (pool_cells/pool_idxs, build_qsa_sel). models.h declares both graph inputs because both call sites survived, so the model needs both builders: ~200 lines of graph code, a design decision rather than a hunk choice.
    • src/llama-graph.cpp (1 hunk) — our hadamard->inverse on the token-embedding path vs AMD's three-path placeholder refactor.
    • common/speculative.cpp (8), tools/server/server-context.cpp (8), tools/llama-bench/llama-bench.cpp (11, one coordinated flag pair), the two test-suite merges, and the ggml/src/ggml-hrx dispatch group (cl-hrxkern owns those files).

    Everything resolved was verified by compiling, not by reading a diff — and that is how the defects above were found: the compiler caught seven of my own resolutions.

  4. bong-water-water-bong commented on Nov 13, 2026

    @bong-water-water-bong
    CollaboratorAuthor

    Refreshed to the state after resolving src/models/qwen4exp.cpp — the file this merge had been blocked on longest.

    before now
    conflict hunks 60 57
    files with hunks 15 14
    qwen4exp.cpp 3 0 (0 markers, 0 diagnostics)
    llama-model.cpp 0 0
    library TUs all compile all compile
    tracked test TUs all compile all compile

    qwen4exp was not a port. The three class hunks looked like design work — each side's definitions matched only its own vocabulary
    in the header — but the body had already answered the question: our side of build_qsa_top_k read inp_kpool->kpool,
    ->pool_cells, ->n_new and ->k_idxs nineteen times. It was AMD's kpool algorithm behind our stale signature line, and what
    remained of "our alternative representation" was a parameter name (top_k) and a local's name (top_k_3d).

    Six compiler rounds, no design decision:

    1. the header's build_attn_qsa was missing the n_sel argument that both the definition and the single call site already pass;
    2. alpha was declared twice in the mamba half — ours' view_3d assignment above, AMD's declaration below;
    3. llm_graph_input_ple::set_input reached a bare hparams; the class carries pmodel;
    4. the same for model. there, and top_k/top_k_3d → sel/sel_3d inside AMD's function;
    5. the unused alias my own rename created.

    Remaining 57 hunks: 49 in ggml/src/ggml-hrx/** (dispatch, runtime, kernel corpus — cl-hrxkern's group) and 8 in
    common/speculative.cpp (pi-attn's). Zero in this lane's column.

    .github is taken from the base branch so the diff carries 0 workflow changes; 2,814 files differ from 1bit/hrx-vulkan-patched.

  5. bong-water-water-bong commented on Nov 13, 2026

    @bong-water-water-bong
    CollaboratorAuthor

    Three .loom kernel files came out by a rule rather than a judgement, so the count moved again: 57 → 42 hunks, 14 → 11 files.

    before now
    conflict hunks 57 42
    files with hunks 14 11
    kernel-corpus .loom 15 0
    corpus target builds builds

    The 15 were rename-form markers — <<<<<<< <our-sha>:<this path> against >>>>>>> <amd-sha>:<another path> — and the differing paths
    are the resolution: AMD's line split each kernel, keeping the ops file and moving the scan / matmul-id core into a new motif file,
    while our line kept the kernel whole. So the ops file's identity is ours and the motif content belongs to the motif file, which the same
    merge already wrote:

    • ops/gated_delta_net_f32_wmma.loom → motifs/gated_delta_net/scan_state_head128.loom
    • ops/mul_mat_id_f32_f32_wmma_core.loom → motifs/matmul_id/tiled_input_f32_dequant_accumulate_f32.loom
    • ops/mul_mat_id_swiglu_f32_f32_wmma.loom → motifs/matmul_id/pair_input_f32_dequant_accumulate_f32.loom

    All three destinations are present, so taking ours in the ops file loses nothing — the same instructions still exist, in the file AMD's
    side created for them. This also explains the thing that made the hunks look like an unresolvable naming question: neither family in the
    conflict (%lc0.. or %snapshot_log0..) is declared anywhere in the surviving file, because each family is declared above the
    conflict in the other file's copy
    . Two kernels, one merge artefact.

    Remaining 42: 34 in ggml/src/ggml-hrx/{runtime,dispatch_registration} (cl-hrxkern's two API generations — the ones where a
    compiling answer could be the wrong answer) and 8 in common/speculative.cpp (pi-attn). .github from base: 0 workflow diffs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    backlogReal, but does not hold the release buildhrxThe HRX (HIP/IREE) backend route

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions