github.com/go-asm/go@v1.21.1-0.20240213172139-40c5ead50c48/cmd/compile/ssa/zcse.go (about) 1 // Copyright 2016 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package ssa 6 7 import "github.com/go-asm/go/cmd/compile/types" 8 9 // zcse does an initial pass of common-subexpression elimination on the 10 // function for values with zero arguments to allow the more expensive cse 11 // to begin with a reduced number of values. Values are just relinked, 12 // nothing is deleted. A subsequent deadcode pass is required to actually 13 // remove duplicate expressions. 14 func zcse(f *Func) { 15 vals := make(map[vkey]*Value) 16 17 for _, b := range f.Blocks { 18 for i := 0; i < len(b.Values); i++ { 19 v := b.Values[i] 20 if opcodeTable[v.Op].argLen == 0 { 21 key := vkey{v.Op, keyFor(v), v.Aux, v.Type} 22 if vals[key] == nil { 23 vals[key] = v 24 if b != f.Entry { 25 // Move v to the entry block so it will dominate every block 26 // where we might use it. This prevents the need for any dominator 27 // calculations in this pass. 28 v.Block = f.Entry 29 f.Entry.Values = append(f.Entry.Values, v) 30 last := len(b.Values) - 1 31 b.Values[i] = b.Values[last] 32 b.Values[last] = nil 33 b.Values = b.Values[:last] 34 35 i-- // process b.Values[i] again 36 } 37 } 38 } 39 } 40 } 41 42 for _, b := range f.Blocks { 43 for _, v := range b.Values { 44 for i, a := range v.Args { 45 if opcodeTable[a.Op].argLen == 0 { 46 key := vkey{a.Op, keyFor(a), a.Aux, a.Type} 47 if rv, ok := vals[key]; ok { 48 v.SetArg(i, rv) 49 } 50 } 51 } 52 } 53 } 54 } 55 56 // vkey is a type used to uniquely identify a zero arg value. 57 type vkey struct { 58 op Op 59 ai int64 // aux int 60 ax Aux // aux 61 t *types.Type // type 62 } 63 64 // keyFor returns the AuxInt portion of a key structure uniquely identifying a 65 // zero arg value for the supported ops. 66 func keyFor(v *Value) int64 { 67 switch v.Op { 68 case OpConst64, OpConst64F, OpConst32F: 69 return v.AuxInt 70 case OpConst32: 71 return int64(int32(v.AuxInt)) 72 case OpConst16: 73 return int64(int16(v.AuxInt)) 74 case OpConst8, OpConstBool: 75 return int64(int8(v.AuxInt)) 76 default: 77 return v.AuxInt 78 } 79 }