| // 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. |
| |
| // values are specified using the following format: |
| // (op <type> [auxint] {aux} arg0 arg1 ...) |
| // the type and aux fields are optional |
| // on the matching side |
| // - the type, aux, and auxint fields must match if they are specified. |
| // on the generated side |
| // - the type of the top-level expression is the same as the one on the left-hand side. |
| // - the type of any subexpressions must be specified explicitly. |
| // - auxint will be 0 if not specified. |
| // - aux will be nil if not specified. |
| |
| // blocks are specified using the following format: |
| // (kind controlvalue succ0 succ1 ...) |
| // controlvalue must be "nil" or a value expression |
| // succ* fields must be variables |
| // For now, the generated successors must be a permutation of the matched successors. |
| |
| // constant folding |
| (Add64 (Const64 [c]) (Const64 [d])) -> (Const64 [c+d]) |
| (AddPtr (ConstPtr [c]) (ConstPtr [d])) -> (ConstPtr [c+d]) |
| (Mul64 (Const64 [c]) (Const64 [d])) -> (Const64 [c*d]) |
| (MulPtr (ConstPtr [c]) (ConstPtr [d])) -> (ConstPtr [c*d]) |
| (IsInBounds (ConstPtr [c]) (ConstPtr [d])) -> (ConstPtr {inBounds(c,d)}) |
| (Eq64 x x) -> (ConstBool {true}) |
| (Eq32 x x) -> (ConstBool {true}) |
| (Eq16 x x) -> (ConstBool {true}) |
| (Eq8 x x) -> (ConstBool {true}) |
| (Neq64 x x) -> (ConstBool {false}) |
| (Neq32 x x) -> (ConstBool {false}) |
| (Neq16 x x) -> (ConstBool {false}) |
| (Neq8 x x) -> (ConstBool {false}) |
| |
| (Com8 (Com8 x)) -> x |
| (Com16 (Com16 x)) -> x |
| (Com32 (Com32 x)) -> x |
| (Com64 (Com64 x)) -> x |
| |
| // tear apart slices |
| // TODO: anything that generates a slice needs to go in here. |
| (SlicePtr (Load ptr mem)) -> (Load ptr mem) |
| (SliceLen (Load ptr mem)) -> (Load (AddPtr <ptr.Type> ptr (ConstPtr <config.Frontend().TypeUintptr()> [config.PtrSize])) mem) |
| (SliceCap (Load ptr mem)) -> (Load (AddPtr <ptr.Type> ptr (ConstPtr <config.Frontend().TypeUintptr()> [config.PtrSize*2])) mem) |
| |
| // slice and interface comparisons |
| // the frontend ensures that we can only compare against nil |
| // start by putting nil on the right to simplify the other rules |
| (EqFat x y) && x.Op == OpConstNil && y.Op != OpConstNil -> (EqFat y x) |
| (NeqFat x y) && x.Op == OpConstNil && y.Op != OpConstNil -> (NeqFat y x) |
| // it suffices to check the first word (backing array for slices, dynamic type for interfaces) |
| (EqFat (Load ptr mem) (ConstNil)) -> (EqPtr (Load <config.Frontend().TypeUintptr()> ptr mem) (ConstPtr <config.Frontend().TypeUintptr()> [0])) |
| (NeqFat (Load ptr mem) (ConstNil)) -> (NeqPtr (Load <config.Frontend().TypeUintptr()> ptr mem) (ConstPtr <config.Frontend().TypeUintptr()> [0])) |
| |
| // indexing operations |
| // Note: bounds check has already been done |
| (ArrayIndex (Load ptr mem) idx) -> (Load (PtrIndex <v.Type.PtrTo()> ptr idx) mem) |
| (PtrIndex <t> ptr idx) -> (AddPtr ptr (MulPtr <config.Frontend().TypeUintptr()> idx (ConstPtr <config.Frontend().TypeUintptr()> [t.Elem().Size()]))) |
| (StructSelect [idx] (Load ptr mem)) -> (Load (OffPtr <v.Type.PtrTo()> [idx] ptr) mem) |
| |
| // big-object moves |
| // TODO: fix size |
| (Store dst (Load <t> src mem) mem) && t.Size() > 8 -> (Move [t.Size()] dst src mem) |
| |
| // string ops |
| (ConstString {s}) -> (StringMake (Addr <config.Frontend().TypeBytePtr()> {config.fe.StringData(s.(string))} (SB <config.Frontend().TypeUintptr()>)) (ConstPtr <config.Frontend().TypeUintptr()> [int64(len(s.(string)))])) |
| (Load <t> ptr mem) && t.IsString() -> (StringMake (Load <config.Frontend().TypeBytePtr()> ptr mem) (Load <config.Frontend().TypeUintptr()> (OffPtr <config.Frontend().TypeBytePtr()> [config.PtrSize] ptr) mem)) |
| (StringPtr (StringMake ptr _)) -> ptr |
| (StringLen (StringMake _ len)) -> len |
| (Store dst str mem) && str.Type.IsString() -> (Store (OffPtr <config.Frontend().TypeBytePtr()> [config.PtrSize] dst) (StringLen <config.Frontend().TypeUintptr()> str) (Store <TypeMem> dst (StringPtr <config.Frontend().TypeBytePtr()> str) mem)) |
| |
| (If (IsNonNil (GetG)) yes no) -> (Plain nil yes) |
| |
| (If (Not cond) yes no) -> (If cond no yes) |
| (If (ConstBool {c}) yes no) && c.(bool) -> (Plain nil yes) |
| (If (ConstBool {c}) yes no) && !c.(bool) -> (Plain nil no) |