Skip to content

cmd/compile: run write barriers before LLVM emission - #32

Merged
zhouguangyuan0718 merged 1 commit into
go1.27.masterfrom
codex/post-expand-llvm-emission
Aug 2, 2026
Merged

cmd/compile: run write barriers before LLVM emission#32
zhouguangyuan0718 merged 1 commit into
go1.27.masterfrom
codex/post-expand-llvm-emission

Conversation

@zhouguangyuan0718

@zhouguangyuan0718 zhouguangyuan0718 commented Aug 1, 2026

Copy link
Copy Markdown

Summary

  • run the Go writebarrier SSA pass in LLVM mode before expand calls
  • emit LLVM from that form so pointer stores retain Go write-barrier semantics
  • lower scalar barriers to llvm.go.gc.write.barrier while preserving the current branchy Go control flow
  • preserve the native raw AuxCall as physical ABI authority for runtime.wbZero/runtime.wbMove, while restoring their semantic LLVM parameters to ptr
  • unconditionally attach go-async-unsafe to every LLVM-emitted function; LLVM PR cmd/objview: add metadata-aware text disassembly #19 therefore emits whole-function PCDATA_UnsafePoint=-2
  • add codegen, IR, GoObj, concurrent-GC, aggregate move/zero, and stack-growth coverage

Unsafe-point model

This version intentionally uses the complete conservative model requested for the first functional write-barrier implementation: every LLVM-emitted function is asynchronous-unsafe for its entire body.

There is no interval scan, unsafe-point start/end intrinsic, SelectionDAG marker, or partial range protocol in this PR. Removing the old WriteMem marker also restores normal optimization; the memory-order test accepts inlining and load forwarding while still checking the write barrier and resulting store.

Exact interval marking is deferred. The previous range-emission prototype is preserved at codex/post-expand-llvm-emission-ranges-backup.

Rebase and prerequisites

Rebased onto go1.27.master@912359eeecb1b00c280bd857e220857de32dbf83, including the merged post-construction nilcheck-marker expansion (#38). This branch preserves that implementation unchanged and does not restore the old BlockEnds CFG bypass.

Pointer allocas are handled exclusively by the #33 / LLVM #18 deopt ptrmap model. This PR contains no capture analysis, fixed-stack preload, alloca relocation, or post-call write-back implementation.

Merged prerequisites:

Open prerequisite:

Statepoint and SSA integration

  • keep original calls alive until every precomputed statepoint live set has been consumed; LLVM block layout is not CFG dominance order
  • validate the actual post-nilcheck call queries for mixedABI: four ordinary safepoints select bitmap {2}, while morestack selects entry bitmap {2,4,18}
  • recognize only the exact dead OpNilCheck tombstone that writebarrier leaves before early deadcode
  • remove the unreachable BlockFirst lowering and all four BlockInvalid skip paths; unexpected block kinds now use the existing fail-closed path
  • handle runtime.newproc, wbZero, and wbMove in one llvmStaticCallSignature path: validate each raw ABIInternal uintptr signature, then construct the semantic LLVM pointer signature without ptrtoint adapter values
  • keep wbZero/wbMove as direct gc-leaf calls; focused checks reject any statepoint that targets either helper
  • update writebarrier helper checks to distinguish the ordinary call from two expanded runtime.panicmem statepoints

Validation

  • clean make.bash toolchain rebuild with the latest vendored go-llvm and exact LLVM payload
  • installed and freshly built statepoint plugins have identical SHA-256
  • plugin CTest: 48/48
  • go test -count=1 -tags="llvm23 dynamicllvm" cmd/compile/internal/ssa cmd/llvmtoolexec
  • direct IR verification, opt -passes=default<O2>, RS4GC rewritten verification, llc -verify-machineinstrs, MIR and object generation through focused tests
  • cmd/internal/testdir Test/LLVM: all 51 codegen and all 47 runtime whitelist cases
  • ABI differential, nilcheck, alloca-statepoint, semantic pointer wbZero/wbMove, writebarrier IR, concurrent GC, and stack-growth suites
  • LLVM AArch64/X86 fixed argument home lit tests: 2/2
  • gofmt, diff-only clang-format, and git diff --check

Scope

This first functional version keeps the branches generated by the Go writebarrier pass. A later optimization can use a more constrained late-expanded intrinsic and exact unsafe intervals. StackObjects precision and the postponed linker indirect-call nosplit graph issue are not included.

@zhouguangyuan0718
zhouguangyuan0718 force-pushed the codex/post-expand-llvm-emission branch from b1149fd to 41b7521 Compare August 1, 2026 04:53
@zhouguangyuan0718
zhouguangyuan0718 changed the base branch from go1.27.master to codex/alloca-statepoint-mutation-correctness August 1, 2026 04:54
@zhouguangyuan0718
zhouguangyuan0718 force-pushed the codex/post-expand-llvm-emission branch from 41b7521 to 71790dd Compare August 1, 2026 08:43
@zhouguangyuan0718
zhouguangyuan0718 changed the base branch from codex/alloca-statepoint-mutation-correctness to go1.27.master August 1, 2026 08:48
@zhouguangyuan0718
zhouguangyuan0718 force-pushed the codex/post-expand-llvm-emission branch 4 times, most recently from b5171a2 to f042189 Compare August 2, 2026 03:14
@zhouguangyuan0718
zhouguangyuan0718 force-pushed the codex/post-expand-llvm-emission branch from f042189 to 15b0620 Compare August 2, 2026 03:23
@zhouguangyuan0718
zhouguangyuan0718 merged commit b4ee53e into go1.27.master Aug 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant