Skip to content

Commit

Permalink
transform: don't escape append arguments if the return value doesn't
Browse files Browse the repository at this point in the history
  • Loading branch information
eliasnaur committed Nov 1, 2024
1 parent 0edeaf6 commit 3dc446d
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 3 deletions.
39 changes: 37 additions & 2 deletions transform/allocs.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,18 @@ func valueEscapesAt(value llvm.Value) llvm.Value {
return use
}
case llvm.Call:
if !hasFlag(use, value, "nocapture") {
return use
if hasFlag(use, value, "nocapture") {
break
}
// If built-in append function escapes its first argument if and
// only if the returned slice pointer escapes.
if fn := use.CalledValue(); !fn.IsAFunction().IsNil() && fn.Name() == "runtime.sliceAppend" {
if at := elemEscapesAt(use, 0); !at.IsNil() {
return at
}
break
}
return use
case llvm.ICmp:
// Comparing pointers don't let the pointer escape.
// This is often a compiler-inserted nil check.
Expand All @@ -170,6 +179,32 @@ func valueEscapesAt(value llvm.Value) llvm.Value {
return llvm.Value{}
}

// elemEscapesAt is like valueEscapesAt, but for an element of a tuple value.
func elemEscapesAt(value llvm.Value, elemIndex uint32) llvm.Value {
uses := getUses(value)
for _, use := range uses {
if use.IsAInstruction().IsNil() {
panic("expected instruction use")
}
switch use.InstructionOpcode() {
case llvm.ExtractValue:
for _, ind := range use.Indices() {
if ind == elemIndex {
if at := valueEscapesAt(use); !at.IsNil() {
return at
}
break
}
}
default:
if at := valueEscapesAt(use); !at.IsNil() {
return at
}
}
}
return llvm.Value{}
}

// logAlloc prints a message to stderr explaining why the given object had to be
// allocated on the heap.
func logAlloc(logger func(token.Position, string), allocCall llvm.Value, reason string) {
Expand Down
7 changes: 6 additions & 1 deletion transform/testdata/allocs2.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func main() {
s4 := make([]byte, 300) // OUT: object allocated on the heap: object size 300 exceeds maximum stack allocation size 256
readByteSlice(s4)

s5 := make([]int, 4) // OUT: object allocated on the heap: escapes at line 27
s5 := make([]int, 4)
_ = append(s5, 5)

s6 := make([]int, 3)
Expand Down Expand Up @@ -58,6 +58,11 @@ func main() {
var rbuf [5]rune
s = string(rbuf[:])
println(s)

sl := make([]rune, 4)
sl_1 := append(sl, 5)
sl_2 := append(sl_1, 5)
println(string(sl_2))
}

func derefInt(x *int) int {
Expand Down

0 comments on commit 3dc446d

Please sign in to comment.