Skip to content

Commit 5d6ef59

Browse files
[Feat] Enable LTO
Signed-off-by: ZhouGuangyuan <zhouguangyuan.xian@gmail.com>
1 parent b2aa3a2 commit 5d6ef59

File tree

8 files changed

+69
-4
lines changed

8 files changed

+69
-4
lines changed

_demo/embed/targetsbuild/build.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ case "$test_dir" in
111111
"riscv32"
112112
"riscv64"
113113
"rp2040"
114+
"nintendoswitch" # undefined symbol under lto, should not work when no-lto
114115
)
115116
;;
116117
defer)

cl/_testdata/cpkg/out.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ source_filename = "github.com/goplus/llgo/cl/_testdata/cpkg"
44
@llvm.used = appending constant [2 x ptr] [ptr @Double, ptr @add], section "llvm.metadata"
55
@"github.com/goplus/llgo/cl/_testdata/cpkg.init$guard" = global i1 false, align 1
66

7-
define double @Double(double %0) {
7+
define dllexport double @Double(double %0) {
88
_llgo_0:
99
%1 = fmul double 2.000000e+00, %0
1010
ret double %1
1111
}
1212

13-
define i64 @add(i64 %0, i64 %1) {
13+
define dllexport i64 @add(i64 %0, i64 %1) {
1414
_llgo_0:
1515
%2 = call i64 @"github.com/goplus/llgo/cl/_testdata/cpkg.add"(i64 %0, i64 %1)
1616
ret i64 %2

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
github.com/creack/goselect v0.1.2 h1:2DNy14+JPjRBgPzAd1thbQp4BSIihxcBf0IXhQXDRa0=
22
github.com/creack/goselect v0.1.2/go.mod h1:a/NhLweNvqIYMuxcMOuWY516Cimucms3DglDzQP3hKY=
3+
github.com/creack/goselect v0.1.3 h1:MaGNMclRo7P2Jl21hBpR1Cn33ITSbKP6E49RtfblLKc=
4+
github.com/creack/goselect v0.1.3/go.mod h1:a/NhLweNvqIYMuxcMOuWY516Cimucms3DglDzQP3hKY=
35
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
46
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
57
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=

internal/build/plan9asm.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,10 @@ func filterPlan9AsmFuncs(pkgPath, goos, goarch string, funcs []plan9asm.Func, re
254254
if pkgPath == "syscall" && goos == "linux" && (goarch == "arm64" || goarch == "amd64") && strings.HasSuffix(resolved, "rawVforkSyscall") {
255255
continue
256256
}
257+
if pkgPath == "syscall" && goos == "darwin" && (goarch == "arm64" || goarch == "amd64") &&
258+
(strings.HasSuffix(resolved, "RawSyscall") || strings.HasSuffix(resolved, "RawSyscall6")) {
259+
continue
260+
}
257261
keep = append(keep, fn)
258262
}
259263
return keep

internal/crosscompile/crosscompile.go

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -225,8 +225,9 @@ func use(goos, goarch string, wasiThreads, forceEspClang bool) (export Export, e
225225
"-Wl,--error-limit=0",
226226
"-fuse-ld=lld",
227227
// Enable ICF (Identical Code Folding) to reduce binary size
228-
"-Xlinker",
229-
"--icf=safe",
228+
"-Wl,--icf=safe",
229+
// Enable ThinLTO, Using default lto kind(thinlto).
230+
"-Wl,--lto-O0",
230231
}
231232
if clangRoot != "" {
232233
clangLib := filepath.Join(clangRoot, "lib")
@@ -249,6 +250,7 @@ func use(goos, goarch string, wasiThreads, forceEspClang bool) (export Export, e
249250
export.CCFLAGS = []string{
250251
"-Qunused-arguments",
251252
"-Wno-unused-command-line-argument",
253+
"-flto=thin",
252254
}
253255

254256
// Add sysroot for macOS only
@@ -499,6 +501,13 @@ func UseTarget(targetName string) (export Export, err error) {
499501
expandedCFlags := env.ExpandEnvSlice(config.CFlags, envs)
500502
cflags = append(cflags, expandedCFlags...)
501503

504+
if config.Linker == "ld.lld" {
505+
// Enable ThinLTO, Using default lto kind(thinlto).
506+
ldflags = append(ldflags, "--lto-O0")
507+
cflags = append(cflags, "-flto=thin")
508+
ccflags = append(ccflags, "-flto=thin")
509+
}
510+
502511
// The following parameters are inspired by tinygo/builder/library.go
503512
// Handle CPU configuration
504513
if cpu != "" {
@@ -545,6 +554,8 @@ func UseTarget(targetName string) (export Export, err error) {
545554
ccflags = append(ccflags, "-fforce-enable-int128")
546555
case "riscv64":
547556
ccflags = append(ccflags, "-march=rv64gc")
557+
// codegen option should be added to ldflags for lto
558+
ldflags = append(ldflags, "-mllvm", "-march=rv64gc")
548559
case "mips":
549560
ccflags = append(ccflags, "-fno-pic")
550561
}
@@ -574,9 +585,13 @@ func UseTarget(targetName string) (export Export, err error) {
574585
// Handle code generation configuration
575586
if config.CodeModel != "" {
576587
ccflags = append(ccflags, "-mcmodel="+config.CodeModel)
588+
// codegen option should be added to ldflags for lto
589+
ldflags = append(ldflags, "-mllvm", "-code-model="+config.CodeModel)
577590
}
578591
if config.TargetABI != "" {
579592
ccflags = append(ccflags, "-mabi="+config.TargetABI)
593+
// codegen option should be added to ldflags for lto
594+
ldflags = append(ldflags, "-mllvm", "-target-abi="+config.TargetABI)
580595
}
581596
if config.RelocationModel != "" {
582597
switch config.RelocationModel {

ssa/datastruct.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,10 @@ func (b Builder) Slice(x, low, high, max Expr) (ret Expr) {
342342
if lowIsNil {
343343
low = prog.IntVal(0, prog.Int())
344344
}
345+
low = b.fitIntSize(low)
346+
if !high.IsNil() {
347+
high = b.fitIntSize(high)
348+
}
345349
switch t := x.raw.Type.Underlying().(type) {
346350
case *types.Basic:
347351
if t.Kind() != types.String {
@@ -382,6 +386,7 @@ func (b Builder) Slice(x, low, high, max Expr) (ret Expr) {
382386
if max.IsNil() {
383387
max = nCap
384388
}
389+
max = b.fitIntSize(max)
385390
ret.impl = b.InlineCall(b.Pkg.rtFunc("NewSlice3"), base, nEltSize, nCap, low, high, max).impl
386391
return
387392
}

ssa/decl.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,10 @@ func (p Package) NewFuncEx(name string, sig *types.Signature, bg Background, has
211211
if instantiated {
212212
fn.SetLinkage(llvm.LinkOnceAnyLinkage)
213213
}
214+
if p.Prog.requiresFramePointer() {
215+
attr := p.mod.Context().CreateStringAttribute("frame-pointer", "all")
216+
fn.AddFunctionAttr(attr)
217+
}
214218
if p.isExportName(name) {
215219
p.markLLVMUsed(fn)
216220
}
@@ -345,6 +349,10 @@ func (p Function) Block(idx int) BasicBlock {
345349
return p.blks[idx]
346350
}
347351

352+
func (p Program) requiresFramePointer() bool {
353+
return p.target != nil && p.target.GOOS == "darwin" && p.target.GOARCH == "arm64"
354+
}
355+
348356
// SetRecover sets the recover block for the function.
349357
func (p Function) SetRecover(blk BasicBlock) {
350358
p.recov = blk

ssa/ssa_test.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,36 @@ func TestNewFuncExLLVMUsed(t *testing.T) {
133133
}
134134
}
135135

136+
func TestNewFuncExFramePointerAttrOnDarwinArm64(t *testing.T) {
137+
prog := NewProgram(&Target{GOOS: "darwin", GOARCH: "arm64"})
138+
pkg := prog.NewPackage("main", "main")
139+
sig := types.NewSignatureType(nil, nil, nil, nil, nil, false)
140+
141+
fn := pkg.NewFunc("Foo", sig, InGo)
142+
attr := fn.impl.GetStringAttributeAtIndex(-1, "frame-pointer")
143+
if attr.IsNil() {
144+
t.Fatal("missing frame-pointer function attribute")
145+
}
146+
if got := pkg.String(); !strings.Contains(got, `"frame-pointer"="all"`) {
147+
t.Fatalf("module missing frame-pointer attribute:\n%s", got)
148+
}
149+
}
150+
151+
func TestNewFuncExFramePointerAttrNotForcedOnOtherTargets(t *testing.T) {
152+
prog := NewProgram(&Target{GOOS: "linux", GOARCH: "amd64"})
153+
pkg := prog.NewPackage("main", "main")
154+
sig := types.NewSignatureType(nil, nil, nil, nil, nil, false)
155+
156+
fn := pkg.NewFunc("Foo", sig, InGo)
157+
attr := fn.impl.GetStringAttributeAtIndex(-1, "frame-pointer")
158+
if !attr.IsNil() {
159+
t.Fatal("unexpected frame-pointer function attribute")
160+
}
161+
if got := pkg.String(); strings.Contains(got, `"frame-pointer"="all"`) {
162+
t.Fatalf("unexpected frame-pointer attribute in module:\n%s", got)
163+
}
164+
}
165+
136166
func TestSetBlock(t *testing.T) {
137167
defer func() {
138168
if r := recover(); r == nil {

0 commit comments

Comments
 (0)