]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: add ellipsis syntax for op-only rewrite rules
authorJosh Bleecher Snyder <josharian@gmail.com>
Wed, 8 Jan 2020 01:18:33 +0000 (17:18 -0800)
committerJosh Bleecher Snyder <josharian@gmail.com>
Thu, 20 Feb 2020 22:34:08 +0000 (22:34 +0000)
This change introduces a new syntax for rewrite rules
that only change a Value's Op. See #36380 for more discussion.

Updating rewrite rules to use ellipses will happen
in follow-up CLs.

Change-Id: I8c56e85de24607579d79729575c89ca80805ba5c
Reviewed-on: https://go-review.googlesource.com/c/go/+/213898
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
src/cmd/compile/internal/ssa/gen/rulegen.go

index 5a222802185486d70f5d26ba202722687c29f9da..c39ded4f9cb542152970f08d7b4cc99a2ff8a853 100644 (file)
@@ -176,6 +176,15 @@ func genRulesSuffix(arch arch, suff string) {
 
        sw := &Switch{expr: exprf("v.Op")}
        for _, op := range ops {
+               eop, ok := parseEllipsisRules(oprules[op], arch)
+               if ok {
+                       swc := &Case{expr: exprf(op)}
+                       swc.add(stmtf("v.Op = %s", eop))
+                       swc.add(stmtf("return true"))
+                       sw.add(swc)
+                       continue
+               }
+
                var ors []string
                for chunk := 0; chunk < len(oprules[op]); chunk += chunkSize {
                        ors = append(ors, fmt.Sprintf("rewriteValue%s%s_%s_%d(v)", arch.name, suff, op, chunk))
@@ -192,6 +201,11 @@ func genRulesSuffix(arch arch, suff string) {
        // because it is too big for some compilers.
        for _, op := range ops {
                rules := oprules[op]
+               _, ok := parseEllipsisRules(oprules[op], arch)
+               if ok {
+                       continue
+               }
+
                // rr is kept between chunks, so that a following chunk checks
                // that the previous one ended with a rule that wasn't
                // unconditional.
@@ -1240,7 +1254,7 @@ func parseValue(val string, arch arch, loc string) (op opData, oparch, typ, auxi
                if x.name != s {
                        return false
                }
-               if x.argLength != -1 && int(x.argLength) != len(args) {
+               if x.argLength != -1 && int(x.argLength) != len(args) && (len(args) != 1 || args[0] != "...") {
                        if strict {
                                return false
                        }
@@ -1507,3 +1521,28 @@ func normalizeMatch(m string, arch arch) string {
        }
        return s.String()
 }
+
+func parseEllipsisRules(rules []Rule, arch arch) (newop string, ok bool) {
+       if len(rules) != 1 {
+               return "", false
+       }
+       rule := rules[0]
+       match, cond, result := rule.parse()
+       if cond != "" || !isEllipsisValue(match) || !isEllipsisValue(result) {
+               return "", false
+       }
+       op, oparch, _, _, _, _ := parseValue(result, arch, rule.loc)
+       return fmt.Sprintf("Op%s%s", oparch, op.name), true
+}
+
+// isEllipsisValue reports whether s is of the form (OpX ...).
+func isEllipsisValue(s string) bool {
+       if len(s) < 2 || s[0] != '(' || s[len(s)-1] != ')' {
+               return false
+       }
+       c := split(s[1 : len(s)-1])
+       if len(c) != 2 || c[1] != "..." {
+               return false
+       }
+       return true
+}