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.
|
// 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
|
// This prevents a single load from being split into multiple loads
|
||||||
// which then might return different values. See test/atomicload.go.
|
// 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)
|
(MOVBQSX x:(MOVBload [off] {sym} ptr mem)) && x.Uses == 1 -> @x.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)
|
(MOVBQZX x:(MOVBload [off] {sym} ptr mem)) && x.Uses == 1 -> @x.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)
|
(MOVWQSX x:(MOVWload [off] {sym} ptr mem)) && x.Uses == 1 -> @x.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)
|
(MOVWQZX x:(MOVWload [off] {sym} ptr mem)) && x.Uses == 1 -> @x.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)
|
(MOVLQSX x:(MOVLload [off] {sym} ptr mem)) && x.Uses == 1 -> @x.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)
|
(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
|
// 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
|
(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.
|
// Combining byte loads into larger (unaligned) loads.
|
||||||
// There are many ways these combinations could occur. This is
|
// There are many ways these combinations could occur. This is
|
||||||
// designed to match the way encoding/binary.LittleEndian does it.
|
// designed to match the way encoding/binary.LittleEndian does it.
|
||||||
(ORW (MOVBQZXload [i] {s} p mem)
|
(ORW x:(MOVBQZXload [i] {s} p mem)
|
||||||
(SHLWconst [8] (MOVBQZXload [i+1] {s} p mem))) -> @v.Args[0].Block (MOVWload [i] {s} p mem)
|
(SHLWconst [8] (MOVBQZXload [i+1] {s} p mem))) -> @x.Block (MOVWload [i] {s} p mem)
|
||||||
|
|
||||||
(ORL (ORL (ORL
|
(ORL (ORL (ORL
|
||||||
(MOVBQZXload [i] {s} p mem)
|
x:(MOVBQZXload [i] {s} p mem)
|
||||||
(SHLLconst [8] (MOVBQZXload [i+1] {s} p mem)))
|
(SHLLconst [8] (MOVBQZXload [i+1] {s} p mem)))
|
||||||
(SHLLconst [16] (MOVBQZXload [i+2] {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
|
(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 [8] (MOVBQZXload [i+1] {s} p mem)))
|
||||||
(SHLQconst [16] (MOVBQZXload [i+2] {s} p mem)))
|
(SHLQconst [16] (MOVBQZXload [i+2] {s} p mem)))
|
||||||
(SHLQconst [24] (MOVBQZXload [i+3] {s} p mem)))
|
(SHLQconst [24] (MOVBQZXload [i+3] {s} p mem)))
|
||||||
(SHLQconst [32] (MOVBQZXload [i+4] {s} p mem)))
|
(SHLQconst [32] (MOVBQZXload [i+4] {s} p mem)))
|
||||||
(SHLQconst [40] (MOVBQZXload [i+5] {s} p mem)))
|
(SHLQconst [40] (MOVBQZXload [i+5] {s} p mem)))
|
||||||
(SHLQconst [48] (MOVBQZXload [i+6] {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.
|
// Simplify nil checks.
|
||||||
// These are inserted by for _, e := range a {}
|
// 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
|
// constant folding
|
||||||
(Trunc16to8 (Const16 [c])) -> (Const8 [int64(int8(c))])
|
(Trunc16to8 (Const16 [c])) -> (Const8 [int64(int8(c))])
|
||||||
|
|
@ -456,7 +456,7 @@
|
||||||
|
|
||||||
// indexing operations
|
// indexing operations
|
||||||
// Note: bounds check has already been done
|
// 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 == 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()])))
|
(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(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))
|
(Load <t.FieldType(3)> (OffPtr <t.FieldType(3).PtrTo()> [t.FieldOff(3)] ptr) mem))
|
||||||
|
|
||||||
(StructSelect [i] (Load <t> ptr mem)) && !config.fe.CanSSA(t) ->
|
(StructSelect [i] x:(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)
|
@x.Block (Load <v.Type> (OffPtr <v.Type.PtrTo()> [t.FieldOff(int(i))] ptr) mem)
|
||||||
|
|
||||||
(Store _ (StructMake0) mem) -> mem
|
(Store _ (StructMake0) mem) -> mem
|
||||||
(Store dst (StructMake1 <t> f0) mem) ->
|
(Store dst (StructMake1 <t> f0) mem) ->
|
||||||
|
|
|
||||||
|
|
@ -214,7 +214,11 @@ func genRules(arch arch) {
|
||||||
// check match of control value
|
// check match of control value
|
||||||
if s[1] != "nil" {
|
if s[1] != "nil" {
|
||||||
fmt.Fprintf(w, "v := b.Control\n")
|
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
|
// assign successor names
|
||||||
|
|
@ -310,26 +314,12 @@ func genRules(arch arch) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func genMatch(w io.Writer, arch arch, match string) {
|
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) {
|
func genMatch0(w io.Writer, arch arch, match, v string, m map[string]struct{}, top bool) {
|
||||||
if match[0] != '(' {
|
if match[0] != '(' || match[len(match)-1] != ')' {
|
||||||
if _, ok := m[match]; ok {
|
panic("non-compound expr in genMatch0: " + match)
|
||||||
// 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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// split body up into regions. Split by spaces/tabs, except those
|
// 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
|
// must match previous variable
|
||||||
fmt.Fprintf(w, "if %s.Type != %s {\nbreak\n}\n", v, t)
|
fmt.Fprintf(w, "if %s.Type != %s {\nbreak\n}\n", v, t)
|
||||||
} else {
|
} else {
|
||||||
m[t] = v + ".Type"
|
m[t] = struct{}{}
|
||||||
fmt.Fprintf(w, "%s := %s.Type\n", t, v)
|
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 {
|
if _, ok := m[x]; ok {
|
||||||
fmt.Fprintf(w, "if %s.AuxInt != %s {\nbreak\n}\n", v, x)
|
fmt.Fprintf(w, "if %s.AuxInt != %s {\nbreak\n}\n", v, x)
|
||||||
} else {
|
} else {
|
||||||
m[x] = v + ".AuxInt"
|
m[x] = struct{}{}
|
||||||
fmt.Fprintf(w, "%s := %s.AuxInt\n", x, v)
|
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 {
|
if _, ok := m[x]; ok {
|
||||||
fmt.Fprintf(w, "if %s.Aux != %s {\nbreak\n}\n", v, x)
|
fmt.Fprintf(w, "if %s.Aux != %s {\nbreak\n}\n", v, x)
|
||||||
} else {
|
} else {
|
||||||
m[x] = v + ".Aux"
|
m[x] = struct{}{}
|
||||||
fmt.Fprintf(w, "%s := %s.Aux\n", x, v)
|
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 {
|
} else {
|
||||||
// variable or sexpr
|
// remember that this variable references the given value
|
||||||
genMatch0(w, arch, a, fmt.Sprintf("%s.Args[%d]", v, argnum), m, false)
|
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++
|
argnum++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -28,10 +28,11 @@ func rewriteValuedec_OpSliceCap(v *Value, config *Config) bool {
|
||||||
// cond:
|
// cond:
|
||||||
// result: cap
|
// result: cap
|
||||||
for {
|
for {
|
||||||
if v.Args[0].Op != OpSliceMake {
|
v_0 := v.Args[0]
|
||||||
|
if v_0.Op != OpSliceMake {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
cap := v.Args[0].Args[2]
|
cap := v_0.Args[2]
|
||||||
v.reset(OpCopy)
|
v.reset(OpCopy)
|
||||||
v.Type = cap.Type
|
v.Type = cap.Type
|
||||||
v.AddArg(cap)
|
v.AddArg(cap)
|
||||||
|
|
@ -46,10 +47,11 @@ func rewriteValuedec_OpSliceLen(v *Value, config *Config) bool {
|
||||||
// cond:
|
// cond:
|
||||||
// result: len
|
// result: len
|
||||||
for {
|
for {
|
||||||
if v.Args[0].Op != OpSliceMake {
|
v_0 := v.Args[0]
|
||||||
|
if v_0.Op != OpSliceMake {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
len := v.Args[0].Args[1]
|
len := v_0.Args[1]
|
||||||
v.reset(OpCopy)
|
v.reset(OpCopy)
|
||||||
v.Type = len.Type
|
v.Type = len.Type
|
||||||
v.AddArg(len)
|
v.AddArg(len)
|
||||||
|
|
@ -64,10 +66,11 @@ func rewriteValuedec_OpSlicePtr(v *Value, config *Config) bool {
|
||||||
// cond:
|
// cond:
|
||||||
// result: ptr
|
// result: ptr
|
||||||
for {
|
for {
|
||||||
if v.Args[0].Op != OpSliceMake {
|
v_0 := v.Args[0]
|
||||||
|
if v_0.Op != OpSliceMake {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
ptr := v.Args[0].Args[0]
|
ptr := v_0.Args[0]
|
||||||
v.reset(OpCopy)
|
v.reset(OpCopy)
|
||||||
v.Type = ptr.Type
|
v.Type = ptr.Type
|
||||||
v.AddArg(ptr)
|
v.AddArg(ptr)
|
||||||
|
|
@ -82,10 +85,11 @@ func rewriteValuedec_OpStringLen(v *Value, config *Config) bool {
|
||||||
// cond:
|
// cond:
|
||||||
// result: len
|
// result: len
|
||||||
for {
|
for {
|
||||||
if v.Args[0].Op != OpStringMake {
|
v_0 := v.Args[0]
|
||||||
|
if v_0.Op != OpStringMake {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
len := v.Args[0].Args[1]
|
len := v_0.Args[1]
|
||||||
v.reset(OpCopy)
|
v.reset(OpCopy)
|
||||||
v.Type = len.Type
|
v.Type = len.Type
|
||||||
v.AddArg(len)
|
v.AddArg(len)
|
||||||
|
|
@ -100,10 +104,11 @@ func rewriteValuedec_OpStringPtr(v *Value, config *Config) bool {
|
||||||
// cond:
|
// cond:
|
||||||
// result: ptr
|
// result: ptr
|
||||||
for {
|
for {
|
||||||
if v.Args[0].Op != OpStringMake {
|
v_0 := v.Args[0]
|
||||||
|
if v_0.Op != OpStringMake {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
ptr := v.Args[0].Args[0]
|
ptr := v_0.Args[0]
|
||||||
v.reset(OpCopy)
|
v.reset(OpCopy)
|
||||||
v.Type = ptr.Type
|
v.Type = ptr.Type
|
||||||
v.AddArg(ptr)
|
v.AddArg(ptr)
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue