aboutsummaryrefslogtreecommitdiff
path: root/src/cmd
diff options
context:
space:
mode:
authorKeith Randall <khr@golang.org>2020-03-19 16:25:08 -0700
committerKeith Randall <khr@golang.org>2020-04-09 21:18:55 +0000
commit28157b3292a9da90a7ceea89e9b01d9dd03b4979 (patch)
tree984d536a28817d99157d768bc397a02995816207 /src/cmd
parenta1550d3ca3a6a90b8bbb610950d1b30649411243 (diff)
downloadgo-28157b3292a9da90a7ceea89e9b01d9dd03b4979.tar.gz
go-28157b3292a9da90a7ceea89e9b01d9dd03b4979.zip
cmd/compile: start implementing strongly typed aux and auxint fields
Right now the Aux and AuxInt fields of ssa.Values are typed as interface{} and int64, respectively. Each rule that uses these values must cast them to the type they actually are (*obj.LSym, or int32, or ValAndOff, etc.), use them, and then cast them back to interface{} or int64. We know for each opcode what the types of the Aux and AuxInt fields should be. So let's modify the rule generator to declare the types to be what we know they should be, autoconverting to and from the generic types for us. That way we can make the rules more type safe. It's difficult to make a single CL for this, so I've coopted the "=>" token to indicate a rule that is strongly typed. "->" rules are processed as before. That will let us migrate a few rules at a time in separate CLs. Hopefully we can reach a state where all rules are strongly typed and we can drop the distinction. This CL changes just a few rules to get a feel for what this transition would look like. I've decided not to put explicit types in the rules. I think it makes the rules somewhat clearer, but definitely more verbose. In particular, the passthrough rules that don't modify the fields in question are verbose for no real reason. Change-Id: I63a1b789ac5702e7caf7934cd49f784235d1d73d Reviewed-on: https://go-review.googlesource.com/c/go/+/190197 Run-TryBot: Keith Randall <khr@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: David Chase <drchase@google.com>
Diffstat (limited to 'src/cmd')
-rw-r--r--src/cmd/compile/internal/gc/ssa.go16
-rw-r--r--src/cmd/compile/internal/ssa/check.go8
-rw-r--r--src/cmd/compile/internal/ssa/config.go2
-rw-r--r--src/cmd/compile/internal/ssa/export_test.go2
-rw-r--r--src/cmd/compile/internal/ssa/gen/AMD64.rules11
-rw-r--r--src/cmd/compile/internal/ssa/gen/generic.rules16
-rw-r--r--src/cmd/compile/internal/ssa/gen/rulegen.go159
-rw-r--r--src/cmd/compile/internal/ssa/op.go3
-rw-r--r--src/cmd/compile/internal/ssa/rewriteAMD64.go64
-rw-r--r--src/cmd/compile/internal/ssa/rewritegeneric.go54
10 files changed, 235 insertions, 100 deletions
diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go
index 5f45361980..345aad3961 100644
--- a/src/cmd/compile/internal/gc/ssa.go
+++ b/src/cmd/compile/internal/gc/ssa.go
@@ -6658,21 +6658,21 @@ func fieldIdx(n *Node) int {
// It also exports a bunch of compiler services for the ssa backend.
type ssafn struct {
curfn *Node
- strings map[string]interface{} // map from constant string to data symbols
- scratchFpMem *Node // temp for floating point register / memory moves on some architectures
- stksize int64 // stack size for current frame
- stkptrsize int64 // prefix of stack containing pointers
- log bool // print ssa debug to the stdout
+ strings map[string]*obj.LSym // map from constant string to data symbols
+ scratchFpMem *Node // temp for floating point register / memory moves on some architectures
+ stksize int64 // stack size for current frame
+ stkptrsize int64 // prefix of stack containing pointers
+ log bool // print ssa debug to the stdout
}
-// StringData returns a symbol (a *types.Sym wrapped in an interface) which
+// StringData returns a symbol which
// is the data component of a global string constant containing s.
-func (e *ssafn) StringData(s string) interface{} {
+func (e *ssafn) StringData(s string) *obj.LSym {
if aux, ok := e.strings[s]; ok {
return aux
}
if e.strings == nil {
- e.strings = make(map[string]interface{})
+ e.strings = make(map[string]*obj.LSym)
}
data := stringsym(e.curfn.Pos, s)
e.strings[s] = data
diff --git a/src/cmd/compile/internal/ssa/check.go b/src/cmd/compile/internal/ssa/check.go
index 4c694a03ac..b246bd9c7d 100644
--- a/src/cmd/compile/internal/ssa/check.go
+++ b/src/cmd/compile/internal/ssa/check.go
@@ -119,6 +119,7 @@ func checkFunc(f *Func) {
// Check to make sure aux values make sense.
canHaveAux := false
canHaveAuxInt := false
+ // TODO: enforce types of Aux in this switch (like auxString does below)
switch opcodeTable[v.Op].auxType {
case auxNone:
case auxBool:
@@ -158,7 +159,12 @@ func checkFunc(f *Func) {
if math.IsNaN(v.AuxFloat()) {
f.Fatalf("value %v has an AuxInt that encodes a NaN", v)
}
- case auxString, auxSym, auxTyp, auxArchSpecific:
+ case auxString:
+ if _, ok := v.Aux.(string); !ok {
+ f.Fatalf("value %v has Aux type %T, want string", v, v.Aux)
+ }
+ canHaveAux = true
+ case auxSym, auxTyp, auxArchSpecific:
canHaveAux = true
case auxSymOff, auxSymValAndOff, auxTypSize:
canHaveAuxInt = true
diff --git a/src/cmd/compile/internal/ssa/config.go b/src/cmd/compile/internal/ssa/config.go
index b51dfcb1f5..fdff3bbdeb 100644
--- a/src/cmd/compile/internal/ssa/config.go
+++ b/src/cmd/compile/internal/ssa/config.go
@@ -135,7 +135,7 @@ type Frontend interface {
Logger
// StringData returns a symbol pointing to the given string's contents.
- StringData(string) interface{} // returns *gc.Sym
+ StringData(string) *obj.LSym
// Auto returns a Node for an auto variable of the given type.
// The SSA compiler uses this function to allocate space for spills.
diff --git a/src/cmd/compile/internal/ssa/export_test.go b/src/cmd/compile/internal/ssa/export_test.go
index 32f0bcf290..a94cce48a4 100644
--- a/src/cmd/compile/internal/ssa/export_test.go
+++ b/src/cmd/compile/internal/ssa/export_test.go
@@ -90,7 +90,7 @@ func (d *DummyAuto) IsAutoTmp() bool {
return true
}
-func (DummyFrontend) StringData(s string) interface{} {
+func (DummyFrontend) StringData(s string) *obj.LSym {
return nil
}
func (DummyFrontend) Auto(pos src.XPos, t *types.Type) GCNode {
diff --git a/src/cmd/compile/internal/ssa/gen/AMD64.rules b/src/cmd/compile/internal/ssa/gen/AMD64.rules
index fcee5cb99f..f9ab02a7ab 100644
--- a/src/cmd/compile/internal/ssa/gen/AMD64.rules
+++ b/src/cmd/compile/internal/ssa/gen/AMD64.rules
@@ -2145,11 +2145,14 @@
(CMP(Q|L|W|B) l:(MOV(Q|L|W|B)load {sym} [off] ptr mem) x) && canMergeLoad(v, l) && clobber(l) -> (CMP(Q|L|W|B)load {sym} [off] ptr x mem)
(CMP(Q|L|W|B) x l:(MOV(Q|L|W|B)load {sym} [off] ptr mem)) && canMergeLoad(v, l) && clobber(l) -> (InvertFlags (CMP(Q|L|W|B)load {sym} [off] ptr x mem))
-(CMP(Q|L|W|B)const l:(MOV(Q|L|W|B)load {sym} [off] ptr mem) [c])
+(CMP(Q|L)const l:(MOV(Q|L)load {sym} [off] ptr mem) [c])
&& l.Uses == 1
- && validValAndOff(c, off)
- && clobber(l) ->
- @l.Block (CMP(Q|L|W|B)constload {sym} [makeValAndOff(c,off)] ptr mem)
+ && clobber(l) =>
+@l.Block (CMP(Q|L)constload {sym} [makeValAndOff32(c,off)] ptr mem)
+(CMP(W|B)const l:(MOV(W|B)load {sym} [off] ptr mem) [c])
+ && l.Uses == 1
+ && clobber(l) =>
+@l.Block (CMP(W|B)constload {sym} [makeValAndOff32(int32(c),off)] ptr mem)
(CMPQload {sym} [off] ptr (MOVQconst [c]) mem) && validValAndOff(c,off) -> (CMPQconstload {sym} [makeValAndOff(c,off)] ptr mem)
(CMPLload {sym} [off] ptr (MOVLconst [c]) mem) && validValAndOff(c,off) -> (CMPLconstload {sym} [makeValAndOff(c,off)] ptr mem)
diff --git a/src/cmd/compile/internal/ssa/gen/generic.rules b/src/cmd/compile/internal/ssa/gen/generic.rules
index e12cf4aa1b..7ae34cec56 100644
--- a/src/cmd/compile/internal/ssa/gen/generic.rules
+++ b/src/cmd/compile/internal/ssa/gen/generic.rules
@@ -873,20 +873,20 @@
// to other passes for optimizations.
(StringPtr (StringMake (Addr <t> {s} base) _)) -> (Addr <t> {s} base)
(StringLen (StringMake _ (Const64 <t> [c]))) -> (Const64 <t> [c])
-(ConstString {s}) && config.PtrSize == 4 && s.(string) == "" ->
+(ConstString {str}) && config.PtrSize == 4 && str == "" =>
(StringMake (ConstNil) (Const32 <typ.Int> [0]))
-(ConstString {s}) && config.PtrSize == 8 && s.(string) == "" ->
+(ConstString {str}) && config.PtrSize == 8 && str == "" =>
(StringMake (ConstNil) (Const64 <typ.Int> [0]))
-(ConstString {s}) && config.PtrSize == 4 && s.(string) != "" ->
+(ConstString {str}) && config.PtrSize == 4 && str != "" =>
(StringMake
- (Addr <typ.BytePtr> {fe.StringData(s.(string))}
+ (Addr <typ.BytePtr> {fe.StringData(str)}
(SB))
- (Const32 <typ.Int> [int64(len(s.(string)))]))
-(ConstString {s}) && config.PtrSize == 8 && s.(string) != "" ->
+ (Const32 <typ.Int> [int32(len(str))]))
+(ConstString {str}) && config.PtrSize == 8 && str != "" =>
(StringMake
- (Addr <typ.BytePtr> {fe.StringData(s.(string))}
+ (Addr <typ.BytePtr> {fe.StringData(str)}
(SB))
- (Const64 <typ.Int> [int64(len(s.(string)))]))
+ (Const64 <typ.Int> [int64(len(str))]))
// slice ops
// Only a few slice rules are provided here. See dec.rules for
diff --git a/src/cmd/compile/internal/ssa/gen/rulegen.go b/src/cmd/compile/internal/ssa/gen/rulegen.go
index 3caa06038a..a2dc110ff7 100644
--- a/src/cmd/compile/internal/ssa/gen/rulegen.go
+++ b/src/cmd/compile/internal/ssa/gen/rulegen.go
@@ -35,7 +35,8 @@ import (
)
// rule syntax:
-// sexpr [&& extra conditions] -> [@block] sexpr
+// sexpr [&& extra conditions] -> [@block] sexpr (untyped)
+// sexpr [&& extra conditions] => [@block] sexpr (typed)
//
// sexpr are s-expressions (lisp-like parenthesized groupings)
// sexpr ::= [variable:](opcode sexpr*)
@@ -74,11 +75,14 @@ func normalizeSpaces(s string) string {
}
// parse returns the matching part of the rule, additional conditions, and the result.
-func (r Rule) parse() (match, cond, result string) {
- s := strings.Split(r.rule, "->")
- if len(s) != 2 {
- log.Fatalf("no arrow in %s", r)
- }
+// parse also reports whether the generated code should use strongly typed aux and auxint fields.
+func (r Rule) parse() (match, cond, result string, typed bool) {
+ arrow := "->"
+ if strings.Contains(r.rule, "=>") {
+ arrow = "=>"
+ typed = true
+ }
+ s := strings.Split(r.rule, arrow)
match = normalizeSpaces(s[0])
result = normalizeSpaces(s[1])
cond = ""
@@ -86,7 +90,7 @@ func (r Rule) parse() (match, cond, result string) {
cond = normalizeSpaces(match[i+2:])
match = normalizeSpaces(match[:i])
}
- return match, cond, result
+ return match, cond, result, typed
}
func genRules(arch arch) { genRulesSuffix(arch, "") }
@@ -112,7 +116,7 @@ func genRulesSuffix(arch arch, suff string) {
scanner := bufio.NewScanner(text)
rule := ""
var lineno int
- var ruleLineno int // line number of "->"
+ var ruleLineno int // line number of "->" or "=>"
for scanner.Scan() {
lineno++
line := scanner.Text()
@@ -126,13 +130,13 @@ func genRulesSuffix(arch arch, suff string) {
if rule == "" {
continue
}
- if !strings.Contains(rule, "->") {
+ if !strings.Contains(rule, "->") && !strings.Contains(rule, "=>") {
continue
}
if ruleLineno == 0 {
ruleLineno = lineno
}
- if strings.HasSuffix(rule, "->") {
+ if strings.HasSuffix(rule, "->") || strings.HasSuffix(rule, "=>") {
continue
}
if unbalanced(rule) {
@@ -147,7 +151,7 @@ func genRulesSuffix(arch arch, suff string) {
continue
}
// Do fancier value op matching.
- match, _, _ := r.parse()
+ match, _, _, _ := r.parse()
op, oparch, _, _, _, _ := parseValue(match, arch, loc)
opname := fmt.Sprintf("Op%s%s", oparch, op.name)
oprules[opname] = append(oprules[opname], r)
@@ -218,7 +222,7 @@ func genRulesSuffix(arch arch, suff string) {
log.Fatalf("unconditional rule %s is followed by other rules", rr.match)
}
rr = &RuleRewrite{loc: rule.loc}
- rr.match, rr.cond, rr.result = rule.parse()
+ rr.match, rr.cond, rr.result, rr.typed = rule.parse()
pos, _ := genMatch(rr, arch, rr.match, fn.arglen >= 0)
if pos == "" {
pos = "v.Pos"
@@ -430,6 +434,8 @@ func (u *unusedInspector) node(node ast.Node) {
for _, stmt := range node.List {
u.node(stmt)
}
+ case *ast.DeclStmt:
+ u.node(node.Decl)
case *ast.IfStmt:
if node.Init != nil {
u.node(node.Init)
@@ -524,6 +530,8 @@ func (u *unusedInspector) node(node ast.Node) {
}
}
case *ast.BasicLit:
+ case *ast.ValueSpec:
+ u.exprs(node.Values)
default:
panic(fmt.Sprintf("unhandled node: %T", node))
}
@@ -762,6 +770,7 @@ type (
alloc int // for unique var names
loc string // file name & line number of the original rule
commuteDepth int // used to track depth of commute loops
+ typed bool // aux and auxint fields should be strongly typed
}
Declare struct {
name string
@@ -815,7 +824,7 @@ func breakf(format string, a ...interface{}) *CondBreak {
func genBlockRewrite(rule Rule, arch arch, data blockData) *RuleRewrite {
rr := &RuleRewrite{loc: rule.loc}
- rr.match, rr.cond, rr.result = rule.parse()
+ rr.match, rr.cond, rr.result, rr.typed = rule.parse()
_, _, auxint, aux, s := extract(rr.match) // remove parens, then split
// check match of control values
@@ -972,20 +981,56 @@ func genMatch0(rr *RuleRewrite, arch arch, match, v string, cnt map[string]int,
}
for _, e := range []struct {
- name, field string
+ name, field, dclType string
}{
- {typ, "Type"},
- {auxint, "AuxInt"},
- {aux, "Aux"},
+ {typ, "Type", "*types.Type"},
+ {auxint, "AuxInt", op.auxIntType()},
+ {aux, "Aux", op.auxType()},
} {
if e.name == "" {
continue
}
+ if !rr.typed {
+ if !token.IsIdentifier(e.name) || rr.declared(e.name) {
+ // code or variable
+ rr.add(breakf("%s.%s != %s", v, e.field, e.name))
+ } else {
+ rr.add(declf(e.name, "%s.%s", v, e.field))
+ }
+ continue
+ }
+
+ if e.dclType == "" {
+ log.Fatalf("op %s has no declared type for %s", op.name, e.field)
+ }
if !token.IsIdentifier(e.name) || rr.declared(e.name) {
- // code or variable
- rr.add(breakf("%s.%s != %s", v, e.field, e.name))
+ switch e.field {
+ case "Aux":
+ if e.dclType == "interface{}" {
+ // see TODO above
+ rr.add(breakf("%s.%s != %s", v, e.field, e.dclType, e.name))
+ } else {
+ rr.add(breakf("%s.%s.(%s) != %s", v, e.field, e.dclType, e.name))
+ }
+ case "AuxInt":
+ rr.add(breakf("%s(%s.%s) != %s", e.dclType, v, e.field, e.name))
+ case "Type":
+ rr.add(breakf("%s.%s != %s", v, e.field, e.name))
+ }
} else {
- rr.add(declf(e.name, "%s.%s", v, e.field))
+ switch e.field {
+ case "Aux":
+ if e.dclType == "interface{}" {
+ // TODO: kind of a hack - allows nil interface through
+ rr.add(declf(e.name, "%s.%s", v, e.field))
+ } else {
+ rr.add(declf(e.name, "%s.%s.(%s)", v, e.field, e.dclType))
+ }
+ case "AuxInt":
+ rr.add(declf(e.name, "%s(%s.%s)", e.dclType, v, e.field))
+ case "Type":
+ rr.add(declf(e.name, "%s.%s", v, e.field))
+ }
}
}
@@ -1146,10 +1191,22 @@ func genResult0(rr *RuleRewrite, arch arch, result string, top, move bool, pos s
}
if auxint != "" {
- rr.add(stmtf("%s.AuxInt = %s", v, auxint))
+ if rr.typed {
+ // Make sure auxint value has the right type.
+ rr.add(stmtf("var _auxint %s = %s", op.auxIntType(), auxint))
+ rr.add(stmtf("%s.AuxInt = int64(_auxint)", v))
+ } else {
+ rr.add(stmtf("%s.AuxInt = %s", v, auxint))
+ }
}
if aux != "" {
- rr.add(stmtf("%s.Aux = %s", v, aux))
+ if rr.typed {
+ // Make sure aux value has the right type.
+ rr.add(stmtf("var _aux %s = %s", op.auxType(), aux))
+ rr.add(stmtf("%s.Aux = _aux", v))
+ } else {
+ rr.add(stmtf("%s.Aux = %s", v, aux))
+ }
}
all := new(strings.Builder)
for i, arg := range args {
@@ -1418,7 +1475,7 @@ func excludeFromExpansion(s string, idx []int) bool {
return true
}
right := s[idx[1]:]
- if strings.Contains(left, "&&") && strings.Contains(right, "->") {
+ if strings.Contains(left, "&&") && (strings.Contains(right, "->") || strings.Contains(right, "=>")) {
// Inside && conditions.
return true
}
@@ -1521,6 +1578,7 @@ func normalizeWhitespace(x string) string {
x = strings.Replace(x, "[ ", "[", -1)
x = strings.Replace(x, " ]", "]", -1)
x = strings.Replace(x, ")->", ") ->", -1)
+ x = strings.Replace(x, ")=>", ") =>", -1)
return x
}
@@ -1576,7 +1634,7 @@ func parseEllipsisRules(rules []Rule, arch arch) (newop string, ok bool) {
return "", false
}
rule := rules[0]
- match, cond, result := rule.parse()
+ match, cond, result, _ := rule.parse()
if cond != "" || !isEllipsisValue(match) || !isEllipsisValue(result) {
if strings.Contains(rule.rule, "...") {
log.Fatalf("%s: found ellipsis in non-ellipsis rule", rule.loc)
@@ -1601,7 +1659,7 @@ func isEllipsisValue(s string) bool {
}
func checkEllipsisRuleCandidate(rule Rule, arch arch) {
- match, cond, result := rule.parse()
+ match, cond, result, _ := rule.parse()
if cond != "" {
return
}
@@ -1653,3 +1711,54 @@ func opByName(arch arch, name string) opData {
log.Fatalf("failed to find op named %s in arch %s", name, arch.name)
panic("unreachable")
}
+
+// auxType returns the Go type that this operation should store in its aux field.
+func (op opData) auxType() string {
+ switch op.aux {
+ case "String":
+ return "string"
+ case "Sym":
+ // Note: a Sym can be an *obj.LSym, a *gc.Node, or nil.
+ // TODO: provide an interface for this. Use a singleton to
+ // represent "no offset".
+ return "interface{}"
+ case "SymOff":
+ return "interface{}"
+ case "SymValAndOff":
+ return "interface{}"
+ case "Typ":
+ return "*types.Type"
+ case "TypSize":
+ return "*types.Type"
+ default:
+ return "invalid"
+ }
+}
+
+// auxIntType returns the Go type that this operation should store in its auxInt field.
+func (op opData) auxIntType() string {
+ switch op.aux {
+ //case "Bool":
+ case "Int8":
+ return "int8"
+ case "Int16":
+ return "int16"
+ case "Int32":
+ return "int32"
+ case "Int64":
+ return "int64"
+ //case "Int128":
+ //case "Float32":
+ //case "Float64":
+ case "SymOff":
+ return "int32"
+ case "SymValAndOff":
+ return "ValAndOff"
+ case "TypSize":
+ return "int64"
+ case "CCop":
+ return "Op"
+ default:
+ return "invalid"
+ }
+}
diff --git a/src/cmd/compile/internal/ssa/op.go b/src/cmd/compile/internal/ssa/op.go
index c32f5c730e..c0042f871c 100644
--- a/src/cmd/compile/internal/ssa/op.go
+++ b/src/cmd/compile/internal/ssa/op.go
@@ -154,6 +154,9 @@ func makeValAndOff(val, off int64) int64 {
}
return ValAndOff(val<<32 + int64(uint32(off))).Int64()
}
+func makeValAndOff32(val, off int32) ValAndOff {
+ return ValAndOff(int64(val)<<32 + int64(uint32(off)))
+}
// offOnly returns the offset half of ValAndOff vo.
// It is intended for use in rewrite rules.
diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go
index fd33591471..746ddacc3a 100644
--- a/src/cmd/compile/internal/ssa/rewriteAMD64.go
+++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go
@@ -6937,26 +6937,28 @@ func rewriteValueAMD64_OpAMD64CMPBconst(v *Value) bool {
return true
}
// match: (CMPBconst l:(MOVBload {sym} [off] ptr mem) [c])
- // cond: l.Uses == 1 && validValAndOff(c, off) && clobber(l)
- // result: @l.Block (CMPBconstload {sym} [makeValAndOff(c,off)] ptr mem)
+ // cond: l.Uses == 1 && clobber(l)
+ // result: @l.Block (CMPBconstload {sym} [makeValAndOff32(int32(c),off)] ptr mem)
for {
- c := v.AuxInt
+ c := int8(v.AuxInt)
l := v_0
if l.Op != OpAMD64MOVBload {
break
}
- off := l.AuxInt
+ off := int32(l.AuxInt)
sym := l.Aux
mem := l.Args[1]
ptr := l.Args[0]
- if !(l.Uses == 1 && validValAndOff(c, off) && clobber(l)) {
+ if !(l.Uses == 1 && clobber(l)) {
break
}
b = l.Block
v0 := b.NewValue0(l.Pos, OpAMD64CMPBconstload, types.TypeFlags)
v.copyOf(v0)
- v0.AuxInt = makeValAndOff(c, off)
- v0.Aux = sym
+ var _auxint ValAndOff = makeValAndOff32(int32(c), off)
+ v0.AuxInt = int64(_auxint)
+ var _aux interface{} = sym
+ v0.Aux = _aux
v0.AddArg2(ptr, mem)
return true
}
@@ -7322,26 +7324,28 @@ func rewriteValueAMD64_OpAMD64CMPLconst(v *Value) bool {
return true
}
// match: (CMPLconst l:(MOVLload {sym} [off] ptr mem) [c])
- // cond: l.Uses == 1 && validValAndOff(c, off) && clobber(l)
- // result: @l.Block (CMPLconstload {sym} [makeValAndOff(c,off)] ptr mem)
+ // cond: l.Uses == 1 && clobber(l)
+ // result: @l.Block (CMPLconstload {sym} [makeValAndOff32(c,off)] ptr mem)
for {
- c := v.AuxInt
+ c := int32(v.AuxInt)
l := v_0
if l.Op != OpAMD64MOVLload {
break
}
- off := l.AuxInt
+ off := int32(l.AuxInt)
sym := l.Aux
mem := l.Args[1]
ptr := l.Args[0]
- if !(l.Uses == 1 && validValAndOff(c, off) && clobber(l)) {
+ if !(l.Uses == 1 && clobber(l)) {
break
}
b = l.Block
v0 := b.NewValue0(l.Pos, OpAMD64CMPLconstload, types.TypeFlags)
v.copyOf(v0)
- v0.AuxInt = makeValAndOff(c, off)
- v0.Aux = sym
+ var _auxint ValAndOff = makeValAndOff32(c, off)
+ v0.AuxInt = int64(_auxint)
+ var _aux interface{} = sym
+ v0.Aux = _aux
v0.AddArg2(ptr, mem)
return true
}
@@ -7887,26 +7891,28 @@ func rewriteValueAMD64_OpAMD64CMPQconst(v *Value) bool {
return true
}
// match: (CMPQconst l:(MOVQload {sym} [off] ptr mem) [c])
- // cond: l.Uses == 1 && validValAndOff(c, off) && clobber(l)
- // result: @l.Block (CMPQconstload {sym} [makeValAndOff(c,off)] ptr mem)
+ // cond: l.Uses == 1 && clobber(l)
+ // result: @l.Block (CMPQconstload {sym} [makeValAndOff32(c,off)] ptr mem)
for {
- c := v.AuxInt
+ c := int32(v.AuxInt)
l := v_0
if l.Op != OpAMD64MOVQload {
break
}
- off := l.AuxInt
+ off := int32(l.AuxInt)
sym := l.Aux
mem := l.Args[1]
ptr := l.Args[0]
- if !(l.Uses == 1 && validValAndOff(c, off) && clobber(l)) {
+ if !(l.Uses == 1 && clobber(l)) {
break
}
b = l.Block
v0 := b.NewValue0(l.Pos, OpAMD64CMPQconstload, types.TypeFlags)
v.copyOf(v0)
- v0.AuxInt = makeValAndOff(c, off)
- v0.Aux = sym
+ var _auxint ValAndOff = makeValAndOff32(c, off)
+ v0.AuxInt = int64(_auxint)
+ var _aux interface{} = sym
+ v0.Aux = _aux
v0.AddArg2(ptr, mem)
return true
}
@@ -8257,26 +8263,28 @@ func rewriteValueAMD64_OpAMD64CMPWconst(v *Value) bool {
return true
}
// match: (CMPWconst l:(MOVWload {sym} [off] ptr mem) [c])
- // cond: l.Uses == 1 && validValAndOff(c, off) && clobber(l)
- // result: @l.Block (CMPWconstload {sym} [makeValAndOff(c,off)] ptr mem)
+ // cond: l.Uses == 1 && clobber(l)
+ // result: @l.Block (CMPWconstload {sym} [makeValAndOff32(int32(c),off)] ptr mem)
for {
- c := v.AuxInt
+ c := int16(v.AuxInt)
l := v_0
if l.Op != OpAMD64MOVWload {
break
}
- off := l.AuxInt
+ off := int32(l.AuxInt)
sym := l.Aux
mem := l.Args[1]
ptr := l.Args[0]
- if !(l.Uses == 1 && validValAndOff(c, off) && clobber(l)) {
+ if !(l.Uses == 1 && clobber(l)) {
break
}
b = l.Block
v0 := b.NewValue0(l.Pos, OpAMD64CMPWconstload, types.TypeFlags)
v.copyOf(v0)
- v0.AuxInt = makeValAndOff(c, off)
- v0.Aux = sym
+ var _auxint ValAndOff = makeValAndOff32(int32(c), off)
+ v0.AuxInt = int64(_auxint)
+ var _aux interface{} = sym
+ v0.Aux = _aux
v0.AddArg2(ptr, mem)
return true
}
diff --git a/src/cmd/compile/internal/ssa/rewritegeneric.go b/src/cmd/compile/internal/ssa/rewritegeneric.go
index f9ce978c4c..72056b87fa 100644
--- a/src/cmd/compile/internal/ssa/rewritegeneric.go
+++ b/src/cmd/compile/internal/ssa/rewritegeneric.go
@@ -3911,69 +3911,75 @@ func rewriteValuegeneric_OpConstString(v *Value) bool {
config := b.Func.Config
fe := b.Func.fe
typ := &b.Func.Config.Types
- // match: (ConstString {s})
- // cond: config.PtrSize == 4 && s.(string) == ""
+ // match: (ConstString {str})
+ // cond: config.PtrSize == 4 && str == ""
// result: (StringMake (ConstNil) (Const32 <typ.Int> [0]))
for {
- s := v.Aux
- if !(config.PtrSize == 4 && s.(string) == "") {
+ str := v.Aux.(string)
+ if !(config.PtrSize == 4 && str == "") {
break
}
v.reset(OpStringMake)
v0 := b.NewValue0(v.Pos, OpConstNil, typ.BytePtr)
v1 := b.NewValue0(v.Pos, OpConst32, typ.Int)
- v1.AuxInt = 0
+ var _auxint int32 = 0
+ v1.AuxInt = int64(_auxint)
v.AddArg2(v0, v1)
return true
}
- // match: (ConstString {s})
- // cond: config.PtrSize == 8 && s.(string) == ""
+ // match: (ConstString {str})
+ // cond: config.PtrSize == 8 && str == ""
// result: (StringMake (ConstNil) (Const64 <typ.Int> [0]))
for {
- s := v.Aux
- if !(config.PtrSize == 8 && s.(string) == "") {
+ str := v.Aux.(string)
+ if !(config.PtrSize == 8 && str == "") {
break
}
v.reset(OpStringMake)
v0 := b.NewValue0(v.Pos, OpConstNil, typ.BytePtr)
v1 := b.NewValue0(v.Pos, OpConst64, typ.Int)
- v1.AuxInt = 0
+ var _auxint int64 = 0
+ v1.AuxInt = int64(_auxint)
v.AddArg2(v0, v1)
return true
}
- // match: (ConstString {s})
- // cond: config.PtrSize == 4 && s.(string) != ""
- // result: (StringMake (Addr <typ.BytePtr> {fe.StringData(s.(string))} (SB)) (Const32 <typ.Int> [int64(len(s.(string)))]))
+ // match: (ConstString {str})
+ // cond: config.PtrSize == 4 && str != ""
+ // result: (StringMake (Addr <typ.BytePtr> {fe.StringData(str)} (SB)) (Const32 <typ.Int> [int32(len(str))]))
for {
- s := v.Aux
- if !(config.PtrSize == 4 && s.(string) != "") {
+ str := v.Aux.(string)
+ if !(config.PtrSize == 4 && str != "") {
break
}
v.reset(OpStringMake)
v0 := b.NewValue0(v.Pos, OpAddr, typ.BytePtr)
- v0.Aux = fe.StringData(s.(string))
+ var _aux interface{} = fe.StringData(str)
+ v0.Aux = _aux
v1 := b.NewValue0(v.Pos, OpSB, typ.Uintptr)
v0.AddArg(v1)
v2 := b.NewValue0(v.Pos, OpConst32, typ.Int)
- v2.AuxInt = int64(len(s.(string)))
+ var _auxint int32 = int32(len(str))
+ v2.AuxInt = int64(_auxint)
v.AddArg2(v0, v2)
return true
}
- // match: (ConstString {s})
- // cond: config.PtrSize == 8 && s.(string) != ""
- // result: (StringMake (Addr <typ.BytePtr> {fe.StringData(s.(string))} (SB)) (Const64 <typ.Int> [int64(len(s.(string)))]))
+ // match: (ConstString {str})
+ // cond: config.PtrSize == 8 && str != ""
+ // result: (StringMake (Addr <typ.BytePtr> {fe.StringData(str)} (SB)) (Const64 <typ.Int> [int64(len(str))]))
for {
- s := v.Aux
- if !(config.PtrSize == 8 && s.(string) != "") {
+ str := v.Aux.(string)
+ if !(config.PtrSize == 8 && str != "") {
break
}
v.reset(OpStringMake)
v0 := b.NewValue0(v.Pos, OpAddr, typ.BytePtr)
- v0.Aux = fe.StringData(s.(string))
+ var _aux interface{} = fe.StringData(str)
+ v0.Aux = _aux
v1 := b.NewValue0(v.Pos, OpSB, typ.Uintptr)
v0.AddArg(v1)
v2 := b.NewValue0(v.Pos, OpConst64, typ.Int)
- v2.AuxInt = int64(len(s.(string)))
+ var _auxint int64 = int64(len(str))
+ v2.AuxInt = int64(_auxint)
v.AddArg2(v0, v2)
return true
}