Skip to content

Commit 3b6f9fe

Browse files
committed
build: use LLVM memcpyopt pass to replace cabi load/store optimization
- 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 #1605
1 parent 0228ae2 commit 3b6f9fe

File tree

4 files changed

+35
-30
lines changed

4 files changed

+35
-30
lines changed

internal/build/build.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ import (
5454
"github.com/goplus/llgo/ssa/abi"
5555
xenv "github.com/goplus/llgo/xtool/env"
5656
"github.com/goplus/llgo/xtool/env/llvm"
57+
gollvm "github.com/goplus/llvm"
5758

5859
llruntime "github.com/goplus/llgo/runtime"
5960
llssa "github.com/goplus/llgo/ssa"
@@ -142,6 +143,7 @@ type Config struct {
142143
SizeFormat string // size report format: text,json (default text)
143144
SizeLevel string // size aggregation level: full,module,package (default module)
144145
CompilerHash string // metadata hash for the running compiler (development builds only)
146+
SkipTargetInfo bool // skip setting data layout and target triple (for test generation)
145147
// GlobalRewrites specifies compile-time overrides for global string variables.
146148
// Keys are fully qualified package paths (e.g. "main" or "github.com/user/pkg").
147149
// Each Rewrites entry maps variable names to replacement string values. Only
@@ -1158,6 +1160,19 @@ func buildPkg(ctx *context, aPkg *aPackage, verbose bool) error {
11581160

11591161
ctx.cTransformer.TransformModule(ret.Path(), ret.Module())
11601162

1163+
// Run LLVM optimization passes (memcpyopt converts load/store to memcpy)
1164+
// Skip when SkipTargetInfo is set (for test generation to avoid target-specific output)
1165+
if !ctx.buildConf.SkipTargetInfo {
1166+
mod := ret.Module()
1167+
mod.SetDataLayout(ctx.prog.DataLayout())
1168+
mod.SetTarget(ctx.prog.Target().Spec().Triple)
1169+
pbo := gollvm.NewPassBuilderOptions()
1170+
defer pbo.Dispose()
1171+
if err := mod.RunPasses("memcpyopt", ctx.prog.TargetMachine(), pbo); err != nil {
1172+
return fmt.Errorf("run LLVM passes failed for %v: %v", pkgPath, err)
1173+
}
1174+
}
1175+
11611176
printCmds := ctx.shouldPrintCommands(verbose)
11621177
cgoLLFiles, cgoLdflags, err := buildCgo(ctx, aPkg, aPkg.Package.Syntax, externs, printCmds)
11631178
if err != nil {

internal/llgen/llgenf.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,9 @@ func genFrom(pkgPath string, abiMode build.AbiMode) (build.Package, error) {
4545
}()
4646

4747
conf := &build.Config{
48-
Mode: build.ModeGen,
49-
AbiMode: abiMode,
48+
Mode: build.ModeGen,
49+
AbiMode: abiMode,
50+
SkipTargetInfo: true,
5051
}
5152
pkgs, err := build.Do([]string{pkgPath}, conf)
5253
if err != nil {

ssa/package.go

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"go/types"
2323
"runtime"
2424
"strconv"
25+
"testing"
2526
"unsafe"
2627

2728
"github.com/goplus/llgo/internal/env"
@@ -117,9 +118,9 @@ type aProgram struct {
117118
py *types.Package
118119
pyget func() *types.Package
119120

120-
target *Target
121-
td llvm.TargetData
122-
// tm llvm.TargetMachine
121+
target *Target
122+
td llvm.TargetData
123+
tm llvm.TargetMachine
123124
named map[string]Type
124125
fnnamed map[string]int
125126

@@ -247,7 +248,7 @@ func NewProgram(target *Target) Program {
247248
}
248249
}
249250
ctx := llvm.NewContext()
250-
td := target.targetData() // TODO(xsw): target config
251+
td, tm := target.targetInfo()
251252
/*
252253
arch := target.GOARCH
253254
if arch == "" {
@@ -261,7 +262,7 @@ func NewProgram(target *Target) Program {
261262
is32Bits := (td.PointerSize() == 4 || is32Bits(target.GOARCH))
262263
return &aProgram{
263264
ctx: ctx, gocvt: newGoTypes(),
264-
target: target, td: td, is32Bits: is32Bits,
265+
target: target, td: td, tm: tm, is32Bits: is32Bits,
265266
ptrSize: td.PointerSize(), named: make(map[string]Type), fnnamed: make(map[string]int),
266267
linkname: make(map[string]string), abiSymbol: make(map[string]Type),
267268
}
@@ -275,6 +276,14 @@ func (p Program) TargetData() llvm.TargetData {
275276
return p.td
276277
}
277278

279+
func (p Program) TargetMachine() llvm.TargetMachine {
280+
return p.tm
281+
}
282+
283+
func (p Program) DataLayout() string {
284+
return p.td.String()
285+
}
286+
278287
func (p Program) SetPatch(patchType func(types.Type) types.Type) {
279288
p.patchType = patchType
280289
}
@@ -413,6 +422,7 @@ func (p Program) NewPackage(name, pkgPath string) Package {
413422
// if p.target.GOARCH != runtime.GOARCH && p.target.GOOS != runtime.GOOS {
414423
// mod.SetTarget(p.target.Spec().Triple)
415424
// }
425+
testing.Testing()
416426

417427
// TODO(xsw): Finalize may cause panic, so comment it.
418428
// mod.Finalize()

ssa/target.go

Lines changed: 2 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ func (t *Target) CtxRegister() CtxRegister {
6262
return CtxRegister{Name: info.Name, Constraint: info.Constraint}
6363
}
6464

65-
func (p *Target) targetData() llvm.TargetData {
65+
func (p *Target) targetInfo() (llvm.TargetData, llvm.TargetMachine) {
6666
spec := p.Spec()
6767
if spec.Triple == "" {
6868
spec.Triple = llvm.DefaultTargetTriple()
@@ -72,30 +72,9 @@ func (p *Target) targetData() llvm.TargetData {
7272
panic(err)
7373
}
7474
machine := t.CreateTargetMachine(spec.Triple, spec.CPU, spec.Features, llvm.CodeGenLevelDefault, llvm.RelocDefault, llvm.CodeModelDefault)
75-
return machine.CreateTargetData()
75+
return machine.CreateTargetData(), machine
7676
}
7777

78-
/*
79-
func (p *Program) targetMachine() llvm.TargetMachine {
80-
if p.tm.C == nil {
81-
spec := p.target.toSpec()
82-
target, err := llvm.GetTargetFromTriple(spec.triple)
83-
if err != nil {
84-
panic(err)
85-
}
86-
p.tm = target.CreateTargetMachine(
87-
spec.triple,
88-
spec.cpu,
89-
spec.features,
90-
llvm.CodeGenLevelDefault,
91-
llvm.RelocDefault,
92-
llvm.CodeModelDefault,
93-
)
94-
}
95-
return p.tm
96-
}
97-
*/
98-
9978
type TargetSpec struct {
10079
Triple string
10180
CPU string

0 commit comments

Comments
 (0)