| // 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 (Const32 [c]) (Const32 [d])) -> (ConstBool [b2i(inBounds32(c,d))]) |
| (IsInBounds (Const64 [c]) (Const64 [d])) -> (ConstBool [b2i(inBounds64(c,d))]) |
| (IsInBounds (ConstPtr [c]) (ConstPtr [d])) && config.PtrSize == 4 -> (ConstBool [b2i(inBounds32(c,d))]) |
| (IsInBounds (ConstPtr [c]) (ConstPtr [d])) && config.PtrSize == 8 -> (ConstBool [b2i(inBounds64(c,d))]) |
| (Eq64 x x) -> (ConstBool [1]) |
| (Eq32 x x) -> (ConstBool [1]) |
| (Eq16 x x) -> (ConstBool [1]) |
| (Eq8 x x) -> (ConstBool [1]) |
| (Neq64 x x) -> (ConstBool [0]) |
| (Neq32 x x) -> (ConstBool [0]) |
| (Neq16 x x) -> (ConstBool [0]) |
| (Neq8 x x) -> (ConstBool [0]) |
| |
| // constant comparisons |
| (Eq64 (Const64 [c]) (Const64 [d])) -> (ConstBool [b2i(int64(c) == int64(d))]) |
| (Eq32 (Const32 [c]) (Const32 [d])) -> (ConstBool [b2i(int32(c) == int32(d))]) |
| (Eq16 (Const16 [c]) (Const16 [d])) -> (ConstBool [b2i(int16(c) == int16(d))]) |
| (Eq8 (Const8 [c]) (Const8 [d])) -> (ConstBool [b2i(int8(c) == int8(d))]) |
| |
| (Neq64 (Const64 [c]) (Const64 [d])) -> (ConstBool [b2i(int64(c) != int64(d))]) |
| (Neq32 (Const32 [c]) (Const32 [d])) -> (ConstBool [b2i(int32(c) != int32(d))]) |
| (Neq16 (Const16 [c]) (Const16 [d])) -> (ConstBool [b2i(int16(c) != int16(d))]) |
| (Neq8 (Const8 [c]) (Const8 [d])) -> (ConstBool [b2i(int8(c) != int8(d))]) |
| |
| (Greater64 (Const64 [c]) (Const64 [d])) -> (ConstBool [b2i(int64(c) > int64(d))]) |
| (Greater32 (Const32 [c]) (Const32 [d])) -> (ConstBool [b2i(int32(c) > int32(d))]) |
| (Greater16 (Const16 [c]) (Const16 [d])) -> (ConstBool [b2i(int16(c) > int16(d))]) |
| (Greater8 (Const8 [c]) (Const8 [d])) -> (ConstBool [b2i(int8(c) > int8(d))]) |
| |
| (Greater64U (Const64 [c]) (Const64 [d])) -> (ConstBool [b2i(uint64(c) > uint64(d))]) |
| (Greater32U (Const32 [c]) (Const32 [d])) -> (ConstBool [b2i(uint32(c) > uint32(d))]) |
| (Greater16U (Const16 [c]) (Const16 [d])) -> (ConstBool [b2i(uint16(c) > uint16(d))]) |
| (Greater8U (Const8 [c]) (Const8 [d])) -> (ConstBool [b2i(uint8(c) > uint8(d))]) |
| |
| (Geq64 (Const64 [c]) (Const64 [d])) -> (ConstBool [b2i(int64(c) >= int64(d))]) |
| (Geq32 (Const32 [c]) (Const32 [d])) -> (ConstBool [b2i(int32(c) >= int32(d))]) |
| (Geq16 (Const16 [c]) (Const16 [d])) -> (ConstBool [b2i(int16(c) >= int16(d))]) |
| (Geq8 (Const8 [c]) (Const8 [d])) -> (ConstBool [b2i(int8(c) >= int8(d))]) |
| |
| (Geq64U (Const64 [c]) (Const64 [d])) -> (ConstBool [b2i(uint64(c) >= uint64(d))]) |
| (Geq32U (Const32 [c]) (Const32 [d])) -> (ConstBool [b2i(uint32(c) >= uint32(d))]) |
| (Geq16U (Const16 [c]) (Const16 [d])) -> (ConstBool [b2i(uint16(c) >= uint16(d))]) |
| (Geq8U (Const8 [c]) (Const8 [d])) -> (ConstBool [b2i(uint8(c) >= uint8(d))]) |
| |
| (Less64 (Const64 [c]) (Const64 [d])) -> (ConstBool [b2i(int64(c) < int64(d))]) |
| (Less32 (Const32 [c]) (Const32 [d])) -> (ConstBool [b2i(int32(c) < int32(d))]) |
| (Less16 (Const16 [c]) (Const16 [d])) -> (ConstBool [b2i(int16(c) < int16(d))]) |
| (Less8 (Const8 [c]) (Const8 [d])) -> (ConstBool [b2i(int8(c) < int8(d))]) |
| |
| (Less64U (Const64 [c]) (Const64 [d])) -> (ConstBool [b2i(uint64(c) < uint64(d))]) |
| (Less32U (Const32 [c]) (Const32 [d])) -> (ConstBool [b2i(uint32(c) < uint32(d))]) |
| (Less16U (Const16 [c]) (Const16 [d])) -> (ConstBool [b2i(uint16(c) < uint16(d))]) |
| (Less8U (Const8 [c]) (Const8 [d])) -> (ConstBool [b2i(uint8(c) < uint8(d))]) |
| |
| (Leq64 (Const64 [c]) (Const64 [d])) -> (ConstBool [b2i(int64(c) <= int64(d))]) |
| (Leq32 (Const32 [c]) (Const32 [d])) -> (ConstBool [b2i(int32(c) <= int32(d))]) |
| (Leq16 (Const16 [c]) (Const16 [d])) -> (ConstBool [b2i(int16(c) <= int16(d))]) |
| (Leq8 (Const8 [c]) (Const8 [d])) -> (ConstBool [b2i(int8(c) <= int8(d))]) |
| |
| (Leq64U (Const64 [c]) (Const64 [d])) -> (ConstBool [b2i(uint64(c) <= uint64(d))]) |
| (Leq32U (Const32 [c]) (Const32 [d])) -> (ConstBool [b2i(uint32(c) <= uint32(d))]) |
| (Leq16U (Const16 [c]) (Const16 [d])) -> (ConstBool [b2i(uint16(c) <= uint16(d))]) |
| (Leq8U (Const8 [c]) (Const8 [d])) -> (ConstBool [b2i(uint8(c) <= uint8(d))]) |
| |
| // simplifications |
| (Or64 x x) -> x |
| (Or32 x x) -> x |
| (Or16 x x) -> x |
| (Or8 x x) -> x |
| (And64 x x) -> x |
| (And32 x x) -> x |
| (And16 x x) -> x |
| (And8 x x) -> x |
| (Xor64 x x) -> (Const64 [0]) |
| (Xor32 x x) -> (Const32 [0]) |
| (Xor16 x x) -> (Const16 [0]) |
| (Xor8 x x) -> (Const8 [0]) |
| (Sub64 x x) -> (Const64 [0]) |
| (Sub32 x x) -> (Const32 [0]) |
| (Sub16 x x) -> (Const16 [0]) |
| (Sub8 x x) -> (Const8 [0]) |
| (Com8 (Com8 x)) -> x |
| (Com16 (Com16 x)) -> x |
| (Com32 (Com32 x)) -> x |
| (Com64 (Com64 x)) -> x |
| |
| // user nil checks |
| (NeqPtr p (ConstNil)) -> (IsNonNil p) |
| (NeqPtr (ConstNil) p) -> (IsNonNil p) |
| (EqPtr p (ConstNil)) -> (Not (IsNonNil p)) |
| (EqPtr (ConstNil) p) -> (Not (IsNonNil p)) |
| |
| // slice and interface comparisons |
| // The frontend ensures that we can only compare against nil, |
| // so we need only compare the first word (interface type or slice ptr). |
| (EqInter x y) -> (EqPtr (ITab x) (ITab y)) |
| (NeqInter x y) -> (NeqPtr (ITab x) (ITab y)) |
| (EqSlice x y) -> (EqPtr (SlicePtr x) (SlicePtr y)) |
| (NeqSlice x y) -> (NeqPtr (SlicePtr x) (SlicePtr y)) |
| |
| // indexing operations |
| // Note: bounds check has already been done |
| (ArrayIndex (Load ptr mem) idx) && b == v.Args[0].Block -> (Load (PtrIndex <v.Type.PtrTo()> ptr idx) mem) |
| (PtrIndex <t> ptr idx) -> (AddPtr ptr (MulPtr idx (ConstPtr [t.Elem().Size()]))) |
| (StructSelect [idx] (Load ptr mem)) -> @v.Args[0].Block (Load <v.Type> (OffPtr <v.Type.PtrTo()> [idx] ptr) mem) |
| |
| // complex ops |
| (ComplexReal (ComplexMake real _ )) -> real |
| (ComplexImag (ComplexMake _ imag )) -> imag |
| |
| (Load <t> ptr mem) && t.IsComplex() && t.Size() == 8 -> |
| (ComplexMake |
| (Load <config.fe.TypeFloat32()> ptr mem) |
| (Load <config.fe.TypeFloat32()> |
| (OffPtr <config.fe.TypeFloat32().PtrTo()> [4] ptr) |
| mem) |
| ) |
| (Store [8] dst (ComplexMake real imag) mem) -> |
| (Store [4] |
| (OffPtr <config.fe.TypeFloat32().PtrTo()> [4] dst) |
| imag |
| (Store [4] dst real mem)) |
| |
| (Load <t> ptr mem) && t.IsComplex() && t.Size() == 16 -> |
| (ComplexMake |
| (Load <config.fe.TypeFloat64()> ptr mem) |
| (Load <config.fe.TypeFloat64()> |
| (OffPtr <config.fe.TypeFloat64().PtrTo()> [8] ptr) |
| mem) |
| ) |
| (Store [16] dst (ComplexMake real imag) mem) -> |
| (Store [8] |
| (OffPtr <config.fe.TypeFloat64().PtrTo()> [8] dst) |
| imag |
| (Store [8] dst real mem)) |
| |
| // string ops |
| (StringPtr (StringMake ptr _)) -> ptr |
| (StringLen (StringMake _ len)) -> len |
| (ConstString {s}) -> |
| (StringMake |
| (Addr <config.fe.TypeBytePtr()> {config.fe.StringData(s.(string))} |
| (SB)) |
| (ConstPtr [int64(len(s.(string)))])) |
| (Load <t> ptr mem) && t.IsString() -> |
| (StringMake |
| (Load <config.fe.TypeBytePtr()> ptr mem) |
| (Load <config.fe.TypeUintptr()> |
| (OffPtr <config.fe.TypeUintptr().PtrTo()> [config.PtrSize] ptr) |
| mem)) |
| (Store [2*config.PtrSize] dst (StringMake ptr len) mem) -> |
| (Store [config.PtrSize] |
| (OffPtr <config.fe.TypeUintptr().PtrTo()> [config.PtrSize] dst) |
| len |
| (Store [config.PtrSize] dst ptr mem)) |
| |
| // slice ops |
| (SlicePtr (SliceMake ptr _ _ )) -> ptr |
| (SliceLen (SliceMake _ len _)) -> len |
| (SliceCap (SliceMake _ _ cap)) -> cap |
| (ConstSlice) -> |
| (SliceMake |
| (ConstNil <config.fe.TypeBytePtr()>) |
| (ConstPtr [0]) |
| (ConstPtr [0])) |
| |
| (Load <t> ptr mem) && t.IsSlice() -> |
| (SliceMake |
| (Load <config.fe.TypeBytePtr()> ptr mem) |
| (Load <config.fe.TypeUintptr()> |
| (OffPtr <config.fe.TypeUintptr().PtrTo()> [config.PtrSize] ptr) |
| mem) |
| (Load <config.fe.TypeUintptr()> |
| (OffPtr <config.fe.TypeUintptr().PtrTo()> [2*config.PtrSize] ptr) |
| mem)) |
| (Store [3*config.PtrSize] dst (SliceMake ptr len cap) mem) -> |
| (Store [config.PtrSize] |
| (OffPtr <config.fe.TypeUintptr().PtrTo()> [2*config.PtrSize] dst) |
| cap |
| (Store [config.PtrSize] |
| (OffPtr <config.fe.TypeUintptr().PtrTo()> [config.PtrSize] dst) |
| len |
| (Store [config.PtrSize] dst ptr mem))) |
| |
| // interface ops |
| (ITab (IMake itab _)) -> itab |
| (IData (IMake _ data)) -> data |
| (ConstInterface) -> |
| (IMake |
| (ConstNil <config.fe.TypeBytePtr()>) |
| (ConstNil <config.fe.TypeBytePtr()>)) |
| (Load <t> ptr mem) && t.IsInterface() -> |
| (IMake |
| (Load <config.fe.TypeBytePtr()> ptr mem) |
| (Load <config.fe.TypeBytePtr()> |
| (OffPtr <config.fe.TypeBytePtr().PtrTo()> [config.PtrSize] ptr) |
| mem)) |
| (Store [2*config.PtrSize] dst (IMake itab data) mem) -> |
| (Store [config.PtrSize] |
| (OffPtr <config.fe.TypeBytePtr().PtrTo()> [config.PtrSize] dst) |
| data |
| (Store [config.PtrSize] dst itab mem)) |
| |
| // un-SSAable values use mem->mem copies |
| (Store [size] dst (Load <t> src mem) mem) && !config.fe.CanSSA(t) -> (Move [size] dst src mem) |
| (Store [size] dst (Load <t> src mem) (VarDef {x} mem)) && !config.fe.CanSSA(t) -> (Move [size] dst src (VarDef {x} mem)) |
| |
| (Check (NilCheck (GetG _) _) next) -> (Plain nil next) |
| |
| (If (Not cond) yes no) -> (If cond no yes) |
| (If (ConstBool [c]) yes no) && c == 1 -> (First nil yes no) |
| (If (ConstBool [c]) yes no) && c == 0 -> (First nil no yes) |
| |
| // Get rid of Convert ops for pointer arithmetic on unsafe.Pointer. |
| (Convert (Add64 (Convert ptr) off)) -> (Add64 ptr off) |