* Move lowering into a separate pass.
* SliceLen/SliceCap is now available to various intermediate passes
which use useful for bounds checking.
* Add a second opt pass to handle the new opportunities
Decreases the code size of binaries in pkg/tool/linux_amd64
by ~45K.
Updates #14564 #14606
Change-Id: I5b2bd6202181c50623a3585fbf15c0d6db6d4685
Reviewed-on: https://go-review.googlesource.com/20172
Run-TryBot: Alexandru Moșoi <alexandru@mosoi.ro>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
{name: "phiopt", fn: phiopt},
{name: "nilcheckelim", fn: nilcheckelim},
{name: "prove", fn: prove},
+ {name: "dec", fn: dec, required: true},
+ {name: "late opt", fn: opt}, // TODO: split required rules and optimizing rules
{name: "generic deadcode", fn: deadcode},
{name: "fuse", fn: fuse},
{name: "dse", fn: dse},
--- /dev/null
+(StringPtr (StringMake ptr _)) -> ptr
+(StringLen (StringMake _ len)) -> len
+
+(SlicePtr (SliceMake ptr _ _ )) -> ptr
+(SliceLen (SliceMake _ len _)) -> len
+(SliceCap (SliceMake _ _ cap)) -> cap
--- /dev/null
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+var decOps = []opData{}
+
+var decBlocks = []blockData{}
+
+func init() {
+ archs = append(archs, arch{"dec", decOps, decBlocks, nil})
+}
(Store [8] dst real mem))
// string ops
-(StringPtr (StringMake ptr _)) -> ptr
-(StringLen (StringMake _ len)) -> len
+(StringPtr (StringMake (Const64 <t> [c]) _)) -> (Const64 <t> [c])
+(StringLen (StringMake _ (Const64 <t> [c]))) -> (Const64 <t> [c])
(ConstString {s}) && config.PtrSize == 4 && s.(string) == "" ->
(StringMake (ConstNil) (Const32 <config.fe.TypeInt()> [0]))
(ConstString {s}) && config.PtrSize == 8 && s.(string) == "" ->
(Store [config.PtrSize] dst ptr mem))
// slice ops
-(SlicePtr (SliceMake ptr _ _ )) -> ptr
-(SliceLen (SliceMake _ len _)) -> len
-(SliceCap (SliceMake _ _ cap)) -> cap
+(SlicePtr (SliceMake (Const64 <t> [c]) _ _)) -> (Const64 <t> [c])
+(SliceLen (SliceMake _ (Const64 <t> [c]) _)) -> (Const64 <t> [c])
+(SliceCap (SliceMake _ _ (Const64 <t> [c]))) -> (Const64 <t> [c])
(ConstSlice) && config.PtrSize == 4 ->
(SliceMake
(ConstNil <config.fe.TypeBytePtr()>)
func opt(f *Func) {
applyRewrite(f, rewriteBlockgeneric, rewriteValuegeneric)
}
+
+func dec(f *Func) {
+ applyRewrite(f, rewriteBlockdec, rewriteValuedec)
+}
--- /dev/null
+// autogenerated from gen/dec.rules: do not edit!
+// generated with: cd gen; go run *.go
+
+package ssa
+
+import "math"
+
+var _ = math.MinInt8 // in case not otherwise used
+func rewriteValuedec(v *Value, config *Config) bool {
+ switch v.Op {
+ case OpSliceCap:
+ return rewriteValuedec_OpSliceCap(v, config)
+ case OpSliceLen:
+ return rewriteValuedec_OpSliceLen(v, config)
+ case OpSlicePtr:
+ return rewriteValuedec_OpSlicePtr(v, config)
+ case OpStringLen:
+ return rewriteValuedec_OpStringLen(v, config)
+ case OpStringPtr:
+ return rewriteValuedec_OpStringPtr(v, config)
+ }
+ return false
+}
+func rewriteValuedec_OpSliceCap(v *Value, config *Config) bool {
+ b := v.Block
+ _ = b
+ // match: (SliceCap (SliceMake _ _ cap))
+ // cond:
+ // result: cap
+ for {
+ if v.Args[0].Op != OpSliceMake {
+ break
+ }
+ cap := v.Args[0].Args[2]
+ v.reset(OpCopy)
+ v.Type = cap.Type
+ v.AddArg(cap)
+ return true
+ }
+ return false
+}
+func rewriteValuedec_OpSliceLen(v *Value, config *Config) bool {
+ b := v.Block
+ _ = b
+ // match: (SliceLen (SliceMake _ len _))
+ // cond:
+ // result: len
+ for {
+ if v.Args[0].Op != OpSliceMake {
+ break
+ }
+ len := v.Args[0].Args[1]
+ v.reset(OpCopy)
+ v.Type = len.Type
+ v.AddArg(len)
+ return true
+ }
+ return false
+}
+func rewriteValuedec_OpSlicePtr(v *Value, config *Config) bool {
+ b := v.Block
+ _ = b
+ // match: (SlicePtr (SliceMake ptr _ _ ))
+ // cond:
+ // result: ptr
+ for {
+ if v.Args[0].Op != OpSliceMake {
+ break
+ }
+ ptr := v.Args[0].Args[0]
+ v.reset(OpCopy)
+ v.Type = ptr.Type
+ v.AddArg(ptr)
+ return true
+ }
+ return false
+}
+func rewriteValuedec_OpStringLen(v *Value, config *Config) bool {
+ b := v.Block
+ _ = b
+ // match: (StringLen (StringMake _ len))
+ // cond:
+ // result: len
+ for {
+ if v.Args[0].Op != OpStringMake {
+ break
+ }
+ len := v.Args[0].Args[1]
+ v.reset(OpCopy)
+ v.Type = len.Type
+ v.AddArg(len)
+ return true
+ }
+ return false
+}
+func rewriteValuedec_OpStringPtr(v *Value, config *Config) bool {
+ b := v.Block
+ _ = b
+ // match: (StringPtr (StringMake ptr _))
+ // cond:
+ // result: ptr
+ for {
+ if v.Args[0].Op != OpStringMake {
+ break
+ }
+ ptr := v.Args[0].Args[0]
+ v.reset(OpCopy)
+ v.Type = ptr.Type
+ v.AddArg(ptr)
+ return true
+ }
+ return false
+}
+func rewriteBlockdec(b *Block) bool {
+ switch b.Kind {
+ }
+ return false
+}
func rewriteValuegeneric_OpSliceCap(v *Value, config *Config) bool {
b := v.Block
_ = b
- // match: (SliceCap (SliceMake _ _ cap))
+ // match: (SliceCap (SliceMake _ _ (Const64 <t> [c])))
// cond:
- // result: cap
+ // result: (Const64 <t> [c])
for {
if v.Args[0].Op != OpSliceMake {
break
}
- cap := v.Args[0].Args[2]
- v.reset(OpCopy)
- v.Type = cap.Type
- v.AddArg(cap)
+ if v.Args[0].Args[2].Op != OpConst64 {
+ break
+ }
+ t := v.Args[0].Args[2].Type
+ c := v.Args[0].Args[2].AuxInt
+ v.reset(OpConst64)
+ v.Type = t
+ v.AuxInt = c
return true
}
return false
func rewriteValuegeneric_OpSliceLen(v *Value, config *Config) bool {
b := v.Block
_ = b
- // match: (SliceLen (SliceMake _ len _))
+ // match: (SliceLen (SliceMake _ (Const64 <t> [c]) _))
// cond:
- // result: len
+ // result: (Const64 <t> [c])
for {
if v.Args[0].Op != OpSliceMake {
break
}
- len := v.Args[0].Args[1]
- v.reset(OpCopy)
- v.Type = len.Type
- v.AddArg(len)
+ if v.Args[0].Args[1].Op != OpConst64 {
+ break
+ }
+ t := v.Args[0].Args[1].Type
+ c := v.Args[0].Args[1].AuxInt
+ v.reset(OpConst64)
+ v.Type = t
+ v.AuxInt = c
return true
}
return false
func rewriteValuegeneric_OpSlicePtr(v *Value, config *Config) bool {
b := v.Block
_ = b
- // match: (SlicePtr (SliceMake ptr _ _ ))
+ // match: (SlicePtr (SliceMake (Const64 <t> [c]) _ _))
// cond:
- // result: ptr
+ // result: (Const64 <t> [c])
for {
if v.Args[0].Op != OpSliceMake {
break
}
- ptr := v.Args[0].Args[0]
- v.reset(OpCopy)
- v.Type = ptr.Type
- v.AddArg(ptr)
+ if v.Args[0].Args[0].Op != OpConst64 {
+ break
+ }
+ t := v.Args[0].Args[0].Type
+ c := v.Args[0].Args[0].AuxInt
+ v.reset(OpConst64)
+ v.Type = t
+ v.AuxInt = c
return true
}
return false
func rewriteValuegeneric_OpStringLen(v *Value, config *Config) bool {
b := v.Block
_ = b
- // match: (StringLen (StringMake _ len))
+ // match: (StringLen (StringMake _ (Const64 <t> [c])))
// cond:
- // result: len
+ // result: (Const64 <t> [c])
for {
if v.Args[0].Op != OpStringMake {
break
}
- len := v.Args[0].Args[1]
- v.reset(OpCopy)
- v.Type = len.Type
- v.AddArg(len)
+ if v.Args[0].Args[1].Op != OpConst64 {
+ break
+ }
+ t := v.Args[0].Args[1].Type
+ c := v.Args[0].Args[1].AuxInt
+ v.reset(OpConst64)
+ v.Type = t
+ v.AuxInt = c
return true
}
return false
func rewriteValuegeneric_OpStringPtr(v *Value, config *Config) bool {
b := v.Block
_ = b
- // match: (StringPtr (StringMake ptr _))
+ // match: (StringPtr (StringMake (Const64 <t> [c]) _))
// cond:
- // result: ptr
+ // result: (Const64 <t> [c])
for {
if v.Args[0].Op != OpStringMake {
break
}
- ptr := v.Args[0].Args[0]
- v.reset(OpCopy)
- v.Type = ptr.Type
- v.AddArg(ptr)
+ if v.Args[0].Args[0].Op != OpConst64 {
+ break
+ }
+ t := v.Args[0].Args[0].Type
+ c := v.Args[0].Args[0].AuxInt
+ v.reset(OpConst64)
+ v.Type = t
+ v.AuxInt = c
return true
}
return false