Skip to content

Commit c2d0a28

Browse files
committed
[WIP] ssa: add memcpyopt pass to optimize load/store to memcpy
- Add TargetMachine and DataLayout methods to Program - Set data layout and target triple on Module creation - Run memcpyopt pass after IR generation (skip runtime packages) This optimization converts consecutive load/store operations on aggregate types to more efficient memcpy/memmove calls. Fixes goplus#1605
1 parent 0228ae2 commit c2d0a28

File tree

3 files changed

+24
-31
lines changed

3 files changed

+24
-31
lines changed

internal/build/build.go

Lines changed: 8 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"
@@ -1158,6 +1159,13 @@ func buildPkg(ctx *context, aPkg *aPackage, verbose bool) error {
11581159

11591160
ctx.cTransformer.TransformModule(ret.Path(), ret.Module())
11601161

1162+
// Run LLVM optimization passes (memcpyopt converts load/store to memcpy)
1163+
pbo := gollvm.NewPassBuilderOptions()
1164+
defer pbo.Dispose()
1165+
if err := ret.Module().RunPasses("memcpyopt", ctx.prog.TargetMachine(), pbo); err != nil {
1166+
return fmt.Errorf("run LLVM passes failed for %v: %v", pkgPath, err)
1167+
}
1168+
11611169
printCmds := ctx.shouldPrintCommands(verbose)
11621170
cgoLLFiles, cgoLdflags, err := buildCgo(ctx, aPkg, aPkg.Package.Syntax, externs, printCmds)
11631171
if err != nil {

ssa/package.go

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ type aProgram struct {
119119

120120
target *Target
121121
td llvm.TargetData
122-
// tm llvm.TargetMachine
122+
tm llvm.TargetMachine
123123
named map[string]Type
124124
fnnamed map[string]int
125125

@@ -247,7 +247,7 @@ func NewProgram(target *Target) Program {
247247
}
248248
}
249249
ctx := llvm.NewContext()
250-
td := target.targetData() // TODO(xsw): target config
250+
td, tm := target.targetDataAndMachine()
251251
/*
252252
arch := target.GOARCH
253253
if arch == "" {
@@ -261,7 +261,7 @@ func NewProgram(target *Target) Program {
261261
is32Bits := (td.PointerSize() == 4 || is32Bits(target.GOARCH))
262262
return &aProgram{
263263
ctx: ctx, gocvt: newGoTypes(),
264-
target: target, td: td, is32Bits: is32Bits,
264+
target: target, td: td, tm: tm, is32Bits: is32Bits,
265265
ptrSize: td.PointerSize(), named: make(map[string]Type), fnnamed: make(map[string]int),
266266
linkname: make(map[string]string), abiSymbol: make(map[string]Type),
267267
}
@@ -275,6 +275,14 @@ func (p Program) TargetData() llvm.TargetData {
275275
return p.td
276276
}
277277

278+
func (p Program) TargetMachine() llvm.TargetMachine {
279+
return p.tm
280+
}
281+
282+
func (p Program) DataLayout() string {
283+
return p.td.String()
284+
}
285+
278286
func (p Program) SetPatch(patchType func(types.Type) types.Type) {
279287
p.patchType = patchType
280288
}
@@ -408,11 +416,9 @@ func (p Program) tyComplex128() llvm.Type {
408416
// NewPackage creates a new package.
409417
func (p Program) NewPackage(name, pkgPath string) Package {
410418
mod := p.ctx.NewModule(pkgPath)
411-
// TODO(lijie): enable target output will check module override, but can't
412-
// pass the snapshot test, so disable it for now
413-
// if p.target.GOARCH != runtime.GOARCH && p.target.GOOS != runtime.GOOS {
414-
// mod.SetTarget(p.target.Spec().Triple)
415-
// }
419+
// Set data layout and target triple for LLVM optimization passes
420+
mod.SetDataLayout(p.DataLayout())
421+
mod.SetTarget(p.target.Spec().Triple)
416422

417423
// TODO(xsw): Finalize may cause panic, so comment it.
418424
// 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) targetDataAndMachine() (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)