Skip to content

Refine LTO reflect MethodByName handling#2029

Open
zhouguangyuan0718 wants to merge 9 commits into
xgo-dev:mainfrom
zhouguangyuan0718:main-lto-0703
Open

Refine LTO reflect MethodByName handling#2029
zhouguangyuan0718 wants to merge 9 commits into
xgo-dev:mainfrom
zhouguangyuan0718:main-lto-0703

Conversation

@zhouguangyuan0718

@zhouguangyuan0718 zhouguangyuan0718 commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Add an optional Linux LLVM LTO plugin that runs before LTO GlobalDCE and refines reflect.Value.MethodByName / reflect.Type.MethodByName reachability after LLVM optimization.
  • Mark dynamic MethodByName call sites in LLGo IR with a reflect-kind attribute and mark the actual method-name argument separately, then preserve and remap those attributes through C ABI lowering.
  • Use the plugin to replace broad dynamic reflect method checks with name-specific llvm.type.checked.load checks when optimized IR proves a finite string-name set, so GlobalDCE can remove methods that cannot be reached by those names.
  • Keep the existing conservative behavior when the method name cannot be resolved precisely, and extend LTO tests with binary symbol checks to guard the expected removals.

Implementation Details

The Go side emits two custom attributes only when the optional LTO plugin path is enabled:

  • llgo.reflect.methodbyname on the call site, with value or type to distinguish reflect.Value.MethodByName from reflect.Type.MethodByName.
  • llgo.reflect.methodbyname.name on the method-name parameter, so later lowering does not need to infer ABI-dependent argument positions.

internal/cabi now carries the call-site marker forward and remaps the name-parameter marker onto the lowered string data argument. This keeps the plugin independent of the pre-lowering Go ABI shape while still letting it find the string value precisely after C ABI lowering.

The plugin is built from ltoplugin/ with CMake against LLVM 19 and registers at FullLinkTimeOptimizationEarlyEP. It scans marked reflect calls, derives finite string sets from the optimized IR, traces the call's sret result users to find the corresponding generic reflect checked-loads, adds name-specific checked-loads for each proven method name, and erases the generic dynamic check when the replacement is complete.

The reflect modeling still distinguishes Value and Type method metadata, so a Value.MethodByName use does not keep the broader Type.MethodByName set alive, and vice versa.

Tests and CI

  • Add LTO plugin cl tests for optimized finite-name MethodByName flows.
  • Add symbol-table checks for GlobalDCE LTO cases, so tests assert that expected unused methods are absent from the final binary.
  • Add Go unit coverage for SSA marker emission and C ABI remapping of the method-name parameter marker.
  • Extend the dev LTO GlobalDCE GitHub Actions job on Linux to build the plugin and run the plugin-specific LTO tests with coverage output.

Validation

  • cmake --build /tmp/llgo-ltoplugin-build
  • LLGO_LTO_PLUGIN=/tmp/llgo-ltoplugin-build/LLGOLTOPlugin.so go test -tags dev ./cl -run '^(TestRunAndTestFromTestltoLTOPlugin|TestBuildAndCheckSymbolsFromTestltoLTOPlugin)' -count=1
  • go test -tags dev ./cl -run '^TestBuildAndCheckSymbolsFromTestlto/globaldce_' -count=1
  • LLGO_LTO_PLUGIN=/tmp/llgo-ltoplugin-build/LLGOLTOPlugin.so go test -tags=dev -timeout 30m -covermode=atomic -coverpkg=github.com/goplus/llgo/ssa,github.com/goplus/llgo/internal/build,github.com/goplus/llgo/internal/crosscompile -coverprofile=/tmp/coverage-dev-lto-plugin-cl.txt -run '^(TestRunAndTestFromTestltoLTOPlugin|TestBuildAndCheckSymbolsFromTestltoLTOPlugin)' ./cl
  • go test -tags dev ./ssa ./internal/cabi -count=1
  • go test -tags dev -cover ./ssa ./internal/cabi -count=1
    • github.com/goplus/llgo/ssa: 87.5%
    • github.com/goplus/llgo/internal/cabi: 82.2%

@codecov

codecov Bot commented Jul 5, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 83.67347% with 8 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
ssa/globaldce.go 76.47% 2 Missing and 2 partials ⚠️
cl/instr.go 0.00% 1 Missing and 1 partial ⚠️
ssa/expr.go 66.66% 1 Missing and 1 partial ⚠️

📢 Thoughts on this report? Let us know!

@zhouguangyuan0718 zhouguangyuan0718 marked this pull request as ready for review July 5, 2026 14:06
@zhouguangyuan0718 zhouguangyuan0718 marked this pull request as draft July 6, 2026 07:00
@zhouguangyuan0718 zhouguangyuan0718 marked this pull request as ready for review July 6, 2026 10:29
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