Commit 259b7edf authored by Keith Randall's avatar Keith Randall

cmd/compile: allow naming of subexpressions

Allow names to be used for subexpressions of match rules.
For example:

(OpA x:(OpB y)) -> ..use x here to refer to the OpB value..

This gets rid of the .Args[0].Args[0]... way of naming we
used to use.

While we're here, give all subexpression matches names instead
of recomputing them with .Args[i] sequences each time they
are referenced.  Makes the generated rule code a bit smaller.

Change-Id: Ie42139f6f208933b75bd2ae8bd34e95419bc0e4e
Reviewed-on: https://go-review.googlesource.com/20997
Run-TryBot: Todd Neal <todd@tneal.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarTodd Neal <todd@tneal.org>
parent d4663e13
......@@ -618,12 +618,12 @@
// Make sure we don't combine these ops if the load has another use.
// This prevents a single load from being split into multiple loads
// which then might return different values. See test/atomicload.go.
(MOVBQSX (MOVBload [off] {sym} ptr mem)) && v.Args[0].Uses == 1 -> @v.Args[0].Block (MOVBQSXload <v.Type> [off] {sym} ptr mem)
(MOVBQZX (MOVBload [off] {sym} ptr mem)) && v.Args[0].Uses == 1 -> @v.Args[0].Block (MOVBQZXload <v.Type> [off] {sym} ptr mem)
(MOVWQSX (MOVWload [off] {sym} ptr mem)) && v.Args[0].Uses == 1 -> @v.Args[0].Block (MOVWQSXload <v.Type> [off] {sym} ptr mem)
(MOVWQZX (MOVWload [off] {sym} ptr mem)) && v.Args[0].Uses == 1 -> @v.Args[0].Block (MOVWQZXload <v.Type> [off] {sym} ptr mem)
(MOVLQSX (MOVLload [off] {sym} ptr mem)) && v.Args[0].Uses == 1 -> @v.Args[0].Block (MOVLQSXload <v.Type> [off] {sym} ptr mem)
(MOVLQZX (MOVLload [off] {sym} ptr mem)) && v.Args[0].Uses == 1 -> @v.Args[0].Block (MOVLQZXload <v.Type> [off] {sym} ptr mem)
(MOVBQSX x:(MOVBload [off] {sym} ptr mem)) && x.Uses == 1 -> @x.Block (MOVBQSXload <v.Type> [off] {sym} ptr mem)
(MOVBQZX x:(MOVBload [off] {sym} ptr mem)) && x.Uses == 1 -> @x.Block (MOVBQZXload <v.Type> [off] {sym} ptr mem)
(MOVWQSX x:(MOVWload [off] {sym} ptr mem)) && x.Uses == 1 -> @x.Block (MOVWQSXload <v.Type> [off] {sym} ptr mem)
(MOVWQZX x:(MOVWload [off] {sym} ptr mem)) && x.Uses == 1 -> @x.Block (MOVWQZXload <v.Type> [off] {sym} ptr mem)
(MOVLQSX x:(MOVLload [off] {sym} ptr mem)) && x.Uses == 1 -> @x.Block (MOVLQSXload <v.Type> [off] {sym} ptr mem)
(MOVLQZX x:(MOVLload [off] {sym} ptr mem)) && x.Uses == 1 -> @x.Block (MOVLQZXload <v.Type> [off] {sym} ptr mem)
// replace load from same location as preceding store with copy
(MOVBload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x
......@@ -1197,21 +1197,21 @@
// Combining byte loads into larger (unaligned) loads.
// There are many ways these combinations could occur. This is
// designed to match the way encoding/binary.LittleEndian does it.
(ORW (MOVBQZXload [i] {s} p mem)
(SHLWconst [8] (MOVBQZXload [i+1] {s} p mem))) -> @v.Args[0].Block (MOVWload [i] {s} p mem)
(ORW x:(MOVBQZXload [i] {s} p mem)
(SHLWconst [8] (MOVBQZXload [i+1] {s} p mem))) -> @x.Block (MOVWload [i] {s} p mem)
(ORL (ORL (ORL
(MOVBQZXload [i] {s} p mem)
x:(MOVBQZXload [i] {s} p mem)
(SHLLconst [8] (MOVBQZXload [i+1] {s} p mem)))
(SHLLconst [16] (MOVBQZXload [i+2] {s} p mem)))
(SHLLconst [24] (MOVBQZXload [i+3] {s} p mem))) -> @v.Args[0].Args[0].Args[0].Block (MOVLload [i] {s} p mem)
(SHLLconst [24] (MOVBQZXload [i+3] {s} p mem))) -> @x.Block (MOVLload [i] {s} p mem)
(ORQ (ORQ (ORQ (ORQ (ORQ (ORQ (ORQ
(MOVBQZXload [i] {s} p mem)
x:(MOVBQZXload [i] {s} p mem)
(SHLQconst [8] (MOVBQZXload [i+1] {s} p mem)))
(SHLQconst [16] (MOVBQZXload [i+2] {s} p mem)))
(SHLQconst [24] (MOVBQZXload [i+3] {s} p mem)))
(SHLQconst [32] (MOVBQZXload [i+4] {s} p mem)))
(SHLQconst [40] (MOVBQZXload [i+5] {s} p mem)))
(SHLQconst [48] (MOVBQZXload [i+6] {s} p mem)))
(SHLQconst [56] (MOVBQZXload [i+7] {s} p mem))) -> @v.Args[0].Args[0].Args[0].Args[0].Args[0].Args[0].Args[0].Block (MOVQload [i] {s} p mem)
(SHLQconst [56] (MOVBQZXload [i+7] {s} p mem))) -> @x.Block (MOVQload [i] {s} p mem)
......@@ -21,7 +21,7 @@
// Simplify nil checks.
// These are inserted by for _, e := range a {}
(NilCheck (Phi x (Add64 (Const64 [c]) y)) mem) && c > 0 && v.Args[0] == y -> (NilCheck x mem)
(NilCheck z:(Phi x (Add64 (Const64 [c]) y)) mem) && c > 0 && z == y -> (NilCheck x mem)
// constant folding
(Trunc16to8 (Const16 [c])) -> (Const8 [int64(int8(c))])
......@@ -456,7 +456,7 @@
// indexing operations
// Note: bounds check has already been done
(ArrayIndex <t> [0] (Load ptr mem)) -> @v.Args[0].Block (Load <t> ptr mem)
(ArrayIndex <t> [0] x:(Load ptr mem)) -> @x.Block (Load <t> ptr mem)
(PtrIndex <t> ptr idx) && config.PtrSize == 4 -> (AddPtr ptr (Mul32 <config.fe.TypeInt()> idx (Const32 <config.fe.TypeInt()> [t.ElemType().Size()])))
(PtrIndex <t> ptr idx) && config.PtrSize == 8 -> (AddPtr ptr (Mul64 <config.fe.TypeInt()> idx (Const64 <config.fe.TypeInt()> [t.ElemType().Size()])))
......@@ -493,8 +493,8 @@
(Load <t.FieldType(2)> (OffPtr <t.FieldType(2).PtrTo()> [t.FieldOff(2)] ptr) mem)
(Load <t.FieldType(3)> (OffPtr <t.FieldType(3).PtrTo()> [t.FieldOff(3)] ptr) mem))
(StructSelect [i] (Load <t> ptr mem)) && !config.fe.CanSSA(t) ->
@v.Args[0].Block (Load <v.Type> (OffPtr <v.Type.PtrTo()> [t.FieldOff(int(i))] ptr) mem)
(StructSelect [i] x:(Load <t> ptr mem)) && !config.fe.CanSSA(t) ->
@x.Block (Load <v.Type> (OffPtr <v.Type.PtrTo()> [t.FieldOff(int(i))] ptr) mem)
(Store _ (StructMake0) mem) -> mem
(Store dst (StructMake1 <t> f0) mem) ->
......
......@@ -214,7 +214,11 @@ func genRules(arch arch) {
// check match of control value
if s[1] != "nil" {
fmt.Fprintf(w, "v := b.Control\n")
genMatch0(w, arch, s[1], "v", map[string]string{}, false)
if strings.Contains(s[1], "(") {
genMatch0(w, arch, s[1], "v", map[string]struct{}{}, false)
} else {
fmt.Fprintf(w, "%s := b.Control\n", s[1])
}
}
// assign successor names
......@@ -310,26 +314,12 @@ func genRules(arch arch) {
}
func genMatch(w io.Writer, arch arch, match string) {
genMatch0(w, arch, match, "v", map[string]string{}, true)
genMatch0(w, arch, match, "v", map[string]struct{}{}, true)
}
func genMatch0(w io.Writer, arch arch, match, v string, m map[string]string, top bool) {
if match[0] != '(' {
if _, ok := m[match]; ok {
// variable already has a definition. Check whether
// the old definition and the new definition match.
// For example, (add x x). Equality is just pointer equality
// on Values (so cse is important to do before lowering).
fmt.Fprintf(w, "if %s != %s {\nbreak\n}\n", v, match)
return
}
// remember that this variable references the given value
if match == "_" {
return
}
m[match] = v
fmt.Fprintf(w, "%s := %s\n", match, v)
return
func genMatch0(w io.Writer, arch arch, match, v string, m map[string]struct{}, top bool) {
if match[0] != '(' || match[len(match)-1] != ')' {
panic("non-compound expr in genMatch0: " + match)
}
// split body up into regions. Split by spaces/tabs, except those
......@@ -356,7 +346,7 @@ func genMatch0(w io.Writer, arch arch, match, v string, m map[string]string, top
// must match previous variable
fmt.Fprintf(w, "if %s.Type != %s {\nbreak\n}\n", v, t)
} else {
m[t] = v + ".Type"
m[t] = struct{}{}
fmt.Fprintf(w, "%s := %s.Type\n", t, v)
}
}
......@@ -371,7 +361,7 @@ func genMatch0(w io.Writer, arch arch, match, v string, m map[string]string, top
if _, ok := m[x]; ok {
fmt.Fprintf(w, "if %s.AuxInt != %s {\nbreak\n}\n", v, x)
} else {
m[x] = v + ".AuxInt"
m[x] = struct{}{}
fmt.Fprintf(w, "%s := %s.AuxInt\n", x, v)
}
}
......@@ -386,13 +376,41 @@ func genMatch0(w io.Writer, arch arch, match, v string, m map[string]string, top
if _, ok := m[x]; ok {
fmt.Fprintf(w, "if %s.Aux != %s {\nbreak\n}\n", v, x)
} else {
m[x] = v + ".Aux"
m[x] = struct{}{}
fmt.Fprintf(w, "%s := %s.Aux\n", x, v)
}
}
} else if a == "_" {
argnum++
} else if !strings.Contains(a, "(") {
// leaf variable
if _, ok := m[a]; ok {
// variable already has a definition. Check whether
// the old definition and the new definition match.
// For example, (add x x). Equality is just pointer equality
// on Values (so cse is important to do before lowering).
fmt.Fprintf(w, "if %s != %s.Args[%d] {\nbreak\n}\n", a, v, argnum)
} else {
// remember that this variable references the given value
m[a] = struct{}{}
fmt.Fprintf(w, "%s := %s.Args[%d]\n", a, v, argnum)
}
argnum++
} else {
// variable or sexpr
genMatch0(w, arch, a, fmt.Sprintf("%s.Args[%d]", v, argnum), m, false)
// compound sexpr
var argname string
colon := strings.Index(a, ":")
openparen := strings.Index(a, "(")
if colon >= 0 && openparen >= 0 && colon < openparen {
// rule-specified name
argname = a[:colon]
a = a[colon+1:]
} else {
// autogenerated name
argname = fmt.Sprintf("%s_%d", v, argnum)
}
fmt.Fprintf(w, "%s := %s.Args[%d]\n", argname, v, argnum)
genMatch0(w, arch, a, argname, m, false)
argnum++
}
}
......
......@@ -28,10 +28,11 @@ func rewriteValuedec_OpSliceCap(v *Value, config *Config) bool {
// cond:
// result: cap
for {
if v.Args[0].Op != OpSliceMake {
v_0 := v.Args[0]
if v_0.Op != OpSliceMake {
break
}
cap := v.Args[0].Args[2]
cap := v_0.Args[2]
v.reset(OpCopy)
v.Type = cap.Type
v.AddArg(cap)
......@@ -46,10 +47,11 @@ func rewriteValuedec_OpSliceLen(v *Value, config *Config) bool {
// cond:
// result: len
for {
if v.Args[0].Op != OpSliceMake {
v_0 := v.Args[0]
if v_0.Op != OpSliceMake {
break
}
len := v.Args[0].Args[1]
len := v_0.Args[1]
v.reset(OpCopy)
v.Type = len.Type
v.AddArg(len)
......@@ -64,10 +66,11 @@ func rewriteValuedec_OpSlicePtr(v *Value, config *Config) bool {
// cond:
// result: ptr
for {
if v.Args[0].Op != OpSliceMake {
v_0 := v.Args[0]
if v_0.Op != OpSliceMake {
break
}
ptr := v.Args[0].Args[0]
ptr := v_0.Args[0]
v.reset(OpCopy)
v.Type = ptr.Type
v.AddArg(ptr)
......@@ -82,10 +85,11 @@ func rewriteValuedec_OpStringLen(v *Value, config *Config) bool {
// cond:
// result: len
for {
if v.Args[0].Op != OpStringMake {
v_0 := v.Args[0]
if v_0.Op != OpStringMake {
break
}
len := v.Args[0].Args[1]
len := v_0.Args[1]
v.reset(OpCopy)
v.Type = len.Type
v.AddArg(len)
......@@ -100,10 +104,11 @@ func rewriteValuedec_OpStringPtr(v *Value, config *Config) bool {
// cond:
// result: ptr
for {
if v.Args[0].Op != OpStringMake {
v_0 := v.Args[0]
if v_0.Op != OpStringMake {
break
}
ptr := v.Args[0].Args[0]
ptr := v_0.Args[0]
v.reset(OpCopy)
v.Type = ptr.Type
v.AddArg(ptr)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment