build: use LLVM memcpyopt pass to replace cabi load/store optimization#1612
build: use LLVM memcpyopt pass to replace cabi load/store optimization#1612xushiwei merged 2 commits intoxgo-dev:mainfrom
Conversation
Summary of ChangesHello @luoliwoshang, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request integrates the LLVM Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request introduces the memcpyopt LLVM pass to optimize load/store operations, which is a great performance improvement. The changes to enable this pass in ssa/package.go and ssa/target.go are well-structured. The bug fix in internal/cabi/cabi.go and the accompanying regression tests are also solid.
My review includes a couple of suggestions to improve maintainability and clarity, mainly regarding a hardcoded package path and an inconsistency in issue numbers in a test file. Overall, this is a good step forward, and I'm looking forward to seeing the WIP parts resolved.
| @@ -0,0 +1,35 @@ | |||
| package main | |||
|
|
|||
| // Regression test for https://github.com/goplus/llgo/issues/1608 | |||
There was a problem hiding this comment.
There seems to be an inconsistency in the issue number. The directory is named return-1605 and the PR description states this fixes #1605, but the comment here refers to issue #1608. The test case appears to be a regression test for the scenario described in issue #1608, which is also referenced in internal/cabi/cabi.go and internal/cabi/cabi_test.go. To improve clarity and avoid future confusion, please consider aligning the directory name with the issue it tests, for example by renaming it to return-1608.
c2d0a28 to
75cc7d4
Compare
| @@ -119,7 +119,7 @@ type aProgram struct { | |||
|
|
|||
| target *Target | |||
| td llvm.TargetData | |||
| // tm llvm.TargetMachine | |||
| tm llvm.TargetMachine | |||
There was a problem hiding this comment.
Resource leak concern: The TargetMachine (tm) is stored but never disposed. LLVM's TargetMachine holds native resources that aren't managed by Go's garbage collector. Consider adding a Dispose() method to aProgram that calls tm.Dispose() (and td.Dispose(), ctx.Dispose()) and ensure callers invoke it when the Program is no longer needed.
This could lead to memory pressure in long-running compilation sessions or when compiling many packages.
| @@ -0,0 +1,35 @@ | |||
| package main | |||
|
|
|||
| // Regression test for https://github.com/goplus/llgo/issues/1608 | |||
There was a problem hiding this comment.
| defer pbo.Dispose() | ||
| if err := ret.Module().RunPasses("memcpyopt", ctx.prog.TargetMachine(), pbo); err != nil { | ||
| return fmt.Errorf("run LLVM passes failed for %v: %v", pkgPath, err) | ||
| } |
There was a problem hiding this comment.
Consider using existing helper: There's an isRuntimePkg() helper function at line 977 that uses env.LLGoRuntimePkg constant. Using it would improve consistency:
| } | |
| if !isRuntimePkg(pkgPath) { |
| return fmt.Errorf("run LLVM passes failed for %v: %v", pkgPath, err) | ||
| } | ||
| } | ||
|
|
There was a problem hiding this comment.
Performance consideration: PassBuilderOptions is created and disposed for every package compilation. For projects with many packages, consider reusing a single instance at the context level to reduce allocation overhead.
Also, the comment mentions runtime packages cause SIGSEGV - it would be helpful to document this more specifically or link to an issue tracking the root cause investigation.
Code Review SummaryThis PR correctly fixes issue #1608 by removing the unsafe memcpy optimization in CABI transformation and delegating memory optimization to LLVM's Key observations:
Minor issues to address:
Overall the fix is well-designed. The runtime package crash warrants a follow-up investigation issue. |
fb8dd9b to
a62459f
Compare
3b6f9fe to
9eac45e
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #1612 +/- ##
==========================================
+ Coverage 91.05% 91.10% +0.04%
==========================================
Files 45 45
Lines 11933 11921 -12
==========================================
- Hits 10866 10861 -5
+ Misses 892 886 -6
+ Partials 175 174 -1 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
@xgopilot merge main branch |
Merged main branch ✅Successfully merged the latest Changes:
Action Required: Please merge this PR in your fork to update the feature branch: |
- Add targetInfo() to return TargetData and TargetMachine - Add TargetMachine() and DataLayout() methods to Program - Set data layout and target triple before running LLVM passes - Run memcpyopt pass after IR generation to convert load/store to memcpy This replaces the manual optimization in cabi with LLVM's built-in memcpyopt pass, which handles more cases and is more robust. Fixes xgo-dev#1605
217c5ce to
5ac9730
Compare
8b39300 to
8da359b
Compare
| return p.td | ||
| } | ||
|
|
||
| func (p Program) TargetMachine() llvm.TargetMachine { |
There was a problem hiding this comment.
@xgopilot also need a expect test for this Method!create pr for me!
There was a problem hiding this comment.
Added test coverage for TargetMachine() and DataLayout() ✅
Enhanced TestTargetMachineAndDataLayout in ssa/ssa_test.go to verify:
TargetMachine()returns a valid (non-nil) target machineTargetData()returns a valid (non-nil) target data
PR Created: luoliwoshang#199
Please merge this PR to include the test coverage in your feature branch.
9c931c9 to
d91fc75
Compare
d91fc75 to
22c03f5
Compare
22c03f5 to
791c2fd
Compare
build: use LLVM memcpyopt pass to replace cabi load/store optimization
Fixed #1604 #1606 #1608
Summary
Use LLVM's built-in
memcpyoptpass to replace the manual load/store optimization in cabi. This pass handles the same optimization more safely and robustly.Changes
targetInfo()to return bothTargetDataandTargetMachineTargetMachinein Program structTargetMachine()andDataLayout()methodsmemcpyoptpass after IR generationExample
For returning large structs, this pass achieves the same optimization as the cabi code, converting load/store patterns to memcpy:
Why use memcpyopt?
Background
LLVM's
memcpyoptpass (Memory Copy Optimization) is enabled at-O1and above. It recognizes patterns like:And converts them to:
Fixes #1605