cmd/compile: optimize unsafe.Slice generated code

We don't need a multiply when the element type is size 0 or 1.

The panic functions don't return, so we don't need any post-call
code (register restores, etc.).

Change-Id: I0dcea5df56d29d7be26554ddca966b3903c672e5
Reviewed-on: https://go-review.googlesource.com/c/go/+/419754
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Run-TryBot: Keith Randall <khr@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: Than McIntosh <thanm@google.com>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
Keith Randall 2022-07-27 09:56:38 -07:00
parent ebf182c82d
commit c2a9c55823
4 changed files with 172 additions and 1 deletions

View File

@ -165,6 +165,8 @@
// Convert x * 1 to x.
(Mul(8|16|32|64) (Const(8|16|32|64) [1]) x) => x
(Select0 (Mul(32|64)uover (Const(32|64) [1]) x)) => x
(Select1 (Mul(32|64)uover (Const(32|64) [1]) x)) => (ConstBool [false])
// Convert x * -1 to -x.
(Mul(8|16|32|64) (Const(8|16|32|64) [-1]) x) => (Neg(8|16|32|64) x)
@ -531,6 +533,8 @@
(Add(64|32|16|8) (Const(64|32|16|8) [0]) x) => x
(Sub(64|32|16|8) x x) => (Const(64|32|16|8) [0])
(Mul(64|32|16|8) (Const(64|32|16|8) [0]) _) => (Const(64|32|16|8) [0])
(Select0 (Mul(64|32)uover (Const(64|32) [0]) x)) => (Const(64|32) [0])
(Select1 (Mul(64|32)uover (Const(64|32) [0]) x)) => (ConstBool [false])
(Com(64|32|16|8) (Com(64|32|16|8) x)) => x
(Com(64|32|16|8) (Const(64|32|16|8) [c])) => (Const(64|32|16|8) [^c])

View File

@ -21260,6 +21260,82 @@ func rewriteValuegeneric_OpSelect0(v *Value) bool {
v.AddArg2(lo, y)
return true
}
// match: (Select0 (Mul32uover (Const32 [1]) x))
// result: x
for {
if v_0.Op != OpMul32uover {
break
}
_ = v_0.Args[1]
v_0_0 := v_0.Args[0]
v_0_1 := v_0.Args[1]
for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
if v_0_0.Op != OpConst32 || auxIntToInt32(v_0_0.AuxInt) != 1 {
continue
}
x := v_0_1
v.copyOf(x)
return true
}
break
}
// match: (Select0 (Mul64uover (Const64 [1]) x))
// result: x
for {
if v_0.Op != OpMul64uover {
break
}
_ = v_0.Args[1]
v_0_0 := v_0.Args[0]
v_0_1 := v_0.Args[1]
for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
if v_0_0.Op != OpConst64 || auxIntToInt64(v_0_0.AuxInt) != 1 {
continue
}
x := v_0_1
v.copyOf(x)
return true
}
break
}
// match: (Select0 (Mul64uover (Const64 [0]) x))
// result: (Const64 [0])
for {
if v_0.Op != OpMul64uover {
break
}
_ = v_0.Args[1]
v_0_0 := v_0.Args[0]
v_0_1 := v_0.Args[1]
for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
if v_0_0.Op != OpConst64 || auxIntToInt64(v_0_0.AuxInt) != 0 {
continue
}
v.reset(OpConst64)
v.AuxInt = int64ToAuxInt(0)
return true
}
break
}
// match: (Select0 (Mul32uover (Const32 [0]) x))
// result: (Const32 [0])
for {
if v_0.Op != OpMul32uover {
break
}
_ = v_0.Args[1]
v_0_0 := v_0.Args[0]
v_0_1 := v_0.Args[1]
for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
if v_0_0.Op != OpConst32 || auxIntToInt32(v_0_0.AuxInt) != 0 {
continue
}
v.reset(OpConst32)
v.AuxInt = int32ToAuxInt(0)
return true
}
break
}
return false
}
func rewriteValuegeneric_OpSelect1(v *Value) bool {
@ -21280,6 +21356,82 @@ func rewriteValuegeneric_OpSelect1(v *Value) bool {
v.AddArg2(lo, y)
return true
}
// match: (Select1 (Mul32uover (Const32 [1]) x))
// result: (ConstBool [false])
for {
if v_0.Op != OpMul32uover {
break
}
_ = v_0.Args[1]
v_0_0 := v_0.Args[0]
v_0_1 := v_0.Args[1]
for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
if v_0_0.Op != OpConst32 || auxIntToInt32(v_0_0.AuxInt) != 1 {
continue
}
v.reset(OpConstBool)
v.AuxInt = boolToAuxInt(false)
return true
}
break
}
// match: (Select1 (Mul64uover (Const64 [1]) x))
// result: (ConstBool [false])
for {
if v_0.Op != OpMul64uover {
break
}
_ = v_0.Args[1]
v_0_0 := v_0.Args[0]
v_0_1 := v_0.Args[1]
for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
if v_0_0.Op != OpConst64 || auxIntToInt64(v_0_0.AuxInt) != 1 {
continue
}
v.reset(OpConstBool)
v.AuxInt = boolToAuxInt(false)
return true
}
break
}
// match: (Select1 (Mul64uover (Const64 [0]) x))
// result: (ConstBool [false])
for {
if v_0.Op != OpMul64uover {
break
}
_ = v_0.Args[1]
v_0_0 := v_0.Args[0]
v_0_1 := v_0.Args[1]
for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
if v_0_0.Op != OpConst64 || auxIntToInt64(v_0_0.AuxInt) != 0 {
continue
}
v.reset(OpConstBool)
v.AuxInt = boolToAuxInt(false)
return true
}
break
}
// match: (Select1 (Mul32uover (Const32 [0]) x))
// result: (ConstBool [false])
for {
if v_0.Op != OpMul32uover {
break
}
_ = v_0.Args[1]
v_0_0 := v_0.Args[0]
v_0_1 := v_0.Args[1]
for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
if v_0_0.Op != OpConst32 || auxIntToInt32(v_0_0.AuxInt) != 0 {
continue
}
v.reset(OpConstBool)
v.AuxInt = boolToAuxInt(false)
return true
}
break
}
return false
}
func rewriteValuegeneric_OpSelectN(v *Value) bool {

View File

@ -1421,7 +1421,7 @@ func (s *state) stmt(n ir.Node) {
s.callResult(n, callNormal)
if n.Op() == ir.OCALLFUNC && n.X.Op() == ir.ONAME && n.X.(*ir.Name).Class == ir.PFUNC {
if fn := n.X.Sym().Name; base.Flag.CompilingRuntime && fn == "throw" ||
n.X.Sym().Pkg == ir.Pkgs.Runtime && (fn == "throwinit" || fn == "gopanic" || fn == "panicwrap" || fn == "block" || fn == "panicmakeslicelen" || fn == "panicmakeslicecap") {
n.X.Sym().Pkg == ir.Pkgs.Runtime && (fn == "throwinit" || fn == "gopanic" || fn == "panicwrap" || fn == "block" || fn == "panicmakeslicelen" || fn == "panicmakeslicecap" || fn == "panicunsafeslicelen" || fn == "panicunsafeslicenilptr") {
m := s.mem()
b := s.endBlock()
b.Kind = ssa.BlockExit

View File

@ -6,6 +6,8 @@
package codegen
import "unsafe"
// This file contains code generation tests related to the handling of
// slice types.
@ -368,3 +370,16 @@ func SliceWithSubtractBound(a []int, b int) []int {
// ppc64:"SUBC",-"NEG"
return a[(3 - b):]
}
// --------------------------------------- //
// Code generation for unsafe.Slice //
// --------------------------------------- //
func Slice1(p *byte, i int) []byte {
// amd64:-"MULQ"
return unsafe.Slice(p, i)
}
func Slice0(p *struct{}, i int) []struct{} {
// amd64:-"MULQ"
return unsafe.Slice(p, i)
}