2015-03-23 17:02:11 -07:00
|
|
|
// 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.
|
|
|
|
|
|
2015-05-28 16:45:33 -07:00
|
|
|
// values are specified using the following format:
|
2015-06-11 21:29:25 -07:00
|
|
|
// (op <type> [auxint] {aux} arg0 arg1 ...)
|
2015-05-28 16:45:33 -07:00
|
|
|
// the type and aux fields are optional
|
|
|
|
|
// on the matching side
|
2015-06-11 21:29:25 -07:00
|
|
|
// - the type, aux, and auxint fields must match if they are specified.
|
2015-05-28 16:45:33 -07:00
|
|
|
// 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.
|
2015-06-11 21:29:25 -07:00
|
|
|
// - auxint will be 0 if not specified.
|
2015-05-28 16:45:33 -07:00
|
|
|
// - 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.
|
|
|
|
|
|
2015-03-23 17:02:11 -07:00
|
|
|
// constant folding
|
2015-07-28 14:19:20 -07:00
|
|
|
(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])
|
2015-08-12 13:48:36 -07:00
|
|
|
(IsInBounds (Const32 [c]) (Const32 [d])) -> (ConstBool {inBounds32(c,d)})
|
|
|
|
|
(IsInBounds (Const64 [c]) (Const64 [d])) -> (ConstBool {inBounds64(c,d)})
|
|
|
|
|
(IsInBounds (ConstPtr [c]) (ConstPtr [d])) && config.PtrSize == 4 -> (ConstBool {inBounds32(c,d)})
|
|
|
|
|
(IsInBounds (ConstPtr [c]) (ConstPtr [d])) && config.PtrSize == 8 -> (ConstBool {inBounds64(c,d)})
|
2015-07-31 12:32:22 +02:00
|
|
|
(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})
|
2015-03-23 17:02:11 -07:00
|
|
|
|
2015-08-14 12:59:33 +02:00
|
|
|
// 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])
|
2015-08-05 10:33:09 -07:00
|
|
|
(Com8 (Com8 x)) -> x
|
|
|
|
|
(Com16 (Com16 x)) -> x
|
|
|
|
|
(Com32 (Com32 x)) -> x
|
|
|
|
|
(Com64 (Com64 x)) -> x
|
2015-07-30 16:02:24 -04:00
|
|
|
|
2015-07-27 13:17:45 -07:00
|
|
|
// 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
|
2015-07-28 14:19:20 -07:00
|
|
|
(EqFat x y) && x.Op == OpConstNil && y.Op != OpConstNil -> (EqFat y x)
|
|
|
|
|
(NeqFat x y) && x.Op == OpConstNil && y.Op != OpConstNil -> (NeqFat y x)
|
2015-07-27 13:17:45 -07:00
|
|
|
// it suffices to check the first word (backing array for slices, dynamic type for interfaces)
|
2015-08-18 10:26:28 -07:00
|
|
|
(EqFat (Load ptr mem) (ConstNil)) -> (EqPtr (Load <config.fe.TypeUintptr()> ptr mem) (ConstPtr <config.fe.TypeUintptr()> [0]))
|
|
|
|
|
(NeqFat (Load ptr mem) (ConstNil)) -> (NeqPtr (Load <config.fe.TypeUintptr()> ptr mem) (ConstPtr <config.fe.TypeUintptr()> [0]))
|
2015-07-27 13:17:45 -07:00
|
|
|
|
2015-05-18 16:44:20 -07:00
|
|
|
// indexing operations
|
2015-04-15 15:51:25 -07:00
|
|
|
// Note: bounds check has already been done
|
2015-06-12 11:01:13 -07:00
|
|
|
(ArrayIndex (Load ptr mem) idx) -> (Load (PtrIndex <v.Type.PtrTo()> ptr idx) mem)
|
2015-08-18 10:26:28 -07:00
|
|
|
(PtrIndex <t> ptr idx) -> (AddPtr ptr (MulPtr <config.fe.TypeUintptr()> idx (ConstPtr <config.fe.TypeUintptr()> [t.Elem().Size()])))
|
2015-07-15 21:33:49 -07:00
|
|
|
(StructSelect [idx] (Load ptr mem)) -> (Load (OffPtr <v.Type.PtrTo()> [idx] ptr) mem)
|
2015-05-18 16:44:20 -07:00
|
|
|
|
2015-08-28 14:24:10 -04:00
|
|
|
// 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 <TypeMem> [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 <TypeMem> [8] dst real mem))
|
|
|
|
|
|
2015-05-27 14:52:22 -07:00
|
|
|
// string ops
|
|
|
|
|
(StringPtr (StringMake ptr _)) -> ptr
|
|
|
|
|
(StringLen (StringMake _ len)) -> len
|
2015-08-18 10:26:28 -07:00
|
|
|
(ConstString {s}) ->
|
|
|
|
|
(StringMake
|
|
|
|
|
(Addr <config.fe.TypeBytePtr()> {config.fe.StringData(s.(string))}
|
|
|
|
|
(SB <config.fe.TypeUintptr()>))
|
|
|
|
|
(ConstPtr <config.fe.TypeUintptr()> [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 <TypeMem> [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 <config.fe.TypeUintptr()>)
|
|
|
|
|
(ConstPtr <config.fe.TypeUintptr()>))
|
|
|
|
|
|
|
|
|
|
(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 <TypeMem> [config.PtrSize]
|
|
|
|
|
(OffPtr <config.fe.TypeUintptr().PtrTo()> [config.PtrSize] dst)
|
|
|
|
|
len
|
|
|
|
|
(Store <TypeMem> [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 <TypeMem> [config.PtrSize] dst itab mem))
|
|
|
|
|
|
|
|
|
|
// big-object moves (TODO: remove?)
|
|
|
|
|
(Store [size] dst (Load src mem) mem) && size > config.IntSize -> (Move [size] dst src mem)
|
2015-06-06 16:03:33 -07:00
|
|
|
|
2015-08-28 16:45:17 -07:00
|
|
|
(If (IsNonNil (GetG)) yes no) -> (First nil yes no)
|
2015-08-12 11:22:16 -07:00
|
|
|
|
2015-07-23 18:44:09 -05:00
|
|
|
(If (Not cond) yes no) -> (If cond no yes)
|
2015-08-28 16:45:17 -07:00
|
|
|
(If (ConstBool {c}) yes no) && c.(bool) -> (First nil yes no)
|
|
|
|
|
(If (ConstBool {c}) yes no) && !c.(bool) -> (First nil no yes)
|