Commit 05434475 authored by Alexandru Moșoi's avatar Alexandru Moșoi Committed by Keith Randall

[dev.ssa] cmd/compile/internal/ssa/gen: enclose rules' code in a for loop

* Enclose each rule's code in a for with no condition
* The loop is ran at most once because it's always terminated by a return.
* Use break when matching condition fails
* Drop rule hashes
* Shaves about 3 lines of code per rule

The binary size is not afected.

Change-Id: I27c3e40dc8cae98dcd50739342dc38db2ef9c247
Reviewed-on: https://go-review.googlesource.com/19220Reviewed-by: default avatarKeith Randall <khr@golang.org>
parent 9278a04a
...@@ -12,7 +12,6 @@ package main ...@@ -12,7 +12,6 @@ package main
import ( import (
"bufio" "bufio"
"bytes" "bytes"
"crypto/md5"
"flag" "flag"
"fmt" "fmt"
"go/format" "go/format"
...@@ -59,10 +58,6 @@ func (r Rule) String() string { ...@@ -59,10 +58,6 @@ func (r Rule) String() string {
return fmt.Sprintf("rule %q at line %d", r.rule, r.lineno) return fmt.Sprintf("rule %q at line %d", r.rule, r.lineno)
} }
func (r Rule) hash() string {
return fmt.Sprintf("%02x", md5.Sum([]byte(r.rule)))
}
// parse returns the matching part of the rule, additional conditions, and the result. // parse returns the matching part of the rule, additional conditions, and the result.
func (r Rule) parse() (match, cond, result string) { func (r Rule) parse() (match, cond, result string) {
s := strings.Split(r.rule, "->") s := strings.Split(r.rule, "->")
...@@ -170,24 +165,16 @@ func genRules(arch arch) { ...@@ -170,24 +165,16 @@ func genRules(arch arch) {
fmt.Fprintln(w, "b := v.Block") fmt.Fprintln(w, "b := v.Block")
fmt.Fprintln(w, "_ = b") fmt.Fprintln(w, "_ = b")
for _, rule := range oprules[op] { for _, rule := range oprules[op] {
// Note: we use a hash to identify the rule so that its
// identity is invariant to adding/removing rules elsewhere
// in the rules file. This is useful to squash spurious
// diffs that would occur if we used rule index.
rulehash := rule.hash()
match, cond, result := rule.parse() match, cond, result := rule.parse()
fmt.Fprintf(w, "// match: %s\n", match) fmt.Fprintf(w, "// match: %s\n", match)
fmt.Fprintf(w, "// cond: %s\n", cond) fmt.Fprintf(w, "// cond: %s\n", cond)
fmt.Fprintf(w, "// result: %s\n", result) fmt.Fprintf(w, "// result: %s\n", result)
fail := fmt.Sprintf("{\ngoto end%s\n}\n", rulehash) fmt.Fprintf(w, "for {\n")
genMatch(w, arch, match)
fmt.Fprintf(w, "{\n")
genMatch(w, arch, match, fail)
if cond != "" { if cond != "" {
fmt.Fprintf(w, "if !(%s) %s", cond, fail) fmt.Fprintf(w, "if !(%s) {\nbreak\n}\n", cond)
} }
genResult(w, arch, result) genResult(w, arch, result)
...@@ -197,8 +184,6 @@ func genRules(arch arch) { ...@@ -197,8 +184,6 @@ func genRules(arch arch) {
fmt.Fprintf(w, "return true\n") fmt.Fprintf(w, "return true\n")
fmt.Fprintf(w, "}\n") fmt.Fprintf(w, "}\n")
fmt.Fprintf(w, "goto end%s\n", rulehash) // use label
fmt.Fprintf(w, "end%s:;\n", rulehash)
} }
fmt.Fprintf(w, "return false\n") fmt.Fprintf(w, "return false\n")
fmt.Fprintf(w, "}\n") fmt.Fprintf(w, "}\n")
...@@ -216,23 +201,19 @@ func genRules(arch arch) { ...@@ -216,23 +201,19 @@ func genRules(arch arch) {
for _, op := range ops { for _, op := range ops {
fmt.Fprintf(w, "case %s:\n", blockName(op, arch)) fmt.Fprintf(w, "case %s:\n", blockName(op, arch))
for _, rule := range blockrules[op] { for _, rule := range blockrules[op] {
rulehash := rule.hash()
match, cond, result := rule.parse() match, cond, result := rule.parse()
fmt.Fprintf(w, "// match: %s\n", match) fmt.Fprintf(w, "// match: %s\n", match)
fmt.Fprintf(w, "// cond: %s\n", cond) fmt.Fprintf(w, "// cond: %s\n", cond)
fmt.Fprintf(w, "// result: %s\n", result) fmt.Fprintf(w, "// result: %s\n", result)
fail := fmt.Sprintf("{\ngoto end%s\n}\n", rulehash) fmt.Fprintf(w, "for {\n")
fmt.Fprintf(w, "{\n")
s := split(match[1 : len(match)-1]) // remove parens, then split s := split(match[1 : len(match)-1]) // remove parens, then split
// 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", fail, map[string]string{}, false) genMatch0(w, arch, s[1], "v", map[string]string{}, false)
} }
// assign successor names // assign successor names
...@@ -244,7 +225,7 @@ func genRules(arch arch) { ...@@ -244,7 +225,7 @@ func genRules(arch arch) {
} }
if cond != "" { if cond != "" {
fmt.Fprintf(w, "if !(%s) %s", cond, fail) fmt.Fprintf(w, "if !(%s) {\nbreak\n}\n", cond)
} }
// Rule matches. Generate result. // Rule matches. Generate result.
...@@ -306,8 +287,6 @@ func genRules(arch arch) { ...@@ -306,8 +287,6 @@ func genRules(arch arch) {
fmt.Fprintf(w, "return true\n") fmt.Fprintf(w, "return true\n")
fmt.Fprintf(w, "}\n") fmt.Fprintf(w, "}\n")
fmt.Fprintf(w, "goto end%s\n", rulehash) // use label
fmt.Fprintf(w, "end%s:;\n", rulehash)
} }
} }
fmt.Fprintf(w, "}\n") fmt.Fprintf(w, "}\n")
...@@ -329,18 +308,18 @@ func genRules(arch arch) { ...@@ -329,18 +308,18 @@ func genRules(arch arch) {
} }
} }
func genMatch(w io.Writer, arch arch, match, fail string) { func genMatch(w io.Writer, arch arch, match string) {
genMatch0(w, arch, match, "v", fail, map[string]string{}, true) genMatch0(w, arch, match, "v", map[string]string{}, true)
} }
func genMatch0(w io.Writer, arch arch, match, v, fail string, m map[string]string, top bool) { func genMatch0(w io.Writer, arch arch, match, v string, m map[string]string, top bool) {
if match[0] != '(' { if match[0] != '(' {
if _, ok := m[match]; ok { if _, ok := m[match]; ok {
// variable already has a definition. Check whether // variable already has a definition. Check whether
// the old definition and the new definition match. // the old definition and the new definition match.
// For example, (add x x). Equality is just pointer equality // For example, (add x x). Equality is just pointer equality
// on Values (so cse is important to do before lowering). // on Values (so cse is important to do before lowering).
fmt.Fprintf(w, "if %s != %s %s", v, match, fail) fmt.Fprintf(w, "if %s != %s {\nbreak\n}\n", v, match)
return return
} }
// remember that this variable references the given value // remember that this variable references the given value
...@@ -358,7 +337,7 @@ func genMatch0(w io.Writer, arch arch, match, v, fail string, m map[string]strin ...@@ -358,7 +337,7 @@ func genMatch0(w io.Writer, arch arch, match, v, fail string, m map[string]strin
// check op // check op
if !top { if !top {
fmt.Fprintf(w, "if %s.Op != %s %s", v, opName(s[0], arch), fail) fmt.Fprintf(w, "if %s.Op != %s {\nbreak\n}\n", v, opName(s[0], arch))
} }
// check type/aux/args // check type/aux/args
...@@ -369,12 +348,12 @@ func genMatch0(w io.Writer, arch arch, match, v, fail string, m map[string]strin ...@@ -369,12 +348,12 @@ func genMatch0(w io.Writer, arch arch, match, v, fail string, m map[string]strin
t := a[1 : len(a)-1] // remove <> t := a[1 : len(a)-1] // remove <>
if !isVariable(t) { if !isVariable(t) {
// code. We must match the results of this code. // code. We must match the results of this code.
fmt.Fprintf(w, "if %s.Type != %s %s", v, t, fail) fmt.Fprintf(w, "if %s.Type != %s {\nbreak\n}\n", v, t)
} else { } else {
// variable // variable
if u, ok := m[t]; ok { if u, ok := m[t]; ok {
// must match previous variable // must match previous variable
fmt.Fprintf(w, "if %s.Type != %s %s", v, u, fail) fmt.Fprintf(w, "if %s.Type != %s {\nbreak\n}\n", v, u)
} else { } else {
m[t] = v + ".Type" m[t] = v + ".Type"
fmt.Fprintf(w, "%s := %s.Type\n", t, v) fmt.Fprintf(w, "%s := %s.Type\n", t, v)
...@@ -385,11 +364,11 @@ func genMatch0(w io.Writer, arch arch, match, v, fail string, m map[string]strin ...@@ -385,11 +364,11 @@ func genMatch0(w io.Writer, arch arch, match, v, fail string, m map[string]strin
x := a[1 : len(a)-1] // remove [] x := a[1 : len(a)-1] // remove []
if !isVariable(x) { if !isVariable(x) {
// code // code
fmt.Fprintf(w, "if %s.AuxInt != %s %s", v, x, fail) fmt.Fprintf(w, "if %s.AuxInt != %s {\nbreak\n}\n", v, x)
} else { } else {
// variable // variable
if y, ok := m[x]; ok { if y, ok := m[x]; ok {
fmt.Fprintf(w, "if %s.AuxInt != %s %s", v, y, fail) fmt.Fprintf(w, "if %s.AuxInt != %s {\nbreak\n}\n", v, y)
} else { } else {
m[x] = v + ".AuxInt" m[x] = v + ".AuxInt"
fmt.Fprintf(w, "%s := %s.AuxInt\n", x, v) fmt.Fprintf(w, "%s := %s.AuxInt\n", x, v)
...@@ -400,11 +379,11 @@ func genMatch0(w io.Writer, arch arch, match, v, fail string, m map[string]strin ...@@ -400,11 +379,11 @@ func genMatch0(w io.Writer, arch arch, match, v, fail string, m map[string]strin
x := a[1 : len(a)-1] // remove {} x := a[1 : len(a)-1] // remove {}
if !isVariable(x) { if !isVariable(x) {
// code // code
fmt.Fprintf(w, "if %s.Aux != %s %s", v, x, fail) fmt.Fprintf(w, "if %s.Aux != %s {\nbreak\n}\n", v, x)
} else { } else {
// variable // variable
if y, ok := m[x]; ok { if y, ok := m[x]; ok {
fmt.Fprintf(w, "if %s.Aux != %s %s", v, y, fail) fmt.Fprintf(w, "if %s.Aux != %s {\nbreak\n}\n", v, y)
} else { } else {
m[x] = v + ".Aux" m[x] = v + ".Aux"
fmt.Fprintf(w, "%s := %s.Aux\n", x, v) fmt.Fprintf(w, "%s := %s.Aux\n", x, v)
...@@ -412,7 +391,7 @@ func genMatch0(w io.Writer, arch arch, match, v, fail string, m map[string]strin ...@@ -412,7 +391,7 @@ func genMatch0(w io.Writer, arch arch, match, v, fail string, m map[string]strin
} }
} else { } else {
// variable or sexpr // variable or sexpr
genMatch0(w, arch, a, fmt.Sprintf("%s.Args[%d]", v, argnum), fail, m, false) genMatch0(w, arch, a, fmt.Sprintf("%s.Args[%d]", v, argnum), m, false)
argnum++ argnum++
} }
} }
......
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