mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
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: Todd Neal <todd@tneal.org>
This commit is contained in:
parent
d4663e1353
commit
259b7edf5c
6 changed files with 3521 additions and 2491 deletions
|
|
@ -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 {
|
||||
// variable or sexpr
|
||||
genMatch0(w, arch, a, fmt.Sprintf("%s.Args[%d]", v, argnum), m, false)
|
||||
// remember that this variable references the given value
|
||||
m[a] = struct{}{}
|
||||
fmt.Fprintf(w, "%s := %s.Args[%d]\n", a, v, argnum)
|
||||
}
|
||||
argnum++
|
||||
} else {
|
||||
// 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++
|
||||
}
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -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)
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue