From adb467ffd2d82b796de12bdd8effa2cfefe01f29 Mon Sep 17 00:00:00 2001 From: Egon Elbre Date: Sat, 2 Jan 2021 16:28:11 +0200 Subject: [PATCH] cmd/compile: reduce inline cost of OCONVOP OCONVOP doesn't have effect in the compiled code so, it can be safely excluded from inline cost calculation. Also make sequence ODEREF OCONVNOP* OADDR cost 1. This is rather common conversion, such as *(*uint32)(unsafe.Pointer(&x)). Fixes #42788 Change-Id: I5001f7e89d985c198b6405694cdd5b819cf3f47a Reviewed-on: https://go-review.googlesource.com/c/go/+/281232 Reviewed-by: Keith Randall Run-TryBot: Keith Randall TryBot-Result: Go Bot Trust: Elias Naur --- src/cmd/compile/internal/inline/inl.go | 16 ++++++++++++++++ test/inline.go | 23 +++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/src/cmd/compile/internal/inline/inl.go b/src/cmd/compile/internal/inline/inl.go index 7d70fca6c9..0e57c17667 100644 --- a/src/cmd/compile/internal/inline/inl.go +++ b/src/cmd/compile/internal/inline/inl.go @@ -384,6 +384,22 @@ func (v *hairyVisitor) doNode(n ir.Node) bool { case ir.OAPPEND: v.budget -= inlineExtraAppendCost + case ir.ODEREF: + // *(*X)(unsafe.Pointer(&x)) is low-cost + n := n.(*ir.StarExpr) + + ptr := n.X + for ptr.Op() == ir.OCONVNOP { + ptr = ptr.(*ir.ConvExpr).X + } + if ptr.Op() == ir.OADDR { + v.budget += 1 // undo half of default cost of ir.ODEREF+ir.OADDR + } + + case ir.OCONVNOP: + // This doesn't produce code, but the children might. + v.budget++ // undo default cost + case ir.ODCLCONST, ir.OFALL: // These nodes don't produce code; omit from inlining budget. return false diff --git a/test/inline.go b/test/inline.go index 37965c0d9d..a79f5589fb 100644 --- a/test/inline.go +++ b/test/inline.go @@ -10,6 +10,7 @@ package foo import ( + "math" "runtime" "unsafe" ) @@ -262,3 +263,25 @@ func gd2() int { // ERROR "can inline gd2" func gd3() func() { // ERROR "can inline gd3" return ii } + +// Issue #42788 - ensure ODEREF OCONVNOP* OADDR is low cost. +func EncodeQuad(d []uint32, x [6]float32) { // ERROR "can inline EncodeQuad" "d does not escape" + _ = d[:6] + d[0] = math.Float32bits(x[0]) // ERROR "inlining call to math.Float32bits" + d[1] = math.Float32bits(x[1]) // ERROR "inlining call to math.Float32bits" + d[2] = math.Float32bits(x[2]) // ERROR "inlining call to math.Float32bits" + d[3] = math.Float32bits(x[3]) // ERROR "inlining call to math.Float32bits" + d[4] = math.Float32bits(x[4]) // ERROR "inlining call to math.Float32bits" + d[5] = math.Float32bits(x[5]) // ERROR "inlining call to math.Float32bits" +} + +// Ensure OCONVNOP is zero cost. +func Conv(v uint64) uint64 { // ERROR "can inline Conv" + return conv2(conv2(conv2(v))) // ERROR "inlining call to (conv1|conv2)" +} +func conv2(v uint64) uint64 { // ERROR "can inline conv2" + return conv1(conv1(conv1(conv1(v)))) // ERROR "inlining call to conv1" +} +func conv1(v uint64) uint64 { // ERROR "can inline conv1" + return uint64(uint64(uint64(uint64(uint64(uint64(uint64(uint64(uint64(uint64(uint64(v))))))))))) +}