Skip to content

Commit a62459f

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 goplus#1605
1 parent 0228ae2 commit a62459f

File tree

3 files changed

+27
-28
lines changed

3 files changed

+27
-28
lines changed

internal/build/build.go

Lines changed: 12 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,17 @@ 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+
// Set data layout and target triple before running passes
1164+
mod := ret.Module()
1165+
mod.SetDataLayout(ctx.prog.DataLayout())
1166+
mod.SetTarget(ctx.prog.Target().Spec().Triple)
1167+
pbo := gollvm.NewPassBuilderOptions()
1168+
defer pbo.Dispose()
1169+
if err := mod.RunPasses("memcpyopt", ctx.prog.TargetMachine(), pbo); err != nil {
1170+
return fmt.Errorf("run LLVM passes failed for %v: %v", pkgPath, err)
1171+
}
1172+
11611173
printCmds := ctx.shouldPrintCommands(verbose)
11621174
cgoLLFiles, cgoLdflags, err := buildCgo(ctx, aPkg, aPkg.Package.Syntax, externs, printCmds)
11631175
if err != nil {

ssa/package.go

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,9 @@ type aProgram struct {
117117
py *types.Package
118118
pyget func() *types.Package
119119

120-
target *Target
121-
td llvm.TargetData
122-
// tm llvm.TargetMachine
120+
target *Target
121+
td llvm.TargetData
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.targetInfo()
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
}

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)