From e81671115c0857d3286e9331870ec9993e81a1a7 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Fri, 10 Jul 2015 12:58:53 -0600 Subject: [dev.ssa] cmd/compile: OANDAND, OOROR Joint hacking with josharian. Hints from matloob and Todd Neal. Now with tests, and OROR. Change-Id: Iff8826fde475691fb72a3eea7396a640b6274af9 Reviewed-on: https://go-review.googlesource.com/12041 Reviewed-by: Keith Randall --- src/cmd/compile/internal/gc/testdata/short_ssa.go | 60 +++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 src/cmd/compile/internal/gc/testdata/short_ssa.go (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/testdata/short_ssa.go b/src/cmd/compile/internal/gc/testdata/short_ssa.go new file mode 100644 index 0000000000..9427423ff3 --- /dev/null +++ b/src/cmd/compile/internal/gc/testdata/short_ssa.go @@ -0,0 +1,60 @@ +// compile + +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Tests short circuiting. + +package main + +func and_ssa(arg1, arg2 bool) bool { + return arg1 && rightCall(arg2) +} + +func or_ssa(arg1, arg2 bool) bool { + return arg1 || rightCall(arg2) +} + +var rightCalled bool + +func rightCall(v bool) bool { + rightCalled = true + return v + select {} // hack to prevent inlining + panic("unreached") +} + +func testAnd(arg1, arg2, wantRes bool) { testShortCircuit("AND", arg1, arg2, and_ssa, arg1, wantRes) } +func testOr(arg1, arg2, wantRes bool) { testShortCircuit("OR", arg1, arg2, or_ssa, !arg1, wantRes) } + +func testShortCircuit(opName string, arg1, arg2 bool, fn func(bool, bool) bool, wantRightCall, wantRes bool) { + rightCalled = false + got := fn(arg1, arg2) + if rightCalled != wantRightCall { + println("failed for", arg1, opName, arg2, "; rightCalled=", rightCalled, "want=", wantRightCall) + failed = true + } + if wantRes != got { + println("failed for", arg1, opName, arg2, "; res=", got, "want=", wantRes) + failed = true + } +} + +var failed = false + +func main() { + testAnd(false, false, false) + testAnd(false, true, false) + testAnd(true, false, false) + testAnd(true, true, true) + + testOr(false, false, false) + testOr(false, true, true) + testOr(true, false, true) + testOr(true, true, true) + + if failed { + panic("failed") + } +} -- cgit v1.3 From 8043f450c170a90de9a04bd801b4f3189ea613ea Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Mon, 20 Jul 2015 15:24:03 -0700 Subject: [dev.ssa] cmd/compile: fix test verb The verb doesn't do anything, but if/when we move these to the test directory, having it be right will be one fewer thing to remember. Change-Id: Ibf0280d7cc14bf48927e25215de6b91c111983d9 Reviewed-on: https://go-review.googlesource.com/12438 Reviewed-by: Brad Fitzpatrick --- src/cmd/compile/internal/gc/testdata/short_ssa.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/testdata/short_ssa.go b/src/cmd/compile/internal/gc/testdata/short_ssa.go index 9427423ff3..1aa7d3e677 100644 --- a/src/cmd/compile/internal/gc/testdata/short_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/short_ssa.go @@ -1,4 +1,4 @@ -// compile +// run // Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style -- cgit v1.3 From 61aa0953e542eb047f22905f84c7d627a35b8607 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Mon, 20 Jul 2015 15:39:14 -0700 Subject: [dev.ssa] cmd/compile: implement control flow handling Add label and goto checks and improve test coverage. Implement OSWITCH and OSELECT. Implement OBREAK and OCONTINUE. Allow generation of code in dead blocks. Change-Id: Ibebb7c98b4b2344f46d38db7c9dce058c56beaac Reviewed-on: https://go-review.googlesource.com/12445 Reviewed-by: Keith Randall --- src/cmd/compile/internal/gc/gen.go | 2 + src/cmd/compile/internal/gc/ssa.go | 316 ++++++++++++++++++++-- src/cmd/compile/internal/gc/ssa_test.go | 17 +- src/cmd/compile/internal/gc/testdata/break_ssa.go | 255 +++++++++++++++++ src/cmd/compile/internal/ssa/compile.go | 1 + test/label.go | 4 + test/label1.go | 31 ++- 7 files changed, 590 insertions(+), 36 deletions(-) create mode 100644 src/cmd/compile/internal/gc/testdata/break_ssa.go (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/gen.go b/src/cmd/compile/internal/gc/gen.go index 764895f15d..6390818e16 100644 --- a/src/cmd/compile/internal/gc/gen.go +++ b/src/cmd/compile/internal/gc/gen.go @@ -141,6 +141,8 @@ func newlab(n *Node) *Label { return lab } +// There is a copy of checkgoto in the new SSA backend. +// Please keep them in sync. func checkgoto(from *Node, to *Node) { if from.Sym == to.Sym { return diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index a77e788a1c..96756b11d0 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -62,7 +62,8 @@ func buildssa(fn *Node) (ssafn *ssa.Func, usessa bool) { // Allocate starting values s.vars = map[*Node]*ssa.Value{} - s.labels = map[string]*ssa.Block{} + s.labels = map[string]*ssaLabel{} + s.labeledNodes = map[*Node]*ssaLabel{} s.startmem = s.entryNewValue0(ssa.OpArg, ssa.TypeMem) s.sp = s.entryNewValue0(ssa.OpSP, s.config.Uintptr) // TODO: use generic pointer type (unsafe.Pointer?) instead s.sb = s.entryNewValue0(ssa.OpSB, s.config.Uintptr) @@ -105,6 +106,31 @@ func buildssa(fn *Node) (ssafn *ssa.Func, usessa bool) { s.exit.Control = s.mem() s.endBlock() + // Check that we used all labels + for name, lab := range s.labels { + if !lab.used() && !lab.reported { + yyerrorl(int(lab.defNode.Lineno), "label %v defined and not used", name) + lab.reported = true + } + if lab.used() && !lab.defined() && !lab.reported { + yyerrorl(int(lab.useNode.Lineno), "label %v not defined", name) + lab.reported = true + } + } + + // Check any forward gotos. Non-forward gotos have already been checked. + for _, n := range s.fwdGotos { + lab := s.labels[n.Left.Sym.Name] + // If the label is undefined, we have already have printed an error. + if lab.defined() { + s.checkgoto(n, lab.defNode) + } + } + + if nerrors > 0 { + return nil, false + } + // Link up variable uses to variable definitions s.linkForwardReferences() @@ -132,8 +158,16 @@ type state struct { // exit block that "return" jumps to (and panics jump to) exit *ssa.Block - // the target block for each label in f - labels map[string]*ssa.Block + // labels and labeled control flow nodes (OFOR, OSWITCH, OSELECT) in f + labels map[string]*ssaLabel + labeledNodes map[*Node]*ssaLabel + + // gotos that jump forward; required for deferred checkgoto calls + fwdGotos []*Node + + // unlabeled break and continue statement tracking + breakTo *ssa.Block // current target for plain break statement + continueTo *ssa.Block // current target for plain continue statement // current location where we're interpreting the AST curBlock *ssa.Block @@ -157,6 +191,34 @@ type state struct { line []int32 } +type ssaLabel struct { + target *ssa.Block // block identified by this label + breakTarget *ssa.Block // block to break to in control flow node identified by this label + continueTarget *ssa.Block // block to continue to in control flow node identified by this label + defNode *Node // label definition Node (OLABEL) + // Label use Node (OGOTO, OBREAK, OCONTINUE). + // Used only for error detection and reporting. + // There might be multiple uses, but we only need to track one. + useNode *Node + reported bool // reported indicates whether an error has already been reported for this label +} + +// defined reports whether the label has a definition (OLABEL node). +func (l *ssaLabel) defined() bool { return l.defNode != nil } + +// used reports whether the label has a use (OGOTO, OBREAK, or OCONTINUE node). +func (l *ssaLabel) used() bool { return l.useNode != nil } + +// label returns the label associated with sym, creating it if necessary. +func (s *state) label(sym *Sym) *ssaLabel { + lab := s.labels[sym.Name] + if lab == nil { + lab = new(ssaLabel) + s.labels[sym.Name] = lab + } + return lab +} + func (s *state) Logf(msg string, args ...interface{}) { s.config.Logf(msg, args...) } func (s *state) Fatalf(msg string, args ...interface{}) { s.config.Fatalf(msg, args...) } func (s *state) Unimplementedf(msg string, args ...interface{}) { s.config.Unimplementedf(msg, args...) } @@ -206,6 +268,10 @@ func (s *state) peekLine() int32 { return s.line[len(s.line)-1] } +func (s *state) Error(msg string, args ...interface{}) { + yyerrorl(int(s.peekLine()), msg, args...) +} + // newValue0 adds a new value with no arguments to the current block. func (s *state) newValue0(op ssa.Op, t ssa.Type) *ssa.Value { return s.curBlock.NewValue0(s.peekLine(), op, t) @@ -293,6 +359,16 @@ func (s *state) stmt(n *Node) { s.pushLine(n.Lineno) defer s.popLine() + // If s.curBlock is nil, then we're about to generate dead code. + // We can't just short-circuit here, though, + // because we check labels and gotos as part of SSA generation. + // Provide a block for the dead code so that we don't have + // to add special cases everywhere else. + if s.curBlock == nil { + dead := s.f.NewBlock(ssa.BlockPlain) + s.startBlock(dead) + } + s.stmtList(n.Ninit) switch n.Op { @@ -325,32 +401,61 @@ func (s *state) stmt(n *Node) { } s.assign(OAS, n.Left.Name.Heapaddr, palloc) - case OLABEL, OGOTO: - if n.Op == OLABEL && isblanksym(n.Left.Sym) { + case OLABEL: + sym := n.Left.Sym + + if isblanksym(sym) { // Empty identifier is valid but useless. // See issues 11589, 11593. return } - // get block at label, or make one - t := s.labels[n.Left.Sym.Name] - if t == nil { - t = s.f.NewBlock(ssa.BlockPlain) - s.labels[n.Left.Sym.Name] = t + + lab := s.label(sym) + + // Associate label with its control flow node, if any + if ctl := n.Name.Defn; ctl != nil { + switch ctl.Op { + case OFOR, OSWITCH, OSELECT: + s.labeledNodes[ctl] = lab + } } - // go to that label (we pretend "label:" is preceded by "goto label") - if b := s.endBlock(); b != nil { - addEdge(b, t) + + if !lab.defined() { + lab.defNode = n + } else { + s.Error("label %v already defined at %v", sym, Ctxt.Line(int(lab.defNode.Lineno))) + lab.reported = true + } + // The label might already have a target block via a goto. + if lab.target == nil { + lab.target = s.f.NewBlock(ssa.BlockPlain) } - if n.Op == OLABEL { - // next we work on the label's target block - s.startBlock(t) + // go to that label (we pretend "label:" is preceded by "goto label") + b := s.endBlock() + addEdge(b, lab.target) + s.startBlock(lab.target) + + case OGOTO: + sym := n.Left.Sym + + lab := s.label(sym) + if lab.target == nil { + lab.target = s.f.NewBlock(ssa.BlockPlain) + } + if !lab.used() { + lab.useNode = n } - if n.Op == OGOTO && s.curBlock == nil { - s.Unimplementedf("goto at start of function; see test/goto.go") - panic("stop compiling here, on pain of infinite loops") + + if lab.defined() { + s.checkgoto(n, lab.defNode) + } else { + s.fwdGotos = append(s.fwdGotos, n) } + b := s.endBlock() + addEdge(b, lab.target) + case OAS, OASWB: s.assign(n.Op, n.Left, n.Right) @@ -396,6 +501,58 @@ func (s *state) stmt(n *Node) { b := s.endBlock() addEdge(b, s.exit) + case OCONTINUE, OBREAK: + var op string + var to *ssa.Block + switch n.Op { + case OCONTINUE: + op = "continue" + to = s.continueTo + case OBREAK: + op = "break" + to = s.breakTo + } + if n.Left == nil { + // plain break/continue + if to == nil { + s.Error("%s is not in a loop", op) + return + } + // nothing to do; "to" is already the correct target + } else { + // labeled break/continue; look up the target + sym := n.Left.Sym + lab := s.label(sym) + if !lab.used() { + lab.useNode = n.Left + } + if !lab.defined() { + s.Error("%s label not defined: %v", op, sym) + lab.reported = true + return + } + switch n.Op { + case OCONTINUE: + to = lab.continueTarget + case OBREAK: + to = lab.breakTarget + } + if to == nil { + // Valid label but not usable with a break/continue here, e.g.: + // for { + // continue abc + // } + // abc: + // for {} + s.Error("invalid %s label %v", op, sym) + lab.reported = true + return + } + } + + b := s.endBlock() + addEdge(b, to) + case OFOR: // OFOR: for Ninit; Left; Right { Nbody } bCond := s.f.NewBlock(ssa.BlockPlain) @@ -422,9 +579,31 @@ func (s *state) stmt(n *Node) { addEdge(b, bBody) addEdge(b, bEnd) + // set up for continue/break in body + prevContinue := s.continueTo + prevBreak := s.breakTo + s.continueTo = bIncr + s.breakTo = bEnd + lab := s.labeledNodes[n] + if lab != nil { + // labeled for loop + lab.continueTarget = bIncr + lab.breakTarget = bEnd + } + // generate body s.startBlock(bBody) s.stmtList(n.Nbody) + + // tear down continue/break + s.continueTo = prevContinue + s.breakTo = prevBreak + if lab != nil { + lab.continueTarget = nil + lab.breakTarget = nil + } + + // done with body, goto incr if b := s.endBlock(); b != nil { addEdge(b, bIncr) } @@ -439,6 +618,32 @@ func (s *state) stmt(n *Node) { } s.startBlock(bEnd) + case OSWITCH, OSELECT: + // These have been mostly rewritten by the front end into their Nbody fields. + // Our main task is to correctly hook up any break statements. + bEnd := s.f.NewBlock(ssa.BlockPlain) + + prevBreak := s.breakTo + s.breakTo = bEnd + lab := s.labeledNodes[n] + if lab != nil { + // labeled + lab.breakTarget = bEnd + } + + // generate body code + s.stmtList(n.Nbody) + + s.breakTo = prevBreak + if lab != nil { + lab.breakTarget = nil + } + + if b := s.endBlock(); b != nil { + addEdge(b, bEnd) + } + s.startBlock(bEnd) + case OVARKILL: // TODO(khr): ??? anything to do here? Only for addrtaken variables? // Maybe just link it in the store chain? @@ -924,14 +1129,66 @@ func (s *state) boundsCheck(idx, len *ssa.Value) { s.startBlock(bNext) } +// checkgoto checks that a goto from from to to does not +// jump into a block or jump over variable declarations. +// It is a copy of checkgoto in the pre-SSA backend, +// modified only for line number handling. +// TODO: document how this works and why it is designed the way it is. +func (s *state) checkgoto(from *Node, to *Node) { + if from.Sym == to.Sym { + return + } + + nf := 0 + for fs := from.Sym; fs != nil; fs = fs.Link { + nf++ + } + nt := 0 + for fs := to.Sym; fs != nil; fs = fs.Link { + nt++ + } + fs := from.Sym + for ; nf > nt; nf-- { + fs = fs.Link + } + if fs != to.Sym { + // decide what to complain about. + // prefer to complain about 'into block' over declarations, + // so scan backward to find most recent block or else dcl. + var block *Sym + + var dcl *Sym + ts := to.Sym + for ; nt > nf; nt-- { + if ts.Pkg == nil { + block = ts + } else { + dcl = ts + } + ts = ts.Link + } + + for ts != fs { + if ts.Pkg == nil { + block = ts + } else { + dcl = ts + } + ts = ts.Link + fs = fs.Link + } + + lno := int(from.Left.Lineno) + if block != nil { + yyerrorl(lno, "goto %v jumps into block starting at %v", from.Left.Sym, Ctxt.Line(int(block.Lastlineno))) + } else { + yyerrorl(lno, "goto %v jumps over declaration of %v at %v", from.Left.Sym, dcl, Ctxt.Line(int(dcl.Lastlineno))) + } + } +} + // variable returns the value of a variable at the current location. func (s *state) variable(name *Node, t ssa.Type) *ssa.Value { - if s.curBlock == nil { - // Unimplemented instead of Fatal because fixedbugs/bug303.go - // demonstrates a case in which this appears to happen legitimately. - // TODO: decide on the correct behavior here. - s.Unimplementedf("nil curblock adding variable %v (%v)", name, t) - } v := s.vars[name] if v == nil { // TODO: get type? Take Sym as arg? @@ -989,8 +1246,13 @@ func (s *state) lookupVarIncoming(b *ssa.Block, t ssa.Type, name *Node) *ssa.Val vals = append(vals, s.lookupVarOutgoing(p, t, name)) } if len(vals) == 0 { - s.Unimplementedf("TODO: Handle fixedbugs/bug076.go") - return nil + // This block is dead; we have no predecessors and we're not the entry block. + // It doesn't matter what we use here as long as it is well-formed, + // so use the default/zero value. + if name == &memvar { + return s.startmem + } + return s.zeroVal(name.Type) } v0 := vals[0] for i := 1; i < len(vals); i++ { diff --git a/src/cmd/compile/internal/gc/ssa_test.go b/src/cmd/compile/internal/gc/ssa_test.go index fbbba6d9cb..4354d020f2 100644 --- a/src/cmd/compile/internal/gc/ssa_test.go +++ b/src/cmd/compile/internal/gc/ssa_test.go @@ -8,23 +8,24 @@ import ( "bytes" "internal/testenv" "os/exec" + "path/filepath" "runtime" "strings" "testing" ) -// Tests OANDAND and OOROR expressions and short circuiting. -// TODO: move these tests elsewhere? perhaps teach test/run.go how to run them -// with a new action verb. -func TestShortCircuit(t *testing.T) { +// TODO: move all these tests elsewhere? +// Perhaps teach test/run.go how to run them with a new action verb. +func runTest(t *testing.T, filename string) { if runtime.GOARCH != "amd64" { t.Skipf("skipping SSA tests on %s for now", runtime.GOARCH) } testenv.MustHaveGoBuild(t) var stdout, stderr bytes.Buffer - cmd := exec.Command("go", "run", "testdata/short_ssa.go") + cmd := exec.Command("go", "run", filepath.Join("testdata", filename)) cmd.Stdout = &stdout cmd.Stderr = &stderr + // TODO: set GOGC=off until we have stackmaps if err := cmd.Run(); err != nil { t.Fatalf("Failed: %v:\nOut: %s\nStderr: %s\n", err, &stdout, &stderr) } @@ -35,3 +36,9 @@ func TestShortCircuit(t *testing.T) { t.Errorf("Unimplemented message found in stderr:\n%s", s) } } + +// TestShortCircuit tests OANDAND and OOROR expressions and short circuiting. +func TestShortCircuit(t *testing.T) { runTest(t, "short_ssa.go") } + +// TestBreakContinue tests that continue and break statements do what they say. +func TestBreakContinue(t *testing.T) { runTest(t, "break_ssa.go") } diff --git a/src/cmd/compile/internal/gc/testdata/break_ssa.go b/src/cmd/compile/internal/gc/testdata/break_ssa.go new file mode 100644 index 0000000000..855ef70049 --- /dev/null +++ b/src/cmd/compile/internal/gc/testdata/break_ssa.go @@ -0,0 +1,255 @@ +// run + +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Tests continue and break. + +package main + +func continuePlain_ssa() int { + var n int + for i := 0; i < 10; i++ { + if i == 6 { + continue + } + n = i + } + return n +} + +func continueLabeled_ssa() int { + var n int +Next: + for i := 0; i < 10; i++ { + if i == 6 { + continue Next + } + n = i + } + return n +} + +func continuePlainInner_ssa() int { + var n int + for j := 0; j < 30; j += 10 { + for i := 0; i < 10; i++ { + if i == 6 { + continue + } + n = i + } + n += j + } + return n +} + +func continueLabeledInner_ssa() int { + var n int + for j := 0; j < 30; j += 10 { + Next: + for i := 0; i < 10; i++ { + if i == 6 { + continue Next + } + n = i + } + n += j + } + return n +} + +func continueLabeledOuter_ssa() int { + var n int +Next: + for j := 0; j < 30; j += 10 { + for i := 0; i < 10; i++ { + if i == 6 { + continue Next + } + n = i + } + n += j + } + return n +} + +func breakPlain_ssa() int { + var n int + for i := 0; i < 10; i++ { + if i == 6 { + break + } + n = i + } + return n +} + +func breakLabeled_ssa() int { + var n int +Next: + for i := 0; i < 10; i++ { + if i == 6 { + break Next + } + n = i + } + return n +} + +func breakPlainInner_ssa() int { + var n int + for j := 0; j < 30; j += 10 { + for i := 0; i < 10; i++ { + if i == 6 { + break + } + n = i + } + n += j + } + return n +} + +func breakLabeledInner_ssa() int { + var n int + for j := 0; j < 30; j += 10 { + Next: + for i := 0; i < 10; i++ { + if i == 6 { + break Next + } + n = i + } + n += j + } + return n +} + +func breakLabeledOuter_ssa() int { + var n int +Next: + for j := 0; j < 30; j += 10 { + for i := 0; i < 10; i++ { + if i == 6 { + break Next + } + n = i + } + n += j + } + return n +} + +var g, h int // globals to ensure optimizations don't collapse our switch statements + +func switchPlain_ssa() int { + var n int + switch g { + case 0: + n = 1 + break + n = 2 + } + return n +} + +func switchLabeled_ssa() int { + var n int +Done: + switch g { + case 0: + n = 1 + break Done + n = 2 + } + return n +} + +func switchPlainInner_ssa() int { + var n int + switch g { + case 0: + n = 1 + switch h { + case 0: + n += 10 + break + } + n = 2 + } + return n +} + +func switchLabeledInner_ssa() int { + var n int + switch g { + case 0: + n = 1 + Done: + switch h { + case 0: + n += 10 + break Done + } + n = 2 + } + return n +} + +func switchLabeledOuter_ssa() int { + var n int +Done: + switch g { + case 0: + n = 1 + switch h { + case 0: + n += 10 + break Done + } + n = 2 + } + return n +} + +func main() { + tests := [...]struct { + name string + fn func() int + want int + }{ + {"continuePlain_ssa", continuePlain_ssa, 9}, + {"continueLabeled_ssa", continueLabeled_ssa, 9}, + {"continuePlainInner_ssa", continuePlainInner_ssa, 29}, + {"continueLabeledInner_ssa", continueLabeledInner_ssa, 29}, + {"continueLabeledOuter_ssa", continueLabeledOuter_ssa, 5}, + + {"breakPlain_ssa", breakPlain_ssa, 5}, + {"breakLabeled_ssa", breakLabeled_ssa, 5}, + {"breakPlainInner_ssa", breakPlainInner_ssa, 25}, + {"breakLabeledInner_ssa", breakLabeledInner_ssa, 25}, + {"breakLabeledOuter_ssa", breakLabeledOuter_ssa, 5}, + + {"switchPlain_ssa", switchPlain_ssa, 1}, + {"switchLabeled_ssa", switchLabeled_ssa, 1}, + {"switchPlainInner_ssa", switchPlainInner_ssa, 2}, + {"switchLabeledInner_ssa", switchLabeledInner_ssa, 2}, + {"switchLabeledOuter_ssa", switchLabeledOuter_ssa, 11}, + + // no select tests; they're identical to switch + } + + var failed bool + for _, test := range tests { + if got := test.fn(); test.fn() != test.want { + print(test.name, "()=", got, ", want ", test.want, "\n") + failed = true + } + } + + if failed { + panic("failed") + } +} diff --git a/src/cmd/compile/internal/ssa/compile.go b/src/cmd/compile/internal/ssa/compile.go index 4a6c2a9404..7a7b9926ed 100644 --- a/src/cmd/compile/internal/ssa/compile.go +++ b/src/cmd/compile/internal/ssa/compile.go @@ -50,6 +50,7 @@ type pass struct { var passes = [...]pass{ {"phielim", phielim}, {"copyelim", copyelim}, + {"early deadcode", deadcode}, // remove generated dead code to avoid doing pointless work during opt {"opt", opt}, {"opt deadcode", deadcode}, // remove any blocks orphaned during opt {"generic cse", cse}, diff --git a/test/label.go b/test/label.go index a1811c2d68..c3c0c27edd 100644 --- a/test/label.go +++ b/test/label.go @@ -58,4 +58,8 @@ L10: default: break L10 } + + goto L10 + + goto go2 // ERROR "label go2 not defined" } diff --git a/test/label1.go b/test/label1.go index bc8fea6f6a..937b5cb900 100644 --- a/test/label1.go +++ b/test/label1.go @@ -31,11 +31,17 @@ L2: break L2 } if x == 1 { - continue L2 // ERROR "invalid continue label .*L2" + continue L2 // ERROR "invalid continue label .*L2|continue is not in a loop" } goto L2 } + for { + if x == 1 { + continue L2 // ERROR "invalid continue label .*L2" + } + } + L3: switch { case x > 10: @@ -43,7 +49,7 @@ L3: break L3 } if x == 12 { - continue L3 // ERROR "invalid continue label .*L3" + continue L3 // ERROR "invalid continue label .*L3|continue is not in a loop" } goto L3 } @@ -54,7 +60,7 @@ L4: break L4 // ERROR "invalid break label .*L4" } if x == 14 { - continue L4 // ERROR "invalid continue label .*L4" + continue L4 // ERROR "invalid continue label .*L4|continue is not in a loop" } if x == 15 { goto L4 @@ -67,7 +73,7 @@ L5: break L5 // ERROR "invalid break label .*L5" } if x == 17 { - continue L5 // ERROR "invalid continue label .*L5" + continue L5 // ERROR "invalid continue label .*L5|continue is not in a loop" } if x == 18 { goto L5 @@ -84,4 +90,21 @@ L5: goto L1 } } + + continue // ERROR "continue is not in a loop" + for { + continue on // ERROR "continue label not defined: on" + } + + break // ERROR "break is not in a loop" + for { + break dance // ERROR "break label not defined: dance" + } + + for { + switch x { + case 1: + continue + } + } } -- cgit v1.3 From db5232620a1722ae1bcdf5f0d8cd15ba0bac2077 Mon Sep 17 00:00:00 2001 From: Todd Neal Date: Sat, 25 Jul 2015 12:53:58 -0500 Subject: [dev.ssa] cmd/compile: only fold 32 bit integers for add/multiply Fix an issue where doasm fails if trying to multiply by a larger than 32 bit const (doasm: notfound ft=9 tt=14 00008 IMULQ $34359738369, CX 9 14). Fix truncation of 64 to 32 bit integer when generating LEA causing incorrect values to be computed. Change-Id: I1e65b63cc32ac673a9bb5a297b578b44c2f1ac8f Reviewed-on: https://go-review.googlesource.com/12678 Reviewed-by: Keith Randall --- src/cmd/compile/internal/gc/ssa_test.go | 3 ++ src/cmd/compile/internal/gc/testdata/arith_ssa.go | 47 +++++++++++++++++++++++ src/cmd/compile/internal/ssa/gen/AMD64.rules | 9 +++-- src/cmd/compile/internal/ssa/rewrite.go | 7 +++- src/cmd/compile/internal/ssa/rewriteAMD64.go | 45 +++++++++++++--------- 5 files changed, 88 insertions(+), 23 deletions(-) create mode 100644 src/cmd/compile/internal/gc/testdata/arith_ssa.go (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/ssa_test.go b/src/cmd/compile/internal/gc/ssa_test.go index 4354d020f2..f51d6de871 100644 --- a/src/cmd/compile/internal/gc/ssa_test.go +++ b/src/cmd/compile/internal/gc/ssa_test.go @@ -42,3 +42,6 @@ func TestShortCircuit(t *testing.T) { runTest(t, "short_ssa.go") } // TestBreakContinue tests that continue and break statements do what they say. func TestBreakContinue(t *testing.T) { runTest(t, "break_ssa.go") } + +// TestArithmetic tests that both backends have the same result for arithmetic expressions. +func TestArithmetic(t *testing.T) { runTest(t, "arith_ssa.go") } diff --git a/src/cmd/compile/internal/gc/testdata/arith_ssa.go b/src/cmd/compile/internal/gc/testdata/arith_ssa.go new file mode 100644 index 0000000000..a4fdf16f7d --- /dev/null +++ b/src/cmd/compile/internal/gc/testdata/arith_ssa.go @@ -0,0 +1,47 @@ +// run + +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Tests arithmetic expressions + +package main + +func test64BitConstMult(a, b int64) { + want := 34359738369*a + b*34359738370 + if got := test64BitConstMult_ssa(a, b); want != got { + println("test64BitConstMult failed, wanted", want, "got", got) + failed = true + } +} +func test64BitConstMult_ssa(a, b int64) int64 { + switch { // prevent inlining + } + return 34359738369*a + b*34359738370 +} + +func test64BitConstAdd(a, b int64) { + want := a + 575815584948629622 + b + 2991856197886747025 + if got := test64BitConstAdd_ssa(a, b); want != got { + println("test64BitConstAdd failed, wanted", want, "got", got) + failed = true + } +} +func test64BitConstAdd_ssa(a, b int64) int64 { + switch { + } + return a + 575815584948629622 + b + 2991856197886747025 +} + +var failed = false + +func main() { + + test64BitConstMult(1, 2) + test64BitConstAdd(1, 2) + + if failed { + panic("failed") + } +} diff --git a/src/cmd/compile/internal/ssa/gen/AMD64.rules b/src/cmd/compile/internal/ssa/gen/AMD64.rules index f1ae4f6a82..7f5fd663e3 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64.rules +++ b/src/cmd/compile/internal/ssa/gen/AMD64.rules @@ -136,12 +136,13 @@ // TODO: Should this be a separate pass? // fold constants into instructions -(ADDQ x (MOVQconst [c])) -> (ADDQconst [c] x) // TODO: restrict c to int32 range? -(ADDQ (MOVQconst [c]) x) -> (ADDQconst [c] x) +// TODO: restrict c to int32 range for all? +(ADDQ x (MOVQconst [c])) && is32Bit(c) -> (ADDQconst [c] x) +(ADDQ (MOVQconst [c]) x) && is32Bit(c) -> (ADDQconst [c] x) (SUBQ x (MOVQconst [c])) -> (SUBQconst x [c]) (SUBQ (MOVQconst [c]) x) -> (NEGQ (SUBQconst x [c])) -(MULQ x (MOVQconst [c])) && c == int64(int32(c)) -> (MULQconst [c] x) -(MULQ (MOVQconst [c]) x) -> (MULQconst [c] x) +(MULQ x (MOVQconst [c])) && is32Bit(c) -> (MULQconst [c] x) +(MULQ (MOVQconst [c]) x) && is32Bit(c) -> (MULQconst [c] x) (ANDQ x (MOVQconst [c])) -> (ANDQconst [c] x) (ANDQ (MOVQconst [c]) x) -> (ANDQconst [c] x) (SHLQ x (MOVQconst [c])) -> (SHLQconst [c] x) diff --git a/src/cmd/compile/internal/ssa/rewrite.go b/src/cmd/compile/internal/ssa/rewrite.go index 90ac7d7a68..a02f1d50b2 100644 --- a/src/cmd/compile/internal/ssa/rewrite.go +++ b/src/cmd/compile/internal/ssa/rewrite.go @@ -130,7 +130,12 @@ func log2(n int64) (l int64) { return l } -// isPowerOfTwo returns true if n is a power of 2. +// isPowerOfTwo reports whether n is a power of 2. func isPowerOfTwo(n int64) bool { return n > 0 && n&(n-1) == 0 } + +// is32Bit reports whether n can be represented as a signed 32 bit integer. +func is32Bit(n int64) bool { + return n == int64(int32(n)) +} diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go index f8642a7bb5..5019e69529 100644 --- a/src/cmd/compile/internal/ssa/rewriteAMD64.go +++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go @@ -6,14 +6,17 @@ func rewriteValueAMD64(v *Value, config *Config) bool { switch v.Op { case OpAMD64ADDQ: // match: (ADDQ x (MOVQconst [c])) - // cond: + // cond: is32Bit(c) // result: (ADDQconst [c] x) { x := v.Args[0] if v.Args[1].Op != OpAMD64MOVQconst { - goto endacffd55e74ee0ff59ad58a18ddfc9973 + goto end1de8aeb1d043e0dadcffd169a99ce5c0 } c := v.Args[1].AuxInt + if !(is32Bit(c)) { + goto end1de8aeb1d043e0dadcffd169a99ce5c0 + } v.Op = OpAMD64ADDQconst v.AuxInt = 0 v.Aux = nil @@ -22,18 +25,21 @@ func rewriteValueAMD64(v *Value, config *Config) bool { v.AddArg(x) return true } - goto endacffd55e74ee0ff59ad58a18ddfc9973 - endacffd55e74ee0ff59ad58a18ddfc9973: + goto end1de8aeb1d043e0dadcffd169a99ce5c0 + end1de8aeb1d043e0dadcffd169a99ce5c0: ; // match: (ADDQ (MOVQconst [c]) x) - // cond: + // cond: is32Bit(c) // result: (ADDQconst [c] x) { if v.Args[0].Op != OpAMD64MOVQconst { - goto end7166f476d744ab7a51125959d3d3c7e2 + goto endca635e3bdecd9e3aeb892f841021dfaa } c := v.Args[0].AuxInt x := v.Args[1] + if !(is32Bit(c)) { + goto endca635e3bdecd9e3aeb892f841021dfaa + } v.Op = OpAMD64ADDQconst v.AuxInt = 0 v.Aux = nil @@ -42,8 +48,8 @@ func rewriteValueAMD64(v *Value, config *Config) bool { v.AddArg(x) return true } - goto end7166f476d744ab7a51125959d3d3c7e2 - end7166f476d744ab7a51125959d3d3c7e2: + goto endca635e3bdecd9e3aeb892f841021dfaa + endca635e3bdecd9e3aeb892f841021dfaa: ; // match: (ADDQ x (SHLQconst [3] y)) // cond: @@ -1223,16 +1229,16 @@ func rewriteValueAMD64(v *Value, config *Config) bool { ; case OpAMD64MULQ: // match: (MULQ x (MOVQconst [c])) - // cond: c == int64(int32(c)) + // cond: is32Bit(c) // result: (MULQconst [c] x) { x := v.Args[0] if v.Args[1].Op != OpAMD64MOVQconst { - goto end680a32a37babfff4bfa7d23be592a131 + goto endb38c6e3e0ddfa25ba0ef9684ac1528c0 } c := v.Args[1].AuxInt - if !(c == int64(int32(c))) { - goto end680a32a37babfff4bfa7d23be592a131 + if !(is32Bit(c)) { + goto endb38c6e3e0ddfa25ba0ef9684ac1528c0 } v.Op = OpAMD64MULQconst v.AuxInt = 0 @@ -1242,18 +1248,21 @@ func rewriteValueAMD64(v *Value, config *Config) bool { v.AddArg(x) return true } - goto end680a32a37babfff4bfa7d23be592a131 - end680a32a37babfff4bfa7d23be592a131: + goto endb38c6e3e0ddfa25ba0ef9684ac1528c0 + endb38c6e3e0ddfa25ba0ef9684ac1528c0: ; // match: (MULQ (MOVQconst [c]) x) - // cond: + // cond: is32Bit(c) // result: (MULQconst [c] x) { if v.Args[0].Op != OpAMD64MOVQconst { - goto endc6e18d6968175d6e58eafa6dcf40c1b8 + goto end9cb4f29b0bd7141639416735dcbb3b87 } c := v.Args[0].AuxInt x := v.Args[1] + if !(is32Bit(c)) { + goto end9cb4f29b0bd7141639416735dcbb3b87 + } v.Op = OpAMD64MULQconst v.AuxInt = 0 v.Aux = nil @@ -1262,8 +1271,8 @@ func rewriteValueAMD64(v *Value, config *Config) bool { v.AddArg(x) return true } - goto endc6e18d6968175d6e58eafa6dcf40c1b8 - endc6e18d6968175d6e58eafa6dcf40c1b8: + goto end9cb4f29b0bd7141639416735dcbb3b87 + end9cb4f29b0bd7141639416735dcbb3b87: ; case OpAMD64MULQconst: // match: (MULQconst [-1] x) -- cgit v1.3 From c9a38ce758e3de93e73842bf42a6e84f182d183a Mon Sep 17 00:00:00 2001 From: Todd Neal Date: Sun, 26 Jul 2015 09:48:20 -0500 Subject: [dev.ssa] cmd/compile: don't flush a value derived from the current value If flushing a value from a register that might be used by the current old-schedule value, save it to the home location. This resolves the error that was changed from panic to unimplemented in CL 12655. Change-Id: If864be34abcd6e11d6117a061376e048a3e29b3a Reviewed-on: https://go-review.googlesource.com/12682 Reviewed-by: Keith Randall Reviewed-by: Josh Bleecher Snyder --- src/cmd/compile/internal/gc/testdata/arith_ssa.go | 20 ++++++++++++++++++++ src/cmd/compile/internal/ssa/regalloc.go | 4 ++-- 2 files changed, 22 insertions(+), 2 deletions(-) (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/testdata/arith_ssa.go b/src/cmd/compile/internal/gc/testdata/arith_ssa.go index a4fdf16f7d..22fc034a1c 100644 --- a/src/cmd/compile/internal/gc/testdata/arith_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/arith_ssa.go @@ -8,6 +8,8 @@ package main +// test64BitConstMulti tests that rewrite rules don't fold 64 bit constants +// into multiply instructions. func test64BitConstMult(a, b int64) { want := 34359738369*a + b*34359738370 if got := test64BitConstMult_ssa(a, b); want != got { @@ -21,6 +23,8 @@ func test64BitConstMult_ssa(a, b int64) int64 { return 34359738369*a + b*34359738370 } +// test64BitConstAdd tests that rewrite rules don't fold 64 bit constants +// into add instructions. func test64BitConstAdd(a, b int64) { want := a + 575815584948629622 + b + 2991856197886747025 if got := test64BitConstAdd_ssa(a, b); want != got { @@ -34,12 +38,28 @@ func test64BitConstAdd_ssa(a, b int64) int64 { return a + 575815584948629622 + b + 2991856197886747025 } +// testRegallocCVSpill tests that regalloc spills a value whose last use is the +// current value. +func testRegallocCVSpill(a, b, c, d int8) { + want := a + -32 + b + 63*c*-87*d + if got := testRegallocCVSpill_ssa(a, b, c, d); want != got { + println("testRegallocCVSpill failed, wanted", want, "got", got) + failed = true + } +} +func testRegallocCVSpill_ssa(a, b, c, d int8) int8 { + switch { + } + return a + -32 + b + 63*c*-87*d +} + var failed = false func main() { test64BitConstMult(1, 2) test64BitConstAdd(1, 2) + testRegallocCVSpill(1, 2, 3, 4) if failed { panic("failed") diff --git a/src/cmd/compile/internal/ssa/regalloc.go b/src/cmd/compile/internal/ssa/regalloc.go index 101eedd93f..a13b8b2a06 100644 --- a/src/cmd/compile/internal/ssa/regalloc.go +++ b/src/cmd/compile/internal/ssa/regalloc.go @@ -238,7 +238,7 @@ func regalloc(f *Func) { if regs[r].v != nil { x := regs[r].v c := regs[r].c - if regs[r].dirty && lastUse[x.ID] > idx { + if regs[r].dirty && lastUse[x.ID] >= idx { // Write x back to home. Its value is currently held in c. x.Op = OpStoreReg x.Aux = nil @@ -317,7 +317,7 @@ func regalloc(f *Func) { if regs[r].v != nil { x := regs[r].v c := regs[r].c - if regs[r].dirty && lastUse[x.ID] > idx { + if regs[r].dirty && lastUse[x.ID] >= idx { // Write x back to home. Its value is currently held in c. x.Op = OpStoreReg x.Aux = nil -- cgit v1.3 From 7402416a8b0dd30c7a245ca053561a87d4021be6 Mon Sep 17 00:00:00 2001 From: Alexandru Moșoi Date: Wed, 29 Jul 2015 17:52:25 +0200 Subject: [dev.ssa] cmd/compile/internal/ssa/gen: implement OOR. From compiling go there were 761 functions where OR was needed. Change-Id: Ied8bf59cec50a3175273387bc7416bd042def6d8 Reviewed-on: https://go-review.googlesource.com/12766 Reviewed-by: Keith Randall Reviewed-by: Josh Bleecher Snyder --- src/cmd/compile/internal/gc/ssa.go | 14 +++- src/cmd/compile/internal/gc/testdata/arith_ssa.go | 22 ++++++ src/cmd/compile/internal/ssa/gen/AMD64.rules | 5 ++ src/cmd/compile/internal/ssa/gen/AMD64Ops.go | 6 ++ src/cmd/compile/internal/ssa/gen/genericOps.go | 5 ++ src/cmd/compile/internal/ssa/opGen.go | 89 +++++++++++++++++++++++ src/cmd/compile/internal/ssa/rewriteAMD64.go | 72 ++++++++++++++++++ 7 files changed, 211 insertions(+), 2 deletions(-) (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 8eeb29d4bd..4334dc729a 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -745,6 +745,15 @@ var opToSSA = map[opAndType]ssa.Op{ opAndType{OAND, TINT64}: ssa.OpAnd64, opAndType{OAND, TUINT64}: ssa.OpAnd64, + opAndType{OOR, TINT8}: ssa.OpOr8, + opAndType{OOR, TUINT8}: ssa.OpOr8, + opAndType{OOR, TINT16}: ssa.OpOr16, + opAndType{OOR, TUINT16}: ssa.OpOr16, + opAndType{OOR, TINT32}: ssa.OpOr32, + opAndType{OOR, TUINT32}: ssa.OpOr32, + opAndType{OOR, TINT64}: ssa.OpOr64, + opAndType{OOR, TUINT64}: ssa.OpOr64, + opAndType{OLSH, TINT8}: ssa.OpLsh8, opAndType{OLSH, TUINT8}: ssa.OpLsh8, opAndType{OLSH, TINT16}: ssa.OpLsh16, @@ -990,7 +999,7 @@ func (s *state) expr(n *Node) *ssa.Value { a := s.expr(n.Left) b := s.expr(n.Right) return s.newValue2(s.ssaOp(n.Op, n.Left.Type), ssa.TypeBool, a, b) - case OADD, OSUB, OMUL, OLSH, ORSH, OAND: + case OADD, OAND, OLSH, OMUL, OOR, ORSH, OSUB: a := s.expr(n.Left) b := s.expr(n.Right) return s.newValue2(s.ssaOp(n.Op, n.Type), a.Type, a, b) @@ -1621,7 +1630,8 @@ func genValue(v *ssa.Value) { p.To.Reg = regnum(v) case ssa.OpAMD64ADDB, ssa.OpAMD64ANDQ, ssa.OpAMD64ANDL, ssa.OpAMD64ANDW, ssa.OpAMD64ANDB, - ssa.OpAMD64MULQ, ssa.OpAMD64MULL, ssa.OpAMD64MULW: + ssa.OpAMD64MULQ, ssa.OpAMD64MULL, ssa.OpAMD64MULW, + ssa.OpAMD64ORQ, ssa.OpAMD64ORL, ssa.OpAMD64ORW, ssa.OpAMD64ORB: r := regnum(v) x := regnum(v.Args[0]) y := regnum(v.Args[1]) diff --git a/src/cmd/compile/internal/gc/testdata/arith_ssa.go b/src/cmd/compile/internal/gc/testdata/arith_ssa.go index 22fc034a1c..2731337dbf 100644 --- a/src/cmd/compile/internal/gc/testdata/arith_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/arith_ssa.go @@ -53,6 +53,28 @@ func testRegallocCVSpill_ssa(a, b, c, d int8) int8 { return a + -32 + b + 63*c*-87*d } +func testBitwiseLogic() { + a, b := uint32(57623283), uint32(1314713839) + if want, got := uint32(38551779), testBitwiseAnd_ssa(a, b); want != got { + println("testBitwiseAnd failed, wanted", want, "got", got) + } + if want, got := uint32(1333785343), testBitwiseOr_ssa(a, b); want != got { + println("testBitwiseAnd failed, wanted", want, "got", got) + } +} + +func testBitwiseAnd_ssa(a, b uint32) uint32 { + switch { // prevent inlining + } + return a & b +} + +func testBitwiseOr_ssa(a, b uint32) uint32 { + switch { // prevent inlining + } + return a | b +} + var failed = false func main() { diff --git a/src/cmd/compile/internal/ssa/gen/AMD64.rules b/src/cmd/compile/internal/ssa/gen/AMD64.rules index 3e667c8951..4ceb6185c5 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64.rules +++ b/src/cmd/compile/internal/ssa/gen/AMD64.rules @@ -21,6 +21,11 @@ (And16 x y) -> (ANDW x y) (And8 x y) -> (ANDB x y) +(Or64 x y) -> (ORQ x y) +(Or32 x y) -> (ORL x y) +(Or16 x y) -> (ORW x y) +(Or8 x y) -> (ORB x y) + (Sub64 x y) -> (SUBQ x y) (Sub32 x y) -> (SUBL x y) (Sub16 x y) -> (SUBW x y) diff --git a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go index 40f7b1680f..1983ae8c44 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go @@ -203,6 +203,12 @@ func init() { {name: "ANDW", reg: gp21, asm: "ANDW"}, // arg0 & arg1 {name: "ANDB", reg: gp21, asm: "ANDB"}, // arg0 & arg1 + {name: "ORQ", reg: gp21, asm: "ORQ"}, // arg0 | arg1 + {name: "ORQconst", reg: gp11, asm: "ORQ"}, // arg0 | auxint + {name: "ORL", reg: gp21, asm: "ORL"}, // arg0 | arg1 + {name: "ORW", reg: gp21, asm: "ORW"}, // arg0 | arg1 + {name: "ORB", reg: gp21, asm: "ORB"}, // arg0 | arg1 + // (InvertFlags (CMPQ a b)) == (CMPQ b a) // So if we want (SETL (CMPQ a b)) but we can't do that because a is a constant, // then we do (SETL (InvertFlags (CMPQ b a))) instead. diff --git a/src/cmd/compile/internal/ssa/gen/genericOps.go b/src/cmd/compile/internal/ssa/gen/genericOps.go index 732641319f..0459a2edc0 100644 --- a/src/cmd/compile/internal/ssa/gen/genericOps.go +++ b/src/cmd/compile/internal/ssa/gen/genericOps.go @@ -32,6 +32,11 @@ var genericOps = []opData{ {name: "And32"}, {name: "And64"}, + {name: "Or8"}, // arg0 | arg1 + {name: "Or16"}, + {name: "Or32"}, + {name: "Or64"}, + {name: "Lsh8"}, // arg0 << arg1 {name: "Lsh16"}, {name: "Lsh32"}, diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index 358459ea8e..4fe098136f 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -134,6 +134,11 @@ const ( OpAMD64ANDL OpAMD64ANDW OpAMD64ANDB + OpAMD64ORQ + OpAMD64ORQconst + OpAMD64ORL + OpAMD64ORW + OpAMD64ORB OpAMD64InvertFlags OpAdd8 @@ -154,6 +159,10 @@ const ( OpAnd16 OpAnd32 OpAnd64 + OpOr8 + OpOr16 + OpOr32 + OpOr64 OpLsh8 OpLsh16 OpLsh32 @@ -1254,6 +1263,70 @@ var opcodeTable = [...]opInfo{ }, }, }, + { + name: "ORQ", + asm: x86.AORQ, + reg: regInfo{ + inputs: []regMask{ + 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + outputs: []regMask{ + 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + }, + }, + { + name: "ORQconst", + asm: x86.AORQ, + reg: regInfo{ + inputs: []regMask{ + 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + outputs: []regMask{ + 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + }, + }, + { + name: "ORL", + asm: x86.AORL, + reg: regInfo{ + inputs: []regMask{ + 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + outputs: []regMask{ + 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + }, + }, + { + name: "ORW", + asm: x86.AORW, + reg: regInfo{ + inputs: []regMask{ + 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + outputs: []regMask{ + 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + }, + }, + { + name: "ORB", + asm: x86.AORB, + reg: regInfo{ + inputs: []regMask{ + 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + outputs: []regMask{ + 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + }, + }, { name: "InvertFlags", reg: regInfo{}, @@ -1331,6 +1404,22 @@ var opcodeTable = [...]opInfo{ name: "And64", generic: true, }, + { + name: "Or8", + generic: true, + }, + { + name: "Or16", + generic: true, + }, + { + name: "Or32", + generic: true, + }, + { + name: "Or64", + generic: true, + }, { name: "Lsh8", generic: true, diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go index b172cf3527..ec8e381201 100644 --- a/src/cmd/compile/internal/ssa/rewriteAMD64.go +++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go @@ -2489,6 +2489,78 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto end0429f947ee7ac49ff45a243e461a5290 end0429f947ee7ac49ff45a243e461a5290: ; + case OpOr16: + // match: (Or16 x y) + // cond: + // result: (ORW x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64ORW + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto end8fedf2c79d5607b7056b0ff015199cbd + end8fedf2c79d5607b7056b0ff015199cbd: + ; + case OpOr32: + // match: (Or32 x y) + // cond: + // result: (ORL x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64ORL + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto endea45bed9ca97d2995b68b53e6012d384 + endea45bed9ca97d2995b68b53e6012d384: + ; + case OpOr64: + // match: (Or64 x y) + // cond: + // result: (ORQ x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64ORQ + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto end3a446becaf2461f4f1a41faeef313f41 + end3a446becaf2461f4f1a41faeef313f41: + ; + case OpOr8: + // match: (Or8 x y) + // cond: + // result: (ORB x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64ORB + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto end6f8a8c559a167d1f0a5901d09a1fb248 + end6f8a8c559a167d1f0a5901d09a1fb248: + ; case OpRsh64: // match: (Rsh64 x y) // cond: y.Type.Size() == 8 -- cgit v1.3 From 9271ecc8c62930e4cac73f9dfe8ef0b1bb97cee6 Mon Sep 17 00:00:00 2001 From: Todd Neal Date: Thu, 30 Jul 2015 13:57:43 -0400 Subject: [dev.ssa] cmd/compile: fix SUBQ generation error Fix code generation error that resulted in a multi-argument NEGQ doasm: notfound ft=13 tt=13 00134 NEGQ AX, AX 13 13 Change-Id: I8b712d21a5523eccbae1f33ccea417844c27073e Reviewed-on: https://go-review.googlesource.com/12869 Reviewed-by: Josh Bleecher Snyder --- src/cmd/compile/internal/gc/ssa.go | 2 -- src/cmd/compile/internal/gc/testdata/arith_ssa.go | 16 +++++++++++++++- 2 files changed, 15 insertions(+), 3 deletions(-) (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 32844093d2..430adc31fd 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -1765,8 +1765,6 @@ func genValue(v *ssa.Value) { p.From.Reg = y if neg { p := Prog(x86.ANEGQ) // TODO: use correct size? This is mostly a hack until regalloc does 2-address correctly - p.From.Type = obj.TYPE_REG - p.From.Reg = r p.To.Type = obj.TYPE_REG p.To.Reg = r } diff --git a/src/cmd/compile/internal/gc/testdata/arith_ssa.go b/src/cmd/compile/internal/gc/testdata/arith_ssa.go index 2731337dbf..3fd2fad457 100644 --- a/src/cmd/compile/internal/gc/testdata/arith_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/arith_ssa.go @@ -75,6 +75,20 @@ func testBitwiseOr_ssa(a, b uint32) uint32 { return a | b } +// testSubqToNegq ensures that the SUBQ -> NEGQ translation works correctly. +func testSubqToNegq(a, b, c, d, e, f, g, h, i, j, k int64) { + want := a + 8207351403619448057 - b - 1779494519303207690 + c*8810076340510052032*d - 4465874067674546219 - e*4361839741470334295 - f + 8688847565426072650*g*8065564729145417479 + if got := testSubqToNegq_ssa(a, b, c, d, e, f, g, h, i, j, k); want != got { + println("testSubqToNegq failed, wanted", want, "got", got) + failed = true + } +} +func testSubqToNegq_ssa(a, b, c, d, e, f, g, h, i, j, k int64) int64 { + switch { // prevent inlining + } + return a + 8207351403619448057 - b - 1779494519303207690 + c*8810076340510052032*d - 4465874067674546219 - e*4361839741470334295 - f + 8688847565426072650*g*8065564729145417479 +} + var failed = false func main() { @@ -82,7 +96,7 @@ func main() { test64BitConstMult(1, 2) test64BitConstAdd(1, 2) testRegallocCVSpill(1, 2, 3, 4) - + testSubqToNegq(1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2) if failed { panic("failed") } -- cgit v1.3 From 6d9362a1f79a916a1a8de0a6bde8a3a94dc89944 Mon Sep 17 00:00:00 2001 From: Alexandru Moșoi Date: Thu, 30 Jul 2015 12:33:36 +0200 Subject: [dev.ssa] cmd/compile/internal/ssa/gen: implement OXOR. From compiling go there were 260 functions where XOR was needed. Much of the required changes for implementing XOR were already done in 12813. Change-Id: I5a68aa028f5ed597bc1d62cedbef3620753dfe82 Reviewed-on: https://go-review.googlesource.com/12901 Reviewed-by: Keith Randall --- src/cmd/compile/internal/gc/ssa.go | 11 ++++++++++- src/cmd/compile/internal/gc/testdata/arith_ssa.go | 17 ++++++++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index b9113b2733..c292e4e014 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -763,6 +763,15 @@ var opToSSA = map[opAndType]ssa.Op{ opAndType{OOR, TINT64}: ssa.OpOr64, opAndType{OOR, TUINT64}: ssa.OpOr64, + opAndType{OXOR, TINT8}: ssa.OpXor8, + opAndType{OXOR, TUINT8}: ssa.OpXor8, + opAndType{OXOR, TINT16}: ssa.OpXor16, + opAndType{OXOR, TUINT16}: ssa.OpXor16, + opAndType{OXOR, TINT32}: ssa.OpXor32, + opAndType{OXOR, TUINT32}: ssa.OpXor32, + opAndType{OXOR, TINT64}: ssa.OpXor64, + opAndType{OXOR, TUINT64}: ssa.OpXor64, + opAndType{OEQ, TBOOL}: ssa.OpEq8, opAndType{OEQ, TINT8}: ssa.OpEq8, opAndType{OEQ, TUINT8}: ssa.OpEq8, @@ -1123,7 +1132,7 @@ func (s *state) expr(n *Node) *ssa.Value { a := s.expr(n.Left) b := s.expr(n.Right) return s.newValue2(s.ssaOp(n.Op, n.Left.Type), ssa.TypeBool, a, b) - case OADD, OSUB, OMUL, OAND, OOR: + case OADD, OAND, OMUL, OOR, OSUB, OXOR: a := s.expr(n.Left) b := s.expr(n.Right) return s.newValue2(s.ssaOp(n.Op, n.Type), a.Type, a, b) diff --git a/src/cmd/compile/internal/gc/testdata/arith_ssa.go b/src/cmd/compile/internal/gc/testdata/arith_ssa.go index 3fd2fad457..0a2290ef7b 100644 --- a/src/cmd/compile/internal/gc/testdata/arith_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/arith_ssa.go @@ -57,9 +57,15 @@ func testBitwiseLogic() { a, b := uint32(57623283), uint32(1314713839) if want, got := uint32(38551779), testBitwiseAnd_ssa(a, b); want != got { println("testBitwiseAnd failed, wanted", want, "got", got) + failed = true } if want, got := uint32(1333785343), testBitwiseOr_ssa(a, b); want != got { - println("testBitwiseAnd failed, wanted", want, "got", got) + println("testBitwiseOr failed, wanted", want, "got", got) + failed = true + } + if want, got := uint32(1295233564), testBitwiseXor_ssa(a, b); want != got { + println("testBitwiseXor failed, wanted", want, "got", got) + failed = true } } @@ -75,6 +81,12 @@ func testBitwiseOr_ssa(a, b uint32) uint32 { return a | b } +func testBitwiseXor_ssa(a, b uint32) uint32 { + switch { // prevent inlining + } + return a ^ b +} + // testSubqToNegq ensures that the SUBQ -> NEGQ translation works correctly. func testSubqToNegq(a, b, c, d, e, f, g, h, i, j, k int64) { want := a + 8207351403619448057 - b - 1779494519303207690 + c*8810076340510052032*d - 4465874067674546219 - e*4361839741470334295 - f + 8688847565426072650*g*8065564729145417479 @@ -83,6 +95,7 @@ func testSubqToNegq(a, b, c, d, e, f, g, h, i, j, k int64) { failed = true } } + func testSubqToNegq_ssa(a, b, c, d, e, f, g, h, i, j, k int64) int64 { switch { // prevent inlining } @@ -97,6 +110,8 @@ func main() { test64BitConstAdd(1, 2) testRegallocCVSpill(1, 2, 3, 4) testSubqToNegq(1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2) + testBitwiseLogic() + if failed { panic("failed") } -- cgit v1.3 From 9b25da732b62d294bc0762d45c77d1a0095d81fa Mon Sep 17 00:00:00 2001 From: Alexandru Moșoi Date: Fri, 31 Jul 2015 12:32:22 +0200 Subject: [dev.ssa] cmd/compile/internal/ssa/gen: add more simplifications rules This is a follow up on https://go-review.googlesource.com/#/c/12420/ with some rules moved to AMD64 closer to the existing rules. Change-Id: Id346bb0fc4459b3c49b826a59cc74308a590310e Reviewed-on: https://go-review.googlesource.com/12906 Reviewed-by: Keith Randall --- src/cmd/compile/internal/gc/testdata/arith_ssa.go | 36 ++ src/cmd/compile/internal/ssa/gen/AMD64.rules | 35 ++ src/cmd/compile/internal/ssa/gen/generic.rules | 8 + src/cmd/compile/internal/ssa/gen/rulegen.go | 4 +- src/cmd/compile/internal/ssa/rewriteAMD64.go | 612 ++++++++++++++++++++++ src/cmd/compile/internal/ssa/rewritegeneric.go | 154 +++++- 6 files changed, 846 insertions(+), 3 deletions(-) (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/testdata/arith_ssa.go b/src/cmd/compile/internal/gc/testdata/arith_ssa.go index 0a2290ef7b..1c8445fbda 100644 --- a/src/cmd/compile/internal/gc/testdata/arith_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/arith_ssa.go @@ -67,6 +67,30 @@ func testBitwiseLogic() { println("testBitwiseXor failed, wanted", want, "got", got) failed = true } + if want, got := int32(832), testBitwiseLsh_ssa(13, 4, 2); want != got { + println("testBitwiseXor failed, wanted", want, "got", got) + failed = true + } + if want, got := int32(0), testBitwiseLsh_ssa(13, 25, 15); want != got { + println("testBitwiseLsh failed, wanted", want, "got", got) + failed = true + } + if want, got := int32(0), testBitwiseLsh_ssa(-13, 25, 15); want != got { + println("testBitwiseLsh failed, wanted", want, "got", got) + failed = true + } + if want, got := int32(0), testBitwiseRsh_ssa(-13, 25, 15); want != got { + println("testBitwiseLsh failed, wanted", want, "got", got) + failed = true + } + if want, got := int32(0), testBitwiseRsh_ssa(13, 25, 15); want != got { + println("testBitwiseLsh failed, wanted", want, "got", got) + failed = true + } + if want, got := int32(-1), testBitwiseRsh_ssa(-13, 25, 15); want != got { + println("testBitwiseLsh failed, wanted", want, "got", got) + failed = true + } } func testBitwiseAnd_ssa(a, b uint32) uint32 { @@ -87,6 +111,18 @@ func testBitwiseXor_ssa(a, b uint32) uint32 { return a ^ b } +func testBitwiseLsh_ssa(a int32, b, c uint32) int32 { + switch { // prevent inlining + } + return a << b << c +} + +func testBitwiseRsh_ssa(a int32, b, c uint32) int32 { + switch { // prevent inlining + } + return a >> b >> c +} + // testSubqToNegq ensures that the SUBQ -> NEGQ translation works correctly. func testSubqToNegq(a, b, c, d, e, f, g, h, i, j, k int64) { want := a + 8207351403619448057 - b - 1779494519303207690 + c*8810076340510052032*d - 4465874067674546219 - e*4361839741470334295 - f + 8688847565426072650*g*8065564729145417479 diff --git a/src/cmd/compile/internal/ssa/gen/AMD64.rules b/src/cmd/compile/internal/ssa/gen/AMD64.rules index d0f5e5b073..dd34404b70 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64.rules +++ b/src/cmd/compile/internal/ssa/gen/AMD64.rules @@ -445,10 +445,22 @@ (ADDLconst [c] (MOVLconst [d])) -> (MOVLconst [c+d]) (ADDWconst [c] (MOVWconst [d])) -> (MOVWconst [c+d]) (ADDBconst [c] (MOVBconst [d])) -> (MOVBconst [c+d]) +(ADDQconst [c] (ADDQconst [d] x)) -> (ADDQconst [c+d] x) +(ADDLconst [c] (ADDLconst [d] x)) -> (ADDLconst [c+d] x) +(ADDWconst [c] (ADDWconst [d] x)) -> (ADDWconst [c+d] x) +(ADDBconst [c] (ADDBconst [d] x)) -> (ADDBconst [c+d] x) (SUBQconst [c] (MOVQconst [d])) -> (MOVQconst [c-d]) (SUBLconst [c] (MOVLconst [d])) -> (MOVLconst [c-d]) (SUBWconst [c] (MOVWconst [d])) -> (MOVWconst [c-d]) (SUBBconst [c] (MOVBconst [d])) -> (MOVBconst [c-d]) +(SUBQconst [c] (SUBQconst [d] x)) -> (ADDQconst [c-d] x) +(SUBLconst [c] (SUBLconst [d] x)) -> (ADDLconst [c-d] x) +(SUBWconst [c] (SUBWconst [d] x)) -> (ADDWconst [c-d] x) +(SUBBconst [c] (SUBBconst [d] x)) -> (ADDBconst [c-d] x) +(NEGQ (MOVQconst [c])) -> (MOVQconst [-c]) +(NEGL (MOVLconst [c])) -> (MOVLconst [-c]) +(NEGW (MOVWconst [c])) -> (MOVWconst [-c]) +(NEGB (MOVBconst [c])) -> (MOVBconst [-c]) (MULQconst [c] (MOVQconst [d])) -> (MOVQconst [c*d]) (MULLconst [c] (MOVLconst [d])) -> (MOVLconst [c*d]) (MULWconst [c] (MOVWconst [d])) -> (MOVWconst [c*d]) @@ -468,3 +480,26 @@ (NOTL (MOVLconst [c])) -> (MOVLconst [^c]) (NOTW (MOVWconst [c])) -> (MOVWconst [^c]) (NOTB (MOVBconst [c])) -> (MOVBconst [^c]) + +// generic simplifications +// TODO: more of this +(ADDQ x (NEGQ y)) -> (SUBQ x y) +(ADDL x (NEGL y)) -> (SUBL x y) +(ADDW x (NEGW y)) -> (SUBW x y) +(ADDB x (NEGB y)) -> (SUBB x y) +(SUBQ x x) -> (MOVQconst [0]) +(SUBL x x) -> (MOVLconst [0]) +(SUBW x x) -> (MOVWconst [0]) +(SUBB x x) -> (MOVBconst [0]) +(ANDQ x x) -> (Copy x) +(ANDL x x) -> (Copy x) +(ANDW x x) -> (Copy x) +(ANDB x x) -> (Copy x) +(ORQ x x) -> (Copy x) +(ORL x x) -> (Copy x) +(ORW x x) -> (Copy x) +(ORB x x) -> (Copy x) +(XORQ x x) -> (MOVQconst [0]) +(XORL x x) -> (MOVLconst [0]) +(XORW x x) -> (MOVWconst [0]) +(XORB x x) -> (MOVBconst [0]) diff --git a/src/cmd/compile/internal/ssa/gen/generic.rules b/src/cmd/compile/internal/ssa/gen/generic.rules index 6a8952d6cb..9cc2f1b9ad 100644 --- a/src/cmd/compile/internal/ssa/gen/generic.rules +++ b/src/cmd/compile/internal/ssa/gen/generic.rules @@ -25,6 +25,14 @@ (Mul64 (Const64 [c]) (Const64 [d])) -> (Const64 [c*d]) (MulPtr (ConstPtr [c]) (ConstPtr [d])) -> (ConstPtr [c*d]) (IsInBounds (ConstPtr [c]) (ConstPtr [d])) -> (ConstPtr {inBounds(c,d)}) +(Eq64 x x) -> (ConstBool {true}) +(Eq32 x x) -> (ConstBool {true}) +(Eq16 x x) -> (ConstBool {true}) +(Eq8 x x) -> (ConstBool {true}) +(Neq64 x x) -> (ConstBool {false}) +(Neq32 x x) -> (ConstBool {false}) +(Neq16 x x) -> (ConstBool {false}) +(Neq8 x x) -> (ConstBool {false}) // tear apart slices // TODO: anything that generates a slice needs to go in here. diff --git a/src/cmd/compile/internal/ssa/gen/rulegen.go b/src/cmd/compile/internal/ssa/gen/rulegen.go index 03cbf7cd57..4b3775ca98 100644 --- a/src/cmd/compile/internal/ssa/gen/rulegen.go +++ b/src/cmd/compile/internal/ssa/gen/rulegen.go @@ -285,12 +285,12 @@ func genMatch(w io.Writer, arch arch, match, fail string) { func genMatch0(w io.Writer, arch arch, match, v, fail string, m map[string]string, top bool) { if match[0] != '(' { - if x, ok := m[match]; ok { + 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 %s", v, x, fail) + fmt.Fprintf(w, "if %s != %s %s", v, match, fail) return } // remember that this variable references the given value diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go index 9e4f133f3b..9157989035 100644 --- a/src/cmd/compile/internal/ssa/rewriteAMD64.go +++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go @@ -45,6 +45,26 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto end28aa1a4abe7e1abcdd64135e9967d39d end28aa1a4abe7e1abcdd64135e9967d39d: ; + // match: (ADDB x (NEGB y)) + // cond: + // result: (SUBB x y) + { + x := v.Args[0] + if v.Args[1].Op != OpAMD64NEGB { + goto end9464509b8874ffb00b43b843da01f0bc + } + y := v.Args[1].Args[0] + v.Op = OpAMD64SUBB + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto end9464509b8874ffb00b43b843da01f0bc + end9464509b8874ffb00b43b843da01f0bc: + ; case OpAMD64ADDBconst: // match: (ADDBconst [c] (MOVBconst [d])) // cond: @@ -65,6 +85,27 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto enda9b1e9e31ccdf0af5f4fe57bf4b1343f enda9b1e9e31ccdf0af5f4fe57bf4b1343f: ; + // match: (ADDBconst [c] (ADDBconst [d] x)) + // cond: + // result: (ADDBconst [c+d] x) + { + c := v.AuxInt + if v.Args[0].Op != OpAMD64ADDBconst { + goto end9b1e6890adbf9d9e447d591b4148cbd0 + } + d := v.Args[0].AuxInt + x := v.Args[0].Args[0] + v.Op = OpAMD64ADDBconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c + d + v.AddArg(x) + return true + } + goto end9b1e6890adbf9d9e447d591b4148cbd0 + end9b1e6890adbf9d9e447d591b4148cbd0: + ; case OpAMD64ADDL: // match: (ADDL x (MOVLconst [c])) // cond: @@ -106,6 +147,26 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto end739561e08a561e26ce3634dc0d5ec733 end739561e08a561e26ce3634dc0d5ec733: ; + // match: (ADDL x (NEGL y)) + // cond: + // result: (SUBL x y) + { + x := v.Args[0] + if v.Args[1].Op != OpAMD64NEGL { + goto end9596df31f2685a49df67c6fb912a521d + } + y := v.Args[1].Args[0] + v.Op = OpAMD64SUBL + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto end9596df31f2685a49df67c6fb912a521d + end9596df31f2685a49df67c6fb912a521d: + ; case OpAMD64ADDLconst: // match: (ADDLconst [c] (MOVLconst [d])) // cond: @@ -126,6 +187,27 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto ende04850e987890abf1d66199042a19c23 ende04850e987890abf1d66199042a19c23: ; + // match: (ADDLconst [c] (ADDLconst [d] x)) + // cond: + // result: (ADDLconst [c+d] x) + { + c := v.AuxInt + if v.Args[0].Op != OpAMD64ADDLconst { + goto endf1dd8673b2fef4950aec87aa7523a236 + } + d := v.Args[0].AuxInt + x := v.Args[0].Args[0] + v.Op = OpAMD64ADDLconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c + d + v.AddArg(x) + return true + } + goto endf1dd8673b2fef4950aec87aa7523a236 + endf1dd8673b2fef4950aec87aa7523a236: + ; case OpAMD64ADDQ: // match: (ADDQ x (MOVQconst [c])) // cond: is32Bit(c) @@ -196,6 +278,26 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto endc02313d35a0525d1d680cd58992e820d endc02313d35a0525d1d680cd58992e820d: ; + // match: (ADDQ x (NEGQ y)) + // cond: + // result: (SUBQ x y) + { + x := v.Args[0] + if v.Args[1].Op != OpAMD64NEGQ { + goto endec8f899c6e175a0147a90750f9bfe0a2 + } + y := v.Args[1].Args[0] + v.Op = OpAMD64SUBQ + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto endec8f899c6e175a0147a90750f9bfe0a2 + endec8f899c6e175a0147a90750f9bfe0a2: + ; case OpAMD64ADDQconst: // match: (ADDQconst [c] (LEAQ8 [d] x y)) // cond: @@ -257,6 +359,27 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto end09dc54395b4e96e8332cf8e4e7481c52 end09dc54395b4e96e8332cf8e4e7481c52: ; + // match: (ADDQconst [c] (ADDQconst [d] x)) + // cond: + // result: (ADDQconst [c+d] x) + { + c := v.AuxInt + if v.Args[0].Op != OpAMD64ADDQconst { + goto endd4cb539641f0dc40bfd0cb7fbb9b0405 + } + d := v.Args[0].AuxInt + x := v.Args[0].Args[0] + v.Op = OpAMD64ADDQconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c + d + v.AddArg(x) + return true + } + goto endd4cb539641f0dc40bfd0cb7fbb9b0405 + endd4cb539641f0dc40bfd0cb7fbb9b0405: + ; case OpAMD64ADDW: // match: (ADDW x (MOVWconst [c])) // cond: @@ -298,6 +421,26 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto ende3aede99966f388afc624f9e86676fd2 ende3aede99966f388afc624f9e86676fd2: ; + // match: (ADDW x (NEGW y)) + // cond: + // result: (SUBW x y) + { + x := v.Args[0] + if v.Args[1].Op != OpAMD64NEGW { + goto end55cf2af0d75f3ec413528eeb799e94d5 + } + y := v.Args[1].Args[0] + v.Op = OpAMD64SUBW + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto end55cf2af0d75f3ec413528eeb799e94d5 + end55cf2af0d75f3ec413528eeb799e94d5: + ; case OpAMD64ADDWconst: // match: (ADDWconst [c] (MOVWconst [d])) // cond: @@ -318,6 +461,27 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto end32541920f2f5a920dfae41d8ebbef00f end32541920f2f5a920dfae41d8ebbef00f: ; + // match: (ADDWconst [c] (ADDWconst [d] x)) + // cond: + // result: (ADDWconst [c+d] x) + { + c := v.AuxInt + if v.Args[0].Op != OpAMD64ADDWconst { + goto end73944f6ddda7e4c050f11d17484ff9a5 + } + d := v.Args[0].AuxInt + x := v.Args[0].Args[0] + v.Op = OpAMD64ADDWconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c + d + v.AddArg(x) + return true + } + goto end73944f6ddda7e4c050f11d17484ff9a5 + end73944f6ddda7e4c050f11d17484ff9a5: + ; case OpAMD64ANDB: // match: (ANDB x (MOVBconst [c])) // cond: @@ -359,6 +523,24 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto end4068edac2ae0f354cf581db210288b98 end4068edac2ae0f354cf581db210288b98: ; + // match: (ANDB x x) + // cond: + // result: (Copy x) + { + x := v.Args[0] + if v.Args[1] != x { + goto end1c1e017efac06c84c72f2d09d6afadc0 + } + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto end1c1e017efac06c84c72f2d09d6afadc0 + end1c1e017efac06c84c72f2d09d6afadc0: + ; case OpAMD64ANDBconst: // match: (ANDBconst [c] _) // cond: int8(c)==0 @@ -457,6 +639,24 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto end0529ba323d9b6f15c41add401ef67959 end0529ba323d9b6f15c41add401ef67959: ; + // match: (ANDL x x) + // cond: + // result: (Copy x) + { + x := v.Args[0] + if v.Args[1] != x { + goto end0ff7ad77f6811c422b0b588f48474ddc + } + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto end0ff7ad77f6811c422b0b588f48474ddc + end0ff7ad77f6811c422b0b588f48474ddc: + ; case OpAMD64ANDLconst: // match: (ANDLconst [c] _) // cond: int32(c)==0 @@ -561,6 +761,24 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto end3035a3bf650b708705fd27dd857ab0a4 end3035a3bf650b708705fd27dd857ab0a4: ; + // match: (ANDQ x x) + // cond: + // result: (Copy x) + { + x := v.Args[0] + if v.Args[1] != x { + goto endb54d87d7a12ba29a9d19b808319ab055 + } + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto endb54d87d7a12ba29a9d19b808319ab055 + endb54d87d7a12ba29a9d19b808319ab055: + ; case OpAMD64ANDQconst: // match: (ANDQconst [0] _) // cond: @@ -657,6 +875,24 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto endea2a25eb525a5dbf6d5132d84ea4e7a5 endea2a25eb525a5dbf6d5132d84ea4e7a5: ; + // match: (ANDW x x) + // cond: + // result: (Copy x) + { + x := v.Args[0] + if v.Args[1] != x { + goto end08c49eea4ac769acc212ebd833934be8 + } + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto end08c49eea4ac769acc212ebd833934be8 + end08c49eea4ac769acc212ebd833934be8: + ; case OpAMD64ANDWconst: // match: (ANDWconst [c] _) // cond: int16(c)==0 @@ -3504,6 +3740,82 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto endbbedad106c011a93243e2062afdcc75f endbbedad106c011a93243e2062afdcc75f: ; + case OpAMD64NEGB: + // match: (NEGB (MOVBconst [c])) + // cond: + // result: (MOVBconst [-c]) + { + if v.Args[0].Op != OpAMD64MOVBconst { + goto end36d0300ba9eab8c9da86246ff653ca96 + } + c := v.Args[0].AuxInt + v.Op = OpAMD64MOVBconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = -c + return true + } + goto end36d0300ba9eab8c9da86246ff653ca96 + end36d0300ba9eab8c9da86246ff653ca96: + ; + case OpAMD64NEGL: + // match: (NEGL (MOVLconst [c])) + // cond: + // result: (MOVLconst [-c]) + { + if v.Args[0].Op != OpAMD64MOVLconst { + goto end7a245ec67e56bd51911e5ba2d0aa0a16 + } + c := v.Args[0].AuxInt + v.Op = OpAMD64MOVLconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = -c + return true + } + goto end7a245ec67e56bd51911e5ba2d0aa0a16 + end7a245ec67e56bd51911e5ba2d0aa0a16: + ; + case OpAMD64NEGQ: + // match: (NEGQ (MOVQconst [c])) + // cond: + // result: (MOVQconst [-c]) + { + if v.Args[0].Op != OpAMD64MOVQconst { + goto end04ddd98bc6724ecb85c80c2a4e2bca5a + } + c := v.Args[0].AuxInt + v.Op = OpAMD64MOVQconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = -c + return true + } + goto end04ddd98bc6724ecb85c80c2a4e2bca5a + end04ddd98bc6724ecb85c80c2a4e2bca5a: + ; + case OpAMD64NEGW: + // match: (NEGW (MOVWconst [c])) + // cond: + // result: (MOVWconst [-c]) + { + if v.Args[0].Op != OpAMD64MOVWconst { + goto end1db6636f0a51848d8a34f6561ecfe7ae + } + c := v.Args[0].AuxInt + v.Op = OpAMD64MOVWconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = -c + return true + } + goto end1db6636f0a51848d8a34f6561ecfe7ae + end1db6636f0a51848d8a34f6561ecfe7ae: + ; case OpAMD64NOTB: // match: (NOTB (MOVBconst [c])) // cond: @@ -3807,6 +4119,24 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto end70b43d531e2097a4f6293f66256a642e end70b43d531e2097a4f6293f66256a642e: ; + // match: (ORB x x) + // cond: + // result: (Copy x) + { + x := v.Args[0] + if v.Args[1] != x { + goto endd53ede4886d67f4b4ae970316a2febb4 + } + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto endd53ede4886d67f4b4ae970316a2febb4 + endd53ede4886d67f4b4ae970316a2febb4: + ; case OpAMD64ORBconst: // match: (ORBconst [c] x) // cond: int8(c)==0 @@ -3905,6 +4235,24 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto enda5bc49524a0cbd2241f792837d0a48a8 enda5bc49524a0cbd2241f792837d0a48a8: ; + // match: (ORL x x) + // cond: + // result: (Copy x) + { + x := v.Args[0] + if v.Args[1] != x { + goto end556b9151cacb9db2803373ce10829b2a + } + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto end556b9151cacb9db2803373ce10829b2a + end556b9151cacb9db2803373ce10829b2a: + ; case OpAMD64ORLconst: // match: (ORLconst [c] x) // cond: int32(c)==0 @@ -4009,6 +4357,24 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto end010afbebcd314e288509d79a16a6d5cc end010afbebcd314e288509d79a16a6d5cc: ; + // match: (ORQ x x) + // cond: + // result: (Copy x) + { + x := v.Args[0] + if v.Args[1] != x { + goto endcad306e115ea011a2a70f4e4e5440de4 + } + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto endcad306e115ea011a2a70f4e4e5440de4 + endcad306e115ea011a2a70f4e4e5440de4: + ; case OpAMD64ORQconst: // match: (ORQconst [0] x) // cond: @@ -4105,6 +4471,24 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto end96405942c9ceb5fcb0ddb85a8709d015 end96405942c9ceb5fcb0ddb85a8709d015: ; + // match: (ORW x x) + // cond: + // result: (Copy x) + { + x := v.Args[0] + if v.Args[1] != x { + goto end7c69794f4a3a6ada00bd868f743d86f8 + } + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto end7c69794f4a3a6ada00bd868f743d86f8 + end7c69794f4a3a6ada00bd868f743d86f8: + ; case OpAMD64ORWconst: // match: (ORWconst [c] x) // cond: int16(c)==0 @@ -5963,6 +6347,24 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto endc288755d69b04d24a6aac32a73956411 endc288755d69b04d24a6aac32a73956411: ; + // match: (SUBB x x) + // cond: + // result: (MOVBconst [0]) + { + x := v.Args[0] + if v.Args[1] != x { + goto ende8904403d937d95b0d6133d3ec92bb45 + } + v.Op = OpAMD64MOVBconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = 0 + return true + } + goto ende8904403d937d95b0d6133d3ec92bb45 + ende8904403d937d95b0d6133d3ec92bb45: + ; case OpAMD64SUBBconst: // match: (SUBBconst [c] (MOVBconst [d])) // cond: @@ -5983,6 +6385,27 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto end0e2d5c3e3c02001a20d5433daa9e8317 end0e2d5c3e3c02001a20d5433daa9e8317: ; + // match: (SUBBconst [c] (SUBBconst [d] x)) + // cond: + // result: (ADDBconst [c-d] x) + { + c := v.AuxInt + if v.Args[0].Op != OpAMD64SUBBconst { + goto end48eccb421dfe0c678ea9c47113521d5a + } + d := v.Args[0].AuxInt + x := v.Args[0].Args[0] + v.Op = OpAMD64ADDBconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c - d + v.AddArg(x) + return true + } + goto end48eccb421dfe0c678ea9c47113521d5a + end48eccb421dfe0c678ea9c47113521d5a: + ; case OpAMD64SUBL: // match: (SUBL x (MOVLconst [c])) // cond: @@ -6027,6 +6450,24 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto endb0efe6e15ec20486b849534a00483ae2 endb0efe6e15ec20486b849534a00483ae2: ; + // match: (SUBL x x) + // cond: + // result: (MOVLconst [0]) + { + x := v.Args[0] + if v.Args[1] != x { + goto end332f1f641f875c69bea7289191e69133 + } + v.Op = OpAMD64MOVLconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = 0 + return true + } + goto end332f1f641f875c69bea7289191e69133 + end332f1f641f875c69bea7289191e69133: + ; case OpAMD64SUBLconst: // match: (SUBLconst [c] (MOVLconst [d])) // cond: @@ -6047,6 +6488,27 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto endbe7466f3c09d9645544bdfc44c37c922 endbe7466f3c09d9645544bdfc44c37c922: ; + // match: (SUBLconst [c] (SUBLconst [d] x)) + // cond: + // result: (ADDLconst [c-d] x) + { + c := v.AuxInt + if v.Args[0].Op != OpAMD64SUBLconst { + goto endb5106962a865bc4654b170c2e29a72c4 + } + d := v.Args[0].AuxInt + x := v.Args[0].Args[0] + v.Op = OpAMD64ADDLconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c - d + v.AddArg(x) + return true + } + goto endb5106962a865bc4654b170c2e29a72c4 + endb5106962a865bc4654b170c2e29a72c4: + ; case OpAMD64SUBQ: // match: (SUBQ x (MOVQconst [c])) // cond: is32Bit(c) @@ -6097,6 +6559,24 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto end8beb96de3efee9206d1bd4b7d777d2cb end8beb96de3efee9206d1bd4b7d777d2cb: ; + // match: (SUBQ x x) + // cond: + // result: (MOVQconst [0]) + { + x := v.Args[0] + if v.Args[1] != x { + goto endd87d1d839d2dc54d9c90fa4f73383480 + } + v.Op = OpAMD64MOVQconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = 0 + return true + } + goto endd87d1d839d2dc54d9c90fa4f73383480 + endd87d1d839d2dc54d9c90fa4f73383480: + ; case OpAMD64SUBQconst: // match: (SUBQconst [c] (MOVQconst [d])) // cond: @@ -6117,6 +6597,27 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto end96c09479fb3c043e875d89d3eb92f1d8 end96c09479fb3c043e875d89d3eb92f1d8: ; + // match: (SUBQconst [c] (SUBQconst [d] x)) + // cond: + // result: (ADDQconst [c-d] x) + { + c := v.AuxInt + if v.Args[0].Op != OpAMD64SUBQconst { + goto enddd9d61b404480adb40cfd7fedd7e5ec4 + } + d := v.Args[0].AuxInt + x := v.Args[0].Args[0] + v.Op = OpAMD64ADDQconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c - d + v.AddArg(x) + return true + } + goto enddd9d61b404480adb40cfd7fedd7e5ec4 + enddd9d61b404480adb40cfd7fedd7e5ec4: + ; case OpAMD64SUBW: // match: (SUBW x (MOVWconst [c])) // cond: @@ -6161,6 +6662,24 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto end44d23f7e65a4b1c42d0e6463f8e493b6 end44d23f7e65a4b1c42d0e6463f8e493b6: ; + // match: (SUBW x x) + // cond: + // result: (MOVWconst [0]) + { + x := v.Args[0] + if v.Args[1] != x { + goto endb970e7c318d04a1afe1dfe08a7ca0d9c + } + v.Op = OpAMD64MOVWconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = 0 + return true + } + goto endb970e7c318d04a1afe1dfe08a7ca0d9c + endb970e7c318d04a1afe1dfe08a7ca0d9c: + ; case OpAMD64SUBWconst: // match: (SUBWconst [c] (MOVWconst [d])) // cond: @@ -6181,6 +6700,27 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto end0e5079577fcf00f5925291dbd68306aa end0e5079577fcf00f5925291dbd68306aa: ; + // match: (SUBWconst [c] (SUBWconst [d] x)) + // cond: + // result: (ADDWconst [c-d] x) + { + c := v.AuxInt + if v.Args[0].Op != OpAMD64SUBWconst { + goto endb628696cf5b329d03782b8093093269b + } + d := v.Args[0].AuxInt + x := v.Args[0].Args[0] + v.Op = OpAMD64ADDWconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c - d + v.AddArg(x) + return true + } + goto endb628696cf5b329d03782b8093093269b + endb628696cf5b329d03782b8093093269b: + ; case OpSignExt16to32: // match: (SignExt16to32 x) // cond: @@ -6617,6 +7157,24 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto endb02a07d9dc7b802c59f013116e952f3f endb02a07d9dc7b802c59f013116e952f3f: ; + // match: (XORB x x) + // cond: + // result: (MOVBconst [0]) + { + x := v.Args[0] + if v.Args[1] != x { + goto end2afddc39503d04d572a3a07878f6c9c9 + } + v.Op = OpAMD64MOVBconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = 0 + return true + } + goto end2afddc39503d04d572a3a07878f6c9c9 + end2afddc39503d04d572a3a07878f6c9c9: + ; case OpAMD64XORBconst: // match: (XORBconst [c] (MOVBconst [d])) // cond: @@ -6678,6 +7236,24 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto end9c1a0af00eeadd8aa325e55f1f3fb89c end9c1a0af00eeadd8aa325e55f1f3fb89c: ; + // match: (XORL x x) + // cond: + // result: (MOVLconst [0]) + { + x := v.Args[0] + if v.Args[1] != x { + goto end7bcf9cfeb69a0d7647389124eb53ce2a + } + v.Op = OpAMD64MOVLconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = 0 + return true + } + goto end7bcf9cfeb69a0d7647389124eb53ce2a + end7bcf9cfeb69a0d7647389124eb53ce2a: + ; case OpAMD64XORLconst: // match: (XORLconst [c] (MOVLconst [d])) // cond: @@ -6745,6 +7321,24 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto endd221a7e3daaaaa29ee385ad36e061b57 endd221a7e3daaaaa29ee385ad36e061b57: ; + // match: (XORQ x x) + // cond: + // result: (MOVQconst [0]) + { + x := v.Args[0] + if v.Args[1] != x { + goto end10575a5d711cf14e6d4dffbb0e8dfaeb + } + v.Op = OpAMD64MOVQconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = 0 + return true + } + goto end10575a5d711cf14e6d4dffbb0e8dfaeb + end10575a5d711cf14e6d4dffbb0e8dfaeb: + ; case OpAMD64XORQconst: // match: (XORQconst [c] (MOVQconst [d])) // cond: @@ -6806,6 +7400,24 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto end51ee62a06d4301e5a4aed7a6639b1d53 end51ee62a06d4301e5a4aed7a6639b1d53: ; + // match: (XORW x x) + // cond: + // result: (MOVWconst [0]) + { + x := v.Args[0] + if v.Args[1] != x { + goto end07f332e857be0c2707797ed480a2faf4 + } + v.Op = OpAMD64MOVWconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = 0 + return true + } + goto end07f332e857be0c2707797ed480a2faf4 + end07f332e857be0c2707797ed480a2faf4: + ; case OpAMD64XORWconst: // match: (XORWconst [c] (MOVWconst [d])) // cond: diff --git a/src/cmd/compile/internal/ssa/rewritegeneric.go b/src/cmd/compile/internal/ssa/rewritegeneric.go index 7d889b89f1..17608d71c4 100644 --- a/src/cmd/compile/internal/ssa/rewritegeneric.go +++ b/src/cmd/compile/internal/ssa/rewritegeneric.go @@ -102,6 +102,82 @@ func rewriteValuegeneric(v *Value, config *Config) bool { goto end68cc91679848c7c30bd8b0a8ed533843 end68cc91679848c7c30bd8b0a8ed533843: ; + case OpEq16: + // match: (Eq16 x x) + // cond: + // result: (ConstBool {true}) + { + x := v.Args[0] + if v.Args[1] != x { + goto enda503589f9b617e708a5ad3ddb047809f + } + v.Op = OpConstBool + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Aux = true + return true + } + goto enda503589f9b617e708a5ad3ddb047809f + enda503589f9b617e708a5ad3ddb047809f: + ; + case OpEq32: + // match: (Eq32 x x) + // cond: + // result: (ConstBool {true}) + { + x := v.Args[0] + if v.Args[1] != x { + goto endc94ae3b97d0090257b02152e437b3e17 + } + v.Op = OpConstBool + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Aux = true + return true + } + goto endc94ae3b97d0090257b02152e437b3e17 + endc94ae3b97d0090257b02152e437b3e17: + ; + case OpEq64: + // match: (Eq64 x x) + // cond: + // result: (ConstBool {true}) + { + x := v.Args[0] + if v.Args[1] != x { + goto end4d21cead60174989467a9c8202dbb91d + } + v.Op = OpConstBool + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Aux = true + return true + } + goto end4d21cead60174989467a9c8202dbb91d + end4d21cead60174989467a9c8202dbb91d: + ; + case OpEq8: + // match: (Eq8 x x) + // cond: + // result: (ConstBool {true}) + { + x := v.Args[0] + if v.Args[1] != x { + goto end73dce8bba164e4f4a1dd701bf8cfb362 + } + v.Op = OpConstBool + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Aux = true + return true + } + goto end73dce8bba164e4f4a1dd701bf8cfb362 + end73dce8bba164e4f4a1dd701bf8cfb362: + ; case OpEqFat: // match: (EqFat x y) // cond: x.Op == OpConstNil && y.Op != OpConstNil @@ -256,6 +332,82 @@ func rewriteValuegeneric(v *Value, config *Config) bool { goto end808c190f346658bb1ad032bf37a1059f end808c190f346658bb1ad032bf37a1059f: ; + case OpNeq16: + // match: (Neq16 x x) + // cond: + // result: (ConstBool {false}) + { + x := v.Args[0] + if v.Args[1] != x { + goto end192755dd3c2be992e9d3deb53794a8d2 + } + v.Op = OpConstBool + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Aux = false + return true + } + goto end192755dd3c2be992e9d3deb53794a8d2 + end192755dd3c2be992e9d3deb53794a8d2: + ; + case OpNeq32: + // match: (Neq32 x x) + // cond: + // result: (ConstBool {false}) + { + x := v.Args[0] + if v.Args[1] != x { + goto endeb23619fc85950a8df7b31126252c4dd + } + v.Op = OpConstBool + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Aux = false + return true + } + goto endeb23619fc85950a8df7b31126252c4dd + endeb23619fc85950a8df7b31126252c4dd: + ; + case OpNeq64: + // match: (Neq64 x x) + // cond: + // result: (ConstBool {false}) + { + x := v.Args[0] + if v.Args[1] != x { + goto endfc6eea780fb4056afb9e4287076da60c + } + v.Op = OpConstBool + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Aux = false + return true + } + goto endfc6eea780fb4056afb9e4287076da60c + endfc6eea780fb4056afb9e4287076da60c: + ; + case OpNeq8: + // match: (Neq8 x x) + // cond: + // result: (ConstBool {false}) + { + x := v.Args[0] + if v.Args[1] != x { + goto endcccf700d93c6d57765b80f92f7b3fa81 + } + v.Op = OpConstBool + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Aux = false + return true + } + goto endcccf700d93c6d57765b80f92f7b3fa81 + endcccf700d93c6d57765b80f92f7b3fa81: + ; case OpNeqFat: // match: (NeqFat x y) // cond: x.Op == OpConstNil && y.Op != OpConstNil @@ -422,7 +574,7 @@ func rewriteValuegeneric(v *Value, config *Config) bool { t := v.Args[1].Type src := v.Args[1].Args[0] mem := v.Args[1].Args[1] - if v.Args[2] != v.Args[1].Args[1] { + if v.Args[2] != mem { goto end324ffb6d2771808da4267f62c854e9c8 } if !(t.Size() > 8) { -- cgit v1.3 From 4ac823eeb8aa08e8fbae01c70d185ec7501f55b7 Mon Sep 17 00:00:00 2001 From: Todd Neal Date: Sun, 2 Aug 2015 20:28:31 -0500 Subject: [dev.ssa] cmd/compile/ssa: test against known values Modify tests to use a known value instead of comparing the backends directly. Change-Id: I32e804e12515885bd94c4f83644cbca03b018fea Reviewed-on: https://go-review.googlesource.com/13042 Reviewed-by: Keith Randall --- src/cmd/compile/internal/gc/testdata/arith_ssa.go | 36 +++++++++++------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/testdata/arith_ssa.go b/src/cmd/compile/internal/gc/testdata/arith_ssa.go index 1c8445fbda..032cc8e1cf 100644 --- a/src/cmd/compile/internal/gc/testdata/arith_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/arith_ssa.go @@ -10,9 +10,9 @@ package main // test64BitConstMulti tests that rewrite rules don't fold 64 bit constants // into multiply instructions. -func test64BitConstMult(a, b int64) { - want := 34359738369*a + b*34359738370 - if got := test64BitConstMult_ssa(a, b); want != got { +func test64BitConstMult() { + want := int64(103079215109) + if got := test64BitConstMult_ssa(1, 2); want != got { println("test64BitConstMult failed, wanted", want, "got", got) failed = true } @@ -25,30 +25,30 @@ func test64BitConstMult_ssa(a, b int64) int64 { // test64BitConstAdd tests that rewrite rules don't fold 64 bit constants // into add instructions. -func test64BitConstAdd(a, b int64) { - want := a + 575815584948629622 + b + 2991856197886747025 - if got := test64BitConstAdd_ssa(a, b); want != got { +func test64BitConstAdd() { + want := int64(3567671782835376650) + if got := test64BitConstAdd_ssa(1, 2); want != got { println("test64BitConstAdd failed, wanted", want, "got", got) failed = true } } func test64BitConstAdd_ssa(a, b int64) int64 { - switch { + switch { // prevent inlining } return a + 575815584948629622 + b + 2991856197886747025 } // testRegallocCVSpill tests that regalloc spills a value whose last use is the // current value. -func testRegallocCVSpill(a, b, c, d int8) { - want := a + -32 + b + 63*c*-87*d - if got := testRegallocCVSpill_ssa(a, b, c, d); want != got { +func testRegallocCVSpill() { + want := int8(-9) + if got := testRegallocCVSpill_ssa(1, 2, 3, 4); want != got { println("testRegallocCVSpill failed, wanted", want, "got", got) failed = true } } func testRegallocCVSpill_ssa(a, b, c, d int8) int8 { - switch { + switch { // prevent inlining } return a + -32 + b + 63*c*-87*d } @@ -124,9 +124,9 @@ func testBitwiseRsh_ssa(a int32, b, c uint32) int32 { } // testSubqToNegq ensures that the SUBQ -> NEGQ translation works correctly. -func testSubqToNegq(a, b, c, d, e, f, g, h, i, j, k int64) { - want := a + 8207351403619448057 - b - 1779494519303207690 + c*8810076340510052032*d - 4465874067674546219 - e*4361839741470334295 - f + 8688847565426072650*g*8065564729145417479 - if got := testSubqToNegq_ssa(a, b, c, d, e, f, g, h, i, j, k); want != got { +func testSubqToNegq() { + want := int64(-318294940372190156) + if got := testSubqToNegq_ssa(1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2); want != got { println("testSubqToNegq failed, wanted", want, "got", got) failed = true } @@ -142,10 +142,10 @@ var failed = false func main() { - test64BitConstMult(1, 2) - test64BitConstAdd(1, 2) - testRegallocCVSpill(1, 2, 3, 4) - testSubqToNegq(1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2) + test64BitConstMult() + test64BitConstAdd() + testRegallocCVSpill() + testSubqToNegq() testBitwiseLogic() if failed { -- cgit v1.3 From a678a5c7a59de585a09d7bde2505b8234cc4422e Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Mon, 3 Aug 2015 12:33:03 -0700 Subject: [dev.ssa] cmd/compile/internal/ssa: Fix scheduler The DFS scheduler doesn't do the right thing. If a Value x is used by more than one other Value, then x is put into the DFS queue when its first user (call it y) is visited. It is not removed and reinserted when the second user of x (call it z) is visited, so the dependency between x and z is not respected. There is no easy way to fix this with the DFS queue because we'd have to rip values out of the middle of the DFS queue. The new scheduler works from the end of the block backwards, scheduling instructions which have had all of their uses already scheduled. A simple priority scheme breaks ties between multiple instructions that are ready to schedule simultaneously. Keep track of whether we've scheduled or not, and make print() use the scheduled order if we have. Fix some shift tests that this change tickles. Add unsigned right shift tests. Change-Id: I44164c10bb92ae8ab8f76d7a5180cbafab826ea1 Reviewed-on: https://go-review.googlesource.com/13069 Reviewed-by: Todd Neal --- src/cmd/compile/internal/gc/testdata/arith_ssa.go | 28 +++- src/cmd/compile/internal/ssa/func.go | 2 + src/cmd/compile/internal/ssa/print.go | 12 +- src/cmd/compile/internal/ssa/schedule.go | 176 +++++++++++----------- 4 files changed, 122 insertions(+), 96 deletions(-) (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/testdata/arith_ssa.go b/src/cmd/compile/internal/gc/testdata/arith_ssa.go index 032cc8e1cf..e69212e9ad 100644 --- a/src/cmd/compile/internal/gc/testdata/arith_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/arith_ssa.go @@ -68,7 +68,7 @@ func testBitwiseLogic() { failed = true } if want, got := int32(832), testBitwiseLsh_ssa(13, 4, 2); want != got { - println("testBitwiseXor failed, wanted", want, "got", got) + println("testBitwiseLsh failed, wanted", want, "got", got) failed = true } if want, got := int32(0), testBitwiseLsh_ssa(13, 25, 15); want != got { @@ -79,16 +79,28 @@ func testBitwiseLogic() { println("testBitwiseLsh failed, wanted", want, "got", got) failed = true } - if want, got := int32(0), testBitwiseRsh_ssa(-13, 25, 15); want != got { - println("testBitwiseLsh failed, wanted", want, "got", got) + if want, got := int32(-13), testBitwiseRsh_ssa(-832, 4, 2); want != got { + println("testBitwiseRsh failed, wanted", want, "got", got) failed = true } if want, got := int32(0), testBitwiseRsh_ssa(13, 25, 15); want != got { - println("testBitwiseLsh failed, wanted", want, "got", got) + println("testBitwiseRsh failed, wanted", want, "got", got) failed = true } if want, got := int32(-1), testBitwiseRsh_ssa(-13, 25, 15); want != got { - println("testBitwiseLsh failed, wanted", want, "got", got) + println("testBitwiseRsh failed, wanted", want, "got", got) + failed = true + } + if want, got := uint32(0x3ffffff), testBitwiseRshU_ssa(0xffffffff, 4, 2); want != got { + println("testBitwiseRshU failed, wanted", want, "got", got) + failed = true + } + if want, got := uint32(0), testBitwiseRshU_ssa(13, 25, 15); want != got { + println("testBitwiseRshU failed, wanted", want, "got", got) + failed = true + } + if want, got := uint32(0), testBitwiseRshU_ssa(0x8aaaaaaa, 25, 15); want != got { + println("testBitwiseRshU failed, wanted", want, "got", got) failed = true } } @@ -123,6 +135,12 @@ func testBitwiseRsh_ssa(a int32, b, c uint32) int32 { return a >> b >> c } +func testBitwiseRshU_ssa(a uint32, b, c uint32) uint32 { + switch { // prevent inlining + } + return a >> b >> c +} + // testSubqToNegq ensures that the SUBQ -> NEGQ translation works correctly. func testSubqToNegq() { want := int64(-318294940372190156) diff --git a/src/cmd/compile/internal/ssa/func.go b/src/cmd/compile/internal/ssa/func.go index ce13075f19..9b6eb7f831 100644 --- a/src/cmd/compile/internal/ssa/func.go +++ b/src/cmd/compile/internal/ssa/func.go @@ -18,6 +18,8 @@ type Func struct { bid idAlloc // block ID allocator vid idAlloc // value ID allocator + scheduled bool // Values in Blocks are in final order + // when register allocation is done, maps value ids to locations RegAlloc []Location // when stackalloc is done, the size of the stack frame diff --git a/src/cmd/compile/internal/ssa/print.go b/src/cmd/compile/internal/ssa/print.go index c8b90c6f93..54d6f542b3 100644 --- a/src/cmd/compile/internal/ssa/print.go +++ b/src/cmd/compile/internal/ssa/print.go @@ -34,9 +34,19 @@ func fprintFunc(w io.Writer, f *Func) { } } io.WriteString(w, "\n") - n := 0 + + if f.scheduled { + // Order of Values has been decided - print in that order. + for _, v := range b.Values { + fmt.Fprint(w, " ") + fmt.Fprintln(w, v.LongString()) + printed[v.ID] = true + } + continue + } // print phis first since all value cycles contain a phi + n := 0 for _, v := range b.Values { if v.Op != OpPhi { continue diff --git a/src/cmd/compile/internal/ssa/schedule.go b/src/cmd/compile/internal/ssa/schedule.go index 15e8ace391..d1596f25e8 100644 --- a/src/cmd/compile/internal/ssa/schedule.go +++ b/src/cmd/compile/internal/ssa/schedule.go @@ -6,121 +6,117 @@ package ssa // Schedule the Values in each Block. After this phase returns, the // order of b.Values matters and is the order in which those values -// will appear in the assembly output. For now it generates an -// arbitrary valid schedule using a topological sort. TODO(khr): +// will appear in the assembly output. For now it generates a +// reasonable valid schedule using a priority queue. TODO(khr): // schedule smarter. func schedule(f *Func) { - const ( - unmarked = 0 - found = 1 - expanded = 2 - done = 3 - ) - state := make([]byte, f.NumValues()) - var queue []*Value //stack-like worklist. Contains found and expanded nodes. + // For each value, the number of times it is used in the block + // by values that have not been scheduled yet. + uses := make([]int, f.NumValues()) + + // "priority" for a value + score := make([]int, f.NumValues()) + + // scheduling order. We queue values in this list in reverse order. var order []*Value - nextMem := make([]*Value, f.NumValues()) // maps mem values to the next live value - additionalEdges := make([][]*Value, f.NumValues()) + // priority queue of legally schedulable (0 unscheduled uses) values + var priq [4][]*Value + for _, b := range f.Blocks { - // Set the nextMem values for this block. If the previous - // write is from a different block, then its nextMem entry - // might have already been set during processing of an earlier - // block. This loop resets the nextMem entries to be correct - // for this block. + // Compute uses. for _, v := range b.Values { - if v.Type.IsMemory() { + if v.Op != OpPhi { + // Note: if a value is used by a phi, it does not induce + // a scheduling edge because that use is from the + // previous iteration. for _, w := range v.Args { - if w.Type.IsMemory() { - nextMem[w.ID] = v + if w.Block == b { + uses[w.ID]++ } } } } - // Add a anti-dependency between each load v and the memory value n - // following the memory value that v loads from. - // This will enforce the single-live-mem restriction. + // Compute score. Larger numbers are scheduled closer to the end of the block. for _, v := range b.Values { - if v.Type.IsMemory() { - continue - } - for _, w := range v.Args { - if w.Type.IsMemory() && nextMem[w.ID] != nil { - // Filter for intra-block edges. - if n := nextMem[w.ID]; n.Block == b { - additionalEdges[n.ID] = append(additionalEdges[n.ID], v) - } - } + switch { + case v.Op == OpPhi: + // We want all the phis first. + score[v.ID] = 0 + case v.Type.IsMemory(): + // Schedule stores as late as possible. + // This makes sure that loads do not get scheduled + // after a following store (1-live-memory requirement). + score[v.ID] = 2 + case v.Type.IsFlags(): + // Schedule flag register generation as late as possible. + // This makes sure that we only have one live flags + // value at a time. + score[v.ID] = 2 + default: + score[v.ID] = 1 } } + if b.Control != nil { + // Force the control value to be scheduled at the end. + score[b.Control.ID] = 3 + // TODO: some times control values are used by other values + // in the block. So the control value will not appear at + // the very end. Decide if this is a problem or not. + } - order = order[:0] - - // Schedule phis first + // Initialize priority queue with schedulable values. + for i := range priq { + priq[i] = priq[i][:0] + } for _, v := range b.Values { - if v.Op == OpPhi { - // TODO: what if a phi is also a control op? It happens for - // mem ops all the time, which shouldn't matter. But for - // regular ops we might be violating invariants about where - // control ops live. - if v == b.Control && !v.Type.IsMemory() { - f.Unimplementedf("phi is a control op %s %s", v, b) - } - order = append(order, v) + if uses[v.ID] == 0 { + s := score[v.ID] + priq[s] = append(priq[s], v) } } - // Topologically sort the non-phi values in b. - for _, v := range b.Values { - if v.Op == OpPhi { - continue + // Schedule highest priority value, update use counts, repeat. + order = order[:0] + for { + // Find highest priority schedulable value. + var v *Value + for i := len(priq) - 1; i >= 0; i-- { + n := len(priq[i]) + if n == 0 { + continue + } + v = priq[i][n-1] + priq[i] = priq[i][:n-1] + break } - if v == b.Control { - continue + if v == nil { + break } - if state[v.ID] != unmarked { - if state[v.ID] != done { - panic("bad state") + + // Add it to the schedule. + order = append(order, v) + + // Update use counts of arguments. + for _, w := range v.Args { + if w.Block != b { + continue } - continue - } - state[v.ID] = found - queue = append(queue, v) - for len(queue) > 0 { - v = queue[len(queue)-1] - switch state[v.ID] { - case found: - state[v.ID] = expanded - // Note that v is not popped. We leave it in place - // until all its children have been explored. - for _, w := range v.Args { - if w.Block == b && w.Op != OpPhi && w != b.Control && state[w.ID] == unmarked { - state[w.ID] = found - queue = append(queue, w) - } - } - for _, w := range additionalEdges[v.ID] { - if w.Block == b && w.Op != OpPhi && w != b.Control && state[w.ID] == unmarked { - state[w.ID] = found - queue = append(queue, w) - } - } - case expanded: - queue = queue[:len(queue)-1] - state[v.ID] = done - order = append(order, v) - default: - panic("bad state") + uses[w.ID]-- + if uses[w.ID] == 0 { + // All uses scheduled, w is now schedulable. + s := score[w.ID] + priq[s] = append(priq[s], w) } } } - if b.Control != nil { - order = append(order, b.Control) + if len(order) != len(b.Values) { + f.Fatalf("schedule does not include all values") + } + for i := 0; i < len(b.Values); i++ { + b.Values[i] = order[len(b.Values)-1-i] } - copy(b.Values, order) } - // TODO: only allow one live flags type (x86) - // This restriction will force and any flag uses to appear before - // the next flag update. This "anti-dependence" is not recorded - // explicitly in ssa form. + + f.scheduled = true } -- cgit v1.3 From 38ed6c10eb056419256beb03eefe289faa7d545b Mon Sep 17 00:00:00 2001 From: Todd Neal Date: Thu, 30 Jul 2015 16:02:24 -0400 Subject: [dev.ssa] cmd/compile: simplify repeated OCOM Rewrite ^{n}x to be ^{n % 2}x. This will eventually resolve a fuzz issue that breaks v1.5. Updates #11352 Change-Id: I1b3f93872d06222f9ff5f6fd5580178ebaf4c003 Reviewed-on: https://go-review.googlesource.com/13110 Reviewed-by: Keith Randall --- src/cmd/compile/internal/gc/testdata/arith_ssa.go | 16 +++++ src/cmd/compile/internal/ssa/gen/generic.rules | 5 ++ src/cmd/compile/internal/ssa/rewritegeneric.go | 76 +++++++++++++++++++++++ 3 files changed, 97 insertions(+) (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/testdata/arith_ssa.go b/src/cmd/compile/internal/gc/testdata/arith_ssa.go index e69212e9ad..6341e9b90d 100644 --- a/src/cmd/compile/internal/gc/testdata/arith_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/arith_ssa.go @@ -156,6 +156,21 @@ func testSubqToNegq_ssa(a, b, c, d, e, f, g, h, i, j, k int64) int64 { return a + 8207351403619448057 - b - 1779494519303207690 + c*8810076340510052032*d - 4465874067674546219 - e*4361839741470334295 - f + 8688847565426072650*g*8065564729145417479 } +func testOcom() { + want1, want2 := int32(0x55555555), int32(-0x55555556) + if got1, got2 := testOcom_ssa(0x55555555, 0x55555555); want1 != got1 || want2 != got2 { + println("testSubqToNegq failed, wanted", want1, "and", want2, + "got", got1, "and", got2) + failed = true + } +} + +func testOcom_ssa(a, b int32) (int32, int32) { + switch { // prevent inlining + } + return ^^^^a, ^^^^^b +} + var failed = false func main() { @@ -165,6 +180,7 @@ func main() { testRegallocCVSpill() testSubqToNegq() testBitwiseLogic() + testOcom() if failed { panic("failed") diff --git a/src/cmd/compile/internal/ssa/gen/generic.rules b/src/cmd/compile/internal/ssa/gen/generic.rules index 9cc2f1b9ad..cb6a20014d 100644 --- a/src/cmd/compile/internal/ssa/gen/generic.rules +++ b/src/cmd/compile/internal/ssa/gen/generic.rules @@ -34,6 +34,11 @@ (Neq16 x x) -> (ConstBool {false}) (Neq8 x x) -> (ConstBool {false}) +(Com8 (Com8 x)) -> (Copy x) +(Com16 (Com16 x)) -> (Copy x) +(Com32 (Com32 x)) -> (Copy x) +(Com64 (Com64 x)) -> (Copy x) + // tear apart slices // TODO: anything that generates a slice needs to go in here. (SlicePtr (Load ptr mem)) -> (Load ptr mem) diff --git a/src/cmd/compile/internal/ssa/rewritegeneric.go b/src/cmd/compile/internal/ssa/rewritegeneric.go index 17608d71c4..bccf81b831 100644 --- a/src/cmd/compile/internal/ssa/rewritegeneric.go +++ b/src/cmd/compile/internal/ssa/rewritegeneric.go @@ -76,6 +76,82 @@ func rewriteValuegeneric(v *Value, config *Config) bool { goto end4894dd7b58383fee5f8a92be08437c33 end4894dd7b58383fee5f8a92be08437c33: ; + case OpCom16: + // match: (Com16 (Com16 x)) + // cond: + // result: (Copy x) + { + if v.Args[0].Op != OpCom16 { + goto end388d572e5a72fd87a07da5cab243ebdc + } + x := v.Args[0].Args[0] + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto end388d572e5a72fd87a07da5cab243ebdc + end388d572e5a72fd87a07da5cab243ebdc: + ; + case OpCom32: + // match: (Com32 (Com32 x)) + // cond: + // result: (Copy x) + { + if v.Args[0].Op != OpCom32 { + goto end5b2b3834acc7313649923604f685e7c5 + } + x := v.Args[0].Args[0] + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto end5b2b3834acc7313649923604f685e7c5 + end5b2b3834acc7313649923604f685e7c5: + ; + case OpCom64: + // match: (Com64 (Com64 x)) + // cond: + // result: (Copy x) + { + if v.Args[0].Op != OpCom64 { + goto end6d6312f25d06a327d92f028b1ce50566 + } + x := v.Args[0].Args[0] + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto end6d6312f25d06a327d92f028b1ce50566 + end6d6312f25d06a327d92f028b1ce50566: + ; + case OpCom8: + // match: (Com8 (Com8 x)) + // cond: + // result: (Copy x) + { + if v.Args[0].Op != OpCom8 { + goto end70cbd85c4b8e82c170dba7c23f8bc0f3 + } + x := v.Args[0].Args[0] + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto end70cbd85c4b8e82c170dba7c23f8bc0f3 + end70cbd85c4b8e82c170dba7c23f8bc0f3: + ; case OpConstString: // match: (ConstString {s}) // cond: -- cgit v1.3 From ca088cf4e59a1e9ef97dbbf16f035a152a8ddda8 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Wed, 5 Aug 2015 15:56:31 -0700 Subject: [dev.ssa] cmd/compile: handle phi control values Tests courtesy of Todd Neal. Change-Id: If657c7c7d3cd1ce01e9d9ad79eb6b2110230c0f9 Reviewed-on: https://go-review.googlesource.com/13267 Reviewed-by: Todd Neal Reviewed-by: Keith Randall --- src/cmd/compile/internal/gc/testdata/ctl_ssa.go | 53 +++++++++++++++++++++++++ src/cmd/compile/internal/ssa/gen/AMD64.rules | 2 +- src/cmd/compile/internal/ssa/rewriteAMD64.go | 9 ++--- 3 files changed, 57 insertions(+), 7 deletions(-) create mode 100644 src/cmd/compile/internal/gc/testdata/ctl_ssa.go (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/testdata/ctl_ssa.go b/src/cmd/compile/internal/gc/testdata/ctl_ssa.go new file mode 100644 index 0000000000..7377c9aee8 --- /dev/null +++ b/src/cmd/compile/internal/gc/testdata/ctl_ssa.go @@ -0,0 +1,53 @@ +// run + +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Test control flow + +package main + +// nor_ssa calculates NOR(a, b). +// It is implemented in a way that generates +// phi control values. +func nor_ssa(a, b bool) bool { + var c bool + if a { + c = true + } + if b { + c = true + } + if c { + return false + } + return true +} + +func testPhiControl() { + tests := [...][3]bool{ // a, b, want + {false, false, true}, + {true, false, false}, + {false, true, false}, + {true, true, false}, + } + for _, test := range tests { + a, b := test[0], test[1] + got := nor_ssa(a, b) + want := test[2] + if want != got { + print("nor(", a, ", ", b, ")=", want, " got ", got, "\n") + failed = true + } + } +} + +var failed = false + +func main() { + testPhiControl() + if failed { + panic("failed") + } +} diff --git a/src/cmd/compile/internal/ssa/gen/AMD64.rules b/src/cmd/compile/internal/ssa/gen/AMD64.rules index e7c712eb17..ea2311cae0 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64.rules +++ b/src/cmd/compile/internal/ssa/gen/AMD64.rules @@ -241,7 +241,7 @@ (If (SETBE cmp) yes no) -> (ULE cmp yes no) (If (SETA cmp) yes no) -> (UGT cmp yes no) (If (SETAE cmp) yes no) -> (UGE cmp yes no) -(If cond yes no) && cond.Op == OpAMD64MOVBload -> (NE (TESTB cond cond) yes no) +(If cond yes no) -> (NE (TESTB cond cond) yes no) (StaticCall [argwid] {target} mem) -> (CALLstatic [argwid] {target} mem) (ClosureCall [argwid] entry closure mem) -> (CALLclosure [argwid] entry closure mem) diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go index 1e7d957f92..4fa95a4726 100644 --- a/src/cmd/compile/internal/ssa/rewriteAMD64.go +++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go @@ -8068,16 +8068,13 @@ func rewriteBlockAMD64(b *Block) bool { end9bea9963c3c5dfb97249a5feb8287f94: ; // match: (If cond yes no) - // cond: cond.Op == OpAMD64MOVBload + // cond: // result: (NE (TESTB cond cond) yes no) { v := b.Control cond := v yes := b.Succs[0] no := b.Succs[1] - if !(cond.Op == OpAMD64MOVBload) { - goto end7e22019fb0effc80f85c05ea30bdb5d9 - } b.Kind = BlockAMD64NE v0 := b.NewValue0(v.Line, OpAMD64TESTB, TypeInvalid) v0.Type = TypeFlags @@ -8088,8 +8085,8 @@ func rewriteBlockAMD64(b *Block) bool { b.Succs[1] = no return true } - goto end7e22019fb0effc80f85c05ea30bdb5d9 - end7e22019fb0effc80f85c05ea30bdb5d9: + goto end012351592edfc708bd3181d7e53f3993 + end012351592edfc708bd3181d7e53f3993: ; case BlockAMD64LE: // match: (LE (InvertFlags cmp) yes no) -- cgit v1.3 From e98edc88c9d8453a22bfe3753d0f49510de0cf83 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Mon, 10 Aug 2015 11:10:53 -0700 Subject: [dev.ssa] cmd/compile/internal/ssa: enforce load-store ordering in scheduler We must make sure that all loads that use a store are scheduled before the next store. Add additional dependency edges to the value graph to enforce this constraint. Change-Id: Iab83644f68bc4c30637085b82ca7467b9d5513a5 Reviewed-on: https://go-review.googlesource.com/13470 Reviewed-by: Josh Bleecher Snyder --- .../compile/internal/gc/testdata/loadstore_ssa.go | 39 ++++++++++++++ src/cmd/compile/internal/ssa/schedule.go | 62 +++++++++++++++++----- 2 files changed, 87 insertions(+), 14 deletions(-) create mode 100644 src/cmd/compile/internal/gc/testdata/loadstore_ssa.go (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/testdata/loadstore_ssa.go b/src/cmd/compile/internal/gc/testdata/loadstore_ssa.go new file mode 100644 index 0000000000..abca2a4bf8 --- /dev/null +++ b/src/cmd/compile/internal/gc/testdata/loadstore_ssa.go @@ -0,0 +1,39 @@ +// run + +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Tests load/store ordering + +package main + +// testLoadStoreOrder tests for reordering of stores/loads. +func testLoadStoreOrder() { + z := uint32(1000) + if testLoadStoreOrder_ssa(&z, 100) == 0 { + println("testLoadStoreOrder failed") + failed = true + } +} +func testLoadStoreOrder_ssa(z *uint32, prec uint) int { + switch { + } + old := *z // load + *z = uint32(prec) // store + if *z < old { // load + return 1 + } + return 0 +} + +var failed = false + +func main() { + + testLoadStoreOrder() + + if failed { + panic("failed") + } +} diff --git a/src/cmd/compile/internal/ssa/schedule.go b/src/cmd/compile/internal/ssa/schedule.go index 9c8e9a1156..8388695fa8 100644 --- a/src/cmd/compile/internal/ssa/schedule.go +++ b/src/cmd/compile/internal/ssa/schedule.go @@ -21,20 +21,47 @@ func schedule(f *Func) { var order []*Value // priority queue of legally schedulable (0 unscheduled uses) values - var priq [4][]*Value + var priq [5][]*Value + + // maps mem values to the next live memory value + nextMem := make([]*Value, f.NumValues()) + // additional pretend arguments for each Value. Used to enforce load/store ordering. + additionalArgs := make([][]*Value, f.NumValues()) for _, b := range f.Blocks { + // Find store chain for block. + for _, v := range b.Values { + if v.Op != OpPhi && v.Type.IsMemory() { + for _, w := range v.Args { + if w.Type.IsMemory() { + nextMem[w.ID] = v + } + } + } + } + // Compute uses. for _, v := range b.Values { - if v.Op != OpPhi { - // Note: if a value is used by a phi, it does not induce + if v.Op == OpPhi { + // If a value is used by a phi, it does not induce // a scheduling edge because that use is from the // previous iteration. - for _, w := range v.Args { - if w.Block == b { - uses[w.ID]++ - } + continue + } + for _, w := range v.Args { + if w.Block == b { + uses[w.ID]++ + } + // Any load must come before the following store. + if v.Type.IsMemory() || !w.Type.IsMemory() { + continue // not a load } + s := nextMem[w.ID] + if s == nil || s.Block != b { + continue + } + additionalArgs[s.ID] = append(additionalArgs[s.ID], v) + uses[v.ID]++ } } // Compute score. Larger numbers are scheduled closer to the end of the block. @@ -44,23 +71,22 @@ func schedule(f *Func) { // We want all the phis first. score[v.ID] = 0 case v.Type.IsMemory(): - // Schedule stores as late as possible. - // This makes sure that loads do not get scheduled - // after a following store (1-live-memory requirement). - score[v.ID] = 2 + // Schedule stores as early as possible. This tends to + // reduce register pressure. + score[v.ID] = 1 case v.Type.IsFlags(): // Schedule flag register generation as late as possible. // This makes sure that we only have one live flags // value at a time. - score[v.ID] = 2 + score[v.ID] = 3 default: - score[v.ID] = 1 + score[v.ID] = 2 } } if b.Control != nil && b.Control.Op != OpPhi { // Force the control value to be scheduled at the end, // unless it is a phi value (which must be first). - score[b.Control.ID] = 3 + score[b.Control.ID] = 4 // TODO: some times control values are used by other values // in the block. So the control value will not appear at // the very end. Decide if this is a problem or not. @@ -110,6 +136,14 @@ func schedule(f *Func) { priq[s] = append(priq[s], w) } } + for _, w := range additionalArgs[v.ID] { + uses[w.ID]-- + if uses[w.ID] == 0 { + // All uses scheduled, w is now schedulable. + s := score[w.ID] + priq[s] = append(priq[s], w) + } + } } if len(order) != len(b.Values) { f.Fatalf("schedule does not include all values") -- cgit v1.3 From 40aba8c4e7ac5babf9901d1948ff56c117e3bcf9 Mon Sep 17 00:00:00 2001 From: David Chase Date: Wed, 5 Aug 2015 22:11:14 -0400 Subject: [dev.ssa] cmd/compile: add support for LROT, and tests Hardcoded the limit on constants only allowed. Change-Id: Idb9b07b4871db7a752a79e492671e9b41207b956 Reviewed-on: https://go-review.googlesource.com/13257 Reviewed-by: Keith Randall Reviewed-by: Josh Bleecher Snyder --- src/cmd/compile/internal/gc/ssa.go | 24 ++++++- src/cmd/compile/internal/gc/testdata/arith_ssa.go | 52 +++++++++++++++ src/cmd/compile/internal/ssa/gen/AMD64.rules | 5 ++ src/cmd/compile/internal/ssa/gen/AMD64Ops.go | 5 ++ src/cmd/compile/internal/ssa/gen/genericOps.go | 25 +++++++ src/cmd/compile/internal/ssa/opGen.go | 72 ++++++++++++++++++++ src/cmd/compile/internal/ssa/rewriteAMD64.go | 80 +++++++++++++++++++++++ 7 files changed, 262 insertions(+), 1 deletion(-) (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 041e321717..13a6d6c009 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -843,6 +843,11 @@ var opToSSA = map[opAndType]ssa.Op{ opAndType{OGE, TUINT32}: ssa.OpGeq32U, opAndType{OGE, TINT64}: ssa.OpGeq64, opAndType{OGE, TUINT64}: ssa.OpGeq64U, + + opAndType{OLROT, TUINT8}: ssa.OpLrot8, + opAndType{OLROT, TUINT16}: ssa.OpLrot16, + opAndType{OLROT, TUINT32}: ssa.OpLrot32, + opAndType{OLROT, TUINT64}: ssa.OpLrot64, } func (s *state) concreteEtype(t *Type) uint8 { @@ -967,6 +972,15 @@ func (s *state) ssaShiftOp(op uint8, t *Type, u *Type) ssa.Op { return x } +func (s *state) ssaRotateOp(op uint8, t *Type) ssa.Op { + etype1 := s.concreteEtype(t) + x, ok := opToSSA[opAndType{op, etype1}] + if !ok { + s.Unimplementedf("unhandled rotate op %s etype=%s", opnames[op], Econv(int(etype1), 0)) + } + return x +} + // expr converts the expression n to ssa, adds it to s and returns the ssa result. func (s *state) expr(n *Node) *ssa.Value { s.pushLine(n.Lineno) @@ -1140,6 +1154,13 @@ func (s *state) expr(n *Node) *ssa.Value { a := s.expr(n.Left) b := s.expr(n.Right) return s.newValue2(s.ssaShiftOp(n.Op, n.Type, n.Right.Type), a.Type, a, b) + case OLROT: + a := s.expr(n.Left) + i := n.Right.Int() + if i <= 0 || i >= n.Type.Size()*8 { + s.Fatalf("Wrong rotate distance for LROT, expected 1 through %d, saw %d", n.Type.Size()*8-1, i) + } + return s.newValue1I(s.ssaRotateOp(n.Op, n.Type), a.Type, i, a) case OANDAND, OOROR: // To implement OANDAND (and OOROR), we introduce a // new temporary variable to hold the result. The @@ -1936,7 +1957,8 @@ func genValue(v *ssa.Value) { ssa.OpAMD64SUBQconst, ssa.OpAMD64SUBLconst, ssa.OpAMD64SUBWconst, ssa.OpAMD64SUBBconst, ssa.OpAMD64SHLQconst, ssa.OpAMD64SHLLconst, ssa.OpAMD64SHLWconst, ssa.OpAMD64SHLBconst, ssa.OpAMD64SHRQconst, ssa.OpAMD64SHRLconst, ssa.OpAMD64SHRWconst, ssa.OpAMD64SHRBconst, - ssa.OpAMD64SARQconst, ssa.OpAMD64SARLconst, ssa.OpAMD64SARWconst, ssa.OpAMD64SARBconst: + ssa.OpAMD64SARQconst, ssa.OpAMD64SARLconst, ssa.OpAMD64SARWconst, ssa.OpAMD64SARBconst, + ssa.OpAMD64ROLQconst, ssa.OpAMD64ROLLconst, ssa.OpAMD64ROLWconst, ssa.OpAMD64ROLBconst: // This code compensates for the fact that the register allocator // doesn't understand 2-address instructions yet. TODO: fix that. x := regnum(v.Args[0]) diff --git a/src/cmd/compile/internal/gc/testdata/arith_ssa.go b/src/cmd/compile/internal/gc/testdata/arith_ssa.go index 6341e9b90d..0dbf9451ab 100644 --- a/src/cmd/compile/internal/gc/testdata/arith_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/arith_ssa.go @@ -171,6 +171,57 @@ func testOcom_ssa(a, b int32) (int32, int32) { return ^^^^a, ^^^^^b } +func lrot1_ssa(w uint8, x uint16, y uint32, z uint64) (a uint8, b uint16, c uint32, d uint64) { + a = (w << 5) | (w >> 3) + b = (x << 13) | (x >> 3) + c = (y << 29) | (y >> 3) + d = (z << 61) | (z >> 3) + return +} + +func lrot2_ssa(w, n uint32) uint32 { + // Want to be sure that a "rotate by 32" which + // is really 0 | (w >> 0) == w + // is correctly compiled. + switch { // prevents inlining + } + return (w << n) | (w >> (32 - n)) +} + +func lrot3_ssa(w uint32) uint32 { + // Want to be sure that a "rotate by 32" which + // is really 0 | (w >> 0) == w + // is correctly compiled. + switch { // prevents inlining + } + return (w << 32) | (w >> (32 - 32)) +} + +func testLrot() { + wantA, wantB, wantC, wantD := uint8(0xe1), uint16(0xe001), + uint32(0xe0000001), uint64(0xe000000000000001) + a, b, c, d := lrot1_ssa(0xf, 0xf, 0xf, 0xf) + if a != wantA || b != wantB || c != wantC || d != wantD { + println("lrot1_ssa(0xf, 0xf, 0xf, 0xf)=", + wantA, wantB, wantC, wantD, ", got", a, b, c, d) + failed = true + } + x := lrot2_ssa(0xb0000001, 32) + wantX := uint32(0xb0000001) + if x != wantX { + println("lrot2_ssa(0xb0000001, 32)=", + wantX, ", got", x) + failed = true + } + x = lrot3_ssa(0xb0000001) + if x != wantX { + println("lrot3_ssa(0xb0000001)=", + wantX, ", got", x) + failed = true + } + +} + var failed = false func main() { @@ -181,6 +232,7 @@ func main() { testSubqToNegq() testBitwiseLogic() testOcom() + testLrot() if failed { panic("failed") diff --git a/src/cmd/compile/internal/ssa/gen/AMD64.rules b/src/cmd/compile/internal/ssa/gen/AMD64.rules index f4a26c8c64..42b3cf2777 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64.rules +++ b/src/cmd/compile/internal/ssa/gen/AMD64.rules @@ -102,6 +102,11 @@ (Lsh8x16 x y) -> (ANDB (SHLB x y) (SBBLcarrymask (CMPWconst [8] y))) (Lsh8x8 x y) -> (ANDB (SHLB x y) (SBBLcarrymask (CMPBconst [8] y))) +(Lrot64 x [c]) -> (ROLQconst [c&63] x) +(Lrot32 x [c]) -> (ROLLconst [c&31] x) +(Lrot16 x [c]) -> (ROLWconst [c&15] x) +(Lrot8 x [c]) -> (ROLBconst [c&7] x) + (Rsh64Ux64 x y) -> (ANDQ (SHRQ x y) (SBBQcarrymask (CMPQconst [64] y))) (Rsh64Ux32 x y) -> (ANDQ (SHRQ x y) (SBBQcarrymask (CMPLconst [64] y))) (Rsh64Ux16 x y) -> (ANDQ (SHRQ x y) (SBBQcarrymask (CMPWconst [64] y))) diff --git a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go index 0c306cbbcb..65fc5c60e1 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go @@ -209,6 +209,11 @@ func init() { {name: "SARWconst", reg: gp11, asm: "SARW"}, // signed arg0 >> auxint, shift amount 0-31 {name: "SARBconst", reg: gp11, asm: "SARB"}, // signed arg0 >> auxint, shift amount 0-31 + {name: "ROLQconst", reg: gp11, asm: "ROLQ"}, // arg0 rotate left auxint, rotate amount 0-63 + {name: "ROLLconst", reg: gp11, asm: "ROLL"}, // arg0 rotate left auxint, rotate amount 0-31 + {name: "ROLWconst", reg: gp11, asm: "ROLW"}, // arg0 rotate left auxint, rotate amount 0-15 + {name: "ROLBconst", reg: gp11, asm: "ROLB"}, // arg0 rotate left auxint, rotate amount 0-7 + // unary ops {name: "NEGQ", reg: gp11, asm: "NEGQ"}, // -arg0 {name: "NEGL", reg: gp11, asm: "NEGL"}, // -arg0 diff --git a/src/cmd/compile/internal/ssa/gen/genericOps.go b/src/cmd/compile/internal/ssa/gen/genericOps.go index 657973e333..4aa6af5c9e 100644 --- a/src/cmd/compile/internal/ssa/gen/genericOps.go +++ b/src/cmd/compile/internal/ssa/gen/genericOps.go @@ -94,6 +94,31 @@ var genericOps = []opData{ {name: "Rsh64Ux32"}, {name: "Rsh64Ux64"}, + // (Left) rotates replace pattern matches in the front end + // of (arg0 << arg1) ^ (arg0 >> (A-arg1)) + // where A is the bit width of arg0 and result. + // Note that because rotates are pattern-matched from + // shifts, that a rotate of arg1=A+k (k > 0) bits originated from + // (arg0 << A+k) ^ (arg0 >> -k) = + // 0 ^ arg0>>huge_unsigned = + // 0 ^ 0 = 0 + // which is not the same as a rotation by A+k + // + // However, in the specific case of k = 0, the result of + // the shift idiom is the same as the result for the + // rotate idiom, i.e., result=arg0. + // This is different from shifts, where + // arg0 << A is defined to be zero. + // + // Because of this, and also because the primary use case + // for rotates is hashing and crypto code with constant + // distance, rotate instructions are only substituted + // when arg1 is a constant between 1 and A-1, inclusive. + {name: "Lrot8"}, + {name: "Lrot16"}, + {name: "Lrot32"}, + {name: "Lrot64"}, + // 2-input comparisons {name: "Eq8"}, // arg0 == arg1 {name: "Eq16"}, diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index e77df40ebd..427fb33f57 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -137,6 +137,10 @@ const ( OpAMD64SARLconst OpAMD64SARWconst OpAMD64SARBconst + OpAMD64ROLQconst + OpAMD64ROLLconst + OpAMD64ROLWconst + OpAMD64ROLBconst OpAMD64NEGQ OpAMD64NEGL OpAMD64NEGW @@ -265,6 +269,10 @@ const ( OpRsh64Ux16 OpRsh64Ux32 OpRsh64Ux64 + OpLrot8 + OpLrot16 + OpLrot32 + OpLrot64 OpEq8 OpEq16 OpEq32 @@ -1454,6 +1462,54 @@ var opcodeTable = [...]opInfo{ }, }, }, + { + name: "ROLQconst", + asm: x86.AROLQ, + reg: regInfo{ + inputs: []regMask{ + 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + outputs: []regMask{ + 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + }, + }, + { + name: "ROLLconst", + asm: x86.AROLL, + reg: regInfo{ + inputs: []regMask{ + 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + outputs: []regMask{ + 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + }, + }, + { + name: "ROLWconst", + asm: x86.AROLW, + reg: regInfo{ + inputs: []regMask{ + 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + outputs: []regMask{ + 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + }, + }, + { + name: "ROLBconst", + asm: x86.AROLB, + reg: regInfo{ + inputs: []regMask{ + 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + outputs: []regMask{ + 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + }, + }, { name: "NEGQ", asm: x86.ANEGQ, @@ -2354,6 +2410,22 @@ var opcodeTable = [...]opInfo{ name: "Rsh64Ux64", generic: true, }, + { + name: "Lrot8", + generic: true, + }, + { + name: "Lrot16", + generic: true, + }, + { + name: "Lrot32", + generic: true, + }, + { + name: "Lrot64", + generic: true, + }, { name: "Eq8", generic: true, diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go index 867d62b1bc..4a9fa71bdb 100644 --- a/src/cmd/compile/internal/ssa/rewriteAMD64.go +++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go @@ -2544,6 +2544,86 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto end8f83bf72293670e75b22d6627bd13f0b end8f83bf72293670e75b22d6627bd13f0b: ; + case OpLrot16: + // match: (Lrot16 x [c]) + // cond: + // result: (ROLWconst [c&15] x) + { + t := v.Type + x := v.Args[0] + c := v.AuxInt + v.Op = OpAMD64ROLWconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = t + v.AuxInt = c & 15 + v.AddArg(x) + return true + } + goto endb23dfa24c619d0068f925899d53ee7fd + endb23dfa24c619d0068f925899d53ee7fd: + ; + case OpLrot32: + // match: (Lrot32 x [c]) + // cond: + // result: (ROLLconst [c&31] x) + { + t := v.Type + x := v.Args[0] + c := v.AuxInt + v.Op = OpAMD64ROLLconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = t + v.AuxInt = c & 31 + v.AddArg(x) + return true + } + goto end38b2215c011896c36845f72ecb72b1b0 + end38b2215c011896c36845f72ecb72b1b0: + ; + case OpLrot64: + // match: (Lrot64 x [c]) + // cond: + // result: (ROLQconst [c&63] x) + { + t := v.Type + x := v.Args[0] + c := v.AuxInt + v.Op = OpAMD64ROLQconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = t + v.AuxInt = c & 63 + v.AddArg(x) + return true + } + goto end5cb355e4f3ca387f252ef4f6a55f9f68 + end5cb355e4f3ca387f252ef4f6a55f9f68: + ; + case OpLrot8: + // match: (Lrot8 x [c]) + // cond: + // result: (ROLBconst [c&7] x) + { + t := v.Type + x := v.Args[0] + c := v.AuxInt + v.Op = OpAMD64ROLBconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = t + v.AuxInt = c & 7 + v.AddArg(x) + return true + } + goto end26bfb3dd5b537cf13ac9f2978d94ed71 + end26bfb3dd5b537cf13ac9f2978d94ed71: + ; case OpLsh16x16: // match: (Lsh16x16 x y) // cond: -- cgit v1.3 From 3b705824ce6cf4827732eb32923835a327c5f963 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Thu, 13 Aug 2015 12:47:50 -0700 Subject: [dev.ssa] cmd/compile: fix constant subtraction rules (SUBQconst [x] y) computes y-x, not x-y. Fixes #12137 Change-Id: Idbd0554eee051102f562240d1756647843666ee6 Reviewed-on: https://go-review.googlesource.com/13631 Reviewed-by: Josh Bleecher Snyder --- src/cmd/compile/internal/gc/testdata/arith_ssa.go | 31 +++++++++ src/cmd/compile/internal/ssa/gen/AMD64.rules | 16 ++--- src/cmd/compile/internal/ssa/rewriteAMD64.go | 80 +++++++++++------------ 3 files changed, 79 insertions(+), 48 deletions(-) (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/testdata/arith_ssa.go b/src/cmd/compile/internal/gc/testdata/arith_ssa.go index 0dbf9451ab..ca96988113 100644 --- a/src/cmd/compile/internal/gc/testdata/arith_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/arith_ssa.go @@ -222,6 +222,36 @@ func testLrot() { } +func sub1_ssa() uint64 { + switch { + } // prevent inlining + v1 := uint64(3) // uint64 + return v1*v1 - (v1&v1)&v1 +} +func sub2_ssa() uint8 { + switch { + } + v1 := uint8(0) + v3 := v1 + v1 + v1 ^ v1 | 3 + v1 ^ v1 | v1 ^ v1 + v1-- // dev.ssa doesn't see this one + return v1 ^ v1*v1 - v3 +} + +func testSubConst() { + x1 := sub1_ssa() + want1 := uint64(6) + if x1 != want1 { + println("sub1_ssa()=", want1, ", got", x1) + failed = true + } + x2 := sub2_ssa() + want2 := uint8(251) + if x2 != want2 { + println("sub2_ssa()=", want2, ", got", x2) + failed = true + } +} + var failed = false func main() { @@ -233,6 +263,7 @@ func main() { testBitwiseLogic() testOcom() testLrot() + testSubConst() if failed { panic("failed") diff --git a/src/cmd/compile/internal/ssa/gen/AMD64.rules b/src/cmd/compile/internal/ssa/gen/AMD64.rules index ab8e44a444..ec142d801e 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64.rules +++ b/src/cmd/compile/internal/ssa/gen/AMD64.rules @@ -483,14 +483,14 @@ (ADDLconst [c] (ADDLconst [d] x)) -> (ADDLconst [c+d] x) (ADDWconst [c] (ADDWconst [d] x)) -> (ADDWconst [c+d] x) (ADDBconst [c] (ADDBconst [d] x)) -> (ADDBconst [c+d] x) -(SUBQconst [c] (MOVQconst [d])) -> (MOVQconst [c-d]) -(SUBLconst [c] (MOVLconst [d])) -> (MOVLconst [c-d]) -(SUBWconst [c] (MOVWconst [d])) -> (MOVWconst [c-d]) -(SUBBconst [c] (MOVBconst [d])) -> (MOVBconst [c-d]) -(SUBQconst [c] (SUBQconst [d] x)) -> (ADDQconst [c-d] x) -(SUBLconst [c] (SUBLconst [d] x)) -> (ADDLconst [c-d] x) -(SUBWconst [c] (SUBWconst [d] x)) -> (ADDWconst [c-d] x) -(SUBBconst [c] (SUBBconst [d] x)) -> (ADDBconst [c-d] x) +(SUBQconst [c] (MOVQconst [d])) -> (MOVQconst [d-c]) +(SUBLconst [c] (MOVLconst [d])) -> (MOVLconst [d-c]) +(SUBWconst [c] (MOVWconst [d])) -> (MOVWconst [d-c]) +(SUBBconst [c] (MOVBconst [d])) -> (MOVBconst [d-c]) +(SUBQconst [c] (SUBQconst [d] x)) -> (ADDQconst [-c-d] x) +(SUBLconst [c] (SUBLconst [d] x)) -> (ADDLconst [-c-d] x) +(SUBWconst [c] (SUBWconst [d] x)) -> (ADDWconst [-c-d] x) +(SUBBconst [c] (SUBBconst [d] x)) -> (ADDBconst [-c-d] x) (NEGQ (MOVQconst [c])) -> (MOVQconst [-c]) (NEGL (MOVLconst [c])) -> (MOVLconst [-c]) (NEGW (MOVWconst [c])) -> (MOVWconst [-c]) diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go index a18097f91e..a9f3ad79ab 100644 --- a/src/cmd/compile/internal/ssa/rewriteAMD64.go +++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go @@ -6801,30 +6801,30 @@ func rewriteValueAMD64(v *Value, config *Config) bool { case OpAMD64SUBBconst: // match: (SUBBconst [c] (MOVBconst [d])) // cond: - // result: (MOVBconst [c-d]) + // result: (MOVBconst [d-c]) { c := v.AuxInt if v.Args[0].Op != OpAMD64MOVBconst { - goto end0e2d5c3e3c02001a20d5433daa9e8317 + goto enddc5383558e2f3eae507afcb94eada964 } d := v.Args[0].AuxInt v.Op = OpAMD64MOVBconst v.AuxInt = 0 v.Aux = nil v.resetArgs() - v.AuxInt = c - d + v.AuxInt = d - c return true } - goto end0e2d5c3e3c02001a20d5433daa9e8317 - end0e2d5c3e3c02001a20d5433daa9e8317: + goto enddc5383558e2f3eae507afcb94eada964 + enddc5383558e2f3eae507afcb94eada964: ; // match: (SUBBconst [c] (SUBBconst [d] x)) // cond: - // result: (ADDBconst [c-d] x) + // result: (ADDBconst [-c-d] x) { c := v.AuxInt if v.Args[0].Op != OpAMD64SUBBconst { - goto end48eccb421dfe0c678ea9c47113521d5a + goto end035c57413a46eb347ecb3736d1510915 } d := v.Args[0].AuxInt x := v.Args[0].Args[0] @@ -6832,12 +6832,12 @@ func rewriteValueAMD64(v *Value, config *Config) bool { v.AuxInt = 0 v.Aux = nil v.resetArgs() - v.AuxInt = c - d + v.AuxInt = -c - d v.AddArg(x) return true } - goto end48eccb421dfe0c678ea9c47113521d5a - end48eccb421dfe0c678ea9c47113521d5a: + goto end035c57413a46eb347ecb3736d1510915 + end035c57413a46eb347ecb3736d1510915: ; case OpAMD64SUBL: // match: (SUBL x (MOVLconst [c])) @@ -6904,30 +6904,30 @@ func rewriteValueAMD64(v *Value, config *Config) bool { case OpAMD64SUBLconst: // match: (SUBLconst [c] (MOVLconst [d])) // cond: - // result: (MOVLconst [c-d]) + // result: (MOVLconst [d-c]) { c := v.AuxInt if v.Args[0].Op != OpAMD64MOVLconst { - goto endbe7466f3c09d9645544bdfc44c37c922 + goto end6c5c6d58d4bdd0a5c2f7bf10b343b41e } d := v.Args[0].AuxInt v.Op = OpAMD64MOVLconst v.AuxInt = 0 v.Aux = nil v.resetArgs() - v.AuxInt = c - d + v.AuxInt = d - c return true } - goto endbe7466f3c09d9645544bdfc44c37c922 - endbe7466f3c09d9645544bdfc44c37c922: + goto end6c5c6d58d4bdd0a5c2f7bf10b343b41e + end6c5c6d58d4bdd0a5c2f7bf10b343b41e: ; // match: (SUBLconst [c] (SUBLconst [d] x)) // cond: - // result: (ADDLconst [c-d] x) + // result: (ADDLconst [-c-d] x) { c := v.AuxInt if v.Args[0].Op != OpAMD64SUBLconst { - goto endb5106962a865bc4654b170c2e29a72c4 + goto end0c9ffb11e8a56ced1b14dbf6bf9a6737 } d := v.Args[0].AuxInt x := v.Args[0].Args[0] @@ -6935,12 +6935,12 @@ func rewriteValueAMD64(v *Value, config *Config) bool { v.AuxInt = 0 v.Aux = nil v.resetArgs() - v.AuxInt = c - d + v.AuxInt = -c - d v.AddArg(x) return true } - goto endb5106962a865bc4654b170c2e29a72c4 - endb5106962a865bc4654b170c2e29a72c4: + goto end0c9ffb11e8a56ced1b14dbf6bf9a6737 + end0c9ffb11e8a56ced1b14dbf6bf9a6737: ; case OpAMD64SUBQ: // match: (SUBQ x (MOVQconst [c])) @@ -7013,30 +7013,30 @@ func rewriteValueAMD64(v *Value, config *Config) bool { case OpAMD64SUBQconst: // match: (SUBQconst [c] (MOVQconst [d])) // cond: - // result: (MOVQconst [c-d]) + // result: (MOVQconst [d-c]) { c := v.AuxInt if v.Args[0].Op != OpAMD64MOVQconst { - goto end96c09479fb3c043e875d89d3eb92f1d8 + goto endb0daebe6831cf381377c3e4248070f25 } d := v.Args[0].AuxInt v.Op = OpAMD64MOVQconst v.AuxInt = 0 v.Aux = nil v.resetArgs() - v.AuxInt = c - d + v.AuxInt = d - c return true } - goto end96c09479fb3c043e875d89d3eb92f1d8 - end96c09479fb3c043e875d89d3eb92f1d8: + goto endb0daebe6831cf381377c3e4248070f25 + endb0daebe6831cf381377c3e4248070f25: ; // match: (SUBQconst [c] (SUBQconst [d] x)) // cond: - // result: (ADDQconst [c-d] x) + // result: (ADDQconst [-c-d] x) { c := v.AuxInt if v.Args[0].Op != OpAMD64SUBQconst { - goto enddd9d61b404480adb40cfd7fedd7e5ec4 + goto end2d40ddb5ae9e90679456254c61858d9d } d := v.Args[0].AuxInt x := v.Args[0].Args[0] @@ -7044,12 +7044,12 @@ func rewriteValueAMD64(v *Value, config *Config) bool { v.AuxInt = 0 v.Aux = nil v.resetArgs() - v.AuxInt = c - d + v.AuxInt = -c - d v.AddArg(x) return true } - goto enddd9d61b404480adb40cfd7fedd7e5ec4 - enddd9d61b404480adb40cfd7fedd7e5ec4: + goto end2d40ddb5ae9e90679456254c61858d9d + end2d40ddb5ae9e90679456254c61858d9d: ; case OpAMD64SUBW: // match: (SUBW x (MOVWconst [c])) @@ -7116,30 +7116,30 @@ func rewriteValueAMD64(v *Value, config *Config) bool { case OpAMD64SUBWconst: // match: (SUBWconst [c] (MOVWconst [d])) // cond: - // result: (MOVWconst [c-d]) + // result: (MOVWconst [d-c]) { c := v.AuxInt if v.Args[0].Op != OpAMD64MOVWconst { - goto end0e5079577fcf00f5925291dbd68306aa + goto endae629a229c399eaed7dbb95b1b0e6f8a } d := v.Args[0].AuxInt v.Op = OpAMD64MOVWconst v.AuxInt = 0 v.Aux = nil v.resetArgs() - v.AuxInt = c - d + v.AuxInt = d - c return true } - goto end0e5079577fcf00f5925291dbd68306aa - end0e5079577fcf00f5925291dbd68306aa: + goto endae629a229c399eaed7dbb95b1b0e6f8a + endae629a229c399eaed7dbb95b1b0e6f8a: ; // match: (SUBWconst [c] (SUBWconst [d] x)) // cond: - // result: (ADDWconst [c-d] x) + // result: (ADDWconst [-c-d] x) { c := v.AuxInt if v.Args[0].Op != OpAMD64SUBWconst { - goto endb628696cf5b329d03782b8093093269b + goto enda59f08d12aa08717b0443b7bb1b71374 } d := v.Args[0].AuxInt x := v.Args[0].Args[0] @@ -7147,12 +7147,12 @@ func rewriteValueAMD64(v *Value, config *Config) bool { v.AuxInt = 0 v.Aux = nil v.resetArgs() - v.AuxInt = c - d + v.AuxInt = -c - d v.AddArg(x) return true } - goto endb628696cf5b329d03782b8093093269b - endb628696cf5b329d03782b8093093269b: + goto enda59f08d12aa08717b0443b7bb1b71374 + enda59f08d12aa08717b0443b7bb1b71374: ; case OpSignExt16to32: // match: (SignExt16to32 x) -- cgit v1.3 From c55870a5412fb374c9c392a06c3949b291c48e15 Mon Sep 17 00:00:00 2001 From: Alexandru Moșoi Date: Fri, 7 Aug 2015 12:19:03 +0200 Subject: [dev.ssa] cmd/compile/internal/gc: handle all inputs for shifts. Disable CX as output for shift operations. Change-Id: I85e6b22d09009b38847082dc375b6108c2dee80a Reviewed-on: https://go-review.googlesource.com/13370 Reviewed-by: Keith Randall --- src/cmd/compile/internal/gc/testdata/arith_ssa.go | 23 ++++++++++++++++++++++ src/cmd/compile/internal/ssa/gen/AMD64Ops.go | 3 ++- src/cmd/compile/internal/ssa/opGen.go | 24 +++++++++++------------ 3 files changed, 37 insertions(+), 13 deletions(-) (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/testdata/arith_ssa.go b/src/cmd/compile/internal/gc/testdata/arith_ssa.go index ca96988113..2a56e2163f 100644 --- a/src/cmd/compile/internal/gc/testdata/arith_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/arith_ssa.go @@ -141,6 +141,28 @@ func testBitwiseRshU_ssa(a uint32, b, c uint32) uint32 { return a >> b >> c } +func testShiftCX_ssa() int { + switch { + } // prevent inlining + v1 := uint8(3) + v4 := (v1 * v1) ^ v1 | v1 - v1 - v1&v1 ^ uint8(3+2) + v1*1>>0 - v1 | 1 | v1<<(2*3|0-0*0^1) + v5 := v4>>(3-0-uint(3)) | v1 | v1 + v1 ^ v4<<(0+1|3&1)<<(uint64(1)<<0*2*0<<0) ^ v1 + v6 := v5 ^ (v1+v1)*v1 | v1 | v1*v1>>(v1&v1)>>(uint(1)<<0*uint(3)>>1)*v1<<2*v1<>2 | (v4 - v1) ^ v1 + v1 ^ v1>>1 | v1 + v1 - v1 ^ v1 + v7 := v6 & v5 << 0 + v1++ + v11 := 2&1 ^ 0 + 3 | int(0^0)<<1>>(1*0*3) ^ 0*0 ^ 3&0*3&3 ^ 3*3 ^ 1 ^ int(2)<<(2*3) + 2 | 2 | 2 ^ 2 + 1 | 3 | 0 ^ int(1)>>1 ^ 2 // int + v7-- + return int(uint64(2*1)<<(3-2)<>v7)-2)&v11 | v11 - int(2)<<0>>(2-1)*(v11*0&v11<<1<<(uint8(2)+v4)) +} + +func testShiftCX() { + want := 141 + if got := testShiftCX_ssa(); want != got { + println("testShiftCX failed, wanted", want, "got", got) + failed = true + } +} + // testSubqToNegq ensures that the SUBQ -> NEGQ translation works correctly. func testSubqToNegq() { want := int64(-318294940372190156) @@ -263,6 +285,7 @@ func main() { testBitwiseLogic() testOcom() testLrot() + testShiftCX() testSubConst() if failed { diff --git a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go index 9e8b2fa018..6c517a950e 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go @@ -72,6 +72,7 @@ func init() { // Common individual register masks var ( + cx = buildReg("CX") gp = buildReg("AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15") gpsp = gp | buildReg("SP") gpspsb = gpsp | buildReg("SB") @@ -91,7 +92,7 @@ func init() { gp11sb = regInfo{inputs: []regMask{gpspsb}, outputs: gponly} gp21 = regInfo{inputs: []regMask{gpsp, gpsp}, outputs: gponly} gp21sb = regInfo{inputs: []regMask{gpspsb, gpsp}, outputs: gponly} - gp21shift = regInfo{inputs: []regMask{gpsp, buildReg("CX")}, outputs: gponly} + gp21shift = regInfo{inputs: []regMask{gpsp, cx}, outputs: []regMask{gp &^ cx}} gp2flags = regInfo{inputs: []regMask{gpsp, gpsp}, outputs: flagsonly} gp1flags = regInfo{inputs: []regMask{gpsp}, outputs: flagsonly} diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index 6f412806c8..dd4462d258 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -1175,7 +1175,7 @@ var opcodeTable = [...]opInfo{ 2, // .CX }, outputs: []regMask{ - 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + 65517, // .AX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, }, }, @@ -1188,7 +1188,7 @@ var opcodeTable = [...]opInfo{ 2, // .CX }, outputs: []regMask{ - 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + 65517, // .AX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, }, }, @@ -1201,7 +1201,7 @@ var opcodeTable = [...]opInfo{ 2, // .CX }, outputs: []regMask{ - 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + 65517, // .AX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, }, }, @@ -1214,7 +1214,7 @@ var opcodeTable = [...]opInfo{ 2, // .CX }, outputs: []regMask{ - 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + 65517, // .AX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, }, }, @@ -1275,7 +1275,7 @@ var opcodeTable = [...]opInfo{ 2, // .CX }, outputs: []regMask{ - 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + 65517, // .AX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, }, }, @@ -1288,7 +1288,7 @@ var opcodeTable = [...]opInfo{ 2, // .CX }, outputs: []regMask{ - 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + 65517, // .AX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, }, }, @@ -1301,7 +1301,7 @@ var opcodeTable = [...]opInfo{ 2, // .CX }, outputs: []regMask{ - 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + 65517, // .AX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, }, }, @@ -1314,7 +1314,7 @@ var opcodeTable = [...]opInfo{ 2, // .CX }, outputs: []regMask{ - 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + 65517, // .AX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, }, }, @@ -1375,7 +1375,7 @@ var opcodeTable = [...]opInfo{ 2, // .CX }, outputs: []regMask{ - 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + 65517, // .AX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, }, }, @@ -1388,7 +1388,7 @@ var opcodeTable = [...]opInfo{ 2, // .CX }, outputs: []regMask{ - 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + 65517, // .AX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, }, }, @@ -1401,7 +1401,7 @@ var opcodeTable = [...]opInfo{ 2, // .CX }, outputs: []regMask{ - 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + 65517, // .AX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, }, }, @@ -1414,7 +1414,7 @@ var opcodeTable = [...]opInfo{ 2, // .CX }, outputs: []regMask{ - 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + 65517, // .AX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, }, }, -- cgit v1.3 From d4cc51d4118027464f61034179908abd0005fab6 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Fri, 14 Aug 2015 21:47:20 -0700 Subject: [dev.ssa] cmd/compile/internal/ssa: Use explicit size for store ops Using the type of the store argument is not safe, it may change during rewriting, giving us the wrong store width. (Store ptr (Trunc32to16 val) mem) This should be a 2-byte store. But we have the rule: (Trunc32to16 x) -> x So if the Trunc rewrite happens before the Store -> MOVW rewrite, then the Store thinks that the value it is storing is 4 bytes in size and uses a MOVL. Bad things ensue. Fix this by encoding the store width explicitly in the auxint field. In general, we can't rely on the type of arguments, as they may change during rewrites. The type of the op itself (as used by the Load rules) is still ok to use. Change-Id: I9e2359e4f657bb0ea0e40038969628bf0f84e584 Reviewed-on: https://go-review.googlesource.com/13636 Reviewed-by: Josh Bleecher Snyder --- src/cmd/compile/internal/gc/ssa.go | 16 ++++- .../compile/internal/gc/testdata/loadstore_ssa.go | 29 +++++++++ src/cmd/compile/internal/ssa/deadstore_test.go | 14 ++-- src/cmd/compile/internal/ssa/func.go | 15 +++++ src/cmd/compile/internal/ssa/gen/AMD64.rules | 9 ++- src/cmd/compile/internal/ssa/gen/generic.rules | 3 +- src/cmd/compile/internal/ssa/gen/genericOps.go | 2 +- src/cmd/compile/internal/ssa/rewriteAMD64.go | 76 ++++++++-------------- src/cmd/compile/internal/ssa/rewritegeneric.go | 22 +++---- src/cmd/compile/internal/ssa/schedule_test.go | 6 +- src/cmd/compile/internal/ssa/shift_test.go | 2 +- 11 files changed, 113 insertions(+), 81 deletions(-) (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index ef6ca692a4..d37181daf5 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -331,6 +331,11 @@ func (s *state) newValue3(op ssa.Op, t ssa.Type, arg0, arg1, arg2 *ssa.Value) *s return s.curBlock.NewValue3(s.peekLine(), op, t, arg0, arg1, arg2) } +// newValue3I adds a new value with three arguments and an auxint value to the current block. +func (s *state) newValue3I(op ssa.Op, t ssa.Type, aux int64, arg0, arg1, arg2 *ssa.Value) *ssa.Value { + return s.curBlock.NewValue3I(s.peekLine(), op, t, aux, arg0, arg1, arg2) +} + // entryNewValue adds a new value with no arguments to the entry block. func (s *state) entryNewValue0(op ssa.Op, t ssa.Type) *ssa.Value { return s.f.Entry.NewValue0(s.peekLine(), op, t) @@ -1365,12 +1370,19 @@ func (s *state) expr(n *Node) *ssa.Value { } func (s *state) assign(op uint8, left *Node, right *Node) { + if left.Op == ONAME && isblank(left) { + if right != nil { + s.expr(right) + } + return + } // TODO: do write barrier // if op == OASWB + t := left.Type + dowidth(t) var val *ssa.Value if right == nil { // right == nil means use the zero value of the assigned type. - t := left.Type if !canSSA(left) { // if we can't ssa this memory, treat it as just zeroing out the backing memory addr := s.addr(left) @@ -1388,7 +1400,7 @@ func (s *state) assign(op uint8, left *Node, right *Node) { } // not ssa-able. Treat as a store. addr := s.addr(left) - s.vars[&memvar] = s.newValue3(ssa.OpStore, ssa.TypeMem, addr, val, s.mem()) + s.vars[&memvar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, t.Size(), addr, val, s.mem()) } // zeroVal returns the zero value for type t. diff --git a/src/cmd/compile/internal/gc/testdata/loadstore_ssa.go b/src/cmd/compile/internal/gc/testdata/loadstore_ssa.go index abca2a4bf8..cf37095742 100644 --- a/src/cmd/compile/internal/gc/testdata/loadstore_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/loadstore_ssa.go @@ -8,6 +8,8 @@ package main +import "fmt" + // testLoadStoreOrder tests for reordering of stores/loads. func testLoadStoreOrder() { z := uint32(1000) @@ -27,11 +29,38 @@ func testLoadStoreOrder_ssa(z *uint32, prec uint) int { return 0 } +func testStoreSize() { + a := [4]uint16{11, 22, 33, 44} + testStoreSize_ssa(&a[0], &a[2], 77) + want := [4]uint16{77, 22, 33, 44} + if a != want { + fmt.Println("testStoreSize failed. want =", want, ", got =", a) + failed = true + } +} +func testStoreSize_ssa(p *uint16, q *uint16, v uint32) { + switch { + } + // Test to make sure that (Store ptr (Trunc32to16 val) mem) + // does not end up as a 32-bit store. It must stay a 16 bit store + // even when Trunc32to16 is rewritten to be a nop. + // To ensure that we get rewrite the Trunc32to16 before + // we rewrite the Store, we force the truncate into an + // earlier basic block by using it on both branches. + w := uint16(v) + if p != nil { + *p = w + } else { + *q = w + } +} + var failed = false func main() { testLoadStoreOrder() + testStoreSize() if failed { panic("failed") diff --git a/src/cmd/compile/internal/ssa/deadstore_test.go b/src/cmd/compile/internal/ssa/deadstore_test.go index 634192f25b..0f295296bd 100644 --- a/src/cmd/compile/internal/ssa/deadstore_test.go +++ b/src/cmd/compile/internal/ssa/deadstore_test.go @@ -19,10 +19,10 @@ func TestDeadStore(t *testing.T) { Valu("addr2", OpAddr, ptrType, 0, nil, "sb"), Valu("addr3", OpAddr, ptrType, 0, nil, "sb"), Valu("zero1", OpZero, TypeMem, 8, nil, "addr3", "start"), - Valu("store1", OpStore, TypeMem, 0, nil, "addr1", "v", "zero1"), - Valu("store2", OpStore, TypeMem, 0, nil, "addr2", "v", "store1"), - Valu("store3", OpStore, TypeMem, 0, nil, "addr1", "v", "store2"), - Valu("store4", OpStore, TypeMem, 0, nil, "addr3", "v", "store3"), + Valu("store1", OpStore, TypeMem, 1, nil, "addr1", "v", "zero1"), + Valu("store2", OpStore, TypeMem, 1, nil, "addr2", "v", "store1"), + Valu("store3", OpStore, TypeMem, 1, nil, "addr1", "v", "store2"), + Valu("store4", OpStore, TypeMem, 1, nil, "addr3", "v", "store3"), Goto("exit")), Bloc("exit", Exit("store3"))) @@ -54,7 +54,7 @@ func TestDeadStorePhi(t *testing.T) { Goto("loop")), Bloc("loop", Valu("phi", OpPhi, TypeMem, 0, nil, "start", "store"), - Valu("store", OpStore, TypeMem, 0, nil, "addr", "v", "phi"), + Valu("store", OpStore, TypeMem, 1, nil, "addr", "v", "phi"), If("v", "loop", "exit")), Bloc("exit", Exit("store"))) @@ -79,8 +79,8 @@ func TestDeadStoreTypes(t *testing.T) { Valu("v", OpConstBool, TypeBool, 0, true), Valu("addr1", OpAddr, t1, 0, nil, "sb"), Valu("addr2", OpAddr, t2, 0, nil, "sb"), - Valu("store1", OpStore, TypeMem, 0, nil, "addr1", "v", "start"), - Valu("store2", OpStore, TypeMem, 0, nil, "addr2", "v", "store1"), + Valu("store1", OpStore, TypeMem, 1, nil, "addr1", "v", "start"), + Valu("store2", OpStore, TypeMem, 1, nil, "addr2", "v", "store1"), Goto("exit")), Bloc("exit", Exit("store2"))) diff --git a/src/cmd/compile/internal/ssa/func.go b/src/cmd/compile/internal/ssa/func.go index 9b6eb7f831..97eb1a443a 100644 --- a/src/cmd/compile/internal/ssa/func.go +++ b/src/cmd/compile/internal/ssa/func.go @@ -249,6 +249,21 @@ func (b *Block) NewValue3(line int32, op Op, t Type, arg0, arg1, arg2 *Value) *V return v } +// NewValue3I returns a new value in the block with three arguments and an auxint value. +func (b *Block) NewValue3I(line int32, op Op, t Type, aux int64, arg0, arg1, arg2 *Value) *Value { + v := &Value{ + ID: b.Func.vid.get(), + Op: op, + Type: t, + AuxInt: aux, + Block: b, + Line: line, + } + v.Args = []*Value{arg0, arg1, arg2} + b.Values = append(b.Values, v) + return v +} + // ConstInt returns an int constant representing its argument. func (f *Func) ConstInt8(line int32, t Type, c int8) *Value { // TODO: cache? diff --git a/src/cmd/compile/internal/ssa/gen/AMD64.rules b/src/cmd/compile/internal/ssa/gen/AMD64.rules index 09e88765b6..0e36737337 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64.rules +++ b/src/cmd/compile/internal/ssa/gen/AMD64.rules @@ -203,11 +203,10 @@ (Load ptr mem) && is32BitInt(t) -> (MOVLload ptr mem) (Load ptr mem) && is16BitInt(t) -> (MOVWload ptr mem) (Load ptr mem) && (t.IsBoolean() || is8BitInt(t)) -> (MOVBload ptr mem) -(Store ptr val mem) && (is64BitInt(val.Type) || isPtr(val.Type)) -> (MOVQstore ptr val mem) -(Store ptr val mem) && is32BitInt(val.Type) -> (MOVLstore ptr val mem) -(Store ptr val mem) && is16BitInt(val.Type) -> (MOVWstore ptr val mem) -(Store ptr val mem) && is8BitInt(val.Type) -> (MOVBstore ptr val mem) -(Store ptr val mem) && val.Type.IsBoolean() -> (MOVBstore ptr val mem) +(Store [8] ptr val mem) -> (MOVQstore ptr val mem) +(Store [4] ptr val mem) -> (MOVLstore ptr val mem) +(Store [2] ptr val mem) -> (MOVWstore ptr val mem) +(Store [1] ptr val mem) -> (MOVBstore ptr val mem) // checks (IsNonNil p) -> (SETNE (TESTQ p p)) diff --git a/src/cmd/compile/internal/ssa/gen/generic.rules b/src/cmd/compile/internal/ssa/gen/generic.rules index 74893cef78..75cd186a43 100644 --- a/src/cmd/compile/internal/ssa/gen/generic.rules +++ b/src/cmd/compile/internal/ssa/gen/generic.rules @@ -81,8 +81,7 @@ (StructSelect [idx] (Load ptr mem)) -> (Load (OffPtr [idx] ptr) mem) // big-object moves -// TODO: fix size -(Store dst (Load src mem) mem) && t.Size() > 8 -> (Move [t.Size()] dst src mem) +(Store [size] dst (Load src mem) mem) && size > config.IntSize -> (Move [size] dst src mem) // string ops (ConstString {s}) -> (StringMake (Addr {config.fe.StringData(s.(string))} (SB )) (ConstPtr [int64(len(s.(string)))])) diff --git a/src/cmd/compile/internal/ssa/gen/genericOps.go b/src/cmd/compile/internal/ssa/gen/genericOps.go index ec4f038f43..496b57e2e1 100644 --- a/src/cmd/compile/internal/ssa/gen/genericOps.go +++ b/src/cmd/compile/internal/ssa/gen/genericOps.go @@ -218,7 +218,7 @@ var genericOps = []opData{ // Memory operations {name: "Load"}, // Load from arg0. arg1=memory - {name: "Store"}, // Store arg1 to arg0. arg2=memory. Returns memory. + {name: "Store"}, // Store arg1 to arg0. arg2=memory, auxint=size. Returns memory. {name: "Move"}, // arg0=destptr, arg1=srcptr, arg2=mem, auxint=size. Returns memory. {name: "Zero"}, // arg0=destptr, arg1=mem, auxint=size. Returns memory. diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go index f3369d6d5f..502efc5640 100644 --- a/src/cmd/compile/internal/ssa/rewriteAMD64.go +++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go @@ -7412,16 +7412,16 @@ func rewriteValueAMD64(v *Value, config *Config) bool { end32c5cbec813d1c2ae94fc9b1090e4b2a: ; case OpStore: - // match: (Store ptr val mem) - // cond: (is64BitInt(val.Type) || isPtr(val.Type)) + // match: (Store [8] ptr val mem) + // cond: // result: (MOVQstore ptr val mem) { + if v.AuxInt != 8 { + goto endd1eb7c3ea0c806e7a53ff3be86186eb7 + } ptr := v.Args[0] val := v.Args[1] mem := v.Args[2] - if !(is64BitInt(val.Type) || isPtr(val.Type)) { - goto endbaeb60123806948cd2433605820d5af1 - } v.Op = OpAMD64MOVQstore v.AuxInt = 0 v.Aux = nil @@ -7431,19 +7431,19 @@ func rewriteValueAMD64(v *Value, config *Config) bool { v.AddArg(mem) return true } - goto endbaeb60123806948cd2433605820d5af1 - endbaeb60123806948cd2433605820d5af1: + goto endd1eb7c3ea0c806e7a53ff3be86186eb7 + endd1eb7c3ea0c806e7a53ff3be86186eb7: ; - // match: (Store ptr val mem) - // cond: is32BitInt(val.Type) + // match: (Store [4] ptr val mem) + // cond: // result: (MOVLstore ptr val mem) { + if v.AuxInt != 4 { + goto end44e3b22360da76ecd59be9a8c2dd1347 + } ptr := v.Args[0] val := v.Args[1] mem := v.Args[2] - if !(is32BitInt(val.Type)) { - goto end582e895008657c728c141c6b95070de7 - } v.Op = OpAMD64MOVLstore v.AuxInt = 0 v.Aux = nil @@ -7453,19 +7453,19 @@ func rewriteValueAMD64(v *Value, config *Config) bool { v.AddArg(mem) return true } - goto end582e895008657c728c141c6b95070de7 - end582e895008657c728c141c6b95070de7: + goto end44e3b22360da76ecd59be9a8c2dd1347 + end44e3b22360da76ecd59be9a8c2dd1347: ; - // match: (Store ptr val mem) - // cond: is16BitInt(val.Type) + // match: (Store [2] ptr val mem) + // cond: // result: (MOVWstore ptr val mem) { + if v.AuxInt != 2 { + goto endd0342b7fd3d0713f3e26922660047c71 + } ptr := v.Args[0] val := v.Args[1] mem := v.Args[2] - if !(is16BitInt(val.Type)) { - goto enda3f6a985b6ebb277665f80ad30b178df - } v.Op = OpAMD64MOVWstore v.AuxInt = 0 v.Aux = nil @@ -7475,41 +7475,19 @@ func rewriteValueAMD64(v *Value, config *Config) bool { v.AddArg(mem) return true } - goto enda3f6a985b6ebb277665f80ad30b178df - enda3f6a985b6ebb277665f80ad30b178df: + goto endd0342b7fd3d0713f3e26922660047c71 + endd0342b7fd3d0713f3e26922660047c71: ; - // match: (Store ptr val mem) - // cond: is8BitInt(val.Type) + // match: (Store [1] ptr val mem) + // cond: // result: (MOVBstore ptr val mem) { - ptr := v.Args[0] - val := v.Args[1] - mem := v.Args[2] - if !(is8BitInt(val.Type)) { - goto ende2dee0bc82f631e3c6b0031bf8d224c1 + if v.AuxInt != 1 { + goto end8e76e20031197ca875889d2b4d0eb1d1 } - v.Op = OpAMD64MOVBstore - v.AuxInt = 0 - v.Aux = nil - v.resetArgs() - v.AddArg(ptr) - v.AddArg(val) - v.AddArg(mem) - return true - } - goto ende2dee0bc82f631e3c6b0031bf8d224c1 - ende2dee0bc82f631e3c6b0031bf8d224c1: - ; - // match: (Store ptr val mem) - // cond: val.Type.IsBoolean() - // result: (MOVBstore ptr val mem) - { ptr := v.Args[0] val := v.Args[1] mem := v.Args[2] - if !(val.Type.IsBoolean()) { - goto end6f343b676bf49740054e459f972b24f5 - } v.Op = OpAMD64MOVBstore v.AuxInt = 0 v.Aux = nil @@ -7519,8 +7497,8 @@ func rewriteValueAMD64(v *Value, config *Config) bool { v.AddArg(mem) return true } - goto end6f343b676bf49740054e459f972b24f5 - end6f343b676bf49740054e459f972b24f5: + goto end8e76e20031197ca875889d2b4d0eb1d1 + end8e76e20031197ca875889d2b4d0eb1d1: ; case OpSub16: // match: (Sub16 x y) diff --git a/src/cmd/compile/internal/ssa/rewritegeneric.go b/src/cmd/compile/internal/ssa/rewritegeneric.go index 8ce0eca9e4..a0c5269e2e 100644 --- a/src/cmd/compile/internal/ssa/rewritegeneric.go +++ b/src/cmd/compile/internal/ssa/rewritegeneric.go @@ -876,35 +876,35 @@ func rewriteValuegeneric(v *Value, config *Config) bool { end459613b83f95b65729d45c2ed663a153: ; case OpStore: - // match: (Store dst (Load src mem) mem) - // cond: t.Size() > 8 - // result: (Move [t.Size()] dst src mem) + // match: (Store [size] dst (Load src mem) mem) + // cond: size > config.IntSize + // result: (Move [size] dst src mem) { + size := v.AuxInt dst := v.Args[0] if v.Args[1].Op != OpLoad { - goto end324ffb6d2771808da4267f62c854e9c8 + goto enda18a7163888e2f4fca9f38bae56cef42 } - t := v.Args[1].Type src := v.Args[1].Args[0] mem := v.Args[1].Args[1] if v.Args[2] != mem { - goto end324ffb6d2771808da4267f62c854e9c8 + goto enda18a7163888e2f4fca9f38bae56cef42 } - if !(t.Size() > 8) { - goto end324ffb6d2771808da4267f62c854e9c8 + if !(size > config.IntSize) { + goto enda18a7163888e2f4fca9f38bae56cef42 } v.Op = OpMove v.AuxInt = 0 v.Aux = nil v.resetArgs() - v.AuxInt = t.Size() + v.AuxInt = size v.AddArg(dst) v.AddArg(src) v.AddArg(mem) return true } - goto end324ffb6d2771808da4267f62c854e9c8 - end324ffb6d2771808da4267f62c854e9c8: + goto enda18a7163888e2f4fca9f38bae56cef42 + enda18a7163888e2f4fca9f38bae56cef42: ; // match: (Store dst str mem) // cond: str.Type.IsString() diff --git a/src/cmd/compile/internal/ssa/schedule_test.go b/src/cmd/compile/internal/ssa/schedule_test.go index 45f3dbcac5..7f62ab9e3b 100644 --- a/src/cmd/compile/internal/ssa/schedule_test.go +++ b/src/cmd/compile/internal/ssa/schedule_test.go @@ -14,9 +14,9 @@ func TestSchedule(t *testing.T) { Valu("mem0", OpArg, TypeMem, 0, ".mem"), Valu("ptr", OpConst64, TypeInt64, 0xABCD, nil), Valu("v", OpConst64, TypeInt64, 12, nil), - Valu("mem1", OpStore, TypeMem, 0, nil, "ptr", "v", "mem0"), - Valu("mem2", OpStore, TypeMem, 0, nil, "ptr", "v", "mem1"), - Valu("mem3", OpStore, TypeInt64, 0, nil, "ptr", "sum", "mem2"), + Valu("mem1", OpStore, TypeMem, 8, nil, "ptr", "v", "mem0"), + Valu("mem2", OpStore, TypeMem, 8, nil, "ptr", "v", "mem1"), + Valu("mem3", OpStore, TypeInt64, 8, nil, "ptr", "sum", "mem2"), Valu("l1", OpLoad, TypeInt64, 0, nil, "ptr", "mem1"), Valu("l2", OpLoad, TypeInt64, 0, nil, "ptr", "mem2"), Valu("sum", OpAdd64, TypeInt64, 0, nil, "l1", "l2"), diff --git a/src/cmd/compile/internal/ssa/shift_test.go b/src/cmd/compile/internal/ssa/shift_test.go index fc26ab82ca..611b418b6d 100644 --- a/src/cmd/compile/internal/ssa/shift_test.go +++ b/src/cmd/compile/internal/ssa/shift_test.go @@ -35,7 +35,7 @@ func makeConstShiftFunc(c *Config, amount int64, op Op, typ Type) fun { Valu("load", OpLoad, typ, 0, nil, "argptr", "mem"), Valu("c", OpConst64, TypeUInt64, amount, nil), Valu("shift", op, typ, 0, nil, "load", "c"), - Valu("store", OpStore, TypeMem, 0, nil, "resptr", "shift", "mem"), + Valu("store", OpStore, TypeMem, 8, nil, "resptr", "shift", "mem"), Exit("store"))) Compile(fun.f) return fun -- cgit v1.3 From 997a9f32b01eb73ee3086e8c9141c1ed30c7ac8d Mon Sep 17 00:00:00 2001 From: David Chase Date: Wed, 12 Aug 2015 16:38:11 -0400 Subject: [dev.ssa] cmd/compile: first unoptimized cut at adding FP support Added F32 and F64 load, store, and addition. Added F32 and F64 multiply. Added F32 and F64 subtraction and division. Added X15 to "clobber" for FP sub/div Added FP constants Added separate FP test in gc/testdata Change-Id: Ifa60dbad948a40011b478d9605862c4b0cc9134c Reviewed-on: https://go-review.googlesource.com/13612 Reviewed-by: Keith Randall --- src/cmd/compile/internal/gc/ssa.go | 242 ++++++--- src/cmd/compile/internal/gc/ssa_test.go | 3 + src/cmd/compile/internal/gc/testdata/fp_ssa.go | 164 ++++++ src/cmd/compile/internal/ssa/func.go | 10 + src/cmd/compile/internal/ssa/gen/AMD64.rules | 46 +- src/cmd/compile/internal/ssa/gen/AMD64Ops.go | 39 ++ src/cmd/compile/internal/ssa/gen/genericOps.go | 16 +- src/cmd/compile/internal/ssa/opGen.go | 294 +++++++++++ src/cmd/compile/internal/ssa/rewrite.go | 8 + src/cmd/compile/internal/ssa/rewriteAMD64.go | 700 +++++++++++++++++++++++++ 10 files changed, 1444 insertions(+), 78 deletions(-) create mode 100644 src/cmd/compile/internal/gc/testdata/fp_ssa.go (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index d37181daf5..4e115a0fcd 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -379,6 +379,12 @@ func (s *state) constInt32(t ssa.Type, c int32) *ssa.Value { func (s *state) constInt64(t ssa.Type, c int64) *ssa.Value { return s.f.ConstInt64(s.peekLine(), t, c) } +func (s *state) constFloat32(t ssa.Type, c float64) *ssa.Value { + return s.f.ConstFloat32(s.peekLine(), t, c) +} +func (s *state) constFloat64(t ssa.Type, c float64) *ssa.Value { + return s.f.ConstFloat64(s.peekLine(), t, c) +} func (s *state) constIntPtr(t ssa.Type, c int64) *ssa.Value { if s.config.PtrSize == 4 && int64(int32(c)) != c { s.Fatalf("pointer constant too big %d", c) @@ -715,25 +721,29 @@ type opAndType struct { } var opToSSA = map[opAndType]ssa.Op{ - opAndType{OADD, TINT8}: ssa.OpAdd8, - opAndType{OADD, TUINT8}: ssa.OpAdd8, - opAndType{OADD, TINT16}: ssa.OpAdd16, - opAndType{OADD, TUINT16}: ssa.OpAdd16, - opAndType{OADD, TINT32}: ssa.OpAdd32, - opAndType{OADD, TUINT32}: ssa.OpAdd32, - opAndType{OADD, TPTR32}: ssa.OpAdd32, - opAndType{OADD, TINT64}: ssa.OpAdd64, - opAndType{OADD, TUINT64}: ssa.OpAdd64, - opAndType{OADD, TPTR64}: ssa.OpAdd64, - - opAndType{OSUB, TINT8}: ssa.OpSub8, - opAndType{OSUB, TUINT8}: ssa.OpSub8, - opAndType{OSUB, TINT16}: ssa.OpSub16, - opAndType{OSUB, TUINT16}: ssa.OpSub16, - opAndType{OSUB, TINT32}: ssa.OpSub32, - opAndType{OSUB, TUINT32}: ssa.OpSub32, - opAndType{OSUB, TINT64}: ssa.OpSub64, - opAndType{OSUB, TUINT64}: ssa.OpSub64, + opAndType{OADD, TINT8}: ssa.OpAdd8, + opAndType{OADD, TUINT8}: ssa.OpAdd8, + opAndType{OADD, TINT16}: ssa.OpAdd16, + opAndType{OADD, TUINT16}: ssa.OpAdd16, + opAndType{OADD, TINT32}: ssa.OpAdd32, + opAndType{OADD, TUINT32}: ssa.OpAdd32, + opAndType{OADD, TPTR32}: ssa.OpAdd32, + opAndType{OADD, TINT64}: ssa.OpAdd64, + opAndType{OADD, TUINT64}: ssa.OpAdd64, + opAndType{OADD, TPTR64}: ssa.OpAdd64, + opAndType{OADD, TFLOAT32}: ssa.OpAdd32F, + opAndType{OADD, TFLOAT64}: ssa.OpAdd64F, + + opAndType{OSUB, TINT8}: ssa.OpSub8, + opAndType{OSUB, TUINT8}: ssa.OpSub8, + opAndType{OSUB, TINT16}: ssa.OpSub16, + opAndType{OSUB, TUINT16}: ssa.OpSub16, + opAndType{OSUB, TINT32}: ssa.OpSub32, + opAndType{OSUB, TUINT32}: ssa.OpSub32, + opAndType{OSUB, TINT64}: ssa.OpSub64, + opAndType{OSUB, TUINT64}: ssa.OpSub64, + opAndType{OSUB, TFLOAT32}: ssa.OpSub32F, + opAndType{OSUB, TFLOAT64}: ssa.OpSub64F, opAndType{ONOT, TBOOL}: ssa.OpNot, @@ -755,14 +765,19 @@ var opToSSA = map[opAndType]ssa.Op{ opAndType{OCOM, TINT64}: ssa.OpCom64, opAndType{OCOM, TUINT64}: ssa.OpCom64, - opAndType{OMUL, TINT8}: ssa.OpMul8, - opAndType{OMUL, TUINT8}: ssa.OpMul8, - opAndType{OMUL, TINT16}: ssa.OpMul16, - opAndType{OMUL, TUINT16}: ssa.OpMul16, - opAndType{OMUL, TINT32}: ssa.OpMul32, - opAndType{OMUL, TUINT32}: ssa.OpMul32, - opAndType{OMUL, TINT64}: ssa.OpMul64, - opAndType{OMUL, TUINT64}: ssa.OpMul64, + opAndType{OMUL, TINT8}: ssa.OpMul8, + opAndType{OMUL, TUINT8}: ssa.OpMul8, + opAndType{OMUL, TINT16}: ssa.OpMul16, + opAndType{OMUL, TUINT16}: ssa.OpMul16, + opAndType{OMUL, TINT32}: ssa.OpMul32, + opAndType{OMUL, TUINT32}: ssa.OpMul32, + opAndType{OMUL, TINT64}: ssa.OpMul64, + opAndType{OMUL, TUINT64}: ssa.OpMul64, + opAndType{OMUL, TFLOAT32}: ssa.OpMul32F, + opAndType{OMUL, TFLOAT64}: ssa.OpMul64F, + + opAndType{ODIV, TFLOAT32}: ssa.OpDiv32F, + opAndType{ODIV, TFLOAT64}: ssa.OpDiv64F, opAndType{OAND, TINT8}: ssa.OpAnd8, opAndType{OAND, TUINT8}: ssa.OpAnd8, @@ -1042,6 +1057,18 @@ func (s *state) expr(n *Node) *ssa.Value { return s.entryNewValue0A(ssa.OpConstBool, n.Type, n.Val().U) case CTNIL: return s.entryNewValue0(ssa.OpConstNil, n.Type) + case CTFLT: + f := n.Val().U.(*Mpflt) + switch n.Type.Size() { + case 4: + return s.constFloat32(n.Type, mpgetflt32(f)) + case 8: + return s.constFloat64(n.Type, mpgetflt(f)) + default: + s.Fatalf("bad float size %d", n.Type.Size()) + return nil + } + default: s.Unimplementedf("unhandled OLITERAL %v", n.Val().Ctype()) return nil @@ -1165,7 +1192,7 @@ func (s *state) expr(n *Node) *ssa.Value { a := s.expr(n.Left) b := s.expr(n.Right) return s.newValue2(s.ssaOp(n.Op, n.Left.Type), Types[TBOOL], a, b) - case OADD, OAND, OMUL, OOR, OSUB, OXOR: + case OADD, OAND, OMUL, OOR, OSUB, ODIV, OXOR: a := s.expr(n.Left) b := s.expr(n.Right) return s.newValue2(s.ssaOp(n.Op, n.Type), a.Type, a, b) @@ -1888,6 +1915,19 @@ func genssa(f *ssa.Func, ptxt *obj.Prog, gcargs, gclocals *Sym) { f.Config.HTML.Close() } +// opregreg emits instructions for +// dest := dest op src +// and also returns the created obj.Prog so it +// may be further adjusted (offset, scale, etc). +func opregreg(op int, dest, src int16) *obj.Prog { + p := Prog(op) + p.From.Type = obj.TYPE_REG + p.To.Type = obj.TYPE_REG + p.To.Reg = dest + p.From.Reg = src + return p +} + func genValue(v *ssa.Value) { lineno = v.Line switch v.Op { @@ -1917,20 +1957,17 @@ func genValue(v *ssa.Value) { p.To.Type = obj.TYPE_REG p.To.Reg = regnum(v) // 2-address opcode arithmetic, symmetric - case ssa.OpAMD64ADDB, + case ssa.OpAMD64ADDB, ssa.OpAMD64ADDSS, ssa.OpAMD64ADDSD, ssa.OpAMD64ANDQ, ssa.OpAMD64ANDL, ssa.OpAMD64ANDW, ssa.OpAMD64ANDB, ssa.OpAMD64ORQ, ssa.OpAMD64ORL, ssa.OpAMD64ORW, ssa.OpAMD64ORB, ssa.OpAMD64XORQ, ssa.OpAMD64XORL, ssa.OpAMD64XORW, ssa.OpAMD64XORB, - ssa.OpAMD64MULQ, ssa.OpAMD64MULL, ssa.OpAMD64MULW, ssa.OpAMD64MULB: + ssa.OpAMD64MULQ, ssa.OpAMD64MULL, ssa.OpAMD64MULW, ssa.OpAMD64MULB, + ssa.OpAMD64MULSS, ssa.OpAMD64MULSD: r := regnum(v) x := regnum(v.Args[0]) y := regnum(v.Args[1]) if x != r && y != r { - p := Prog(regMoveAMD64(v.Type.Size())) - p.From.Type = obj.TYPE_REG - p.From.Reg = x - p.To.Type = obj.TYPE_REG - p.To.Reg = r + opregreg(regMoveByTypeAMD64(v.Type), r, x) x = r } p := Prog(v.Op.Asm()) @@ -1954,23 +1991,34 @@ func genValue(v *ssa.Value) { neg = true } if x != r { - p := Prog(regMoveAMD64(v.Type.Size())) - p.From.Type = obj.TYPE_REG - p.From.Reg = x - p.To.Type = obj.TYPE_REG - p.To.Reg = r + opregreg(regMoveByTypeAMD64(v.Type), r, x) } + opregreg(v.Op.Asm(), r, y) - p := Prog(v.Op.Asm()) - p.From.Type = obj.TYPE_REG - p.To.Type = obj.TYPE_REG - p.To.Reg = r - p.From.Reg = y if neg { p := Prog(x86.ANEGQ) // TODO: use correct size? This is mostly a hack until regalloc does 2-address correctly p.To.Type = obj.TYPE_REG p.To.Reg = r } + case ssa.OpAMD64SUBSS, ssa.OpAMD64SUBSD, ssa.OpAMD64DIVSS, ssa.OpAMD64DIVSD: + r := regnum(v) + x := regnum(v.Args[0]) + y := regnum(v.Args[1]) + if y == r && x != r { + // r/y := x op r/y, need to preserve x and rewrite to + // r/y := r/y op x15 + x15 := int16(x86.REG_X15) + // register move y to x15 + // register move x to y + // rename y with x15 + opregreg(regMoveByTypeAMD64(v.Type), x15, y) + opregreg(regMoveByTypeAMD64(v.Type), r, x) + y = x15 + } else if x != r { + opregreg(regMoveByTypeAMD64(v.Type), r, x) + } + opregreg(v.Op.Asm(), r, y) + case ssa.OpAMD64SHLQ, ssa.OpAMD64SHLL, ssa.OpAMD64SHLW, ssa.OpAMD64SHLB, ssa.OpAMD64SHRQ, ssa.OpAMD64SHRL, ssa.OpAMD64SHRW, ssa.OpAMD64SHRB, ssa.OpAMD64SARQ, ssa.OpAMD64SARL, ssa.OpAMD64SARW, ssa.OpAMD64SARB: @@ -2117,15 +2165,22 @@ func genValue(v *ssa.Value) { p.From.Offset = i p.To.Type = obj.TYPE_REG p.To.Reg = x - case ssa.OpAMD64MOVQload, ssa.OpAMD64MOVLload, ssa.OpAMD64MOVWload, ssa.OpAMD64MOVBload, ssa.OpAMD64MOVBQSXload, ssa.OpAMD64MOVBQZXload: + case ssa.OpAMD64MOVSSconst, ssa.OpAMD64MOVSDconst: + x := regnum(v) + p := Prog(v.Op.Asm()) + p.From.Type = obj.TYPE_FCONST + p.From.Val = v.Aux.(float64) + p.To.Type = obj.TYPE_REG + p.To.Reg = x + case ssa.OpAMD64MOVQload, ssa.OpAMD64MOVSSload, ssa.OpAMD64MOVSDload, ssa.OpAMD64MOVLload, ssa.OpAMD64MOVWload, ssa.OpAMD64MOVBload, ssa.OpAMD64MOVBQSXload, ssa.OpAMD64MOVBQZXload: p := Prog(v.Op.Asm()) p.From.Type = obj.TYPE_MEM p.From.Reg = regnum(v.Args[0]) addAux(&p.From, v) p.To.Type = obj.TYPE_REG p.To.Reg = regnum(v) - case ssa.OpAMD64MOVQloadidx8: - p := Prog(x86.AMOVQ) + case ssa.OpAMD64MOVQloadidx8, ssa.OpAMD64MOVSDloadidx8: + p := Prog(v.Op.Asm()) p.From.Type = obj.TYPE_MEM p.From.Reg = regnum(v.Args[0]) addAux(&p.From, v) @@ -2133,15 +2188,24 @@ func genValue(v *ssa.Value) { p.From.Index = regnum(v.Args[1]) p.To.Type = obj.TYPE_REG p.To.Reg = regnum(v) - case ssa.OpAMD64MOVQstore, ssa.OpAMD64MOVLstore, ssa.OpAMD64MOVWstore, ssa.OpAMD64MOVBstore: + case ssa.OpAMD64MOVSSloadidx4: + p := Prog(v.Op.Asm()) + p.From.Type = obj.TYPE_MEM + p.From.Reg = regnum(v.Args[0]) + addAux(&p.From, v) + p.From.Scale = 4 + p.From.Index = regnum(v.Args[1]) + p.To.Type = obj.TYPE_REG + p.To.Reg = regnum(v) + case ssa.OpAMD64MOVQstore, ssa.OpAMD64MOVSSstore, ssa.OpAMD64MOVSDstore, ssa.OpAMD64MOVLstore, ssa.OpAMD64MOVWstore, ssa.OpAMD64MOVBstore: p := Prog(v.Op.Asm()) p.From.Type = obj.TYPE_REG p.From.Reg = regnum(v.Args[1]) p.To.Type = obj.TYPE_MEM p.To.Reg = regnum(v.Args[0]) addAux(&p.To, v) - case ssa.OpAMD64MOVQstoreidx8: - p := Prog(x86.AMOVQ) + case ssa.OpAMD64MOVQstoreidx8, ssa.OpAMD64MOVSDstoreidx8: + p := Prog(v.Op.Asm()) p.From.Type = obj.TYPE_REG p.From.Reg = regnum(v.Args[2]) p.To.Type = obj.TYPE_MEM @@ -2149,6 +2213,15 @@ func genValue(v *ssa.Value) { p.To.Scale = 8 p.To.Index = regnum(v.Args[1]) addAux(&p.To, v) + case ssa.OpAMD64MOVSSstoreidx4: + p := Prog(v.Op.Asm()) + p.From.Type = obj.TYPE_REG + p.From.Reg = regnum(v.Args[2]) + p.To.Type = obj.TYPE_MEM + p.To.Reg = regnum(v.Args[0]) + p.To.Scale = 4 + p.To.Index = regnum(v.Args[1]) + addAux(&p.To, v) case ssa.OpAMD64MOVLQSX, ssa.OpAMD64MOVWQSX, ssa.OpAMD64MOVBQSX, ssa.OpAMD64MOVLQZX, ssa.OpAMD64MOVWQZX, ssa.OpAMD64MOVBQZX: p := Prog(v.Op.Asm()) p.From.Type = obj.TYPE_REG @@ -2178,29 +2251,26 @@ func genValue(v *ssa.Value) { x := regnum(v.Args[0]) y := regnum(v) if x != y { - p := Prog(x86.AMOVQ) - p.From.Type = obj.TYPE_REG - p.From.Reg = x - p.To.Type = obj.TYPE_REG - p.To.Reg = y + opregreg(regMoveByTypeAMD64(v.Type), y, x) } case ssa.OpLoadReg: if v.Type.IsFlags() { v.Unimplementedf("load flags not implemented: %v", v.LongString()) return } - p := Prog(movSize(v.Type.Size())) + p := Prog(movSizeByType(v.Type)) p.From.Type = obj.TYPE_MEM p.From.Reg = x86.REG_SP p.From.Offset = localOffset(v.Args[0]) p.To.Type = obj.TYPE_REG p.To.Reg = regnum(v) + case ssa.OpStoreReg: if v.Type.IsFlags() { v.Unimplementedf("store flags not implemented: %v", v.LongString()) return } - p := Prog(movSize(v.Type.Size())) + p := Prog(movSizeByType(v.Type)) p.From.Type = obj.TYPE_REG p.From.Reg = regnum(v.Args[0]) p.To.Type = obj.TYPE_MEM @@ -2215,10 +2285,12 @@ func genValue(v *ssa.Value) { v.Fatalf("phi arg at different location than phi: %v @ %v, but arg %v @ %v\n%s\n", v, loc, a, aloc, v.Block.Func) } } - case ssa.OpConst8, ssa.OpConst16, ssa.OpConst32, ssa.OpConst64, ssa.OpConstString, ssa.OpConstNil, ssa.OpConstBool: + case ssa.OpConst8, ssa.OpConst16, ssa.OpConst32, ssa.OpConst64, ssa.OpConstString, ssa.OpConstNil, ssa.OpConstBool, + ssa.OpConst32F, ssa.OpConst64F: if v.Block.Func.RegAlloc[v.ID] != nil { v.Fatalf("const value %v shouldn't have a location", v) } + case ssa.OpArg: // memory arg needs no code // TODO: check that only mem arg goes here. @@ -2316,21 +2388,12 @@ func genValue(v *ssa.Value) { } } -// movSize returns the MOV instruction of the given width. -func movSize(width int64) (asm int) { - switch width { - case 1: - asm = x86.AMOVB - case 2: - asm = x86.AMOVW - case 4: - asm = x86.AMOVL - case 8: - asm = x86.AMOVQ - default: - panic(fmt.Errorf("bad movSize %d", width)) - } - return asm +// movSizeByType returns the MOV instruction of the given type. +func movSizeByType(t ssa.Type) (asm int) { + // For x86, there's no difference between reg move opcodes + // and memory move opcodes. + asm = regMoveByTypeAMD64(t) + return } // movZero generates a register indirect move with a 0 immediate and keeps track of bytes left and next offset @@ -2553,10 +2616,39 @@ func regMoveAMD64(width int64) int { case 8: return x86.AMOVQ default: - panic("bad register width") + panic("bad int register width") } } +func regMoveByTypeAMD64(t ssa.Type) int { + width := t.Size() + if t.IsFloat() { + switch width { + case 4: + return x86.AMOVSS + case 8: + return x86.AMOVSD + default: + panic("bad float register width") + } + } else { + switch width { + case 1: + return x86.AMOVB + case 2: + return x86.AMOVW + case 4: + return x86.AMOVL + case 8: + return x86.AMOVQ + default: + panic("bad int register width") + } + } + + panic("bad register type") +} + // regnum returns the register (in cmd/internal/obj numbering) to // which v has been allocated. Panics if v is not assigned to a // register. diff --git a/src/cmd/compile/internal/gc/ssa_test.go b/src/cmd/compile/internal/gc/ssa_test.go index f51d6de871..f0060cb12d 100644 --- a/src/cmd/compile/internal/gc/ssa_test.go +++ b/src/cmd/compile/internal/gc/ssa_test.go @@ -45,3 +45,6 @@ func TestBreakContinue(t *testing.T) { runTest(t, "break_ssa.go") } // TestArithmetic tests that both backends have the same result for arithmetic expressions. func TestArithmetic(t *testing.T) { runTest(t, "arith_ssa.go") } + +// TestFP tests that both backends have the same result for floating point expressions. +func TestFP(t *testing.T) { runTest(t, "fp_ssa.go") } diff --git a/src/cmd/compile/internal/gc/testdata/fp_ssa.go b/src/cmd/compile/internal/gc/testdata/fp_ssa.go new file mode 100644 index 0000000000..73366cdfa8 --- /dev/null +++ b/src/cmd/compile/internal/gc/testdata/fp_ssa.go @@ -0,0 +1,164 @@ +// run + +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Tests floating point arithmetic expressions + +package main + +import "fmt" + +func fail64(s string, f func(a, b float64) float64, a, b, e float64) int { + d := f(a, b) + if d != e { + fmt.Printf("For (float64) %v %v %v, expected %v, got %v\n", a, s, b, e, d) + return 1 + } + return 0 +} + +func fail32(s string, f func(a, b float32) float32, a, b, e float32) int { + d := f(a, b) + if d != e { + fmt.Printf("For (float32) %v %v %v, expected %v, got %v\n", a, s, b, e, d) + return 1 + } + return 0 +} + +func expect64(s string, x, expected float64) int { + if x != expected { + println("Expected", expected, "for", s, ", got", x) + } + return 0 +} + +// manysub_ssa is designed to tickle bugs that depend on register +// pressure or unfriendly operand ordering in registers (and at +// least once it succeeded in this). +func manysub_ssa(a, b, c, d float64) (aa, ab, ac, ad, ba, bb, bc, bd, ca, cb, cc, cd, da, db, dc, dd float64) { + switch { + } + aa = a + 11.0 - a + ab = a - b + ac = a - c + ad = a - d + ba = b - a + bb = b + 22.0 - b + bc = b - c + bd = b - d + ca = c - a + cb = c - b + cc = c + 33.0 - c + cd = c - d + da = d - a + db = d - b + dc = d - c + dd = d + 44.0 - d + return +} + +func add64_ssa(a, b float64) float64 { + switch { + } + return a + b +} + +func mul64_ssa(a, b float64) float64 { + switch { + } + return a * b +} + +func sub64_ssa(a, b float64) float64 { + switch { + } + return a - b +} + +func div64_ssa(a, b float64) float64 { + switch { + } + return a / b +} + +func add32_ssa(a, b float32) float32 { + switch { + } + return a + b +} + +func mul32_ssa(a, b float32) float32 { + switch { + } + return a * b +} + +func sub32_ssa(a, b float32) float32 { + switch { + } + return a - b +} +func div32_ssa(a, b float32) float32 { + switch { + } + return a / b +} + +func main() { + + a := 3.0 + b := 4.0 + + c := float32(3.0) + d := float32(4.0) + + tiny := float32(1.5E-45) // smallest f32 denorm = 2**(-149) + dtiny := float64(tiny) // well within range of f64 + + fails := 0 + fails += fail64("+", add64_ssa, a, b, 7.0) + fails += fail64("*", mul64_ssa, a, b, 12.0) + fails += fail64("-", sub64_ssa, a, b, -1.0) + fails += fail64("/", div64_ssa, a, b, 0.75) + + fails += fail32("+", add32_ssa, c, d, 7.0) + fails += fail32("*", mul32_ssa, c, d, 12.0) + fails += fail32("-", sub32_ssa, c, d, -1.0) + fails += fail32("/", div32_ssa, c, d, 0.75) + + // denorm-squared should underflow to zero. + fails += fail32("*", mul32_ssa, tiny, tiny, 0) + + // but should not underflow in float and in fact is exactly representable. + fails += fail64("*", mul64_ssa, dtiny, dtiny, 1.9636373861190906e-90) + + aa, ab, ac, ad, ba, bb, bc, bd, ca, cb, cc, cd, da, db, dc, dd := manysub_ssa(1000.0, 100.0, 10.0, 1.0) + + fails += expect64("aa", aa, 11.0) + fails += expect64("ab", ab, 900.0) + fails += expect64("ac", ac, 990.0) + fails += expect64("ad", ad, 999.0) + + fails += expect64("ba", ba, -900.0) + fails += expect64("bb", bb, 22.0) + fails += expect64("bc", bc, 90.0) + fails += expect64("bd", bd, 99.0) + + fails += expect64("ca", ca, -990.0) + fails += expect64("cb", cb, -90.0) + fails += expect64("cc", cc, 33.0) + fails += expect64("cd", cd, 9.0) + + fails += expect64("da", da, -999.0) + fails += expect64("db", db, -99.0) + fails += expect64("dc", dc, -9.0) + fails += expect64("dd", dd, 44.0) + + if fails > 0 { + fmt.Printf("Saw %v failures\n", fails) + panic("Failed.") + } +} diff --git a/src/cmd/compile/internal/ssa/func.go b/src/cmd/compile/internal/ssa/func.go index 97eb1a443a..09bfff2bfc 100644 --- a/src/cmd/compile/internal/ssa/func.go +++ b/src/cmd/compile/internal/ssa/func.go @@ -285,6 +285,16 @@ func (f *Func) ConstIntPtr(line int32, t Type, c int64) *Value { // TODO: cache? return f.Entry.NewValue0I(line, OpConstPtr, t, c) } +func (f *Func) ConstFloat32(line int32, t Type, c float64) *Value { + // TODO: cache? + // For now stuff FP values into aux interface + return f.Entry.NewValue0A(line, OpConst32F, t, c) +} +func (f *Func) ConstFloat64(line int32, t Type, c float64) *Value { + // TODO: cache? + // For now stuff FP values into aux interface + return f.Entry.NewValue0A(line, OpConst64F, t, c) +} func (f *Func) Logf(msg string, args ...interface{}) { f.Config.Logf(msg, args...) } func (f *Func) Fatalf(msg string, args ...interface{}) { f.Config.Fatalf(msg, args...) } diff --git a/src/cmd/compile/internal/ssa/gen/AMD64.rules b/src/cmd/compile/internal/ssa/gen/AMD64.rules index 0e36737337..9ea9781d93 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64.rules +++ b/src/cmd/compile/internal/ssa/gen/AMD64.rules @@ -15,17 +15,26 @@ (Add32 x y) -> (ADDL x y) (Add16 x y) -> (ADDW x y) (Add8 x y) -> (ADDB x y) +(Add32F x y) -> (ADDSS x y) +(Add64F x y) -> (ADDSD x y) (Sub64 x y) -> (SUBQ x y) (Sub32 x y) -> (SUBL x y) (Sub16 x y) -> (SUBW x y) (Sub8 x y) -> (SUBB x y) +(Sub32F x y) -> (SUBSS x y) +(Sub64F x y) -> (SUBSD x y) (Mul64 x y) -> (MULQ x y) (MulPtr x y) -> (MULQ x y) (Mul32 x y) -> (MULL x y) (Mul16 x y) -> (MULW x y) (Mul8 x y) -> (MULB x y) +(Mul32F x y) -> (MULSS x y) +(Mul64F x y) -> (MULSD x y) + +(Div32F x y) -> (DIVSS x y) +(Div64F x y) -> (DIVSD x y) (And64 x y) -> (ANDQ x y) (And32 x y) -> (ANDL x y) @@ -203,6 +212,13 @@ (Load ptr mem) && is32BitInt(t) -> (MOVLload ptr mem) (Load ptr mem) && is16BitInt(t) -> (MOVWload ptr mem) (Load ptr mem) && (t.IsBoolean() || is8BitInt(t)) -> (MOVBload ptr mem) +(Load ptr mem) && is32BitFloat(t) -> (MOVSSload ptr mem) +(Load ptr mem) && is64BitFloat(t) -> (MOVSDload ptr mem) + +// These more-specific FP versions of Store pattern should come first. +(Store [8] ptr val mem) && is64BitFloat(val.Type) -> (MOVSDstore ptr val mem) +(Store [4] ptr val mem) && is32BitFloat(val.Type) -> (MOVSSstore ptr val mem) + (Store [8] ptr val mem) -> (MOVQstore ptr val mem) (Store [4] ptr val mem) -> (MOVLstore ptr val mem) (Store [2] ptr val mem) -> (MOVWstore ptr val mem) @@ -225,6 +241,8 @@ (Const16 [val]) -> (MOVWconst [val]) (Const32 [val]) -> (MOVLconst [val]) (Const64 [val]) -> (MOVQconst [val]) +(Const32F {val}) -> (MOVSSconst {val}) +(Const64F {val}) -> (MOVSDconst {val}) (ConstPtr [val]) -> (MOVQconst [val]) (ConstNil) -> (MOVQconst [0]) (ConstBool {b}) && !b.(bool) -> (MOVBconst [0]) @@ -404,13 +422,39 @@ (MOVQstore [off1] {sym1} (LEAQ [off2] {sym2} base) val mem) && (sym1 == nil || sym2 == nil) -> (MOVQstore [addOff(off1,off2)] {mergeSym(sym1,sym2)} base val mem) +(MOVSSload [off1] (ADDQconst [off2] ptr) mem) -> (MOVSSload [addOff(off1, off2)] ptr mem) +(MOVSSstore [off1] (ADDQconst [off2] ptr) val mem) -> (MOVSSstore [addOff(off1, off2)] ptr val mem) + +(MOVSSload [off1] {sym1} (LEAQ [off2] {sym2} base) mem) && (sym1 == nil || sym2 == nil) -> + (MOVSSload [addOff(off1,off2)] {mergeSym(sym1,sym2)} base mem) +(MOVSSstore [off1] {sym1} (LEAQ [off2] {sym2} base) val mem) && (sym1 == nil || sym2 == nil) -> + (MOVSSstore [addOff(off1,off2)] {mergeSym(sym1,sym2)} base val mem) + +(MOVSDload [off1] (ADDQconst [off2] ptr) mem) -> (MOVSDload [addOff(off1, off2)] ptr mem) +(MOVSDstore [off1] (ADDQconst [off2] ptr) val mem) -> (MOVSDstore [addOff(off1, off2)] ptr val mem) + +(MOVSDload [off1] {sym1} (LEAQ [off2] {sym2} base) mem) && (sym1 == nil || sym2 == nil) -> + (MOVSDload [addOff(off1,off2)] {mergeSym(sym1,sym2)} base mem) +(MOVSDstore [off1] {sym1} (LEAQ [off2] {sym2} base) val mem) && (sym1 == nil || sym2 == nil) -> + (MOVSDstore [addOff(off1,off2)] {mergeSym(sym1,sym2)} base val mem) + // indexed loads and stores (MOVQload [off1] (LEAQ8 [off2] ptr idx) mem) -> (MOVQloadidx8 [addOff(off1, off2)] ptr idx mem) (MOVQstore [off1] (LEAQ8 [off2] ptr idx) val mem) -> (MOVQstoreidx8 [addOff(off1, off2)] ptr idx val mem) - (MOVQloadidx8 [off1] (ADDQconst [off2] ptr) idx mem) -> (MOVQloadidx8 [addOff(off1, off2)] ptr idx mem) (MOVQstoreidx8 [off1] (ADDQconst [off2] ptr) idx val mem) -> (MOVQstoreidx8 [addOff(off1, off2)] ptr idx val mem) +(MOVSSload [off1] (LEAQ4 [off2] ptr idx) mem) -> (MOVSSloadidx4 [addOff(off1, off2)] ptr idx mem) +(MOVSSstore [off1] (LEAQ4 [off2] ptr idx) val mem) -> (MOVSSstoreidx4 [addOff(off1, off2)] ptr idx val mem) +(MOVSSloadidx4 [off1] (ADDQconst [off2] ptr) idx mem) -> (MOVSSloadidx4 [addOff(off1, off2)] ptr idx mem) +(MOVSSstoreidx4 [off1] (ADDQconst [off2] ptr) idx val mem) -> (MOVSSstoreidx4 [addOff(off1, off2)] ptr idx val mem) + +(MOVSDload [off1] (LEAQ8 [off2] ptr idx) mem) -> (MOVSDloadidx8 [addOff(off1, off2)] ptr idx mem) +(MOVSDstore [off1] (LEAQ8 [off2] ptr idx) val mem) -> (MOVSDstoreidx8 [addOff(off1, off2)] ptr idx val mem) +(MOVSDloadidx8 [off1] (ADDQconst [off2] ptr) idx mem) -> (MOVSDloadidx8 [addOff(off1, off2)] ptr idx mem) +(MOVSDstoreidx8 [off1] (ADDQconst [off2] ptr) idx val mem) -> (MOVSDstoreidx8 [addOff(off1, off2)] ptr idx val mem) + + (ADDQconst [0] x) -> x // lower Zero instructions with word sizes diff --git a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go index 0a7268a2f6..8bdcfaaac7 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go @@ -73,7 +73,9 @@ func init() { // Common individual register masks var ( cx = buildReg("CX") + x15 = buildReg("X15") gp = buildReg("AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15") + fp = buildReg("X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15") gpsp = gp | buildReg("SP") gpspsb = gpsp | buildReg("SB") flags = buildReg("FLAGS") @@ -82,6 +84,7 @@ func init() { // Common slices of register masks var ( gponly = []regMask{gp} + fponly = []regMask{fp} flagsonly = []regMask{flags} ) @@ -104,6 +107,20 @@ func init() { gpstore = regInfo{inputs: []regMask{gpspsb, gpsp, 0}} gpstoreconst = regInfo{inputs: []regMask{gpspsb, 0}} gpstoreidx = regInfo{inputs: []regMask{gpspsb, gpsp, gpsp, 0}} + + // fp11 = regInfo{inputs: fponly, outputs: fponly} + fp01 = regInfo{inputs: []regMask{}, outputs: fponly} + fp21 = regInfo{inputs: []regMask{fp, fp}, outputs: fponly} + fp21x15 = regInfo{inputs: []regMask{fp &^ x15, fp &^ x15}, + clobbers: x15, outputs: []regMask{fp &^ x15}} + // fp2flags = regInfo{inputs: []regMask{fp, fp}, outputs: flagsonly} + // fp1flags = regInfo{inputs: fponly, outputs: flagsonly} + + fpload = regInfo{inputs: []regMask{gpspsb, 0}, outputs: fponly} + fploadidx = regInfo{inputs: []regMask{gpspsb, gpsp, 0}, outputs: fponly} + + fpstore = regInfo{inputs: []regMask{gpspsb, fp, 0}} + fpstoreidx = regInfo{inputs: []regMask{gpspsb, gpsp, fp, 0}} ) // Suffixes encode the bit width of various instructions. @@ -111,6 +128,28 @@ func init() { // TODO: 2-address instructions. Mark ops as needing matching input/output regs. var AMD64ops = []opData{ + // fp ops + {name: "ADDSS", reg: fp21, asm: "ADDSS"}, // fp32 add + {name: "ADDSD", reg: fp21, asm: "ADDSD"}, // fp64 add + {name: "SUBSS", reg: fp21x15, asm: "SUBSS"}, // fp32 sub + {name: "SUBSD", reg: fp21x15, asm: "SUBSD"}, // fp64 sub + {name: "MULSS", reg: fp21, asm: "MULSS"}, // fp32 mul + {name: "MULSD", reg: fp21, asm: "MULSD"}, // fp64 mul + {name: "DIVSS", reg: fp21x15, asm: "DIVSS"}, // fp32 div + {name: "DIVSD", reg: fp21x15, asm: "DIVSD"}, // fp64 div + + {name: "MOVSSload", reg: fpload, asm: "MOVSS"}, // fp32 load + {name: "MOVSDload", reg: fpload, asm: "MOVSD"}, // fp64 load + {name: "MOVSSconst", reg: fp01, asm: "MOVSS"}, // fp32 constant + {name: "MOVSDconst", reg: fp01, asm: "MOVSD"}, // fp64 constant + {name: "MOVSSloadidx4", reg: fploadidx, asm: "MOVSS"}, // fp32 load + {name: "MOVSDloadidx8", reg: fploadidx, asm: "MOVSD"}, // fp64 load + + {name: "MOVSSstore", reg: fpstore, asm: "MOVSS"}, // fp32 store + {name: "MOVSDstore", reg: fpstore, asm: "MOVSD"}, // fp64 store + {name: "MOVSSstoreidx4", reg: fpstoreidx, asm: "MOVSS"}, // fp32 indexed by 4i store + {name: "MOVSDstoreidx8", reg: fpstoreidx, asm: "MOVSD"}, // fp64 indexed by 8i store + // binary ops {name: "ADDQ", reg: gp21, asm: "ADDQ"}, // arg0 + arg1 {name: "ADDL", reg: gp21, asm: "ADDL"}, // arg0 + arg1 diff --git a/src/cmd/compile/internal/ssa/gen/genericOps.go b/src/cmd/compile/internal/ssa/gen/genericOps.go index 496b57e2e1..1488e0f644 100644 --- a/src/cmd/compile/internal/ssa/gen/genericOps.go +++ b/src/cmd/compile/internal/ssa/gen/genericOps.go @@ -13,19 +13,29 @@ var genericOps = []opData{ {name: "Add32"}, {name: "Add64"}, {name: "AddPtr"}, - // TODO: Add32F, Add64F, Add64C, Add128C + {name: "Add32F"}, + {name: "Add64F"}, + // TODO: Add64C, Add128C {name: "Sub8"}, // arg0 - arg1 {name: "Sub16"}, {name: "Sub32"}, {name: "Sub64"}, - // TODO: Sub32F, Sub64F, Sub64C, Sub128C + {name: "Sub32F"}, + {name: "Sub64F"}, + // TODO: Sub64C, Sub128C {name: "Mul8"}, // arg0 * arg1 {name: "Mul16"}, {name: "Mul32"}, {name: "Mul64"}, {name: "MulPtr"}, // MulPtr is used for address calculations + {name: "Mul32F"}, + {name: "Mul64F"}, + + {name: "Div32F"}, // arg0 / arg1 + {name: "Div64F"}, + // TODO: Div8, Div16, Div32, Div64 and unsigned {name: "And8"}, // arg0 & arg1 {name: "And16"}, @@ -200,6 +210,8 @@ var genericOps = []opData{ {name: "Const16"}, {name: "Const32"}, {name: "Const64"}, + {name: "Const32F"}, + {name: "Const64F"}, {name: "ConstPtr"}, // pointer-sized integer constant // TODO: Const32F, ... diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index 6a5acadde6..2155cd318e 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -51,6 +51,24 @@ func (k BlockKind) String() string { return blockString[k] } const ( OpInvalid Op = iota + OpAMD64ADDSS + OpAMD64ADDSD + OpAMD64SUBSS + OpAMD64SUBSD + OpAMD64MULSS + OpAMD64MULSD + OpAMD64DIVSS + OpAMD64DIVSD + OpAMD64MOVSSload + OpAMD64MOVSDload + OpAMD64MOVSSconst + OpAMD64MOVSDconst + OpAMD64MOVSSloadidx4 + OpAMD64MOVSDloadidx8 + OpAMD64MOVSSstore + OpAMD64MOVSDstore + OpAMD64MOVSSstoreidx4 + OpAMD64MOVSDstoreidx8 OpAMD64ADDQ OpAMD64ADDL OpAMD64ADDW @@ -204,15 +222,23 @@ const ( OpAdd32 OpAdd64 OpAddPtr + OpAdd32F + OpAdd64F OpSub8 OpSub16 OpSub32 OpSub64 + OpSub32F + OpSub64F OpMul8 OpMul16 OpMul32 OpMul64 OpMulPtr + OpMul32F + OpMul64F + OpDiv32F + OpDiv64F OpAnd8 OpAnd16 OpAnd32 @@ -339,6 +365,8 @@ const ( OpConst16 OpConst32 OpConst64 + OpConst32F + OpConst64F OpConstPtr OpArg OpAddr @@ -393,6 +421,232 @@ const ( var opcodeTable = [...]opInfo{ {name: "OpInvalid"}, + { + name: "ADDSS", + asm: x86.AADDSS, + reg: regInfo{ + inputs: []regMask{ + 4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + 4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + }, + outputs: []regMask{ + 4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + }, + }, + }, + { + name: "ADDSD", + asm: x86.AADDSD, + reg: regInfo{ + inputs: []regMask{ + 4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + 4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + }, + outputs: []regMask{ + 4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + }, + }, + }, + { + name: "SUBSS", + asm: x86.ASUBSS, + reg: regInfo{ + inputs: []regMask{ + 2147418112, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 + 2147418112, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 + }, + clobbers: 2147483648, // .X15 + outputs: []regMask{ + 2147418112, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 + }, + }, + }, + { + name: "SUBSD", + asm: x86.ASUBSD, + reg: regInfo{ + inputs: []regMask{ + 2147418112, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 + 2147418112, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 + }, + clobbers: 2147483648, // .X15 + outputs: []regMask{ + 2147418112, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 + }, + }, + }, + { + name: "MULSS", + asm: x86.AMULSS, + reg: regInfo{ + inputs: []regMask{ + 4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + 4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + }, + outputs: []regMask{ + 4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + }, + }, + }, + { + name: "MULSD", + asm: x86.AMULSD, + reg: regInfo{ + inputs: []regMask{ + 4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + 4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + }, + outputs: []regMask{ + 4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + }, + }, + }, + { + name: "DIVSS", + asm: x86.ADIVSS, + reg: regInfo{ + inputs: []regMask{ + 2147418112, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 + 2147418112, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 + }, + clobbers: 2147483648, // .X15 + outputs: []regMask{ + 2147418112, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 + }, + }, + }, + { + name: "DIVSD", + asm: x86.ADIVSD, + reg: regInfo{ + inputs: []regMask{ + 2147418112, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 + 2147418112, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 + }, + clobbers: 2147483648, // .X15 + outputs: []regMask{ + 2147418112, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 + }, + }, + }, + { + name: "MOVSSload", + asm: x86.AMOVSS, + reg: regInfo{ + inputs: []regMask{ + 4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB + 0, + }, + outputs: []regMask{ + 4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + }, + }, + }, + { + name: "MOVSDload", + asm: x86.AMOVSD, + reg: regInfo{ + inputs: []regMask{ + 4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB + 0, + }, + outputs: []regMask{ + 4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + }, + }, + }, + { + name: "MOVSSconst", + asm: x86.AMOVSS, + reg: regInfo{ + outputs: []regMask{ + 4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + }, + }, + }, + { + name: "MOVSDconst", + asm: x86.AMOVSD, + reg: regInfo{ + outputs: []regMask{ + 4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + }, + }, + }, + { + name: "MOVSSloadidx4", + asm: x86.AMOVSS, + reg: regInfo{ + inputs: []regMask{ + 4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB + 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + 0, + }, + outputs: []regMask{ + 4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + }, + }, + }, + { + name: "MOVSDloadidx8", + asm: x86.AMOVSD, + reg: regInfo{ + inputs: []regMask{ + 4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB + 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + 0, + }, + outputs: []regMask{ + 4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + }, + }, + }, + { + name: "MOVSSstore", + asm: x86.AMOVSS, + reg: regInfo{ + inputs: []regMask{ + 4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB + 4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + 0, + }, + }, + }, + { + name: "MOVSDstore", + asm: x86.AMOVSD, + reg: regInfo{ + inputs: []regMask{ + 4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB + 4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + 0, + }, + }, + }, + { + name: "MOVSSstoreidx4", + asm: x86.AMOVSS, + reg: regInfo{ + inputs: []regMask{ + 4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB + 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + 4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + 0, + }, + }, + }, + { + name: "MOVSDstoreidx8", + asm: x86.AMOVSD, + reg: regInfo{ + inputs: []regMask{ + 4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB + 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + 4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + 0, + }, + }, + }, { name: "ADDQ", asm: x86.AADDQ, @@ -2177,6 +2431,14 @@ var opcodeTable = [...]opInfo{ name: "AddPtr", generic: true, }, + { + name: "Add32F", + generic: true, + }, + { + name: "Add64F", + generic: true, + }, { name: "Sub8", generic: true, @@ -2193,6 +2455,14 @@ var opcodeTable = [...]opInfo{ name: "Sub64", generic: true, }, + { + name: "Sub32F", + generic: true, + }, + { + name: "Sub64F", + generic: true, + }, { name: "Mul8", generic: true, @@ -2213,6 +2483,22 @@ var opcodeTable = [...]opInfo{ name: "MulPtr", generic: true, }, + { + name: "Mul32F", + generic: true, + }, + { + name: "Mul64F", + generic: true, + }, + { + name: "Div32F", + generic: true, + }, + { + name: "Div64F", + generic: true, + }, { name: "And8", generic: true, @@ -2717,6 +3003,14 @@ var opcodeTable = [...]opInfo{ name: "Const64", generic: true, }, + { + name: "Const32F", + generic: true, + }, + { + name: "Const64F", + generic: true, + }, { name: "ConstPtr", generic: true, diff --git a/src/cmd/compile/internal/ssa/rewrite.go b/src/cmd/compile/internal/ssa/rewrite.go index aae8220f81..4b9430abab 100644 --- a/src/cmd/compile/internal/ssa/rewrite.go +++ b/src/cmd/compile/internal/ssa/rewrite.go @@ -76,6 +76,14 @@ func applyRewrite(f *Func, rb func(*Block) bool, rv func(*Value, *Config) bool) // Common functions called from rewriting rules +func is64BitFloat(t Type) bool { + return t.Size() == 8 && t.IsFloat() +} + +func is32BitFloat(t Type) bool { + return t.Size() == 4 && t.IsFloat() +} + func is64BitInt(t Type) bool { return t.Size() == 8 && t.IsInteger() } diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go index 502efc5640..75393ad58a 100644 --- a/src/cmd/compile/internal/ssa/rewriteAMD64.go +++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go @@ -1076,6 +1076,24 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto endc445ea2a65385445676cd684ae9a42b5 endc445ea2a65385445676cd684ae9a42b5: ; + case OpAdd32F: + // match: (Add32F x y) + // cond: + // result: (ADDSS x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64ADDSS + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto end5d82e1c10823774894c036b7c5b8fed4 + end5d82e1c10823774894c036b7c5b8fed4: + ; case OpAdd64: // match: (Add64 x y) // cond: @@ -1094,6 +1112,24 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto endd88f18b3f39e3ccc201477a616f0abc0 endd88f18b3f39e3ccc201477a616f0abc0: ; + case OpAdd64F: + // match: (Add64F x y) + // cond: + // result: (ADDSD x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64ADDSD + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto end62f2de6c70abd214e6987ee37976653a + end62f2de6c70abd214e6987ee37976653a: + ; case OpAdd8: // match: (Add8 x y) // cond: @@ -1520,6 +1556,22 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto enddae5807662af67143a3ac3ad9c63bae5 enddae5807662af67143a3ac3ad9c63bae5: ; + case OpConst32F: + // match: (Const32F {val}) + // cond: + // result: (MOVSSconst {val}) + { + val := v.Aux + v.Op = OpAMD64MOVSSconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Aux = val + return true + } + goto end30a68b43982e55971cc58f893ae2c04a + end30a68b43982e55971cc58f893ae2c04a: + ; case OpConst64: // match: (Const64 [val]) // cond: @@ -1536,6 +1588,22 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto endc630434ae7f143ab69d5f482a9b52b5f endc630434ae7f143ab69d5f482a9b52b5f: ; + case OpConst64F: + // match: (Const64F {val}) + // cond: + // result: (MOVSDconst {val}) + { + val := v.Aux + v.Op = OpAMD64MOVSDconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Aux = val + return true + } + goto end958041a44a2ee8fc571cbc0832fad285 + end958041a44a2ee8fc571cbc0832fad285: + ; case OpConst8: // match: (Const8 [val]) // cond: @@ -1620,6 +1688,42 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto endc395c0a53eeccf597e225a07b53047d1 endc395c0a53eeccf597e225a07b53047d1: ; + case OpDiv32F: + // match: (Div32F x y) + // cond: + // result: (DIVSS x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64DIVSS + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto enddca0462c7b176c4138854d7d5627ab5b + enddca0462c7b176c4138854d7d5627ab5b: + ; + case OpDiv64F: + // match: (Div64F x y) + // cond: + // result: (DIVSD x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64DIVSD + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto end12299d76db5144a60f564d34ba97eb43 + end12299d76db5144a60f564d34ba97eb43: + ; case OpEq16: // match: (Eq16 x y) // cond: @@ -2558,6 +2662,48 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto end8f83bf72293670e75b22d6627bd13f0b end8f83bf72293670e75b22d6627bd13f0b: ; + // match: (Load ptr mem) + // cond: is32BitFloat(t) + // result: (MOVSSload ptr mem) + { + t := v.Type + ptr := v.Args[0] + mem := v.Args[1] + if !(is32BitFloat(t)) { + goto end63383c4895805881aabceebea3c4c533 + } + v.Op = OpAMD64MOVSSload + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(ptr) + v.AddArg(mem) + return true + } + goto end63383c4895805881aabceebea3c4c533 + end63383c4895805881aabceebea3c4c533: + ; + // match: (Load ptr mem) + // cond: is64BitFloat(t) + // result: (MOVSDload ptr mem) + { + t := v.Type + ptr := v.Args[0] + mem := v.Args[1] + if !(is64BitFloat(t)) { + goto end99d0858c0a5bb72f0fe4decc748da812 + } + v.Op = OpAMD64MOVSDload + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(ptr) + v.AddArg(mem) + return true + } + goto end99d0858c0a5bb72f0fe4decc748da812 + end99d0858c0a5bb72f0fe4decc748da812: + ; case OpLrot16: // match: (Lrot16 x [c]) // cond: @@ -3466,6 +3612,438 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto end01c970657b0fdefeab82458c15022163 end01c970657b0fdefeab82458c15022163: ; + case OpAMD64MOVSDload: + // match: (MOVSDload [off1] (ADDQconst [off2] ptr) mem) + // cond: + // result: (MOVSDload [addOff(off1, off2)] ptr mem) + { + off1 := v.AuxInt + if v.Args[0].Op != OpAMD64ADDQconst { + goto endb30d8b19da953bcc24db5adcaf3cd3de + } + off2 := v.Args[0].AuxInt + ptr := v.Args[0].Args[0] + mem := v.Args[1] + v.Op = OpAMD64MOVSDload + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = addOff(off1, off2) + v.AddArg(ptr) + v.AddArg(mem) + return true + } + goto endb30d8b19da953bcc24db5adcaf3cd3de + endb30d8b19da953bcc24db5adcaf3cd3de: + ; + // match: (MOVSDload [off1] {sym1} (LEAQ [off2] {sym2} base) mem) + // cond: (sym1 == nil || sym2 == nil) + // result: (MOVSDload [addOff(off1,off2)] {mergeSym(sym1,sym2)} base mem) + { + off1 := v.AuxInt + sym1 := v.Aux + if v.Args[0].Op != OpAMD64LEAQ { + goto end3d7dc2a0979c214ad64f1c782b3fdeec + } + off2 := v.Args[0].AuxInt + sym2 := v.Args[0].Aux + base := v.Args[0].Args[0] + mem := v.Args[1] + if !(sym1 == nil || sym2 == nil) { + goto end3d7dc2a0979c214ad64f1c782b3fdeec + } + v.Op = OpAMD64MOVSDload + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = addOff(off1, off2) + v.Aux = mergeSym(sym1, sym2) + v.AddArg(base) + v.AddArg(mem) + return true + } + goto end3d7dc2a0979c214ad64f1c782b3fdeec + end3d7dc2a0979c214ad64f1c782b3fdeec: + ; + // match: (MOVSDload [off1] (LEAQ8 [off2] ptr idx) mem) + // cond: + // result: (MOVSDloadidx8 [addOff(off1, off2)] ptr idx mem) + { + off1 := v.AuxInt + if v.Args[0].Op != OpAMD64LEAQ8 { + goto end290f413641e9c9b3a21dbffb8e6f51ce + } + off2 := v.Args[0].AuxInt + ptr := v.Args[0].Args[0] + idx := v.Args[0].Args[1] + mem := v.Args[1] + v.Op = OpAMD64MOVSDloadidx8 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = addOff(off1, off2) + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + goto end290f413641e9c9b3a21dbffb8e6f51ce + end290f413641e9c9b3a21dbffb8e6f51ce: + ; + case OpAMD64MOVSDloadidx8: + // match: (MOVSDloadidx8 [off1] (ADDQconst [off2] ptr) idx mem) + // cond: + // result: (MOVSDloadidx8 [addOff(off1, off2)] ptr idx mem) + { + off1 := v.AuxInt + if v.Args[0].Op != OpAMD64ADDQconst { + goto enda922ba4bafd07007398d143ff201635a + } + off2 := v.Args[0].AuxInt + ptr := v.Args[0].Args[0] + idx := v.Args[1] + mem := v.Args[2] + v.Op = OpAMD64MOVSDloadidx8 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = addOff(off1, off2) + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + goto enda922ba4bafd07007398d143ff201635a + enda922ba4bafd07007398d143ff201635a: + ; + case OpAMD64MOVSDstore: + // match: (MOVSDstore [off1] (ADDQconst [off2] ptr) val mem) + // cond: + // result: (MOVSDstore [addOff(off1, off2)] ptr val mem) + { + off1 := v.AuxInt + if v.Args[0].Op != OpAMD64ADDQconst { + goto endb8906053f3ffca146218392d4358440e + } + off2 := v.Args[0].AuxInt + ptr := v.Args[0].Args[0] + val := v.Args[1] + mem := v.Args[2] + v.Op = OpAMD64MOVSDstore + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = addOff(off1, off2) + v.AddArg(ptr) + v.AddArg(val) + v.AddArg(mem) + return true + } + goto endb8906053f3ffca146218392d4358440e + endb8906053f3ffca146218392d4358440e: + ; + // match: (MOVSDstore [off1] {sym1} (LEAQ [off2] {sym2} base) val mem) + // cond: (sym1 == nil || sym2 == nil) + // result: (MOVSDstore [addOff(off1,off2)] {mergeSym(sym1,sym2)} base val mem) + { + off1 := v.AuxInt + sym1 := v.Aux + if v.Args[0].Op != OpAMD64LEAQ { + goto endc62528d624da256376080f662fa73cc5 + } + off2 := v.Args[0].AuxInt + sym2 := v.Args[0].Aux + base := v.Args[0].Args[0] + val := v.Args[1] + mem := v.Args[2] + if !(sym1 == nil || sym2 == nil) { + goto endc62528d624da256376080f662fa73cc5 + } + v.Op = OpAMD64MOVSDstore + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = addOff(off1, off2) + v.Aux = mergeSym(sym1, sym2) + v.AddArg(base) + v.AddArg(val) + v.AddArg(mem) + return true + } + goto endc62528d624da256376080f662fa73cc5 + endc62528d624da256376080f662fa73cc5: + ; + // match: (MOVSDstore [off1] (LEAQ8 [off2] ptr idx) val mem) + // cond: + // result: (MOVSDstoreidx8 [addOff(off1, off2)] ptr idx val mem) + { + off1 := v.AuxInt + if v.Args[0].Op != OpAMD64LEAQ8 { + goto endd76d67faa7541d73e075d15443daec5f + } + off2 := v.Args[0].AuxInt + ptr := v.Args[0].Args[0] + idx := v.Args[0].Args[1] + val := v.Args[1] + mem := v.Args[2] + v.Op = OpAMD64MOVSDstoreidx8 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = addOff(off1, off2) + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(val) + v.AddArg(mem) + return true + } + goto endd76d67faa7541d73e075d15443daec5f + endd76d67faa7541d73e075d15443daec5f: + ; + case OpAMD64MOVSDstoreidx8: + // match: (MOVSDstoreidx8 [off1] (ADDQconst [off2] ptr) idx val mem) + // cond: + // result: (MOVSDstoreidx8 [addOff(off1, off2)] ptr idx val mem) + { + off1 := v.AuxInt + if v.Args[0].Op != OpAMD64ADDQconst { + goto endc0c523fd517b8432a9f946e3c3c54c83 + } + off2 := v.Args[0].AuxInt + ptr := v.Args[0].Args[0] + idx := v.Args[1] + val := v.Args[2] + mem := v.Args[3] + v.Op = OpAMD64MOVSDstoreidx8 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = addOff(off1, off2) + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(val) + v.AddArg(mem) + return true + } + goto endc0c523fd517b8432a9f946e3c3c54c83 + endc0c523fd517b8432a9f946e3c3c54c83: + ; + case OpAMD64MOVSSload: + // match: (MOVSSload [off1] (ADDQconst [off2] ptr) mem) + // cond: + // result: (MOVSSload [addOff(off1, off2)] ptr mem) + { + off1 := v.AuxInt + if v.Args[0].Op != OpAMD64ADDQconst { + goto endfd8ae39356d66610e8efcc54825cc022 + } + off2 := v.Args[0].AuxInt + ptr := v.Args[0].Args[0] + mem := v.Args[1] + v.Op = OpAMD64MOVSSload + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = addOff(off1, off2) + v.AddArg(ptr) + v.AddArg(mem) + return true + } + goto endfd8ae39356d66610e8efcc54825cc022 + endfd8ae39356d66610e8efcc54825cc022: + ; + // match: (MOVSSload [off1] {sym1} (LEAQ [off2] {sym2} base) mem) + // cond: (sym1 == nil || sym2 == nil) + // result: (MOVSSload [addOff(off1,off2)] {mergeSym(sym1,sym2)} base mem) + { + off1 := v.AuxInt + sym1 := v.Aux + if v.Args[0].Op != OpAMD64LEAQ { + goto end86f5c0b840432898d1e4624da1ad8918 + } + off2 := v.Args[0].AuxInt + sym2 := v.Args[0].Aux + base := v.Args[0].Args[0] + mem := v.Args[1] + if !(sym1 == nil || sym2 == nil) { + goto end86f5c0b840432898d1e4624da1ad8918 + } + v.Op = OpAMD64MOVSSload + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = addOff(off1, off2) + v.Aux = mergeSym(sym1, sym2) + v.AddArg(base) + v.AddArg(mem) + return true + } + goto end86f5c0b840432898d1e4624da1ad8918 + end86f5c0b840432898d1e4624da1ad8918: + ; + // match: (MOVSSload [off1] (LEAQ4 [off2] ptr idx) mem) + // cond: + // result: (MOVSSloadidx4 [addOff(off1, off2)] ptr idx mem) + { + off1 := v.AuxInt + if v.Args[0].Op != OpAMD64LEAQ4 { + goto end479f98c68c30173148913157084607d2 + } + off2 := v.Args[0].AuxInt + ptr := v.Args[0].Args[0] + idx := v.Args[0].Args[1] + mem := v.Args[1] + v.Op = OpAMD64MOVSSloadidx4 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = addOff(off1, off2) + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + goto end479f98c68c30173148913157084607d2 + end479f98c68c30173148913157084607d2: + ; + case OpAMD64MOVSSloadidx4: + // match: (MOVSSloadidx4 [off1] (ADDQconst [off2] ptr) idx mem) + // cond: + // result: (MOVSSloadidx4 [addOff(off1, off2)] ptr idx mem) + { + off1 := v.AuxInt + if v.Args[0].Op != OpAMD64ADDQconst { + goto end45b6855e44d0714ef12a148d4ed57ea0 + } + off2 := v.Args[0].AuxInt + ptr := v.Args[0].Args[0] + idx := v.Args[1] + mem := v.Args[2] + v.Op = OpAMD64MOVSSloadidx4 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = addOff(off1, off2) + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + goto end45b6855e44d0714ef12a148d4ed57ea0 + end45b6855e44d0714ef12a148d4ed57ea0: + ; + case OpAMD64MOVSSstore: + // match: (MOVSSstore [off1] (ADDQconst [off2] ptr) val mem) + // cond: + // result: (MOVSSstore [addOff(off1, off2)] ptr val mem) + { + off1 := v.AuxInt + if v.Args[0].Op != OpAMD64ADDQconst { + goto endd5dd6aabcca196087990cf227b93376a + } + off2 := v.Args[0].AuxInt + ptr := v.Args[0].Args[0] + val := v.Args[1] + mem := v.Args[2] + v.Op = OpAMD64MOVSSstore + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = addOff(off1, off2) + v.AddArg(ptr) + v.AddArg(val) + v.AddArg(mem) + return true + } + goto endd5dd6aabcca196087990cf227b93376a + endd5dd6aabcca196087990cf227b93376a: + ; + // match: (MOVSSstore [off1] {sym1} (LEAQ [off2] {sym2} base) val mem) + // cond: (sym1 == nil || sym2 == nil) + // result: (MOVSSstore [addOff(off1,off2)] {mergeSym(sym1,sym2)} base val mem) + { + off1 := v.AuxInt + sym1 := v.Aux + if v.Args[0].Op != OpAMD64LEAQ { + goto endbb6c6bcd6d4f898318314e310920f8d9 + } + off2 := v.Args[0].AuxInt + sym2 := v.Args[0].Aux + base := v.Args[0].Args[0] + val := v.Args[1] + mem := v.Args[2] + if !(sym1 == nil || sym2 == nil) { + goto endbb6c6bcd6d4f898318314e310920f8d9 + } + v.Op = OpAMD64MOVSSstore + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = addOff(off1, off2) + v.Aux = mergeSym(sym1, sym2) + v.AddArg(base) + v.AddArg(val) + v.AddArg(mem) + return true + } + goto endbb6c6bcd6d4f898318314e310920f8d9 + endbb6c6bcd6d4f898318314e310920f8d9: + ; + // match: (MOVSSstore [off1] (LEAQ4 [off2] ptr idx) val mem) + // cond: + // result: (MOVSSstoreidx4 [addOff(off1, off2)] ptr idx val mem) + { + off1 := v.AuxInt + if v.Args[0].Op != OpAMD64LEAQ4 { + goto end20b3a5a13e1c44d49e59eb4af0749503 + } + off2 := v.Args[0].AuxInt + ptr := v.Args[0].Args[0] + idx := v.Args[0].Args[1] + val := v.Args[1] + mem := v.Args[2] + v.Op = OpAMD64MOVSSstoreidx4 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = addOff(off1, off2) + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(val) + v.AddArg(mem) + return true + } + goto end20b3a5a13e1c44d49e59eb4af0749503 + end20b3a5a13e1c44d49e59eb4af0749503: + ; + case OpAMD64MOVSSstoreidx4: + // match: (MOVSSstoreidx4 [off1] (ADDQconst [off2] ptr) idx val mem) + // cond: + // result: (MOVSSstoreidx4 [addOff(off1, off2)] ptr idx val mem) + { + off1 := v.AuxInt + if v.Args[0].Op != OpAMD64ADDQconst { + goto end97e6b5fc52597982bc1a9e4b14561d96 + } + off2 := v.Args[0].AuxInt + ptr := v.Args[0].Args[0] + idx := v.Args[1] + val := v.Args[2] + mem := v.Args[3] + v.Op = OpAMD64MOVSSstoreidx4 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = addOff(off1, off2) + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(val) + v.AddArg(mem) + return true + } + goto end97e6b5fc52597982bc1a9e4b14561d96 + end97e6b5fc52597982bc1a9e4b14561d96: + ; case OpAMD64MOVWstore: // match: (MOVWstore ptr (MOVWQSX x) mem) // cond: @@ -3953,6 +4531,24 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto ende144381f85808e5144782804768e2859 ende144381f85808e5144782804768e2859: ; + case OpMul32F: + // match: (Mul32F x y) + // cond: + // result: (MULSS x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64MULSS + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto end32105a3bfe0237b799b69d83b3f171ca + end32105a3bfe0237b799b69d83b3f171ca: + ; case OpMul64: // match: (Mul64 x y) // cond: @@ -3971,6 +4567,24 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto end38da21e77ac329eb643b20e7d97d5853 end38da21e77ac329eb643b20e7d97d5853: ; + case OpMul64F: + // match: (Mul64F x y) + // cond: + // result: (MULSD x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64MULSD + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto end0ff6e1919fb0a3e549eb82b43edf1f52 + end0ff6e1919fb0a3e549eb82b43edf1f52: + ; case OpMul8: // match: (Mul8 x y) // cond: @@ -7412,6 +8026,56 @@ func rewriteValueAMD64(v *Value, config *Config) bool { end32c5cbec813d1c2ae94fc9b1090e4b2a: ; case OpStore: + // match: (Store [8] ptr val mem) + // cond: is64BitFloat(val.Type) + // result: (MOVSDstore ptr val mem) + { + if v.AuxInt != 8 { + goto endaeec4f61bc8e67dbf3fa2f79fe4c2b9e + } + ptr := v.Args[0] + val := v.Args[1] + mem := v.Args[2] + if !(is64BitFloat(val.Type)) { + goto endaeec4f61bc8e67dbf3fa2f79fe4c2b9e + } + v.Op = OpAMD64MOVSDstore + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(ptr) + v.AddArg(val) + v.AddArg(mem) + return true + } + goto endaeec4f61bc8e67dbf3fa2f79fe4c2b9e + endaeec4f61bc8e67dbf3fa2f79fe4c2b9e: + ; + // match: (Store [4] ptr val mem) + // cond: is32BitFloat(val.Type) + // result: (MOVSSstore ptr val mem) + { + if v.AuxInt != 4 { + goto endf638ca0a75871b5062da15324d0e0384 + } + ptr := v.Args[0] + val := v.Args[1] + mem := v.Args[2] + if !(is32BitFloat(val.Type)) { + goto endf638ca0a75871b5062da15324d0e0384 + } + v.Op = OpAMD64MOVSSstore + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(ptr) + v.AddArg(val) + v.AddArg(mem) + return true + } + goto endf638ca0a75871b5062da15324d0e0384 + endf638ca0a75871b5062da15324d0e0384: + ; // match: (Store [8] ptr val mem) // cond: // result: (MOVQstore ptr val mem) @@ -7536,6 +8200,24 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto enddc3a2a488bda8c5856f93343e5ffe5f8 enddc3a2a488bda8c5856f93343e5ffe5f8: ; + case OpSub32F: + // match: (Sub32F x y) + // cond: + // result: (SUBSS x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SUBSS + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto end20193c1804b0e707702a884fb8abd60d + end20193c1804b0e707702a884fb8abd60d: + ; case OpSub64: // match: (Sub64 x y) // cond: @@ -7554,6 +8236,24 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto endd88d5646309fd9174584888ecc8aca2c endd88d5646309fd9174584888ecc8aca2c: ; + case OpSub64F: + // match: (Sub64F x y) + // cond: + // result: (SUBSD x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SUBSD + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto end5d5af7b8a3326bf9151f00a0013b73d7 + end5d5af7b8a3326bf9151f00a0013b73d7: + ; case OpSub8: // match: (Sub8 x y) // cond: -- cgit v1.3 From 0b46b42943ee9d7ad4e9a19772d22468718173c9 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Tue, 11 Aug 2015 12:51:33 -0700 Subject: [dev.ssa] cmd/compile/internal/ssa: New register allocator Implement a global (whole function) register allocator. This replaces the local (per basic block) register allocator. Clobbering of registers by instructions is handled properly. A separate change will add the correct clobbers to all the instructions. Change-Id: I38ce4dc7dccb8303c1c0e0295fe70247b0a3f2ea Reviewed-on: https://go-review.googlesource.com/13622 Reviewed-by: Josh Bleecher Snyder Reviewed-by: Todd Neal --- src/cmd/compile/internal/gc/ssa.go | 12 +- .../compile/internal/gc/testdata/regalloc_ssa.go | 57 ++ src/cmd/compile/internal/ssa/deadcode.go | 8 + src/cmd/compile/internal/ssa/gen/AMD64Ops.go | 34 +- src/cmd/compile/internal/ssa/gen/main.go | 42 +- src/cmd/compile/internal/ssa/html.go | 2 +- src/cmd/compile/internal/ssa/op.go | 7 +- src/cmd/compile/internal/ssa/opGen.go | 909 ++++++++-------- src/cmd/compile/internal/ssa/regalloc.go | 1081 ++++++++++++++------ src/cmd/compile/internal/ssa/stackalloc.go | 18 +- src/cmd/compile/internal/ssa/tighten.go | 7 - src/cmd/compile/internal/ssa/value.go | 4 +- 12 files changed, 1439 insertions(+), 742 deletions(-) create mode 100644 src/cmd/compile/internal/gc/testdata/regalloc_ssa.go (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 4e115a0fcd..ef90ed40e7 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -2277,7 +2277,10 @@ func genValue(v *ssa.Value) { p.To.Reg = x86.REG_SP p.To.Offset = localOffset(v) case ssa.OpPhi: - // just check to make sure regalloc did it right + // just check to make sure regalloc and stackalloc did it right + if v.Type.IsMemory() { + return + } f := v.Block.Func loc := f.RegAlloc[v.ID] for _, a := range v.Args { @@ -2376,13 +2379,16 @@ func genValue(v *ssa.Value) { case ssa.OpAMD64InvertFlags: v.Fatalf("InvertFlags should never make it to codegen %v", v) case ssa.OpAMD64REPSTOSQ: + p := Prog(x86.AXORL) // TODO: lift out zeroing into its own instruction? + p.From.Type = obj.TYPE_REG + p.From.Reg = x86.REG_AX + p.To.Type = obj.TYPE_REG + p.To.Reg = x86.REG_AX Prog(x86.AREP) Prog(x86.ASTOSQ) - v.Unimplementedf("REPSTOSQ clobbers not implemented: %s", v.LongString()) case ssa.OpAMD64REPMOVSB: Prog(x86.AREP) Prog(x86.AMOVSB) - v.Unimplementedf("REPMOVSB clobbers not implemented: %s", v.LongString()) default: v.Unimplementedf("genValue not implemented: %s", v.LongString()) } diff --git a/src/cmd/compile/internal/gc/testdata/regalloc_ssa.go b/src/cmd/compile/internal/gc/testdata/regalloc_ssa.go new file mode 100644 index 0000000000..f752692952 --- /dev/null +++ b/src/cmd/compile/internal/gc/testdata/regalloc_ssa.go @@ -0,0 +1,57 @@ +// run + +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Tests phi implementation + +package main + +func phiOverwrite_ssa() int { + var n int + for i := 0; i < 10; i++ { + if i == 6 { + break + } + n = i + } + return n +} + +func phiOverwrite() { + want := 5 + got := phiOverwrite_ssa() + if got != want { + println("phiOverwrite_ssa()=", want, ", got", got) + failed = true + } +} + +func phiOverwriteBig_ssa() int { + var a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z int + a = 1 + for idx := 0; idx < 26; idx++ { + a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z = b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, a + } + return a*1 + b*2 + c*3 + d*4 + e*5 + f*6 + g*7 + h*8 + i*9 + j*10 + k*11 + l*12 + m*13 + n*14 + o*15 + p*16 + q*17 + r*18 + s*19 + t*20 + u*21 + v*22 + w*23 + x*24 + y*25 + z*26 +} + +func phiOverwriteBig() { + want := 1 + got := phiOverwriteBig_ssa() + if got != want { + println("phiOverwriteBig_ssa()=", want, ", got", got) + failed = true + } +} + +var failed = false + +func main() { + phiOverwrite() + phiOverwriteBig() + if failed { + panic("failed") + } +} diff --git a/src/cmd/compile/internal/ssa/deadcode.go b/src/cmd/compile/internal/ssa/deadcode.go index 109b3dd09f..8c306c8412 100644 --- a/src/cmd/compile/internal/ssa/deadcode.go +++ b/src/cmd/compile/internal/ssa/deadcode.go @@ -59,6 +59,14 @@ func findlive(f *Func) (reachable []bool, live []bool) { // deadcode removes dead code from f. func deadcode(f *Func) { + // deadcode after regalloc is forbidden for now. Regalloc + // doesn't quite generate legal SSA which will lead to some + // required moves being eliminated. See the comment at the + // top of regalloc.go for details. + if f.RegAlloc != nil { + f.Fatalf("deadcode after regalloc") + } + reachable, live := findlive(f) // Remove dead values from blocks' value list. Return dead diff --git a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go index 8bdcfaaac7..5aa5e60e33 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go @@ -72,13 +72,14 @@ func init() { // Common individual register masks var ( - cx = buildReg("CX") - x15 = buildReg("X15") - gp = buildReg("AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15") - fp = buildReg("X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15") - gpsp = gp | buildReg("SP") - gpspsb = gpsp | buildReg("SB") - flags = buildReg("FLAGS") + cx = buildReg("CX") + x15 = buildReg("X15") + gp = buildReg("AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15") + fp = buildReg("X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15") + gpsp = gp | buildReg("SP") + gpspsb = gpsp | buildReg("SB") + flags = buildReg("FLAGS") + callerSave = gp | fp | flags ) // Common slices of register masks @@ -90,16 +91,16 @@ func init() { // Common regInfo var ( - gp01 = regInfo{inputs: []regMask{}, outputs: gponly} - gp11 = regInfo{inputs: []regMask{gpsp}, outputs: gponly} - gp11sb = regInfo{inputs: []regMask{gpspsb}, outputs: gponly} - gp21 = regInfo{inputs: []regMask{gpsp, gpsp}, outputs: gponly} - gp21sb = regInfo{inputs: []regMask{gpspsb, gpsp}, outputs: gponly} - gp21shift = regInfo{inputs: []regMask{gpsp, cx}, outputs: []regMask{gp &^ cx}} + gp01 = regInfo{inputs: []regMask{}, outputs: gponly, clobbers: flags} + gp11 = regInfo{inputs: []regMask{gpsp}, outputs: gponly, clobbers: flags} + gp11sb = regInfo{inputs: []regMask{gpspsb}, outputs: gponly, clobbers: flags} + gp21 = regInfo{inputs: []regMask{gpsp, gpsp}, outputs: gponly, clobbers: flags} + gp21sb = regInfo{inputs: []regMask{gpspsb, gpsp}, outputs: gponly, clobbers: flags} + gp21shift = regInfo{inputs: []regMask{gpsp, cx}, outputs: []regMask{gp &^ cx}, clobbers: flags} gp2flags = regInfo{inputs: []regMask{gpsp, gpsp}, outputs: flagsonly} gp1flags = regInfo{inputs: []regMask{gpsp}, outputs: flagsonly} - flagsgp = regInfo{inputs: flagsonly, outputs: gponly} + flagsgp = regInfo{inputs: flagsonly, outputs: gponly, clobbers: flags} gpload = regInfo{inputs: []regMask{gpspsb, 0}, outputs: gponly} gploadidx = regInfo{inputs: []regMask{gpspsb, gpsp, 0}, outputs: gponly} @@ -122,6 +123,7 @@ func init() { fpstore = regInfo{inputs: []regMask{gpspsb, fp, 0}} fpstoreidx = regInfo{inputs: []regMask{gpspsb, gpsp, fp, 0}} ) + // TODO: most ops clobber flags // Suffixes encode the bit width of various instructions. // Q = 64 bit, L = 32 bit, W = 16 bit, B = 8 bit @@ -318,8 +320,8 @@ func init() { {name: "REPSTOSQ", reg: regInfo{[]regMask{buildReg("DI"), buildReg("CX")}, buildReg("DI AX CX"), nil}}, // store arg1 8-byte words containing zero into arg0 using STOSQ. arg2=mem. //TODO: set register clobber to everything? - {name: "CALLstatic"}, // call static function aux.(*gc.Sym). arg0=mem, returns mem - {name: "CALLclosure", reg: regInfo{[]regMask{gpsp, buildReg("DX"), 0}, 0, nil}}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem returns mem + {name: "CALLstatic", reg: regInfo{clobbers: callerSave}}, // call static function aux.(*gc.Sym). arg0=mem, returns mem + {name: "CALLclosure", reg: regInfo{[]regMask{gpsp, buildReg("DX"), 0}, callerSave, nil}}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem returns mem {name: "REPMOVSB", reg: regInfo{[]regMask{buildReg("DI"), buildReg("SI"), buildReg("CX")}, buildReg("DI SI CX"), nil}}, // move arg2 bytes from arg1 to arg0. arg3=mem, returns memory diff --git a/src/cmd/compile/internal/ssa/gen/main.go b/src/cmd/compile/internal/ssa/gen/main.go index 97ac802cbd..6620c0a1d0 100644 --- a/src/cmd/compile/internal/ssa/gen/main.go +++ b/src/cmd/compile/internal/ssa/gen/main.go @@ -15,6 +15,7 @@ import ( "io/ioutil" "log" "regexp" + "sort" ) type arch struct { @@ -125,11 +126,22 @@ func genOp() { fmt.Fprintf(w, "asm: x86.A%s,\n", v.asm) } fmt.Fprintln(w, "reg:regInfo{") - // reg inputs - if len(v.reg.inputs) > 0 { - fmt.Fprintln(w, "inputs: []regMask{") - for _, r := range v.reg.inputs { - fmt.Fprintf(w, "%d,%s\n", r, a.regMaskComment(r)) + + // Compute input allocation order. We allocate from the + // most to the least constrained input. This order guarantees + // that we will always be able to find a register. + var s []intPair + for i, r := range v.reg.inputs { + if r != 0 { + s = append(s, intPair{countRegs(r), i}) + } + } + if len(s) > 0 { + sort.Sort(byKey(s)) + fmt.Fprintln(w, "inputs: []inputInfo{") + for _, p := range s { + r := v.reg.inputs[p.val] + fmt.Fprintf(w, "{%d,%d},%s\n", p.val, r, a.regMaskComment(r)) } fmt.Fprintln(w, "},") } @@ -205,3 +217,23 @@ func genLower() { genRules(a) } } + +// countRegs returns the number of set bits in the register mask. +func countRegs(r regMask) int { + n := 0 + for r != 0 { + n += int(r & 1) + r >>= 1 + } + return n +} + +// for sorting a pair of integers by key +type intPair struct { + key, val int +} +type byKey []intPair + +func (a byKey) Len() int { return len(a) } +func (a byKey) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +func (a byKey) Less(i, j int) bool { return a[i].key < a[j].key } diff --git a/src/cmd/compile/internal/ssa/html.go b/src/cmd/compile/internal/ssa/html.go index 848e016129..5c23320680 100644 --- a/src/cmd/compile/internal/ssa/html.go +++ b/src/cmd/compile/internal/ssa/html.go @@ -362,7 +362,7 @@ func (v *Value) LongHTML() string { s += fmt.Sprintf(" %s", a.HTML()) } r := v.Block.Func.RegAlloc - if r != nil && r[v.ID] != nil { + if int(v.ID) < len(r) && r[v.ID] != nil { s += " : " + r[v.ID].Name() } diff --git a/src/cmd/compile/internal/ssa/op.go b/src/cmd/compile/internal/ssa/op.go index 4ca8c770cb..356084fb02 100644 --- a/src/cmd/compile/internal/ssa/op.go +++ b/src/cmd/compile/internal/ssa/op.go @@ -19,8 +19,13 @@ type opInfo struct { generic bool // this is a generic (arch-independent) opcode } +type inputInfo struct { + idx int // index in Args array + regs regMask // allowed input registers +} + type regInfo struct { - inputs []regMask + inputs []inputInfo // ordered in register allocation order clobbers regMask outputs []regMask // NOTE: values can only have 1 output for now. } diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index 2155cd318e..cbabbfade5 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -425,9 +425,9 @@ var opcodeTable = [...]opInfo{ name: "ADDSS", asm: x86.AADDSS, reg: regInfo{ - inputs: []regMask{ - 4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 - 4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + inputs: []inputInfo{ + {0, 4294901760}, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + {1, 4294901760}, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 }, outputs: []regMask{ 4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 @@ -438,9 +438,9 @@ var opcodeTable = [...]opInfo{ name: "ADDSD", asm: x86.AADDSD, reg: regInfo{ - inputs: []regMask{ - 4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 - 4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + inputs: []inputInfo{ + {0, 4294901760}, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + {1, 4294901760}, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 }, outputs: []regMask{ 4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 @@ -451,9 +451,9 @@ var opcodeTable = [...]opInfo{ name: "SUBSS", asm: x86.ASUBSS, reg: regInfo{ - inputs: []regMask{ - 2147418112, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 - 2147418112, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 + inputs: []inputInfo{ + {0, 2147418112}, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 + {1, 2147418112}, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 }, clobbers: 2147483648, // .X15 outputs: []regMask{ @@ -465,9 +465,9 @@ var opcodeTable = [...]opInfo{ name: "SUBSD", asm: x86.ASUBSD, reg: regInfo{ - inputs: []regMask{ - 2147418112, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 - 2147418112, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 + inputs: []inputInfo{ + {0, 2147418112}, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 + {1, 2147418112}, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 }, clobbers: 2147483648, // .X15 outputs: []regMask{ @@ -479,9 +479,9 @@ var opcodeTable = [...]opInfo{ name: "MULSS", asm: x86.AMULSS, reg: regInfo{ - inputs: []regMask{ - 4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 - 4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + inputs: []inputInfo{ + {0, 4294901760}, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + {1, 4294901760}, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 }, outputs: []regMask{ 4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 @@ -492,9 +492,9 @@ var opcodeTable = [...]opInfo{ name: "MULSD", asm: x86.AMULSD, reg: regInfo{ - inputs: []regMask{ - 4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 - 4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + inputs: []inputInfo{ + {0, 4294901760}, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + {1, 4294901760}, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 }, outputs: []regMask{ 4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 @@ -505,9 +505,9 @@ var opcodeTable = [...]opInfo{ name: "DIVSS", asm: x86.ADIVSS, reg: regInfo{ - inputs: []regMask{ - 2147418112, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 - 2147418112, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 + inputs: []inputInfo{ + {0, 2147418112}, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 + {1, 2147418112}, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 }, clobbers: 2147483648, // .X15 outputs: []regMask{ @@ -519,9 +519,9 @@ var opcodeTable = [...]opInfo{ name: "DIVSD", asm: x86.ADIVSD, reg: regInfo{ - inputs: []regMask{ - 2147418112, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 - 2147418112, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 + inputs: []inputInfo{ + {0, 2147418112}, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 + {1, 2147418112}, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 }, clobbers: 2147483648, // .X15 outputs: []regMask{ @@ -533,9 +533,8 @@ var opcodeTable = [...]opInfo{ name: "MOVSSload", asm: x86.AMOVSS, reg: regInfo{ - inputs: []regMask{ - 4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB - 0, + inputs: []inputInfo{ + {0, 4295032831}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB }, outputs: []regMask{ 4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 @@ -546,9 +545,8 @@ var opcodeTable = [...]opInfo{ name: "MOVSDload", asm: x86.AMOVSD, reg: regInfo{ - inputs: []regMask{ - 4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB - 0, + inputs: []inputInfo{ + {0, 4295032831}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB }, outputs: []regMask{ 4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 @@ -577,10 +575,9 @@ var opcodeTable = [...]opInfo{ name: "MOVSSloadidx4", asm: x86.AMOVSS, reg: regInfo{ - inputs: []regMask{ - 4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 0, + inputs: []inputInfo{ + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + {0, 4295032831}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB }, outputs: []regMask{ 4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 @@ -591,10 +588,9 @@ var opcodeTable = [...]opInfo{ name: "MOVSDloadidx8", asm: x86.AMOVSD, reg: regInfo{ - inputs: []regMask{ - 4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 0, + inputs: []inputInfo{ + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + {0, 4295032831}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB }, outputs: []regMask{ 4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 @@ -605,10 +601,9 @@ var opcodeTable = [...]opInfo{ name: "MOVSSstore", asm: x86.AMOVSS, reg: regInfo{ - inputs: []regMask{ - 4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB - 4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 - 0, + inputs: []inputInfo{ + {1, 4294901760}, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + {0, 4295032831}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB }, }, }, @@ -616,10 +611,9 @@ var opcodeTable = [...]opInfo{ name: "MOVSDstore", asm: x86.AMOVSD, reg: regInfo{ - inputs: []regMask{ - 4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB - 4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 - 0, + inputs: []inputInfo{ + {1, 4294901760}, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + {0, 4295032831}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB }, }, }, @@ -627,11 +621,10 @@ var opcodeTable = [...]opInfo{ name: "MOVSSstoreidx4", asm: x86.AMOVSS, reg: regInfo{ - inputs: []regMask{ - 4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 - 0, + inputs: []inputInfo{ + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + {2, 4294901760}, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + {0, 4295032831}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB }, }, }, @@ -639,11 +632,10 @@ var opcodeTable = [...]opInfo{ name: "MOVSDstoreidx8", asm: x86.AMOVSD, reg: regInfo{ - inputs: []regMask{ - 4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 - 0, + inputs: []inputInfo{ + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + {2, 4294901760}, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + {0, 4295032831}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB }, }, }, @@ -651,10 +643,11 @@ var opcodeTable = [...]opInfo{ name: "ADDQ", asm: x86.AADDQ, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -664,10 +657,11 @@ var opcodeTable = [...]opInfo{ name: "ADDL", asm: x86.AADDL, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -677,10 +671,11 @@ var opcodeTable = [...]opInfo{ name: "ADDW", asm: x86.AADDW, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -690,10 +685,11 @@ var opcodeTable = [...]opInfo{ name: "ADDB", asm: x86.AADDB, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -703,9 +699,10 @@ var opcodeTable = [...]opInfo{ name: "ADDQconst", asm: x86.AADDQ, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -715,9 +712,10 @@ var opcodeTable = [...]opInfo{ name: "ADDLconst", asm: x86.AADDL, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -727,9 +725,10 @@ var opcodeTable = [...]opInfo{ name: "ADDWconst", asm: x86.AADDW, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -739,9 +738,10 @@ var opcodeTable = [...]opInfo{ name: "ADDBconst", asm: x86.AADDB, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -751,10 +751,11 @@ var opcodeTable = [...]opInfo{ name: "SUBQ", asm: x86.ASUBQ, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -764,10 +765,11 @@ var opcodeTable = [...]opInfo{ name: "SUBL", asm: x86.ASUBL, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -777,10 +779,11 @@ var opcodeTable = [...]opInfo{ name: "SUBW", asm: x86.ASUBW, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -790,10 +793,11 @@ var opcodeTable = [...]opInfo{ name: "SUBB", asm: x86.ASUBB, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -803,9 +807,10 @@ var opcodeTable = [...]opInfo{ name: "SUBQconst", asm: x86.ASUBQ, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -815,9 +820,10 @@ var opcodeTable = [...]opInfo{ name: "SUBLconst", asm: x86.ASUBL, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -827,9 +833,10 @@ var opcodeTable = [...]opInfo{ name: "SUBWconst", asm: x86.ASUBW, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -839,9 +846,10 @@ var opcodeTable = [...]opInfo{ name: "SUBBconst", asm: x86.ASUBB, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -851,10 +859,11 @@ var opcodeTable = [...]opInfo{ name: "MULQ", asm: x86.AIMULQ, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -864,10 +873,11 @@ var opcodeTable = [...]opInfo{ name: "MULL", asm: x86.AIMULL, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -877,10 +887,11 @@ var opcodeTable = [...]opInfo{ name: "MULW", asm: x86.AIMULW, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -890,10 +901,11 @@ var opcodeTable = [...]opInfo{ name: "MULB", asm: x86.AIMULW, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -903,9 +915,10 @@ var opcodeTable = [...]opInfo{ name: "MULQconst", asm: x86.AIMULQ, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -915,9 +928,10 @@ var opcodeTable = [...]opInfo{ name: "MULLconst", asm: x86.AIMULL, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -927,9 +941,10 @@ var opcodeTable = [...]opInfo{ name: "MULWconst", asm: x86.AIMULW, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -939,9 +954,10 @@ var opcodeTable = [...]opInfo{ name: "MULBconst", asm: x86.AIMULW, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -951,10 +967,11 @@ var opcodeTable = [...]opInfo{ name: "ANDQ", asm: x86.AANDQ, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -964,10 +981,11 @@ var opcodeTable = [...]opInfo{ name: "ANDL", asm: x86.AANDL, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -977,10 +995,11 @@ var opcodeTable = [...]opInfo{ name: "ANDW", asm: x86.AANDW, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -990,10 +1009,11 @@ var opcodeTable = [...]opInfo{ name: "ANDB", asm: x86.AANDB, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1003,9 +1023,10 @@ var opcodeTable = [...]opInfo{ name: "ANDQconst", asm: x86.AANDQ, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1015,9 +1036,10 @@ var opcodeTable = [...]opInfo{ name: "ANDLconst", asm: x86.AANDL, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1027,9 +1049,10 @@ var opcodeTable = [...]opInfo{ name: "ANDWconst", asm: x86.AANDW, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1039,9 +1062,10 @@ var opcodeTable = [...]opInfo{ name: "ANDBconst", asm: x86.AANDB, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1051,10 +1075,11 @@ var opcodeTable = [...]opInfo{ name: "ORQ", asm: x86.AORQ, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1064,10 +1089,11 @@ var opcodeTable = [...]opInfo{ name: "ORL", asm: x86.AORL, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1077,10 +1103,11 @@ var opcodeTable = [...]opInfo{ name: "ORW", asm: x86.AORW, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1090,10 +1117,11 @@ var opcodeTable = [...]opInfo{ name: "ORB", asm: x86.AORB, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1103,9 +1131,10 @@ var opcodeTable = [...]opInfo{ name: "ORQconst", asm: x86.AORQ, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1115,9 +1144,10 @@ var opcodeTable = [...]opInfo{ name: "ORLconst", asm: x86.AORL, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1127,9 +1157,10 @@ var opcodeTable = [...]opInfo{ name: "ORWconst", asm: x86.AORW, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1139,9 +1170,10 @@ var opcodeTable = [...]opInfo{ name: "ORBconst", asm: x86.AORB, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1151,10 +1183,11 @@ var opcodeTable = [...]opInfo{ name: "XORQ", asm: x86.AXORQ, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1164,10 +1197,11 @@ var opcodeTable = [...]opInfo{ name: "XORL", asm: x86.AXORL, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1177,10 +1211,11 @@ var opcodeTable = [...]opInfo{ name: "XORW", asm: x86.AXORW, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1190,10 +1225,11 @@ var opcodeTable = [...]opInfo{ name: "XORB", asm: x86.AXORB, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1203,9 +1239,10 @@ var opcodeTable = [...]opInfo{ name: "XORQconst", asm: x86.AXORQ, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1215,9 +1252,10 @@ var opcodeTable = [...]opInfo{ name: "XORLconst", asm: x86.AXORL, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1227,9 +1265,10 @@ var opcodeTable = [...]opInfo{ name: "XORWconst", asm: x86.AXORW, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1239,9 +1278,10 @@ var opcodeTable = [...]opInfo{ name: "XORBconst", asm: x86.AXORB, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1251,9 +1291,9 @@ var opcodeTable = [...]opInfo{ name: "CMPQ", asm: x86.ACMPQ, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, outputs: []regMask{ 8589934592, // .FLAGS @@ -1264,9 +1304,9 @@ var opcodeTable = [...]opInfo{ name: "CMPL", asm: x86.ACMPL, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, outputs: []regMask{ 8589934592, // .FLAGS @@ -1277,9 +1317,9 @@ var opcodeTable = [...]opInfo{ name: "CMPW", asm: x86.ACMPW, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, outputs: []regMask{ 8589934592, // .FLAGS @@ -1290,9 +1330,9 @@ var opcodeTable = [...]opInfo{ name: "CMPB", asm: x86.ACMPB, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, outputs: []regMask{ 8589934592, // .FLAGS @@ -1303,8 +1343,8 @@ var opcodeTable = [...]opInfo{ name: "CMPQconst", asm: x86.ACMPQ, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, outputs: []regMask{ 8589934592, // .FLAGS @@ -1315,8 +1355,8 @@ var opcodeTable = [...]opInfo{ name: "CMPLconst", asm: x86.ACMPL, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, outputs: []regMask{ 8589934592, // .FLAGS @@ -1327,8 +1367,8 @@ var opcodeTable = [...]opInfo{ name: "CMPWconst", asm: x86.ACMPW, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, outputs: []regMask{ 8589934592, // .FLAGS @@ -1339,8 +1379,8 @@ var opcodeTable = [...]opInfo{ name: "CMPBconst", asm: x86.ACMPB, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, outputs: []regMask{ 8589934592, // .FLAGS @@ -1351,9 +1391,9 @@ var opcodeTable = [...]opInfo{ name: "TESTQ", asm: x86.ATESTQ, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, outputs: []regMask{ 8589934592, // .FLAGS @@ -1364,9 +1404,9 @@ var opcodeTable = [...]opInfo{ name: "TESTL", asm: x86.ATESTL, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, outputs: []regMask{ 8589934592, // .FLAGS @@ -1377,9 +1417,9 @@ var opcodeTable = [...]opInfo{ name: "TESTW", asm: x86.ATESTW, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, outputs: []regMask{ 8589934592, // .FLAGS @@ -1390,9 +1430,9 @@ var opcodeTable = [...]opInfo{ name: "TESTB", asm: x86.ATESTB, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, outputs: []regMask{ 8589934592, // .FLAGS @@ -1403,8 +1443,8 @@ var opcodeTable = [...]opInfo{ name: "TESTQconst", asm: x86.ATESTQ, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, outputs: []regMask{ 8589934592, // .FLAGS @@ -1415,8 +1455,8 @@ var opcodeTable = [...]opInfo{ name: "TESTLconst", asm: x86.ATESTL, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, outputs: []regMask{ 8589934592, // .FLAGS @@ -1427,8 +1467,8 @@ var opcodeTable = [...]opInfo{ name: "TESTWconst", asm: x86.ATESTW, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, outputs: []regMask{ 8589934592, // .FLAGS @@ -1439,8 +1479,8 @@ var opcodeTable = [...]opInfo{ name: "TESTBconst", asm: x86.ATESTB, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, outputs: []regMask{ 8589934592, // .FLAGS @@ -1451,10 +1491,11 @@ var opcodeTable = [...]opInfo{ name: "SHLQ", asm: x86.ASHLQ, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 2, // .CX + inputs: []inputInfo{ + {1, 2}, // .CX + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65517, // .AX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1464,10 +1505,11 @@ var opcodeTable = [...]opInfo{ name: "SHLL", asm: x86.ASHLL, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 2, // .CX + inputs: []inputInfo{ + {1, 2}, // .CX + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65517, // .AX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1477,10 +1519,11 @@ var opcodeTable = [...]opInfo{ name: "SHLW", asm: x86.ASHLW, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 2, // .CX + inputs: []inputInfo{ + {1, 2}, // .CX + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65517, // .AX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1490,10 +1533,11 @@ var opcodeTable = [...]opInfo{ name: "SHLB", asm: x86.ASHLB, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 2, // .CX + inputs: []inputInfo{ + {1, 2}, // .CX + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65517, // .AX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1503,9 +1547,10 @@ var opcodeTable = [...]opInfo{ name: "SHLQconst", asm: x86.ASHLQ, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1515,9 +1560,10 @@ var opcodeTable = [...]opInfo{ name: "SHLLconst", asm: x86.ASHLL, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1527,9 +1573,10 @@ var opcodeTable = [...]opInfo{ name: "SHLWconst", asm: x86.ASHLW, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1539,9 +1586,10 @@ var opcodeTable = [...]opInfo{ name: "SHLBconst", asm: x86.ASHLB, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1551,10 +1599,11 @@ var opcodeTable = [...]opInfo{ name: "SHRQ", asm: x86.ASHRQ, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 2, // .CX + inputs: []inputInfo{ + {1, 2}, // .CX + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65517, // .AX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1564,10 +1613,11 @@ var opcodeTable = [...]opInfo{ name: "SHRL", asm: x86.ASHRL, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 2, // .CX + inputs: []inputInfo{ + {1, 2}, // .CX + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65517, // .AX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1577,10 +1627,11 @@ var opcodeTable = [...]opInfo{ name: "SHRW", asm: x86.ASHRW, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 2, // .CX + inputs: []inputInfo{ + {1, 2}, // .CX + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65517, // .AX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1590,10 +1641,11 @@ var opcodeTable = [...]opInfo{ name: "SHRB", asm: x86.ASHRB, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 2, // .CX + inputs: []inputInfo{ + {1, 2}, // .CX + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65517, // .AX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1603,9 +1655,10 @@ var opcodeTable = [...]opInfo{ name: "SHRQconst", asm: x86.ASHRQ, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1615,9 +1668,10 @@ var opcodeTable = [...]opInfo{ name: "SHRLconst", asm: x86.ASHRL, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1627,9 +1681,10 @@ var opcodeTable = [...]opInfo{ name: "SHRWconst", asm: x86.ASHRW, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1639,9 +1694,10 @@ var opcodeTable = [...]opInfo{ name: "SHRBconst", asm: x86.ASHRB, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1651,10 +1707,11 @@ var opcodeTable = [...]opInfo{ name: "SARQ", asm: x86.ASARQ, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 2, // .CX + inputs: []inputInfo{ + {1, 2}, // .CX + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65517, // .AX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1664,10 +1721,11 @@ var opcodeTable = [...]opInfo{ name: "SARL", asm: x86.ASARL, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 2, // .CX + inputs: []inputInfo{ + {1, 2}, // .CX + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65517, // .AX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1677,10 +1735,11 @@ var opcodeTable = [...]opInfo{ name: "SARW", asm: x86.ASARW, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 2, // .CX + inputs: []inputInfo{ + {1, 2}, // .CX + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65517, // .AX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1690,10 +1749,11 @@ var opcodeTable = [...]opInfo{ name: "SARB", asm: x86.ASARB, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 2, // .CX + inputs: []inputInfo{ + {1, 2}, // .CX + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65517, // .AX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1703,9 +1763,10 @@ var opcodeTable = [...]opInfo{ name: "SARQconst", asm: x86.ASARQ, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1715,9 +1776,10 @@ var opcodeTable = [...]opInfo{ name: "SARLconst", asm: x86.ASARL, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1727,9 +1789,10 @@ var opcodeTable = [...]opInfo{ name: "SARWconst", asm: x86.ASARW, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1739,9 +1802,10 @@ var opcodeTable = [...]opInfo{ name: "SARBconst", asm: x86.ASARB, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1751,9 +1815,10 @@ var opcodeTable = [...]opInfo{ name: "ROLQconst", asm: x86.AROLQ, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1763,9 +1828,10 @@ var opcodeTable = [...]opInfo{ name: "ROLLconst", asm: x86.AROLL, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1775,9 +1841,10 @@ var opcodeTable = [...]opInfo{ name: "ROLWconst", asm: x86.AROLW, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1787,9 +1854,10 @@ var opcodeTable = [...]opInfo{ name: "ROLBconst", asm: x86.AROLB, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1799,9 +1867,10 @@ var opcodeTable = [...]opInfo{ name: "NEGQ", asm: x86.ANEGQ, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1811,9 +1880,10 @@ var opcodeTable = [...]opInfo{ name: "NEGL", asm: x86.ANEGL, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1823,9 +1893,10 @@ var opcodeTable = [...]opInfo{ name: "NEGW", asm: x86.ANEGW, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1835,9 +1906,10 @@ var opcodeTable = [...]opInfo{ name: "NEGB", asm: x86.ANEGB, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1847,9 +1919,10 @@ var opcodeTable = [...]opInfo{ name: "NOTQ", asm: x86.ANOTQ, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1859,9 +1932,10 @@ var opcodeTable = [...]opInfo{ name: "NOTL", asm: x86.ANOTL, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1871,9 +1945,10 @@ var opcodeTable = [...]opInfo{ name: "NOTW", asm: x86.ANOTW, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1883,9 +1958,10 @@ var opcodeTable = [...]opInfo{ name: "NOTB", asm: x86.ANOTB, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1895,9 +1971,10 @@ var opcodeTable = [...]opInfo{ name: "SBBQcarrymask", asm: x86.ASBBQ, reg: regInfo{ - inputs: []regMask{ - 8589934592, // .FLAGS + inputs: []inputInfo{ + {0, 8589934592}, // .FLAGS }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1907,9 +1984,10 @@ var opcodeTable = [...]opInfo{ name: "SBBLcarrymask", asm: x86.ASBBL, reg: regInfo{ - inputs: []regMask{ - 8589934592, // .FLAGS + inputs: []inputInfo{ + {0, 8589934592}, // .FLAGS }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1919,9 +1997,10 @@ var opcodeTable = [...]opInfo{ name: "SETEQ", asm: x86.ASETEQ, reg: regInfo{ - inputs: []regMask{ - 8589934592, // .FLAGS + inputs: []inputInfo{ + {0, 8589934592}, // .FLAGS }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1931,9 +2010,10 @@ var opcodeTable = [...]opInfo{ name: "SETNE", asm: x86.ASETNE, reg: regInfo{ - inputs: []regMask{ - 8589934592, // .FLAGS + inputs: []inputInfo{ + {0, 8589934592}, // .FLAGS }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1943,9 +2023,10 @@ var opcodeTable = [...]opInfo{ name: "SETL", asm: x86.ASETLT, reg: regInfo{ - inputs: []regMask{ - 8589934592, // .FLAGS + inputs: []inputInfo{ + {0, 8589934592}, // .FLAGS }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1955,9 +2036,10 @@ var opcodeTable = [...]opInfo{ name: "SETLE", asm: x86.ASETLE, reg: regInfo{ - inputs: []regMask{ - 8589934592, // .FLAGS + inputs: []inputInfo{ + {0, 8589934592}, // .FLAGS }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1967,9 +2049,10 @@ var opcodeTable = [...]opInfo{ name: "SETG", asm: x86.ASETGT, reg: regInfo{ - inputs: []regMask{ - 8589934592, // .FLAGS + inputs: []inputInfo{ + {0, 8589934592}, // .FLAGS }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1979,9 +2062,10 @@ var opcodeTable = [...]opInfo{ name: "SETGE", asm: x86.ASETGE, reg: regInfo{ - inputs: []regMask{ - 8589934592, // .FLAGS + inputs: []inputInfo{ + {0, 8589934592}, // .FLAGS }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -1991,9 +2075,10 @@ var opcodeTable = [...]opInfo{ name: "SETB", asm: x86.ASETCS, reg: regInfo{ - inputs: []regMask{ - 8589934592, // .FLAGS + inputs: []inputInfo{ + {0, 8589934592}, // .FLAGS }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -2003,9 +2088,10 @@ var opcodeTable = [...]opInfo{ name: "SETBE", asm: x86.ASETLS, reg: regInfo{ - inputs: []regMask{ - 8589934592, // .FLAGS + inputs: []inputInfo{ + {0, 8589934592}, // .FLAGS }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -2015,9 +2101,10 @@ var opcodeTable = [...]opInfo{ name: "SETA", asm: x86.ASETHI, reg: regInfo{ - inputs: []regMask{ - 8589934592, // .FLAGS + inputs: []inputInfo{ + {0, 8589934592}, // .FLAGS }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -2027,9 +2114,10 @@ var opcodeTable = [...]opInfo{ name: "SETAE", asm: x86.ASETCC, reg: regInfo{ - inputs: []regMask{ - 8589934592, // .FLAGS + inputs: []inputInfo{ + {0, 8589934592}, // .FLAGS }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -2039,9 +2127,10 @@ var opcodeTable = [...]opInfo{ name: "MOVBQSX", asm: x86.AMOVBQSX, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -2051,9 +2140,10 @@ var opcodeTable = [...]opInfo{ name: "MOVBQZX", asm: x86.AMOVBQZX, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -2063,9 +2153,10 @@ var opcodeTable = [...]opInfo{ name: "MOVWQSX", asm: x86.AMOVWQSX, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -2075,9 +2166,10 @@ var opcodeTable = [...]opInfo{ name: "MOVWQZX", asm: x86.AMOVWQZX, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -2087,9 +2179,10 @@ var opcodeTable = [...]opInfo{ name: "MOVLQSX", asm: x86.AMOVLQSX, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -2099,9 +2192,10 @@ var opcodeTable = [...]opInfo{ name: "MOVLQZX", asm: x86.AMOVLQZX, reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -2111,6 +2205,7 @@ var opcodeTable = [...]opInfo{ name: "MOVBconst", asm: x86.AMOVB, reg: regInfo{ + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -2120,6 +2215,7 @@ var opcodeTable = [...]opInfo{ name: "MOVWconst", asm: x86.AMOVW, reg: regInfo{ + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -2129,6 +2225,7 @@ var opcodeTable = [...]opInfo{ name: "MOVLconst", asm: x86.AMOVL, reg: regInfo{ + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -2138,6 +2235,7 @@ var opcodeTable = [...]opInfo{ name: "MOVQconst", asm: x86.AMOVQ, reg: regInfo{ + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -2146,9 +2244,10 @@ var opcodeTable = [...]opInfo{ { name: "LEAQ", reg: regInfo{ - inputs: []regMask{ - 4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB + inputs: []inputInfo{ + {0, 4295032831}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -2157,10 +2256,11 @@ var opcodeTable = [...]opInfo{ { name: "LEAQ1", reg: regInfo{ - inputs: []regMask{ - 4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + {0, 4295032831}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -2169,10 +2269,11 @@ var opcodeTable = [...]opInfo{ { name: "LEAQ2", reg: regInfo{ - inputs: []regMask{ - 4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + {0, 4295032831}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -2181,10 +2282,11 @@ var opcodeTable = [...]opInfo{ { name: "LEAQ4", reg: regInfo{ - inputs: []regMask{ - 4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + {0, 4295032831}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -2193,10 +2295,11 @@ var opcodeTable = [...]opInfo{ { name: "LEAQ8", reg: regInfo{ - inputs: []regMask{ - 4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + inputs: []inputInfo{ + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + {0, 4295032831}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -2206,9 +2309,8 @@ var opcodeTable = [...]opInfo{ name: "MOVBload", asm: x86.AMOVB, reg: regInfo{ - inputs: []regMask{ - 4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB - 0, + inputs: []inputInfo{ + {0, 4295032831}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB }, outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 @@ -2219,9 +2321,8 @@ var opcodeTable = [...]opInfo{ name: "MOVBQSXload", asm: x86.AMOVBQSX, reg: regInfo{ - inputs: []regMask{ - 4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB - 0, + inputs: []inputInfo{ + {0, 4295032831}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB }, outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 @@ -2232,9 +2333,8 @@ var opcodeTable = [...]opInfo{ name: "MOVBQZXload", asm: x86.AMOVBQZX, reg: regInfo{ - inputs: []regMask{ - 4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB - 0, + inputs: []inputInfo{ + {0, 4295032831}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB }, outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 @@ -2245,9 +2345,8 @@ var opcodeTable = [...]opInfo{ name: "MOVWload", asm: x86.AMOVW, reg: regInfo{ - inputs: []regMask{ - 4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB - 0, + inputs: []inputInfo{ + {0, 4295032831}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB }, outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 @@ -2258,9 +2357,8 @@ var opcodeTable = [...]opInfo{ name: "MOVLload", asm: x86.AMOVL, reg: regInfo{ - inputs: []regMask{ - 4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB - 0, + inputs: []inputInfo{ + {0, 4295032831}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB }, outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 @@ -2271,9 +2369,8 @@ var opcodeTable = [...]opInfo{ name: "MOVQload", asm: x86.AMOVQ, reg: regInfo{ - inputs: []regMask{ - 4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB - 0, + inputs: []inputInfo{ + {0, 4295032831}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB }, outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 @@ -2284,10 +2381,9 @@ var opcodeTable = [...]opInfo{ name: "MOVQloadidx8", asm: x86.AMOVQ, reg: regInfo{ - inputs: []regMask{ - 4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 0, + inputs: []inputInfo{ + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + {0, 4295032831}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB }, outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 @@ -2298,10 +2394,9 @@ var opcodeTable = [...]opInfo{ name: "MOVBstore", asm: x86.AMOVB, reg: regInfo{ - inputs: []regMask{ - 4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 0, + inputs: []inputInfo{ + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + {0, 4295032831}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB }, }, }, @@ -2309,10 +2404,9 @@ var opcodeTable = [...]opInfo{ name: "MOVWstore", asm: x86.AMOVW, reg: regInfo{ - inputs: []regMask{ - 4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 0, + inputs: []inputInfo{ + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + {0, 4295032831}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB }, }, }, @@ -2320,10 +2414,9 @@ var opcodeTable = [...]opInfo{ name: "MOVLstore", asm: x86.AMOVL, reg: regInfo{ - inputs: []regMask{ - 4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 0, + inputs: []inputInfo{ + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + {0, 4295032831}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB }, }, }, @@ -2331,10 +2424,9 @@ var opcodeTable = [...]opInfo{ name: "MOVQstore", asm: x86.AMOVQ, reg: regInfo{ - inputs: []regMask{ - 4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 0, + inputs: []inputInfo{ + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + {0, 4295032831}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB }, }, }, @@ -2342,54 +2434,54 @@ var opcodeTable = [...]opInfo{ name: "MOVQstoreidx8", asm: x86.AMOVQ, reg: regInfo{ - inputs: []regMask{ - 4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 0, + inputs: []inputInfo{ + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + {2, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + {0, 4295032831}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB }, }, }, { name: "MOVXzero", reg: regInfo{ - inputs: []regMask{ - 4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB - 0, + inputs: []inputInfo{ + {0, 4295032831}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB }, }, }, { name: "REPSTOSQ", reg: regInfo{ - inputs: []regMask{ - 128, // .DI - 2, // .CX + inputs: []inputInfo{ + {0, 128}, // .DI + {1, 2}, // .CX }, clobbers: 131, // .AX .CX .DI }, }, { name: "CALLstatic", - reg: regInfo{}, + reg: regInfo{ + clobbers: 12884901871, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 .FLAGS + }, }, { name: "CALLclosure", reg: regInfo{ - inputs: []regMask{ - 65535, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 - 4, // .DX - 0, + inputs: []inputInfo{ + {1, 4}, // .DX + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 12884901871, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 .FLAGS }, }, { name: "REPMOVSB", reg: regInfo{ - inputs: []regMask{ - 128, // .DI - 64, // .SI - 2, // .CX + inputs: []inputInfo{ + {0, 128}, // .DI + {1, 64}, // .SI + {2, 2}, // .CX }, clobbers: 194, // .CX .SI .DI }, @@ -2405,6 +2497,7 @@ var opcodeTable = [...]opInfo{ { name: "LoweredGetG", reg: regInfo{ + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, diff --git a/src/cmd/compile/internal/ssa/regalloc.go b/src/cmd/compile/internal/ssa/regalloc.go index b8a2f24c33..d593faf95b 100644 --- a/src/cmd/compile/internal/ssa/regalloc.go +++ b/src/cmd/compile/internal/ssa/regalloc.go @@ -2,22 +2,132 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +// Register allocation. +// +// We use a version of a linear scan register allocator. We treat the +// whole function as a single long basic block and run through +// it using a greedy register allocator. Then all merge edges +// (those targeting a block with len(Preds)>1) are processed to +// shuffle data into the place that the target of the edge expects. +// +// The greedy allocator moves values into registers just before they +// are used, spills registers only when necessary, and spills the +// value whose next use is farthest in the future. +// +// The register allocator requires that a block is not scheduled until +// at least one of its predecessors have been scheduled. The most recent +// such predecessor provides the starting register state for a block. +// +// It also requires that there are no critical edges (critical = +// comes from a block with >1 successor and goes to a block with >1 +// predecessor). This makes it easy to add fixup code on merge edges - +// the source of a merge edge has only one successor, so we can add +// fixup code to the end of that block. + +// Spilling +// +// For every value, we generate a spill immediately after the value itself. +// x = Op y z : AX +// x2 = StoreReg x +// While AX still holds x, any uses of x will use that value. When AX is needed +// for another value, we simply reuse AX. Spill code has already been generated +// so there is no code generated at "spill" time. When x is referenced +// subsequently, we issue a load to restore x to a register using x2 as +// its argument: +// x3 = Restore x2 : CX +// x3 can then be used wherever x is referenced again. +// If the spill (x2) is never used, it will be removed at the end of regalloc. +// +// Phi values are special, as always. We define two kinds of phis, those +// where the merge happens in a register (a "register" phi) and those where +// the merge happens in a stack location (a "stack" phi). +// +// A register phi must have the phi and all of its inputs allocated to the +// same register. Register phis are spilled similarly to regular ops: +// b1: y = ... : AX b2: z = ... : AX +// goto b3 goto b3 +// b3: x = phi(y, z) : AX +// x2 = StoreReg x +// +// A stack phi must have the phi and all of its inputs allocated to the same +// stack location. Stack phis start out life already spilled - each phi +// input must be a store (using StoreReg) at the end of the corresponding +// predecessor block. +// b1: y = ... : AX b2: z = ... : BX +// y2 = StoreReg y z2 = StoreReg z +// goto b3 goto b3 +// b3: x = phi(y2, z2) +// The stack allocator knows that StoreReg args of stack-allocated phis +// must be allocated to the same stack slot as the phi that uses them. +// x is now a spilled value and a restore must appear before its first use. + +// TODO + +// Use an affinity graph to mark two values which should use the +// same register. This affinity graph will be used to prefer certain +// registers for allocation. This affinity helps eliminate moves that +// are required for phi implementations and helps generate allocations +// for 2-register architectures. + +// Note: regalloc generates a not-quite-SSA output. If we have: +// +// b1: x = ... : AX +// x2 = StoreReg x +// ... AX gets reused for something else ... +// if ... goto b3 else b4 +// +// b3: x3 = LoadReg x2 : BX b4: x4 = LoadReg x2 : CX +// ... use x3 ... ... use x4 ... +// +// b2: ... use x3 ... +// +// If b3 is the primary predecessor of b2, then we use x3 in b2 and +// add a x4:CX->BX copy at the end of b4. +// But the definition of x3 doesn't dominate b2. We should really +// insert a dummy phi at the start of b2 (x5=phi(x3,x4):BX) to keep +// SSA form. For now, we ignore this problem as remaining in strict +// SSA form isn't needed after regalloc. We'll just leave the use +// of x3 not dominated by the definition of x3, and the CX->BX copy +// will have no use (so don't run deadcode after regalloc!). +// TODO: maybe we should introduce these extra phis? + package ssa -import "sort" +import ( + "fmt" + "unsafe" +) -func setloc(home []Location, v *Value, loc Location) []Location { - for v.ID >= ID(len(home)) { - home = append(home, nil) - } - home[v.ID] = loc - return home +const regDebug = false + +// regalloc performs register allocation on f. It sets f.RegAlloc +// to the resulting allocation. +func regalloc(f *Func) { + var s regAllocState + s.init(f) + s.regalloc(f) } -type register uint +type register uint8 + +const noRegister register = 255 type regMask uint64 +func (m regMask) String() string { + s := "" + for r := register(0); r < numRegs; r++ { + if m>>r&1 == 0 { + continue + } + if s != "" { + s += " " + } + s += fmt.Sprintf("r%d", r) + } + return s +} + // TODO: make arch-dependent var numRegs register = 64 @@ -84,343 +194,719 @@ func pickReg(r regMask) register { } } -// regalloc performs register allocation on f. It sets f.RegAlloc -// to the resulting allocation. -func regalloc(f *Func) { - // For now, a very simple allocator. Everything has a home - // location on the stack (TBD as a subsequent stackalloc pass). - // Values live in the home locations at basic block boundaries. - // We use a simple greedy allocator within a basic block. - home := make([]Location, f.NumValues()) +// A use is a record of a position (2*pc for value uses, odd numbers for other uses) +// and a value ID that is used at that position. +type use struct { + idx int32 + vid ID +} - addPhiCopies(f) // add copies of phi inputs in preceeding blocks +type valState struct { + regs regMask // the set of registers holding a Value (usually just one) + uses []int32 // sorted list of places where Value is used + usestorage [2]int32 + spill *Value // spilled copy of the Value + spill2 *Value // special alternate spill location used for phi resolution + spillUsed bool + spill2used bool +} - // Compute live values at the end of each block. - live := live(f) - lastUse := make([]int, f.NumValues()) +type regState struct { + v *Value // Original (preregalloc) Value stored in this register. + c *Value // A Value equal to v which is currently in register. Might be v or a copy of it. + // If a register is unused, v==c==nil +} - var oldSched []*Value +type regAllocState struct { + f *Func + + // for each block, its primary predecessor. + // A predecessor of b is primary if it is the closest + // predecessor that appears before b in the layout order. + // We record the index in the Preds list where the primary predecessor sits. + primary []int32 + + // live values on each edge. live[b.ID][idx] is a list of value IDs + // which are live on b's idx'th successor edge. + live [][][]ID + + // current state of each (preregalloc) Value + values []valState + + // current state of each register + regs []regState + + // registers that contain values which can't be kicked out + nospill regMask + + // mask of registers currently in use + used regMask + + // An ordered list (by idx) of all uses in the function + uses []use - // Hack to find sp and sb Values and assign them a register. - // TODO: make not so hacky; update the tighten pass when this is done - var sp, sb *Value - for _, v := range f.Entry.Values { - switch v.Op { - case OpSP: - sp = v - home = setloc(home, v, ®isters[4]) // TODO: arch-dependent - case OpSB: - sb = v - home = setloc(home, v, ®isters[32]) // TODO: arch-dependent + // Home locations (registers) for Values + home []Location + + // current block we're working on + curBlock *Block +} + +// freeReg frees up register r. Any current user of r is kicked out. +func (s *regAllocState) freeReg(r register) { + v := s.regs[r].v + if v == nil { + s.f.Fatalf("tried to free an already free register %d\n", r) + } + + // Mark r as unused. + if regDebug { + fmt.Printf("freeReg %d (dump %s/%s)\n", r, v, s.regs[r].c) + } + s.regs[r] = regState{} + s.values[v.ID].regs &^= regMask(1) << r + s.used &^= regMask(1) << r +} + +// freeRegs frees up all registers listed in m. +func (s *regAllocState) freeRegs(m regMask) { + for m&s.used != 0 { + s.freeReg(pickReg(m & s.used)) + } +} + +func (s *regAllocState) setHome(v *Value, r register) { + // Remember assignment. + for int(v.ID) >= len(s.home) { + s.home = append(s.home, nil) + s.home = s.home[:cap(s.home)] + } + s.home[v.ID] = ®isters[r] +} +func (s *regAllocState) getHome(v *Value) register { + if int(v.ID) >= len(s.home) || s.home[v.ID] == nil { + return noRegister + } + return register(s.home[v.ID].(*Register).Num) +} + +// assignReg assigns register r to hold c, a copy of v. +// r must be unused. +func (s *regAllocState) assignReg(r register, v *Value, c *Value) { + if regDebug { + fmt.Printf("assignReg %d %s/%s\n", r, v, c) + } + if s.regs[r].v != nil { + s.f.Fatalf("tried to assign register %d to %s/%s but it is already used by %s", r, v, c, s.regs[r].v) + } + + // Update state. + s.regs[r] = regState{v, c} + s.values[v.ID].regs |= regMask(1) << r + s.used |= regMask(1) << r + s.setHome(c, r) +} + +// allocReg picks an unused register from regmask. If there is no unused register, +// a Value will be kicked out of a register to make room. +func (s *regAllocState) allocReg(mask regMask) register { + // Pick a register to use. + mask &^= s.nospill + if mask == 0 { + s.f.Fatalf("no register available") + } + + var r register + if unused := mask & ^s.used; unused != 0 { + // Pick an unused register. + return pickReg(unused) + // TODO: use affinity graph to pick a good register + } + // Pick a value to spill. Spill the value with the + // farthest-in-the-future use. + // TODO: Prefer registers with already spilled Values? + // TODO: Modify preference using affinity graph. + mask &^= 1<<4 | 1<<32 // don't spill SP or SB + maxuse := int32(-1) + for t := register(0); t < numRegs; t++ { + if mask>>t&1 == 0 { + continue + } + v := s.regs[t].v + if len(s.values[v.ID].uses) == 0 { + // This can happen when fixing up merge blocks at the end. + // We've already run through the use lists so they are empty. + // Any register would be ok at this point. + r = t + maxuse = 0 + break } + if n := s.values[v.ID].uses[0]; n > maxuse { + r = t + maxuse = n + } + } + if maxuse == -1 { + s.f.Unimplementedf("couldn't find register to spill") + } + s.freeReg(r) + return r +} + +// allocValToReg allocates v to a register selected from regMask and +// returns the register copy of v. Any previous user is kicked out and spilled +// (if necessary). Load code is added at the current pc. If nospill is set the +// allocated register is marked nospill so the assignment cannot be +// undone until the caller allows it by clearing nospill. Returns a +// *Value which is either v or a copy of v allocated to the chosen register. +func (s *regAllocState) allocValToReg(v *Value, mask regMask, nospill bool) *Value { + vi := &s.values[v.ID] + + // Check if v is already in a requested register. + if mask&vi.regs != 0 { + r := pickReg(mask & vi.regs) + if s.regs[r].v != v || s.regs[r].c == nil { + panic("bad register state") + } + if nospill { + s.nospill |= regMask(1) << r + } + return s.regs[r].c + } + + // SP and SB are allocated specially. No regular value should + // be allocated to them. + mask &^= 1<<4 | 1<<32 + + // Allocate a register. + r := s.allocReg(mask) + + // Allocate v to the new register. + var c *Value + if vi.regs != 0 { + // Copy from a register that v is already in. + r2 := pickReg(vi.regs) + if s.regs[r2].v != v { + panic("bad register state") + } + c = s.curBlock.NewValue1(v.Line, OpCopy, v.Type, s.regs[r2].c) + } else { + // Load v from its spill location. + // TODO: rematerialize if we can. + if vi.spill2 != nil { + c = s.curBlock.NewValue1(v.Line, OpLoadReg, v.Type, vi.spill2) + vi.spill2used = true + } else { + c = s.curBlock.NewValue1(v.Line, OpLoadReg, v.Type, vi.spill) + vi.spillUsed = true + } + if v.Type.IsFlags() { + v.Unimplementedf("spill of flags not implemented yet") + } + } + s.assignReg(r, v, c) + if nospill { + s.nospill |= regMask(1) << r + } + return c +} + +func (s *regAllocState) init(f *Func) { + if numRegs > noRegister || numRegs > register(unsafe.Sizeof(regMask(0))*8) { + panic("too many registers") + } + + s.f = f + s.regs = make([]regState, numRegs) + s.values = make([]valState, f.NumValues()) + for i := range s.values { + s.values[i].uses = s.values[i].usestorage[:0] } + s.live = f.live() - // Register allocate each block separately. All live values will live - // in home locations (stack slots) between blocks. + // Compute block order. This array allows us to distinguish forward edges + // from backward edges and compute how far they go. + blockOrder := make([]int32, f.NumBlocks()) + for i, b := range f.Blocks { + blockOrder[b.ID] = int32(i) + } + + // Compute primary predecessors. + s.primary = make([]int32, f.NumBlocks()) for _, b := range f.Blocks { + best := -1 + for i, p := range b.Preds { + if blockOrder[p.ID] >= blockOrder[b.ID] { + continue // backward edge + } + if best == -1 || blockOrder[p.ID] > blockOrder[b.Preds[best].ID] { + best = i + } + } + s.primary[b.ID] = int32(best) + } - // Compute the index of the last use of each Value in the Block. - // Scheduling has already happened, so Values are totally ordered. - // lastUse[x] = max(i) where b.Value[i] uses Value x. - for i, v := range b.Values { - lastUse[v.ID] = -1 - for _, w := range v.Args { - // could condition this store on w.Block == b, but no need - lastUse[w.ID] = i + // Compute uses. We assign a PC to each Value in the program, in f.Blocks + // and then b.Values order. Uses are recorded using this numbering. + // Uses by Values are recorded as 2*PC. Special uses (block control values, + // pseudo-uses for backedges) are recorded as 2*(last PC in block)+1. + var pc int32 + for _, b := range f.Blocks { + // uses in regular Values + for _, v := range b.Values { + for _, a := range v.Args { + s.values[a.ID].uses = append(s.values[a.ID].uses, pc*2) + s.uses = append(s.uses, use{pc * 2, a.ID}) } + pc++ } - // Values which are live at block exit have a lastUse of len(b.Values). + // use as a block control value + endIdx := pc*2 - 1 if b.Control != nil { - lastUse[b.Control.ID] = len(b.Values) + s.values[b.Control.ID].uses = append(s.values[b.Control.ID].uses, endIdx) + s.uses = append(s.uses, use{endIdx, b.Control.ID}) } - // Values live after block exit have a lastUse of len(b.Values)+1. - for _, vid := range live[b.ID] { - lastUse[vid] = len(b.Values) + 1 + // uses by backedges + // Backedges are treated as uses so that the uses span the entire live + // range of the value. + for i, c := range b.Succs { + if blockOrder[c.ID] > blockOrder[b.ID] { + continue // forward edge + } + for _, vid := range s.live[b.ID][i] { + s.values[vid].uses = append(s.values[vid].uses, endIdx) + s.uses = append(s.uses, use{endIdx, vid}) + } } + } + if pc*2 < 0 { + f.Fatalf("pc too large: function too big") + } +} - // For each register, store which value it contains - type regInfo struct { - v *Value // stack-homed original value (or nil if empty) - c *Value // the register copy of v - dirty bool // if the stack-homed copy is out of date +// clearUses drops any uses <= useIdx. Any values which have no future +// uses are dropped from registers. +func (s *regAllocState) clearUses(useIdx int32) { + for len(s.uses) > 0 && s.uses[0].idx <= useIdx { + idx := s.uses[0].idx + vid := s.uses[0].vid + s.uses = s.uses[1:] + + vi := &s.values[vid] + if vi.uses[0] != idx { + s.f.Fatalf("use mismatch for v%d\n", vid) } - regs := make([]regInfo, numRegs) + vi.uses = vi.uses[1:] + if len(vi.uses) != 0 { + continue + } + // Value is dead, free all registers that hold it (except SP & SB). + s.freeRegs(vi.regs &^ (1<<4 | 1<<32)) + } +} - // TODO: hack: initialize fixed registers - regs[4] = regInfo{sp, sp, false} - regs[32] = regInfo{sb, sb, false} +// Sets the state of the registers to that encoded in state. +func (s *regAllocState) setState(state []regState) { + s.freeRegs(s.used) + for r, x := range state { + if x.c == nil { + continue + } + s.assignReg(register(r), x.v, x.c) + } +} - var used regMask // has a 1 for each non-nil entry in regs - var dirty regMask // has a 1 for each dirty entry in regs +func (s *regAllocState) regalloc(f *Func) { + liveset := newSparseSet(f.NumValues()) + argset := newSparseSet(f.NumValues()) + var oldSched []*Value + var phis []*Value + var stackPhis []*Value + var regPhis []*Value + + if f.Entry != f.Blocks[0] { + f.Fatalf("entry block must be first") + } + + var phiRegs []register + + // For each merge block, we record the starting register state (after phi ops) + // for that merge block. Indexed by blockid/regnum. + startRegs := make([][]*Value, f.NumBlocks()) + // end state of registers for each block, idexed by blockid/regnum. + endRegs := make([][]regState, f.NumBlocks()) + var pc int32 + for _, b := range f.Blocks { + s.curBlock = b - oldSched = append(oldSched[:0], b.Values...) + // Make a copy of the block schedule so we can generate a new one in place. + // We make a separate copy for phis and regular values. + nphi := 0 + for _, v := range b.Values { + if v.Op != OpPhi { + break + } + nphi++ + } + phis = append(phis[:0], b.Values[:nphi]...) + oldSched = append(oldSched[:0], b.Values[nphi:]...) b.Values = b.Values[:0] - for idx, v := range oldSched { - // For each instruction, do: - // set up inputs to v in registers - // pick output register - // run insn - // mark output register as dirty - // Note that v represents the Value at "home" (on the stack), and c - // is its register equivalent. There are two ways to establish c: - // - use of v. c will be a load from v's home. - // - definition of v. c will be identical to v but will live in - // a register. v will be modified into a spill of c. - regspec := opcodeTable[v.Op].reg - if v.Op == OpCopy { - // TODO: make this less of a hack - regspec = opcodeTable[OpAMD64ADDQconst].reg + // Initialize start state of block. + if b == f.Entry { + // Regalloc state is empty to start. + if nphi > 0 { + f.Fatalf("phis in entry block") } - inputs := regspec.inputs - outputs := regspec.outputs - if len(inputs) == 0 && len(outputs) == 0 { - // No register allocation required (or none specified yet) + } else if len(b.Preds) == 1 { + // Start regalloc state with the end state of the previous block. + s.setState(endRegs[b.Preds[0].ID]) + if nphi > 0 { + f.Fatalf("phis in single-predecessor block") + } + } else { + // This is the complicated case. We have more than one predecessor, + // which means we may have Phi ops. + + // Copy phi ops into new schedule. + b.Values = append(b.Values, phis...) + + // Start with the final register state of the primary predecessor + idx := s.primary[b.ID] + if idx < 0 { + f.Fatalf("block with no primary predecessor %s", b) + } + p := b.Preds[idx] + s.setState(endRegs[p.ID]) + + // Drop anything not live on the c->b edge. + var idx2 int + for idx2 = 0; idx2 < len(p.Succs); idx2++ { + if p.Succs[idx2] == b { + break + } + } + liveset.clear() + liveset.addAll(s.live[p.ID][idx2]) + for r := register(0); r < numRegs; r++ { + v := s.regs[r].v + if v == nil { + continue + } + if !liveset.contains(v.ID) { + s.freeReg(r) + } + } + + // Decide on registers for phi ops. Use the registers determined + // by the primary predecessor if we can. + // TODO: pick best of (already processed) predecessors? + // Majority vote? Deepest nesting level? + phiRegs = phiRegs[:0] + var used regMask + for _, v := range phis { + if v.Type.IsMemory() { + phiRegs = append(phiRegs, noRegister) + continue + } + regs := s.values[v.Args[idx].ID].regs + m := regs &^ used + var r register + if m != 0 { + r = pickReg(m) + used |= regMask(1) << r + } else { + r = noRegister + } + phiRegs = append(phiRegs, r) + } + // Change register user from phi input to phi. Add phi spill code. + for i, v := range phis { + if v.Type.IsMemory() { + continue + } + r := phiRegs[i] + if r == noRegister { + // stack-based phi + // Spills will be inserted in all the predecessors below. + s.values[v.ID].spill = v // v starts life spilled + s.values[v.ID].spillUsed = true // use is guaranteed + continue + } + // register-based phi + // Transfer ownership of register from input arg to phi. + s.freeReg(r) + s.assignReg(r, v, v) + // Spill the phi in case we need to restore it later. + spill := b.NewValue1(v.Line, OpStoreReg, v.Type, v) + s.values[v.ID].spill = spill + s.values[v.ID].spillUsed = false + } + + // Save the starting state for use by incoming edges below. + startRegs[b.ID] = make([]*Value, numRegs) + for r := register(0); r < numRegs; r++ { + startRegs[b.ID][r] = s.regs[r].v + } + } + + // Process all the non-phi values. + pc += int32(nphi) + for _, v := range oldSched { + if v.Op == OpPhi { + f.Fatalf("phi %s not at start of block", v) + } + if v.Op == OpSP { + s.assignReg(4, v, v) // TODO: arch-dependent b.Values = append(b.Values, v) + pc++ continue } - if v.Op == OpCopy && v.Type.IsMemory() { + if v.Op == OpSB { + s.assignReg(32, v, v) // TODO: arch-dependent b.Values = append(b.Values, v) + pc++ continue } - - // Compute a good input ordering. Start with the most constrained input. - order := make([]intPair, len(inputs)) - for i, input := range inputs { - order[i] = intPair{countRegs(input), i} + s.clearUses(pc*2 - 1) + regspec := opcodeTable[v.Op].reg + if regDebug { + fmt.Printf("%d: working on %s %s %v\n", pc, v, v.LongString(), regspec) + } + if len(regspec.inputs) == 0 && len(regspec.outputs) == 0 { + // No register allocation required (or none specified yet) + s.freeRegs(regspec.clobbers) + b.Values = append(b.Values, v) + pc++ + continue } - sort.Sort(byKey(order)) - // nospill contains registers that we can't spill because - // we already set them up for use by the current instruction. - var nospill regMask - nospill |= 0x100000010 // SP & SB can't be spilled (TODO: arch-specific) + // TODO: If value is rematerializeable, don't issue it here. + // Instead, rely on argument loading code to put it in a register when needed. - // Move inputs into registers - for _, o := range order { - w := v.Args[o.val] - mask := inputs[o.val] - if mask == 0 { - // Input doesn't need a register - continue - } - // TODO: 2-address overwrite instructions + // Move arguments to registers + for _, i := range regspec.inputs { + a := v.Args[i.idx] + v.Args[i.idx] = s.allocValToReg(a, i.regs, true) + } - // Find registers that w is already in - var wreg regMask - for r := register(0); r < numRegs; r++ { - if regs[r].v == w { - wreg |= regMask(1) << r - } - } + // Now that all args are in regs, we're ready to issue the value itself. + // Before we pick a register for the value, allow input registers + // to be deallocated. We do this here so that the output can use the + // same register as a dying input. + s.nospill = 0 + s.clearUses(pc * 2) + + // Dump any registers which will be clobbered + s.freeRegs(regspec.clobbers) + + // Pick register for output. + var r register + var mask regMask + if len(regspec.outputs) > 0 { + mask = regspec.outputs[0] + } + if mask != 0 { + r = s.allocReg(mask) + s.assignReg(r, v, v) + } - var r register - if mask&wreg != 0 { - // w is already in an allowed register. We're done. - r = pickReg(mask & wreg) - } else { - // Pick a register for w - // Priorities (in order) - // - an unused register - // - a clean register - // - a dirty register - // TODO: for used registers, pick the one whose next use is the - // farthest in the future. - mask &^= nospill - if mask & ^dirty != 0 { - mask &^= dirty - } - if mask & ^used != 0 { - mask &^= used - } - r = pickReg(mask) - - // Kick out whomever is using this register. - if regs[r].v != nil { - x := regs[r].v - c := regs[r].c - if regs[r].dirty && lastUse[x.ID] >= idx { - // Write x back to home. Its value is currently held in c. - x.Op = OpStoreReg - x.Aux = nil - x.resetArgs() - x.AddArg(c) - b.Values = append(b.Values, x) - regs[r].dirty = false - dirty &^= regMask(1) << r - } - regs[r].v = nil - regs[r].c = nil - used &^= regMask(1) << r - } + // Issue the Value itself. + b.Values = append(b.Values, v) - // Load w into this register - var c *Value - if len(w.Args) == 0 { - // Materialize w - if w.Op == OpSB { - c = w - } else if w.Op == OpSP { - c = b.NewValue1(w.Line, OpCopy, w.Type, w) - } else { - c = b.NewValue0IA(w.Line, w.Op, w.Type, w.AuxInt, w.Aux) - } - } else if len(w.Args) == 1 && (w.Args[0].Op == OpSP || w.Args[0].Op == OpSB) { - // Materialize offsets from SP/SB - c = b.NewValue1IA(w.Line, w.Op, w.Type, w.AuxInt, w.Aux, w.Args[0]) - } else if wreg != 0 { - // Copy from another register. - // Typically just an optimization, but this is - // required if w is dirty. - s := pickReg(wreg) - // inv: s != r - c = b.NewValue1(w.Line, OpCopy, w.Type, regs[s].c) - } else { - // Load from home location - c = b.NewValue1(w.Line, OpLoadReg, w.Type, w) - } - home = setloc(home, c, ®isters[r]) - // Remember what we did - regs[r].v = w - regs[r].c = c - regs[r].dirty = false - used |= regMask(1) << r - } + // Issue a spill for this value. We issue spills unconditionally, + // then at the end of regalloc delete the ones we never use. + spill := b.NewValue1(v.Line, OpStoreReg, v.Type, v) + s.values[v.ID].spill = spill + s.values[v.ID].spillUsed = false - // Replace w with its in-register copy. - v.SetArg(o.val, regs[r].c) + // Increment pc for next Value. + pc++ + } - // Remember not to undo this register assignment until after - // the instruction is issued. - nospill |= regMask(1) << r - } + // Load control value into reg + if b.Control != nil && !b.Control.Type.IsMemory() { + // TODO: regspec for block control values, instead of using + // register set from the control op's output. + s.allocValToReg(b.Control, opcodeTable[b.Control.Op].reg.outputs[0], false) + } - // TODO: do any clobbering + // Record endRegs + endRegs[b.ID] = make([]regState, numRegs) + copy(endRegs[b.ID], s.regs) - // pick a register for v itself. - if len(outputs) > 1 { - panic("can't do multi-output yet") + // Allow control Values and Values live only on backedges to be dropped. + s.clearUses(pc*2 - 1) + } + + // Process merge block input edges. They are the tricky ones. + dst := make([]*Value, numRegs) + for _, b := range f.Blocks { + if len(b.Preds) <= 1 { + continue + } + for i, p := range b.Preds { + if regDebug { + fmt.Printf("processing %s->%s\n", p, b) } - if len(outputs) == 0 || outputs[0] == 0 { - // output doesn't need a register - b.Values = append(b.Values, v) - } else { - mask := outputs[0] - if mask & ^dirty != 0 { - mask &^= dirty + + // Find phis, separate them into stack & register classes. + stackPhis = stackPhis[:0] + regPhis = regPhis[:0] + for _, v := range b.Values { + if v.Op != OpPhi { + break } - if mask & ^used != 0 { - mask &^= used + if v.Type.IsMemory() { + continue } - r := pickReg(mask) - - // Kick out whomever is using this register. - if regs[r].v != nil { - x := regs[r].v - c := regs[r].c - if regs[r].dirty && lastUse[x.ID] >= idx { - // Write x back to home. Its value is currently held in c. - x.Op = OpStoreReg - x.Aux = nil - x.resetArgs() - x.AddArg(c) - b.Values = append(b.Values, x) - regs[r].dirty = false - dirty &^= regMask(1) << r - } - regs[r].v = nil - regs[r].c = nil - used &^= regMask(1) << r + if s.getHome(v) != noRegister { + regPhis = append(regPhis, v) + } else { + stackPhis = append(stackPhis, v) } - - // Reissue v with new op, with r as its home. - c := b.NewValue0IA(v.Line, v.Op, v.Type, v.AuxInt, v.Aux) - c.AddArgs(v.Args...) - home = setloc(home, c, ®isters[r]) - - // Remember what we did - regs[r].v = v - regs[r].c = c - regs[r].dirty = true - used |= regMask(1) << r - dirty |= regMask(1) << r } - } - // If the block ends in a call, we must put the call after the spill code. - var call *Value - if b.Kind == BlockCall { - call = b.Control - if call != b.Values[len(b.Values)-1] { - b.Fatalf("call not at end of block %v %v", b, call) + // Start with the state that exists at the end of the + // predecessor block. We'll be adding instructions here + // to shuffle registers & stack phis into the right spot. + s.setState(endRegs[p.ID]) + s.curBlock = p + + // Handle stack-based phi ops first. We need to handle them + // first because we need a register with which to copy them. + + // We must be careful not to overwrite any stack phis which are + // themselves args of other phis. For example: + // v1 = phi(v2, v3) : 8(SP) + // v2 = phi(v4, v5) : 16(SP) + // Here we must not write v2 until v2 is read and written to v1. + // The situation could be even more complicated, with cycles, etc. + // So in the interest of being simple, we find all the phis which + // are arguments of other phis and copy their values to a temporary + // location first. This temporary location is called "spill2" and + // represents a higher-priority but temporary spill location for the value. + // Note this is not a problem for register-based phis because + // if needed we will use the spilled location as the source, and + // the spill location is not clobbered by the code generated here. + argset.clear() + for _, v := range stackPhis { + argset.add(v.Args[i].ID) } - b.Values = b.Values[:len(b.Values)-1] - // TODO: do this for all control types? - } - - // at the end of the block, spill any remaining dirty, live values - for r := register(0); r < numRegs; r++ { - if !regs[r].dirty { - continue + for _, v := range regPhis { + argset.add(v.Args[i].ID) } - v := regs[r].v - c := regs[r].c - if lastUse[v.ID] <= len(oldSched) { - if v == v.Block.Control { - // link control value to register version - v.Block.Control = c + for _, v := range stackPhis { + if !argset.contains(v.ID) { + continue } - continue // not live after block + // This stack-based phi is the argument of some other + // phi in this block. We must make a copy of its + // value so that we don't clobber it prematurely. + c := s.allocValToReg(v, s.values[v.ID].regs|1<<0, false) + d := p.NewValue1(v.Line, OpStoreReg, v.Type, c) + s.values[v.ID].spill2 = d } - // change v to be a copy of c - v.Op = OpStoreReg - v.Aux = nil - v.resetArgs() - v.AddArg(c) - b.Values = append(b.Values, v) + // Assign to stack-based phis. We do stack phis first because + // we might need a register to do the assignment. + for _, v := range stackPhis { + // Load phi arg into a register, then store it with a StoreReg. + // If already in a register, use that. If not, use register 0. + // TODO: choose a better default register (set of reg by type?). + c := s.allocValToReg(v.Args[i], s.values[v.Args[i].ID].regs|1<<0, false) + v.Args[i] = p.NewValue1(v.Line, OpStoreReg, v.Type, c) + } + // Figure out what value goes in each register. + for r := register(0); r < numRegs; r++ { + dst[r] = startRegs[b.ID][r] + } + // Handle register-based phi ops. + for _, v := range regPhis { + r := s.getHome(v) + if dst[r] != v { + f.Fatalf("dst not right") + } + v.Args[i] = s.allocValToReg(v.Args[i], regMask(1)<CX and CX->DX, do the latter first. Now if we do the + // former first then the latter must be a restore instead of a register move. + + // Erase any spills we never used + for i := range s.values { + vi := s.values[i] + if vi.spillUsed { + continue + } + spill := vi.spill + if spill == nil { + // Constants, SP, SB, ... + continue } + spill.Op = OpInvalid + spill.Type = TypeInvalid + spill.resetArgs() } - f.RegAlloc = home - deadcode(f) // remove values that had all of their uses rematerialized. TODO: separate pass? -} - -// addPhiCopies adds copies of phi inputs in the blocks -// immediately preceding the phi's block. -func addPhiCopies(f *Func) { for _, b := range f.Blocks { - phis := true // all phis should appear first; confirm that as we go + i := 0 for _, v := range b.Values { - switch { - case v.Op == OpPhi && !phis: - f.Fatalf("phi var %v not at beginning of block %v:\n%s\n", v, v.Block, f) - break - case v.Op != OpPhi: - phis = false + if v.Op == OpInvalid { continue - case v.Type.IsMemory(): // TODO: only "regallocable" types - continue - } - for i, w := range v.Args { - c := b.Preds[i] - cpy := c.NewValue1(w.Line, OpCopy, v.Type, w) - v.Args[i] = cpy } + b.Values[i] = v + i++ } + b.Values = b.Values[:i] + // TODO: zero b.Values[i:], recycle Values + // Not important now because this is the last phase that manipulates Values } + + // Set final regalloc result. + f.RegAlloc = s.home } -// live returns a map from block ID to a list of value IDs live at the end of that block +// live returns a map from block ID and successor edge index to a list +// of value IDs live on that edge. // TODO: this could be quadratic if lots of variables are live across lots of // basic blocks. Figure out a way to make this function (or, more precisely, the user // of this function) require only linear size & time. -func live(f *Func) [][]ID { - live := make([][]ID, f.NumBlocks()) +func (f *Func) live() [][][]ID { + live := make([][][]ID, f.NumBlocks()) + for _, b := range f.Blocks { + live[b.ID] = make([][]ID, len(b.Succs)) + } var phis []*Value s := newSparseSet(f.NumValues()) @@ -445,7 +931,11 @@ func live(f *Func) [][]ID { for _, b := range po { // Start with known live values at the end of the block s.clear() - s.addAll(live[b.ID]) + for i := 0; i < len(b.Succs); i++ { + s.addAll(live[b.ID][i]) + } + + // Mark control value as live if b.Control != nil { s.add(b.Control.ID) } @@ -467,19 +957,24 @@ func live(f *Func) [][]ID { // for each predecessor of b, expand its list of live-at-end values // invariant: s contains the values live at the start of b (excluding phi inputs) for i, p := range b.Preds { + // Find index of b in p's successors. + var j int + for j = 0; j < len(p.Succs); j++ { + if p.Succs[j] == b { + break + } + } t.clear() - t.addAll(live[p.ID]) + t.addAll(live[p.ID][j]) t.addAll(s.contents()) for _, v := range phis { t.add(v.Args[i].ID) } - if t.size() == len(live[p.ID]) { + if t.size() == len(live[p.ID][j]) { continue } // grow p's live set - c := make([]ID, t.size()) - copy(c, t.contents()) - live[p.ID] = c + live[p.ID][j] = append(live[p.ID][j][:0], t.contents()...) changed = true } } @@ -490,13 +985,3 @@ func live(f *Func) [][]ID { } return live } - -// for sorting a pair of integers by key -type intPair struct { - key, val int -} -type byKey []intPair - -func (a byKey) Len() int { return len(a) } -func (a byKey) Swap(i, j int) { a[i], a[j] = a[j], a[i] } -func (a byKey) Less(i, j int) bool { return a[i].key < a[j].key } diff --git a/src/cmd/compile/internal/ssa/stackalloc.go b/src/cmd/compile/internal/ssa/stackalloc.go index 064b84a804..626fb8f369 100644 --- a/src/cmd/compile/internal/ssa/stackalloc.go +++ b/src/cmd/compile/internal/ssa/stackalloc.go @@ -4,6 +4,15 @@ package ssa +// setloc sets the home location of v to loc. +func setloc(home []Location, v *Value, loc Location) []Location { + for v.ID >= ID(len(home)) { + home = append(home, nil) + } + home[v.ID] = loc + return home +} + // stackalloc allocates storage in the stack frame for // all Values that did not get a register. func stackalloc(f *Func) { @@ -26,7 +35,7 @@ func stackalloc(f *Func) { // so stackmap is smaller. // Assign stack locations to phis first, because we - // must also assign the same locations to the phi copies + // must also assign the same locations to the phi stores // introduced during regalloc. for _, b := range f.Blocks { for _, v := range b.Values { @@ -36,12 +45,19 @@ func stackalloc(f *Func) { if v.Type.IsMemory() { // TODO: only "regallocable" types continue } + if int(v.ID) < len(home) && home[v.ID] != nil { + continue // register-based phi + } + // stack-based phi n = align(n, v.Type.Alignment()) f.Logf("stackalloc: %d-%d for %v\n", n, n+v.Type.Size(), v) loc := &LocalSlot{n} n += v.Type.Size() home = setloc(home, v, loc) for _, w := range v.Args { + if w.Op != OpStoreReg { + f.Fatalf("stack-based phi must have StoreReg args") + } home = setloc(home, w, loc) } } diff --git a/src/cmd/compile/internal/ssa/tighten.go b/src/cmd/compile/internal/ssa/tighten.go index 02b1f701f5..a43218095e 100644 --- a/src/cmd/compile/internal/ssa/tighten.go +++ b/src/cmd/compile/internal/ssa/tighten.go @@ -57,13 +57,6 @@ func tighten(f *Func) { if v.Op == OpPhi { continue } - if v.Op == OpSB || v.Op == OpSP { - // regalloc expects OpSP and OpSB values to be in the entry block, - // so don't move them. - // TODO: Handle this more gracefully in regalloc and - // remove this restriction. - continue - } if uses[v.ID] == 1 && !phi[v.ID] && home[v.ID] != b && len(v.Args) < 2 { // v is used in exactly one block, and it is not b. // Furthermore, it takes at most one input, diff --git a/src/cmd/compile/internal/ssa/value.go b/src/cmd/compile/internal/ssa/value.go index e6e23d5270..286edc0cda 100644 --- a/src/cmd/compile/internal/ssa/value.go +++ b/src/cmd/compile/internal/ssa/value.go @@ -11,7 +11,7 @@ import "fmt" // if they preserve the value of the Value (e.g. changing a (mul 2 x) to an (add x x)). type Value struct { // A unique identifier for the value. For performance we allocate these IDs - // densely starting at 0. There is no guarantee that there won't be occasional holes, though. + // densely starting at 1. There is no guarantee that there won't be occasional holes, though. ID ID // The operation that computes this value. See op.go. @@ -69,7 +69,7 @@ func (v *Value) LongString() string { s += fmt.Sprintf(" %v", a) } r := v.Block.Func.RegAlloc - if r != nil && r[v.ID] != nil { + if int(v.ID) < len(r) && r[v.ID] != nil { s += " : " + r[v.ID].Name() } return s -- cgit v1.3 From a45f2d8f2898d23804de473841d42670fcdda5dc Mon Sep 17 00:00:00 2001 From: Todd Neal Date: Mon, 17 Aug 2015 17:46:06 -0500 Subject: [dev.ssa] cmd/compile/internal/ssa: implement ODIV Implement integer division for non-consts. Change-Id: If40cbde20e5f0ebb9993064def7be468e4eca076 Reviewed-on: https://go-review.googlesource.com/13644 Reviewed-by: Keith Randall --- src/cmd/compile/internal/gc/ssa.go | 80 +++ src/cmd/compile/internal/gc/ssa_test.go | 3 + .../internal/gc/testdata/arithBoundary_ssa.go | 640 +++++++++++++++++++++ src/cmd/compile/internal/ssa/TODO | 3 +- src/cmd/compile/internal/ssa/gen/AMD64.rules | 9 + src/cmd/compile/internal/ssa/gen/AMD64Ops.go | 12 + src/cmd/compile/internal/ssa/gen/genericOps.go | 9 + src/cmd/compile/internal/ssa/opGen.go | 130 +++++ src/cmd/compile/internal/ssa/rewriteAMD64.go | 156 +++++ 9 files changed, 1041 insertions(+), 1 deletion(-) create mode 100644 src/cmd/compile/internal/gc/testdata/arithBoundary_ssa.go (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index ef90ed40e7..90b29b9b09 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -779,6 +779,15 @@ var opToSSA = map[opAndType]ssa.Op{ opAndType{ODIV, TFLOAT32}: ssa.OpDiv32F, opAndType{ODIV, TFLOAT64}: ssa.OpDiv64F, + opAndType{ODIV, TINT8}: ssa.OpDiv8, + opAndType{ODIV, TUINT8}: ssa.OpDiv8u, + opAndType{ODIV, TINT16}: ssa.OpDiv16, + opAndType{ODIV, TUINT16}: ssa.OpDiv16u, + opAndType{ODIV, TINT32}: ssa.OpDiv32, + opAndType{ODIV, TUINT32}: ssa.OpDiv32u, + opAndType{ODIV, TINT64}: ssa.OpDiv64, + opAndType{ODIV, TUINT64}: ssa.OpDiv64u, + opAndType{OAND, TINT8}: ssa.OpAnd8, opAndType{OAND, TUINT8}: ssa.OpAnd8, opAndType{OAND, TINT16}: ssa.OpAnd16, @@ -2019,6 +2028,77 @@ func genValue(v *ssa.Value) { } opregreg(v.Op.Asm(), r, y) + case ssa.OpAMD64DIVQ, ssa.OpAMD64DIVL, ssa.OpAMD64DIVW, + ssa.OpAMD64DIVQU, ssa.OpAMD64DIVLU, ssa.OpAMD64DIVWU: + + // Arg[0] is already in AX as it's the only register we allow + // and AX is the only output + x := regnum(v.Args[1]) + + // CPU faults upon signed overflow, which occurs when most + // negative int is divided by -1. So we check for division + // by -1 and negate the input. + var j *obj.Prog + if v.Op == ssa.OpAMD64DIVQ || v.Op == ssa.OpAMD64DIVL || + v.Op == ssa.OpAMD64DIVW { + + var c *obj.Prog + switch v.Op { + case ssa.OpAMD64DIVQ: + c = Prog(x86.ACMPQ) + case ssa.OpAMD64DIVL: + c = Prog(x86.ACMPL) + case ssa.OpAMD64DIVW: + c = Prog(x86.ACMPW) + } + c.From.Type = obj.TYPE_REG + c.From.Reg = x + c.To.Type = obj.TYPE_CONST + c.To.Offset = -1 + + j = Prog(x86.AJEQ) + j.To.Type = obj.TYPE_BRANCH + + } + + // dividend is ax, so we sign extend to + // dx:ax for DIV input + switch v.Op { + case ssa.OpAMD64DIVQU: + fallthrough + case ssa.OpAMD64DIVLU: + fallthrough + case ssa.OpAMD64DIVWU: + c := Prog(x86.AXORQ) + c.From.Type = obj.TYPE_REG + c.From.Reg = x86.REG_DX + c.To.Type = obj.TYPE_REG + c.To.Reg = x86.REG_DX + case ssa.OpAMD64DIVQ: + Prog(x86.ACQO) + case ssa.OpAMD64DIVL: + Prog(x86.ACDQ) + case ssa.OpAMD64DIVW: + Prog(x86.ACWD) + } + + p := Prog(v.Op.Asm()) + p.From.Type = obj.TYPE_REG + p.From.Reg = x + + // signed division, rest of the check for -1 case + if j != nil { + j2 := Prog(obj.AJMP) + j2.To.Type = obj.TYPE_BRANCH + + n := Prog(x86.ANEGQ) + n.To.Type = obj.TYPE_REG + n.To.Reg = x86.REG_AX + + j.To.Val = n + j2.To.Val = Pc + } + case ssa.OpAMD64SHLQ, ssa.OpAMD64SHLL, ssa.OpAMD64SHLW, ssa.OpAMD64SHLB, ssa.OpAMD64SHRQ, ssa.OpAMD64SHRL, ssa.OpAMD64SHRW, ssa.OpAMD64SHRB, ssa.OpAMD64SARQ, ssa.OpAMD64SARL, ssa.OpAMD64SARW, ssa.OpAMD64SARB: diff --git a/src/cmd/compile/internal/gc/ssa_test.go b/src/cmd/compile/internal/gc/ssa_test.go index f0060cb12d..d4dfa5d5bf 100644 --- a/src/cmd/compile/internal/gc/ssa_test.go +++ b/src/cmd/compile/internal/gc/ssa_test.go @@ -48,3 +48,6 @@ func TestArithmetic(t *testing.T) { runTest(t, "arith_ssa.go") } // TestFP tests that both backends have the same result for floating point expressions. func TestFP(t *testing.T) { runTest(t, "fp_ssa.go") } + +// TestArithmeticBoundary tests boundary results for arithmetic operations. +func TestArithmeticBoundary(t *testing.T) { runTest(t, "arithBoundary_ssa.go") } diff --git a/src/cmd/compile/internal/gc/testdata/arithBoundary_ssa.go b/src/cmd/compile/internal/gc/testdata/arithBoundary_ssa.go new file mode 100644 index 0000000000..8f84026a5d --- /dev/null +++ b/src/cmd/compile/internal/gc/testdata/arithBoundary_ssa.go @@ -0,0 +1,640 @@ +package main + +import "fmt" + +type utd64 struct { + a, b uint64 + add, sub, mul, div uint64 +} +type itd64 struct { + a, b int64 + add, sub, mul, div int64 +} +type utd32 struct { + a, b uint32 + add, sub, mul, div uint32 +} +type itd32 struct { + a, b int32 + add, sub, mul, div int32 +} +type utd16 struct { + a, b uint16 + add, sub, mul, div uint16 +} +type itd16 struct { + a, b int16 + add, sub, mul, div int16 +} +type utd8 struct { + a, b uint8 + add, sub, mul, div uint8 +} +type itd8 struct { + a, b int8 + add, sub, mul, div int8 +} + +func add_uint64_ssa(a, b uint64) uint64 { + switch { + } + return a + b +} +func sub_uint64_ssa(a, b uint64) uint64 { + switch { + } + return a - b +} +func div_uint64_ssa(a, b uint64) uint64 { + switch { + } + return a / b +} +func mul_uint64_ssa(a, b uint64) uint64 { + switch { + } + return a * b +} +func add_int64_ssa(a, b int64) int64 { + switch { + } + return a + b +} +func sub_int64_ssa(a, b int64) int64 { + switch { + } + return a - b +} +func div_int64_ssa(a, b int64) int64 { + switch { + } + return a / b +} +func mul_int64_ssa(a, b int64) int64 { + switch { + } + return a * b +} +func add_uint32_ssa(a, b uint32) uint32 { + switch { + } + return a + b +} +func sub_uint32_ssa(a, b uint32) uint32 { + switch { + } + return a - b +} +func div_uint32_ssa(a, b uint32) uint32 { + switch { + } + return a / b +} +func mul_uint32_ssa(a, b uint32) uint32 { + switch { + } + return a * b +} +func add_int32_ssa(a, b int32) int32 { + switch { + } + return a + b +} +func sub_int32_ssa(a, b int32) int32 { + switch { + } + return a - b +} +func div_int32_ssa(a, b int32) int32 { + switch { + } + return a / b +} +func mul_int32_ssa(a, b int32) int32 { + switch { + } + return a * b +} +func add_uint16_ssa(a, b uint16) uint16 { + switch { + } + return a + b +} +func sub_uint16_ssa(a, b uint16) uint16 { + switch { + } + return a - b +} +func div_uint16_ssa(a, b uint16) uint16 { + switch { + } + return a / b +} +func mul_uint16_ssa(a, b uint16) uint16 { + switch { + } + return a * b +} +func add_int16_ssa(a, b int16) int16 { + switch { + } + return a + b +} +func sub_int16_ssa(a, b int16) int16 { + switch { + } + return a - b +} +func div_int16_ssa(a, b int16) int16 { + switch { + } + return a / b +} +func mul_int16_ssa(a, b int16) int16 { + switch { + } + return a * b +} +func add_uint8_ssa(a, b uint8) uint8 { + switch { + } + return a + b +} +func sub_uint8_ssa(a, b uint8) uint8 { + switch { + } + return a - b +} +func div_uint8_ssa(a, b uint8) uint8 { + switch { + } + return a / b +} +func mul_uint8_ssa(a, b uint8) uint8 { + switch { + } + return a * b +} +func add_int8_ssa(a, b int8) int8 { + switch { + } + return a + b +} +func sub_int8_ssa(a, b int8) int8 { + switch { + } + return a - b +} +func div_int8_ssa(a, b int8) int8 { + switch { + } + return a / b +} +func mul_int8_ssa(a, b int8) int8 { + switch { + } + return a * b +} + +var uint64_data []utd64 = []utd64{utd64{a: 0, b: 0, add: 0, sub: 0, mul: 0}, + utd64{a: 0, b: 1, add: 1, sub: 18446744073709551615, mul: 0, div: 0}, + utd64{a: 0, b: 4294967296, add: 4294967296, sub: 18446744069414584320, mul: 0, div: 0}, + utd64{a: 0, b: 18446744073709551615, add: 18446744073709551615, sub: 1, mul: 0, div: 0}, + utd64{a: 1, b: 0, add: 1, sub: 1, mul: 0}, + utd64{a: 1, b: 1, add: 2, sub: 0, mul: 1, div: 1}, + utd64{a: 1, b: 4294967296, add: 4294967297, sub: 18446744069414584321, mul: 4294967296, div: 0}, + utd64{a: 1, b: 18446744073709551615, add: 0, sub: 2, mul: 18446744073709551615, div: 0}, + utd64{a: 4294967296, b: 0, add: 4294967296, sub: 4294967296, mul: 0}, + utd64{a: 4294967296, b: 1, add: 4294967297, sub: 4294967295, mul: 4294967296, div: 4294967296}, + utd64{a: 4294967296, b: 4294967296, add: 8589934592, sub: 0, mul: 0, div: 1}, + utd64{a: 4294967296, b: 18446744073709551615, add: 4294967295, sub: 4294967297, mul: 18446744069414584320, div: 0}, + utd64{a: 18446744073709551615, b: 0, add: 18446744073709551615, sub: 18446744073709551615, mul: 0}, + utd64{a: 18446744073709551615, b: 1, add: 0, sub: 18446744073709551614, mul: 18446744073709551615, div: 18446744073709551615}, + utd64{a: 18446744073709551615, b: 4294967296, add: 4294967295, sub: 18446744069414584319, mul: 18446744069414584320, div: 4294967295}, + utd64{a: 18446744073709551615, b: 18446744073709551615, add: 18446744073709551614, sub: 0, mul: 1, div: 1}, +} +var int64_data []itd64 = []itd64{itd64{a: -9223372036854775808, b: -9223372036854775808, add: 0, sub: 0, mul: 0, div: 1}, + itd64{a: -9223372036854775808, b: -9223372036854775807, add: 1, sub: -1, mul: -9223372036854775808, div: 1}, + itd64{a: -9223372036854775808, b: -4294967296, add: 9223372032559808512, sub: -9223372032559808512, mul: 0, div: 2147483648}, + itd64{a: -9223372036854775808, b: -1, add: 9223372036854775807, sub: -9223372036854775807, mul: -9223372036854775808, div: -9223372036854775808}, + itd64{a: -9223372036854775808, b: 0, add: -9223372036854775808, sub: -9223372036854775808, mul: 0}, + itd64{a: -9223372036854775808, b: 1, add: -9223372036854775807, sub: 9223372036854775807, mul: -9223372036854775808, div: -9223372036854775808}, + itd64{a: -9223372036854775808, b: 4294967296, add: -9223372032559808512, sub: 9223372032559808512, mul: 0, div: -2147483648}, + itd64{a: -9223372036854775808, b: 9223372036854775806, add: -2, sub: 2, mul: 0, div: -1}, + itd64{a: -9223372036854775808, b: 9223372036854775807, add: -1, sub: 1, mul: -9223372036854775808, div: -1}, + itd64{a: -9223372036854775807, b: -9223372036854775808, add: 1, sub: 1, mul: -9223372036854775808, div: 0}, + itd64{a: -9223372036854775807, b: -9223372036854775807, add: 2, sub: 0, mul: 1, div: 1}, + itd64{a: -9223372036854775807, b: -4294967296, add: 9223372032559808513, sub: -9223372032559808511, mul: -4294967296, div: 2147483647}, + itd64{a: -9223372036854775807, b: -1, add: -9223372036854775808, sub: -9223372036854775806, mul: 9223372036854775807, div: 9223372036854775807}, + itd64{a: -9223372036854775807, b: 0, add: -9223372036854775807, sub: -9223372036854775807, mul: 0}, + itd64{a: -9223372036854775807, b: 1, add: -9223372036854775806, sub: -9223372036854775808, mul: -9223372036854775807, div: -9223372036854775807}, + itd64{a: -9223372036854775807, b: 4294967296, add: -9223372032559808511, sub: 9223372032559808513, mul: 4294967296, div: -2147483647}, + itd64{a: -9223372036854775807, b: 9223372036854775806, add: -1, sub: 3, mul: 9223372036854775806, div: -1}, + itd64{a: -9223372036854775807, b: 9223372036854775807, add: 0, sub: 2, mul: -1, div: -1}, + itd64{a: -4294967296, b: -9223372036854775808, add: 9223372032559808512, sub: 9223372032559808512, mul: 0, div: 0}, + itd64{a: -4294967296, b: -9223372036854775807, add: 9223372032559808513, sub: 9223372032559808511, mul: -4294967296, div: 0}, + itd64{a: -4294967296, b: -4294967296, add: -8589934592, sub: 0, mul: 0, div: 1}, + itd64{a: -4294967296, b: -1, add: -4294967297, sub: -4294967295, mul: 4294967296, div: 4294967296}, + itd64{a: -4294967296, b: 0, add: -4294967296, sub: -4294967296, mul: 0}, + itd64{a: -4294967296, b: 1, add: -4294967295, sub: -4294967297, mul: -4294967296, div: -4294967296}, + itd64{a: -4294967296, b: 4294967296, add: 0, sub: -8589934592, mul: 0, div: -1}, + itd64{a: -4294967296, b: 9223372036854775806, add: 9223372032559808510, sub: 9223372032559808514, mul: 8589934592, div: 0}, + itd64{a: -4294967296, b: 9223372036854775807, add: 9223372032559808511, sub: 9223372032559808513, mul: 4294967296, div: 0}, + itd64{a: -1, b: -9223372036854775808, add: 9223372036854775807, sub: 9223372036854775807, mul: -9223372036854775808, div: 0}, + itd64{a: -1, b: -9223372036854775807, add: -9223372036854775808, sub: 9223372036854775806, mul: 9223372036854775807, div: 0}, + itd64{a: -1, b: -4294967296, add: -4294967297, sub: 4294967295, mul: 4294967296, div: 0}, + itd64{a: -1, b: -1, add: -2, sub: 0, mul: 1, div: 1}, + itd64{a: -1, b: 0, add: -1, sub: -1, mul: 0}, + itd64{a: -1, b: 1, add: 0, sub: -2, mul: -1, div: -1}, + itd64{a: -1, b: 4294967296, add: 4294967295, sub: -4294967297, mul: -4294967296, div: 0}, + itd64{a: -1, b: 9223372036854775806, add: 9223372036854775805, sub: -9223372036854775807, mul: -9223372036854775806, div: 0}, + itd64{a: -1, b: 9223372036854775807, add: 9223372036854775806, sub: -9223372036854775808, mul: -9223372036854775807, div: 0}, + itd64{a: 0, b: -9223372036854775808, add: -9223372036854775808, sub: -9223372036854775808, mul: 0, div: 0}, + itd64{a: 0, b: -9223372036854775807, add: -9223372036854775807, sub: 9223372036854775807, mul: 0, div: 0}, + itd64{a: 0, b: -4294967296, add: -4294967296, sub: 4294967296, mul: 0, div: 0}, + itd64{a: 0, b: -1, add: -1, sub: 1, mul: 0, div: 0}, + itd64{a: 0, b: 0, add: 0, sub: 0, mul: 0}, + itd64{a: 0, b: 1, add: 1, sub: -1, mul: 0, div: 0}, + itd64{a: 0, b: 4294967296, add: 4294967296, sub: -4294967296, mul: 0, div: 0}, + itd64{a: 0, b: 9223372036854775806, add: 9223372036854775806, sub: -9223372036854775806, mul: 0, div: 0}, + itd64{a: 0, b: 9223372036854775807, add: 9223372036854775807, sub: -9223372036854775807, mul: 0, div: 0}, + itd64{a: 1, b: -9223372036854775808, add: -9223372036854775807, sub: -9223372036854775807, mul: -9223372036854775808, div: 0}, + itd64{a: 1, b: -9223372036854775807, add: -9223372036854775806, sub: -9223372036854775808, mul: -9223372036854775807, div: 0}, + itd64{a: 1, b: -4294967296, add: -4294967295, sub: 4294967297, mul: -4294967296, div: 0}, + itd64{a: 1, b: -1, add: 0, sub: 2, mul: -1, div: -1}, + itd64{a: 1, b: 0, add: 1, sub: 1, mul: 0}, + itd64{a: 1, b: 1, add: 2, sub: 0, mul: 1, div: 1}, + itd64{a: 1, b: 4294967296, add: 4294967297, sub: -4294967295, mul: 4294967296, div: 0}, + itd64{a: 1, b: 9223372036854775806, add: 9223372036854775807, sub: -9223372036854775805, mul: 9223372036854775806, div: 0}, + itd64{a: 1, b: 9223372036854775807, add: -9223372036854775808, sub: -9223372036854775806, mul: 9223372036854775807, div: 0}, + itd64{a: 4294967296, b: -9223372036854775808, add: -9223372032559808512, sub: -9223372032559808512, mul: 0, div: 0}, + itd64{a: 4294967296, b: -9223372036854775807, add: -9223372032559808511, sub: -9223372032559808513, mul: 4294967296, div: 0}, + itd64{a: 4294967296, b: -4294967296, add: 0, sub: 8589934592, mul: 0, div: -1}, + itd64{a: 4294967296, b: -1, add: 4294967295, sub: 4294967297, mul: -4294967296, div: -4294967296}, + itd64{a: 4294967296, b: 0, add: 4294967296, sub: 4294967296, mul: 0}, + itd64{a: 4294967296, b: 1, add: 4294967297, sub: 4294967295, mul: 4294967296, div: 4294967296}, + itd64{a: 4294967296, b: 4294967296, add: 8589934592, sub: 0, mul: 0, div: 1}, + itd64{a: 4294967296, b: 9223372036854775806, add: -9223372032559808514, sub: -9223372032559808510, mul: -8589934592, div: 0}, + itd64{a: 4294967296, b: 9223372036854775807, add: -9223372032559808513, sub: -9223372032559808511, mul: -4294967296, div: 0}, + itd64{a: 9223372036854775806, b: -9223372036854775808, add: -2, sub: -2, mul: 0, div: 0}, + itd64{a: 9223372036854775806, b: -9223372036854775807, add: -1, sub: -3, mul: 9223372036854775806, div: 0}, + itd64{a: 9223372036854775806, b: -4294967296, add: 9223372032559808510, sub: -9223372032559808514, mul: 8589934592, div: -2147483647}, + itd64{a: 9223372036854775806, b: -1, add: 9223372036854775805, sub: 9223372036854775807, mul: -9223372036854775806, div: -9223372036854775806}, + itd64{a: 9223372036854775806, b: 0, add: 9223372036854775806, sub: 9223372036854775806, mul: 0}, + itd64{a: 9223372036854775806, b: 1, add: 9223372036854775807, sub: 9223372036854775805, mul: 9223372036854775806, div: 9223372036854775806}, + itd64{a: 9223372036854775806, b: 4294967296, add: -9223372032559808514, sub: 9223372032559808510, mul: -8589934592, div: 2147483647}, + itd64{a: 9223372036854775806, b: 9223372036854775806, add: -4, sub: 0, mul: 4, div: 1}, + itd64{a: 9223372036854775806, b: 9223372036854775807, add: -3, sub: -1, mul: -9223372036854775806, div: 0}, + itd64{a: 9223372036854775807, b: -9223372036854775808, add: -1, sub: -1, mul: -9223372036854775808, div: 0}, + itd64{a: 9223372036854775807, b: -9223372036854775807, add: 0, sub: -2, mul: -1, div: -1}, + itd64{a: 9223372036854775807, b: -4294967296, add: 9223372032559808511, sub: -9223372032559808513, mul: 4294967296, div: -2147483647}, + itd64{a: 9223372036854775807, b: -1, add: 9223372036854775806, sub: -9223372036854775808, mul: -9223372036854775807, div: -9223372036854775807}, + itd64{a: 9223372036854775807, b: 0, add: 9223372036854775807, sub: 9223372036854775807, mul: 0}, + itd64{a: 9223372036854775807, b: 1, add: -9223372036854775808, sub: 9223372036854775806, mul: 9223372036854775807, div: 9223372036854775807}, + itd64{a: 9223372036854775807, b: 4294967296, add: -9223372032559808513, sub: 9223372032559808511, mul: -4294967296, div: 2147483647}, + itd64{a: 9223372036854775807, b: 9223372036854775806, add: -3, sub: 1, mul: -9223372036854775806, div: 1}, + itd64{a: 9223372036854775807, b: 9223372036854775807, add: -2, sub: 0, mul: 1, div: 1}, +} +var uint32_data []utd32 = []utd32{utd32{a: 0, b: 0, add: 0, sub: 0, mul: 0}, + utd32{a: 0, b: 1, add: 1, sub: 4294967295, mul: 0, div: 0}, + utd32{a: 0, b: 4294967295, add: 4294967295, sub: 1, mul: 0, div: 0}, + utd32{a: 1, b: 0, add: 1, sub: 1, mul: 0}, + utd32{a: 1, b: 1, add: 2, sub: 0, mul: 1, div: 1}, + utd32{a: 1, b: 4294967295, add: 0, sub: 2, mul: 4294967295, div: 0}, + utd32{a: 4294967295, b: 0, add: 4294967295, sub: 4294967295, mul: 0}, + utd32{a: 4294967295, b: 1, add: 0, sub: 4294967294, mul: 4294967295, div: 4294967295}, + utd32{a: 4294967295, b: 4294967295, add: 4294967294, sub: 0, mul: 1, div: 1}, +} +var int32_data []itd32 = []itd32{itd32{a: -2147483648, b: -2147483648, add: 0, sub: 0, mul: 0, div: 1}, + itd32{a: -2147483648, b: -2147483647, add: 1, sub: -1, mul: -2147483648, div: 1}, + itd32{a: -2147483648, b: -1, add: 2147483647, sub: -2147483647, mul: -2147483648, div: -2147483648}, + itd32{a: -2147483648, b: 0, add: -2147483648, sub: -2147483648, mul: 0}, + itd32{a: -2147483648, b: 1, add: -2147483647, sub: 2147483647, mul: -2147483648, div: -2147483648}, + itd32{a: -2147483648, b: 2147483647, add: -1, sub: 1, mul: -2147483648, div: -1}, + itd32{a: -2147483647, b: -2147483648, add: 1, sub: 1, mul: -2147483648, div: 0}, + itd32{a: -2147483647, b: -2147483647, add: 2, sub: 0, mul: 1, div: 1}, + itd32{a: -2147483647, b: -1, add: -2147483648, sub: -2147483646, mul: 2147483647, div: 2147483647}, + itd32{a: -2147483647, b: 0, add: -2147483647, sub: -2147483647, mul: 0}, + itd32{a: -2147483647, b: 1, add: -2147483646, sub: -2147483648, mul: -2147483647, div: -2147483647}, + itd32{a: -2147483647, b: 2147483647, add: 0, sub: 2, mul: -1, div: -1}, + itd32{a: -1, b: -2147483648, add: 2147483647, sub: 2147483647, mul: -2147483648, div: 0}, + itd32{a: -1, b: -2147483647, add: -2147483648, sub: 2147483646, mul: 2147483647, div: 0}, + itd32{a: -1, b: -1, add: -2, sub: 0, mul: 1, div: 1}, + itd32{a: -1, b: 0, add: -1, sub: -1, mul: 0}, + itd32{a: -1, b: 1, add: 0, sub: -2, mul: -1, div: -1}, + itd32{a: -1, b: 2147483647, add: 2147483646, sub: -2147483648, mul: -2147483647, div: 0}, + itd32{a: 0, b: -2147483648, add: -2147483648, sub: -2147483648, mul: 0, div: 0}, + itd32{a: 0, b: -2147483647, add: -2147483647, sub: 2147483647, mul: 0, div: 0}, + itd32{a: 0, b: -1, add: -1, sub: 1, mul: 0, div: 0}, + itd32{a: 0, b: 0, add: 0, sub: 0, mul: 0}, + itd32{a: 0, b: 1, add: 1, sub: -1, mul: 0, div: 0}, + itd32{a: 0, b: 2147483647, add: 2147483647, sub: -2147483647, mul: 0, div: 0}, + itd32{a: 1, b: -2147483648, add: -2147483647, sub: -2147483647, mul: -2147483648, div: 0}, + itd32{a: 1, b: -2147483647, add: -2147483646, sub: -2147483648, mul: -2147483647, div: 0}, + itd32{a: 1, b: -1, add: 0, sub: 2, mul: -1, div: -1}, + itd32{a: 1, b: 0, add: 1, sub: 1, mul: 0}, + itd32{a: 1, b: 1, add: 2, sub: 0, mul: 1, div: 1}, + itd32{a: 1, b: 2147483647, add: -2147483648, sub: -2147483646, mul: 2147483647, div: 0}, + itd32{a: 2147483647, b: -2147483648, add: -1, sub: -1, mul: -2147483648, div: 0}, + itd32{a: 2147483647, b: -2147483647, add: 0, sub: -2, mul: -1, div: -1}, + itd32{a: 2147483647, b: -1, add: 2147483646, sub: -2147483648, mul: -2147483647, div: -2147483647}, + itd32{a: 2147483647, b: 0, add: 2147483647, sub: 2147483647, mul: 0}, + itd32{a: 2147483647, b: 1, add: -2147483648, sub: 2147483646, mul: 2147483647, div: 2147483647}, + itd32{a: 2147483647, b: 2147483647, add: -2, sub: 0, mul: 1, div: 1}, +} +var uint16_data []utd16 = []utd16{utd16{a: 0, b: 0, add: 0, sub: 0, mul: 0}, + utd16{a: 0, b: 1, add: 1, sub: 65535, mul: 0, div: 0}, + utd16{a: 0, b: 65535, add: 65535, sub: 1, mul: 0, div: 0}, + utd16{a: 1, b: 0, add: 1, sub: 1, mul: 0}, + utd16{a: 1, b: 1, add: 2, sub: 0, mul: 1, div: 1}, + utd16{a: 1, b: 65535, add: 0, sub: 2, mul: 65535, div: 0}, + utd16{a: 65535, b: 0, add: 65535, sub: 65535, mul: 0}, + utd16{a: 65535, b: 1, add: 0, sub: 65534, mul: 65535, div: 65535}, + utd16{a: 65535, b: 65535, add: 65534, sub: 0, mul: 1, div: 1}, +} +var int16_data []itd16 = []itd16{itd16{a: -32768, b: -32768, add: 0, sub: 0, mul: 0, div: 1}, + itd16{a: -32768, b: -32767, add: 1, sub: -1, mul: -32768, div: 1}, + itd16{a: -32768, b: -1, add: 32767, sub: -32767, mul: -32768, div: -32768}, + itd16{a: -32768, b: 0, add: -32768, sub: -32768, mul: 0}, + itd16{a: -32768, b: 1, add: -32767, sub: 32767, mul: -32768, div: -32768}, + itd16{a: -32768, b: 32766, add: -2, sub: 2, mul: 0, div: -1}, + itd16{a: -32768, b: 32767, add: -1, sub: 1, mul: -32768, div: -1}, + itd16{a: -32767, b: -32768, add: 1, sub: 1, mul: -32768, div: 0}, + itd16{a: -32767, b: -32767, add: 2, sub: 0, mul: 1, div: 1}, + itd16{a: -32767, b: -1, add: -32768, sub: -32766, mul: 32767, div: 32767}, + itd16{a: -32767, b: 0, add: -32767, sub: -32767, mul: 0}, + itd16{a: -32767, b: 1, add: -32766, sub: -32768, mul: -32767, div: -32767}, + itd16{a: -32767, b: 32766, add: -1, sub: 3, mul: 32766, div: -1}, + itd16{a: -32767, b: 32767, add: 0, sub: 2, mul: -1, div: -1}, + itd16{a: -1, b: -32768, add: 32767, sub: 32767, mul: -32768, div: 0}, + itd16{a: -1, b: -32767, add: -32768, sub: 32766, mul: 32767, div: 0}, + itd16{a: -1, b: -1, add: -2, sub: 0, mul: 1, div: 1}, + itd16{a: -1, b: 0, add: -1, sub: -1, mul: 0}, + itd16{a: -1, b: 1, add: 0, sub: -2, mul: -1, div: -1}, + itd16{a: -1, b: 32766, add: 32765, sub: -32767, mul: -32766, div: 0}, + itd16{a: -1, b: 32767, add: 32766, sub: -32768, mul: -32767, div: 0}, + itd16{a: 0, b: -32768, add: -32768, sub: -32768, mul: 0, div: 0}, + itd16{a: 0, b: -32767, add: -32767, sub: 32767, mul: 0, div: 0}, + itd16{a: 0, b: -1, add: -1, sub: 1, mul: 0, div: 0}, + itd16{a: 0, b: 0, add: 0, sub: 0, mul: 0}, + itd16{a: 0, b: 1, add: 1, sub: -1, mul: 0, div: 0}, + itd16{a: 0, b: 32766, add: 32766, sub: -32766, mul: 0, div: 0}, + itd16{a: 0, b: 32767, add: 32767, sub: -32767, mul: 0, div: 0}, + itd16{a: 1, b: -32768, add: -32767, sub: -32767, mul: -32768, div: 0}, + itd16{a: 1, b: -32767, add: -32766, sub: -32768, mul: -32767, div: 0}, + itd16{a: 1, b: -1, add: 0, sub: 2, mul: -1, div: -1}, + itd16{a: 1, b: 0, add: 1, sub: 1, mul: 0}, + itd16{a: 1, b: 1, add: 2, sub: 0, mul: 1, div: 1}, + itd16{a: 1, b: 32766, add: 32767, sub: -32765, mul: 32766, div: 0}, + itd16{a: 1, b: 32767, add: -32768, sub: -32766, mul: 32767, div: 0}, + itd16{a: 32766, b: -32768, add: -2, sub: -2, mul: 0, div: 0}, + itd16{a: 32766, b: -32767, add: -1, sub: -3, mul: 32766, div: 0}, + itd16{a: 32766, b: -1, add: 32765, sub: 32767, mul: -32766, div: -32766}, + itd16{a: 32766, b: 0, add: 32766, sub: 32766, mul: 0}, + itd16{a: 32766, b: 1, add: 32767, sub: 32765, mul: 32766, div: 32766}, + itd16{a: 32766, b: 32766, add: -4, sub: 0, mul: 4, div: 1}, + itd16{a: 32766, b: 32767, add: -3, sub: -1, mul: -32766, div: 0}, + itd16{a: 32767, b: -32768, add: -1, sub: -1, mul: -32768, div: 0}, + itd16{a: 32767, b: -32767, add: 0, sub: -2, mul: -1, div: -1}, + itd16{a: 32767, b: -1, add: 32766, sub: -32768, mul: -32767, div: -32767}, + itd16{a: 32767, b: 0, add: 32767, sub: 32767, mul: 0}, + itd16{a: 32767, b: 1, add: -32768, sub: 32766, mul: 32767, div: 32767}, + itd16{a: 32767, b: 32766, add: -3, sub: 1, mul: -32766, div: 1}, + itd16{a: 32767, b: 32767, add: -2, sub: 0, mul: 1, div: 1}, +} +var uint8_data []utd8 = []utd8{utd8{a: 0, b: 0, add: 0, sub: 0, mul: 0}, + utd8{a: 0, b: 1, add: 1, sub: 255, mul: 0, div: 0}, + utd8{a: 0, b: 255, add: 255, sub: 1, mul: 0, div: 0}, + utd8{a: 1, b: 0, add: 1, sub: 1, mul: 0}, + utd8{a: 1, b: 1, add: 2, sub: 0, mul: 1, div: 1}, + utd8{a: 1, b: 255, add: 0, sub: 2, mul: 255, div: 0}, + utd8{a: 255, b: 0, add: 255, sub: 255, mul: 0}, + utd8{a: 255, b: 1, add: 0, sub: 254, mul: 255, div: 255}, + utd8{a: 255, b: 255, add: 254, sub: 0, mul: 1, div: 1}, +} +var int8_data []itd8 = []itd8{itd8{a: -128, b: -128, add: 0, sub: 0, mul: 0, div: 1}, + itd8{a: -128, b: -127, add: 1, sub: -1, mul: -128, div: 1}, + itd8{a: -128, b: -1, add: 127, sub: -127, mul: -128, div: -128}, + itd8{a: -128, b: 0, add: -128, sub: -128, mul: 0}, + itd8{a: -128, b: 1, add: -127, sub: 127, mul: -128, div: -128}, + itd8{a: -128, b: 126, add: -2, sub: 2, mul: 0, div: -1}, + itd8{a: -128, b: 127, add: -1, sub: 1, mul: -128, div: -1}, + itd8{a: -127, b: -128, add: 1, sub: 1, mul: -128, div: 0}, + itd8{a: -127, b: -127, add: 2, sub: 0, mul: 1, div: 1}, + itd8{a: -127, b: -1, add: -128, sub: -126, mul: 127, div: 127}, + itd8{a: -127, b: 0, add: -127, sub: -127, mul: 0}, + itd8{a: -127, b: 1, add: -126, sub: -128, mul: -127, div: -127}, + itd8{a: -127, b: 126, add: -1, sub: 3, mul: 126, div: -1}, + itd8{a: -127, b: 127, add: 0, sub: 2, mul: -1, div: -1}, + itd8{a: -1, b: -128, add: 127, sub: 127, mul: -128, div: 0}, + itd8{a: -1, b: -127, add: -128, sub: 126, mul: 127, div: 0}, + itd8{a: -1, b: -1, add: -2, sub: 0, mul: 1, div: 1}, + itd8{a: -1, b: 0, add: -1, sub: -1, mul: 0}, + itd8{a: -1, b: 1, add: 0, sub: -2, mul: -1, div: -1}, + itd8{a: -1, b: 126, add: 125, sub: -127, mul: -126, div: 0}, + itd8{a: -1, b: 127, add: 126, sub: -128, mul: -127, div: 0}, + itd8{a: 0, b: -128, add: -128, sub: -128, mul: 0, div: 0}, + itd8{a: 0, b: -127, add: -127, sub: 127, mul: 0, div: 0}, + itd8{a: 0, b: -1, add: -1, sub: 1, mul: 0, div: 0}, + itd8{a: 0, b: 0, add: 0, sub: 0, mul: 0}, + itd8{a: 0, b: 1, add: 1, sub: -1, mul: 0, div: 0}, + itd8{a: 0, b: 126, add: 126, sub: -126, mul: 0, div: 0}, + itd8{a: 0, b: 127, add: 127, sub: -127, mul: 0, div: 0}, + itd8{a: 1, b: -128, add: -127, sub: -127, mul: -128, div: 0}, + itd8{a: 1, b: -127, add: -126, sub: -128, mul: -127, div: 0}, + itd8{a: 1, b: -1, add: 0, sub: 2, mul: -1, div: -1}, + itd8{a: 1, b: 0, add: 1, sub: 1, mul: 0}, + itd8{a: 1, b: 1, add: 2, sub: 0, mul: 1, div: 1}, + itd8{a: 1, b: 126, add: 127, sub: -125, mul: 126, div: 0}, + itd8{a: 1, b: 127, add: -128, sub: -126, mul: 127, div: 0}, + itd8{a: 126, b: -128, add: -2, sub: -2, mul: 0, div: 0}, + itd8{a: 126, b: -127, add: -1, sub: -3, mul: 126, div: 0}, + itd8{a: 126, b: -1, add: 125, sub: 127, mul: -126, div: -126}, + itd8{a: 126, b: 0, add: 126, sub: 126, mul: 0}, + itd8{a: 126, b: 1, add: 127, sub: 125, mul: 126, div: 126}, + itd8{a: 126, b: 126, add: -4, sub: 0, mul: 4, div: 1}, + itd8{a: 126, b: 127, add: -3, sub: -1, mul: -126, div: 0}, + itd8{a: 127, b: -128, add: -1, sub: -1, mul: -128, div: 0}, + itd8{a: 127, b: -127, add: 0, sub: -2, mul: -1, div: -1}, + itd8{a: 127, b: -1, add: 126, sub: -128, mul: -127, div: -127}, + itd8{a: 127, b: 0, add: 127, sub: 127, mul: 0}, + itd8{a: 127, b: 1, add: -128, sub: 126, mul: 127, div: 127}, + itd8{a: 127, b: 126, add: -3, sub: 1, mul: -126, div: 1}, + itd8{a: 127, b: 127, add: -2, sub: 0, mul: 1, div: 1}, +} +var failed bool + +func main() { + + for _, v := range uint64_data { + if got := add_uint64_ssa(v.a, v.b); got != v.add { + fmt.Printf("add_uint64 %d+%d = %d, wanted %d\n", v.a, v.b, got, v.add) + failed = true + } + if got := sub_uint64_ssa(v.a, v.b); got != v.sub { + fmt.Printf("sub_uint64 %d-%d = %d, wanted %d\n", v.a, v.b, got, v.sub) + failed = true + } + if v.b != 0 { + if got := div_uint64_ssa(v.a, v.b); got != v.div { + fmt.Printf("div_uint64 %d/%d = %d, wanted %d\n", v.a, v.b, got, v.div) + failed = true + } + + } + if got := mul_uint64_ssa(v.a, v.b); got != v.mul { + fmt.Printf("mul_uint64 %d*%d = %d, wanted %d\n", v.a, v.b, got, v.mul) + failed = true + } + } + for _, v := range int64_data { + if got := add_int64_ssa(v.a, v.b); got != v.add { + fmt.Printf("add_int64 %d+%d = %d, wanted %d\n", v.a, v.b, got, v.add) + failed = true + } + if got := sub_int64_ssa(v.a, v.b); got != v.sub { + fmt.Printf("sub_int64 %d-%d = %d, wanted %d\n", v.a, v.b, got, v.sub) + failed = true + } + if v.b != 0 { + if got := div_int64_ssa(v.a, v.b); got != v.div { + fmt.Printf("div_int64 %d/%d = %d, wanted %d\n", v.a, v.b, got, v.div) + failed = true + } + + } + if got := mul_int64_ssa(v.a, v.b); got != v.mul { + fmt.Printf("mul_int64 %d*%d = %d, wanted %d\n", v.a, v.b, got, v.mul) + failed = true + } + } + for _, v := range uint32_data { + if got := add_uint32_ssa(v.a, v.b); got != v.add { + fmt.Printf("add_uint32 %d+%d = %d, wanted %d\n", v.a, v.b, got, v.add) + failed = true + } + if got := sub_uint32_ssa(v.a, v.b); got != v.sub { + fmt.Printf("sub_uint32 %d-%d = %d, wanted %d\n", v.a, v.b, got, v.sub) + failed = true + } + if v.b != 0 { + if got := div_uint32_ssa(v.a, v.b); got != v.div { + fmt.Printf("div_uint32 %d/%d = %d, wanted %d\n", v.a, v.b, got, v.div) + failed = true + } + + } + if got := mul_uint32_ssa(v.a, v.b); got != v.mul { + fmt.Printf("mul_uint32 %d*%d = %d, wanted %d\n", v.a, v.b, got, v.mul) + failed = true + } + } + for _, v := range int32_data { + if got := add_int32_ssa(v.a, v.b); got != v.add { + fmt.Printf("add_int32 %d+%d = %d, wanted %d\n", v.a, v.b, got, v.add) + failed = true + } + if got := sub_int32_ssa(v.a, v.b); got != v.sub { + fmt.Printf("sub_int32 %d-%d = %d, wanted %d\n", v.a, v.b, got, v.sub) + failed = true + } + if v.b != 0 { + if got := div_int32_ssa(v.a, v.b); got != v.div { + fmt.Printf("div_int32 %d/%d = %d, wanted %d\n", v.a, v.b, got, v.div) + failed = true + } + + } + if got := mul_int32_ssa(v.a, v.b); got != v.mul { + fmt.Printf("mul_int32 %d*%d = %d, wanted %d\n", v.a, v.b, got, v.mul) + failed = true + } + } + for _, v := range uint16_data { + if got := add_uint16_ssa(v.a, v.b); got != v.add { + fmt.Printf("add_uint16 %d+%d = %d, wanted %d\n", v.a, v.b, got, v.add) + failed = true + } + if got := sub_uint16_ssa(v.a, v.b); got != v.sub { + fmt.Printf("sub_uint16 %d-%d = %d, wanted %d\n", v.a, v.b, got, v.sub) + failed = true + } + if v.b != 0 { + if got := div_uint16_ssa(v.a, v.b); got != v.div { + fmt.Printf("div_uint16 %d/%d = %d, wanted %d\n", v.a, v.b, got, v.div) + failed = true + } + + } + if got := mul_uint16_ssa(v.a, v.b); got != v.mul { + fmt.Printf("mul_uint16 %d*%d = %d, wanted %d\n", v.a, v.b, got, v.mul) + failed = true + } + } + for _, v := range int16_data { + if got := add_int16_ssa(v.a, v.b); got != v.add { + fmt.Printf("add_int16 %d+%d = %d, wanted %d\n", v.a, v.b, got, v.add) + failed = true + } + if got := sub_int16_ssa(v.a, v.b); got != v.sub { + fmt.Printf("sub_int16 %d-%d = %d, wanted %d\n", v.a, v.b, got, v.sub) + failed = true + } + if v.b != 0 { + if got := div_int16_ssa(v.a, v.b); got != v.div { + fmt.Printf("div_int16 %d/%d = %d, wanted %d\n", v.a, v.b, got, v.div) + failed = true + } + + } + if got := mul_int16_ssa(v.a, v.b); got != v.mul { + fmt.Printf("mul_int16 %d*%d = %d, wanted %d\n", v.a, v.b, got, v.mul) + failed = true + } + } + for _, v := range uint8_data { + if got := add_uint8_ssa(v.a, v.b); got != v.add { + fmt.Printf("add_uint8 %d+%d = %d, wanted %d\n", v.a, v.b, got, v.add) + failed = true + } + if got := sub_uint8_ssa(v.a, v.b); got != v.sub { + fmt.Printf("sub_uint8 %d-%d = %d, wanted %d\n", v.a, v.b, got, v.sub) + failed = true + } + if v.b != 0 { + if got := div_uint8_ssa(v.a, v.b); got != v.div { + fmt.Printf("div_uint8 %d/%d = %d, wanted %d\n", v.a, v.b, got, v.div) + failed = true + } + + } + if got := mul_uint8_ssa(v.a, v.b); got != v.mul { + fmt.Printf("mul_uint8 %d*%d = %d, wanted %d\n", v.a, v.b, got, v.mul) + failed = true + } + } + for _, v := range int8_data { + if got := add_int8_ssa(v.a, v.b); got != v.add { + fmt.Printf("add_int8 %d+%d = %d, wanted %d\n", v.a, v.b, got, v.add) + failed = true + } + if got := sub_int8_ssa(v.a, v.b); got != v.sub { + fmt.Printf("sub_int8 %d-%d = %d, wanted %d\n", v.a, v.b, got, v.sub) + failed = true + } + if v.b != 0 { + if got := div_int8_ssa(v.a, v.b); got != v.div { + fmt.Printf("div_int8 %d/%d = %d, wanted %d\n", v.a, v.b, got, v.div) + failed = true + } + + } + if got := mul_int8_ssa(v.a, v.b); got != v.mul { + fmt.Printf("mul_int8 %d*%d = %d, wanted %d\n", v.a, v.b, got, v.mul) + failed = true + } + } + if failed { + panic("tests failed") + } +} diff --git a/src/cmd/compile/internal/ssa/TODO b/src/cmd/compile/internal/ssa/TODO index d049bea872..1773dbbc98 100644 --- a/src/cmd/compile/internal/ssa/TODO +++ b/src/cmd/compile/internal/ssa/TODO @@ -5,7 +5,7 @@ Coverage -------- - Floating point numbers - Complex numbers -- Integer division +- Integer division (HMUL & MOD) - Fat objects (strings/slices/interfaces) vs. Phi - Defer? - Closure args @@ -49,6 +49,7 @@ Optimizations (better compiler) - OpStore uses 3 args. Increase the size of Value.argstorage to 3? - Constant cache - Reuseable slices (e.g. []int of size NumValues()) cached in Func +- Handle signed division overflow and sign extension earlier Regalloc -------- diff --git a/src/cmd/compile/internal/ssa/gen/AMD64.rules b/src/cmd/compile/internal/ssa/gen/AMD64.rules index 9ea9781d93..0cde6f26d4 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64.rules +++ b/src/cmd/compile/internal/ssa/gen/AMD64.rules @@ -36,6 +36,15 @@ (Div32F x y) -> (DIVSS x y) (Div64F x y) -> (DIVSD x y) +(Div64 x y) -> (DIVQ x y) +(Div64u x y) -> (DIVQU x y) +(Div32 x y) -> (DIVL x y) +(Div32u x y) -> (DIVLU x y) +(Div16 x y) -> (DIVW x y) +(Div16u x y) -> (DIVWU x y) +(Div8 x y) -> (DIVW (SignExt8to16 x) (SignExt8to16 y)) +(Div8u x y) -> (DIVWU (ZeroExt8to16 x) (ZeroExt8to16 y)) + (And64 x y) -> (ANDQ x y) (And32 x y) -> (ANDL x y) (And16 x y) -> (ANDW x y) diff --git a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go index 5aa5e60e33..220e5b01cd 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go @@ -72,7 +72,9 @@ func init() { // Common individual register masks var ( + ax = buildReg("AX") cx = buildReg("CX") + dx = buildReg("DX") x15 = buildReg("X15") gp = buildReg("AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15") fp = buildReg("X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15") @@ -97,6 +99,8 @@ func init() { gp21 = regInfo{inputs: []regMask{gpsp, gpsp}, outputs: gponly, clobbers: flags} gp21sb = regInfo{inputs: []regMask{gpspsb, gpsp}, outputs: gponly, clobbers: flags} gp21shift = regInfo{inputs: []regMask{gpsp, cx}, outputs: []regMask{gp &^ cx}, clobbers: flags} + gp11div = regInfo{inputs: []regMask{ax, gpsp &^ dx}, outputs: []regMask{ax}, + clobbers: dx | flags} gp2flags = regInfo{inputs: []regMask{gpsp, gpsp}, outputs: flagsonly} gp1flags = regInfo{inputs: []regMask{gpsp}, outputs: flagsonly} @@ -180,6 +184,14 @@ func init() { {name: "MULWconst", reg: gp11, asm: "IMULW"}, // arg0 * auxint {name: "MULBconst", reg: gp11, asm: "IMULW"}, // arg0 * auxint + {name: "DIVQ", reg: gp11div, asm: "IDIVQ"}, // arg0 / arg1 + {name: "DIVL", reg: gp11div, asm: "IDIVL"}, // arg0 / arg1 + {name: "DIVW", reg: gp11div, asm: "IDIVW"}, // arg0 / arg1 + + {name: "DIVQU", reg: gp11div, asm: "DIVQ"}, // arg0 / arg1 + {name: "DIVLU", reg: gp11div, asm: "DIVL"}, // arg0 / arg1 + {name: "DIVWU", reg: gp11div, asm: "DIVW"}, // arg0 / arg1 + {name: "ANDQ", reg: gp21, asm: "ANDQ"}, // arg0 & arg1 {name: "ANDL", reg: gp21, asm: "ANDL"}, // arg0 & arg1 {name: "ANDW", reg: gp21, asm: "ANDW"}, // arg0 & arg1 diff --git a/src/cmd/compile/internal/ssa/gen/genericOps.go b/src/cmd/compile/internal/ssa/gen/genericOps.go index 1488e0f644..a0d8f8e000 100644 --- a/src/cmd/compile/internal/ssa/gen/genericOps.go +++ b/src/cmd/compile/internal/ssa/gen/genericOps.go @@ -37,6 +37,15 @@ var genericOps = []opData{ {name: "Div64F"}, // TODO: Div8, Div16, Div32, Div64 and unsigned + {name: "Div8"}, // arg0 / arg1 + {name: "Div8u"}, + {name: "Div16"}, + {name: "Div16u"}, + {name: "Div32"}, + {name: "Div32u"}, + {name: "Div64"}, + {name: "Div64u"}, + {name: "And8"}, // arg0 & arg1 {name: "And16"}, {name: "And32"}, diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index cbabbfade5..44fd6e3737 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -93,6 +93,12 @@ const ( OpAMD64MULLconst OpAMD64MULWconst OpAMD64MULBconst + OpAMD64DIVQ + OpAMD64DIVL + OpAMD64DIVW + OpAMD64DIVQU + OpAMD64DIVLU + OpAMD64DIVWU OpAMD64ANDQ OpAMD64ANDL OpAMD64ANDW @@ -239,6 +245,14 @@ const ( OpMul64F OpDiv32F OpDiv64F + OpDiv8 + OpDiv8u + OpDiv16 + OpDiv16u + OpDiv32 + OpDiv32u + OpDiv64 + OpDiv64u OpAnd8 OpAnd16 OpAnd32 @@ -963,6 +977,90 @@ var opcodeTable = [...]opInfo{ }, }, }, + { + name: "DIVQ", + asm: x86.AIDIVQ, + reg: regInfo{ + inputs: []inputInfo{ + {0, 1}, // .AX + {1, 65531}, // .AX .CX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + clobbers: 8589934596, // .DX .FLAGS + outputs: []regMask{ + 1, // .AX + }, + }, + }, + { + name: "DIVL", + asm: x86.AIDIVL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 1}, // .AX + {1, 65531}, // .AX .CX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + clobbers: 8589934596, // .DX .FLAGS + outputs: []regMask{ + 1, // .AX + }, + }, + }, + { + name: "DIVW", + asm: x86.AIDIVW, + reg: regInfo{ + inputs: []inputInfo{ + {0, 1}, // .AX + {1, 65531}, // .AX .CX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + clobbers: 8589934596, // .DX .FLAGS + outputs: []regMask{ + 1, // .AX + }, + }, + }, + { + name: "DIVQU", + asm: x86.ADIVQ, + reg: regInfo{ + inputs: []inputInfo{ + {0, 1}, // .AX + {1, 65531}, // .AX .CX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + clobbers: 8589934596, // .DX .FLAGS + outputs: []regMask{ + 1, // .AX + }, + }, + }, + { + name: "DIVLU", + asm: x86.ADIVL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 1}, // .AX + {1, 65531}, // .AX .CX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + clobbers: 8589934596, // .DX .FLAGS + outputs: []regMask{ + 1, // .AX + }, + }, + }, + { + name: "DIVWU", + asm: x86.ADIVW, + reg: regInfo{ + inputs: []inputInfo{ + {0, 1}, // .AX + {1, 65531}, // .AX .CX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + clobbers: 8589934596, // .DX .FLAGS + outputs: []regMask{ + 1, // .AX + }, + }, + }, { name: "ANDQ", asm: x86.AANDQ, @@ -2592,6 +2690,38 @@ var opcodeTable = [...]opInfo{ name: "Div64F", generic: true, }, + { + name: "Div8", + generic: true, + }, + { + name: "Div8u", + generic: true, + }, + { + name: "Div16", + generic: true, + }, + { + name: "Div16u", + generic: true, + }, + { + name: "Div32", + generic: true, + }, + { + name: "Div32u", + generic: true, + }, + { + name: "Div64", + generic: true, + }, + { + name: "Div64u", + generic: true, + }, { name: "And8", generic: true, diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go index 75393ad58a..993838b537 100644 --- a/src/cmd/compile/internal/ssa/rewriteAMD64.go +++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go @@ -1688,6 +1688,60 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto endc395c0a53eeccf597e225a07b53047d1 endc395c0a53eeccf597e225a07b53047d1: ; + case OpDiv16: + // match: (Div16 x y) + // cond: + // result: (DIVW x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64DIVW + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto endb60a86e606726640c84d3e1e5a5ce890 + endb60a86e606726640c84d3e1e5a5ce890: + ; + case OpDiv16u: + // match: (Div16u x y) + // cond: + // result: (DIVWU x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64DIVWU + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto end6af9e212a865593e506bfdf7db67c9ec + end6af9e212a865593e506bfdf7db67c9ec: + ; + case OpDiv32: + // match: (Div32 x y) + // cond: + // result: (DIVL x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64DIVL + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto endf20ac71407e57c2904684d3cc33cf697 + endf20ac71407e57c2904684d3cc33cf697: + ; case OpDiv32F: // match: (Div32F x y) // cond: @@ -1706,6 +1760,42 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto enddca0462c7b176c4138854d7d5627ab5b enddca0462c7b176c4138854d7d5627ab5b: ; + case OpDiv32u: + // match: (Div32u x y) + // cond: + // result: (DIVLU x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64DIVLU + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto enda22604d23eeb1298008c97b817f60bbd + enda22604d23eeb1298008c97b817f60bbd: + ; + case OpDiv64: + // match: (Div64 x y) + // cond: + // result: (DIVQ x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64DIVQ + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto end86490d9b337333dfc09a413e1e0120a9 + end86490d9b337333dfc09a413e1e0120a9: + ; case OpDiv64F: // match: (Div64F x y) // cond: @@ -1724,6 +1814,72 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto end12299d76db5144a60f564d34ba97eb43 end12299d76db5144a60f564d34ba97eb43: ; + case OpDiv64u: + // match: (Div64u x y) + // cond: + // result: (DIVQU x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64DIVQU + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto endf871d8b397e5fad6a5b500cc0c759a8d + endf871d8b397e5fad6a5b500cc0c759a8d: + ; + case OpDiv8: + // match: (Div8 x y) + // cond: + // result: (DIVW (SignExt8to16 x) (SignExt8to16 y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64DIVW + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpSignExt8to16, TypeInvalid) + v0.Type = config.Frontend().TypeInt16() + v0.AddArg(x) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpSignExt8to16, TypeInvalid) + v1.Type = config.Frontend().TypeInt16() + v1.AddArg(y) + v.AddArg(v1) + return true + } + goto ende25a7899b9c7a869f74226b4b6033084 + ende25a7899b9c7a869f74226b4b6033084: + ; + case OpDiv8u: + // match: (Div8u x y) + // cond: + // result: (DIVWU (ZeroExt8to16 x) (ZeroExt8to16 y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64DIVWU + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpZeroExt8to16, TypeInvalid) + v0.Type = config.Frontend().TypeUInt16() + v0.AddArg(x) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpZeroExt8to16, TypeInvalid) + v1.Type = config.Frontend().TypeUInt16() + v1.AddArg(y) + v.AddArg(v1) + return true + } + goto ende655b41d48feafc4d139b815a3b7b55c + ende655b41d48feafc4d139b815a3b7b55c: + ; case OpEq16: // match: (Eq16 x y) // cond: -- cgit v1.3 From 67cbd5b51d3700fc1976f71a711882bfdd7e8304 Mon Sep 17 00:00:00 2001 From: Todd Neal Date: Tue, 18 Aug 2015 19:14:47 -0500 Subject: [dev.ssa] cmd/compile/internal/ssa: implement OHMUL Adds support for high multiply which is used by the frontend when rewriting const division. The frontend currently only does this for 8, 16, and 32 bit integer arithmetic. Change-Id: I9b6c6018f3be827a50ee6c185454ebc79b3094c8 Reviewed-on: https://go-review.googlesource.com/13696 Reviewed-by: Keith Randall --- src/cmd/compile/internal/gc/ssa.go | 30 +- src/cmd/compile/internal/gc/ssa_test.go | 3 + .../compile/internal/gc/testdata/arithConst_ssa.go | 3979 ++++++++++++++++++++ src/cmd/compile/internal/gc/testdata/arith_ssa.go | 2 +- src/cmd/compile/internal/ssa/TODO | 3 +- src/cmd/compile/internal/ssa/gen/AMD64.rules | 7 + src/cmd/compile/internal/ssa/gen/AMD64Ops.go | 10 +- src/cmd/compile/internal/ssa/gen/genericOps.go | 8 + src/cmd/compile/internal/ssa/opGen.go | 120 + src/cmd/compile/internal/ssa/rewriteAMD64.go | 108 + 10 files changed, 4266 insertions(+), 4 deletions(-) create mode 100644 src/cmd/compile/internal/gc/testdata/arithConst_ssa.go (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 90b29b9b09..f2dd20bcb4 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -779,6 +779,13 @@ var opToSSA = map[opAndType]ssa.Op{ opAndType{ODIV, TFLOAT32}: ssa.OpDiv32F, opAndType{ODIV, TFLOAT64}: ssa.OpDiv64F, + opAndType{OHMUL, TINT8}: ssa.OpHmul8, + opAndType{OHMUL, TUINT8}: ssa.OpHmul8u, + opAndType{OHMUL, TINT16}: ssa.OpHmul16, + opAndType{OHMUL, TUINT16}: ssa.OpHmul16u, + opAndType{OHMUL, TINT32}: ssa.OpHmul32, + opAndType{OHMUL, TUINT32}: ssa.OpHmul32u, + opAndType{ODIV, TINT8}: ssa.OpDiv8, opAndType{ODIV, TUINT8}: ssa.OpDiv8u, opAndType{ODIV, TINT16}: ssa.OpDiv16, @@ -1201,7 +1208,7 @@ func (s *state) expr(n *Node) *ssa.Value { a := s.expr(n.Left) b := s.expr(n.Right) return s.newValue2(s.ssaOp(n.Op, n.Left.Type), Types[TBOOL], a, b) - case OADD, OAND, OMUL, OOR, OSUB, ODIV, OXOR: + case OADD, OAND, OMUL, OOR, OSUB, ODIV, OXOR, OHMUL: a := s.expr(n.Left) b := s.expr(n.Right) return s.newValue2(s.ssaOp(n.Op, n.Type), a.Type, a, b) @@ -2099,6 +2106,27 @@ func genValue(v *ssa.Value) { j2.To.Val = Pc } + case ssa.OpAMD64HMULL, ssa.OpAMD64HMULW, ssa.OpAMD64HMULB, + ssa.OpAMD64HMULLU, ssa.OpAMD64HMULWU, ssa.OpAMD64HMULBU: + // the frontend rewrites constant division by 8/16/32 bit integers into + // HMUL by a constant + + // Arg[0] is already in AX as it's the only register we allow + // and DX is the only output we care about (the high bits) + p := Prog(v.Op.Asm()) + p.From.Type = obj.TYPE_REG + p.From.Reg = regnum(v.Args[1]) + + // IMULB puts the high portion in AH instead of DL, + // so move it to DL for consistency + if v.Type.Size() == 1 { + m := Prog(x86.AMOVB) + m.From.Type = obj.TYPE_REG + m.From.Reg = x86.REG_AH + m.To.Type = obj.TYPE_REG + m.To.Reg = x86.REG_DX + } + case ssa.OpAMD64SHLQ, ssa.OpAMD64SHLL, ssa.OpAMD64SHLW, ssa.OpAMD64SHLB, ssa.OpAMD64SHRQ, ssa.OpAMD64SHRL, ssa.OpAMD64SHRW, ssa.OpAMD64SHRB, ssa.OpAMD64SARQ, ssa.OpAMD64SARL, ssa.OpAMD64SARW, ssa.OpAMD64SARB: diff --git a/src/cmd/compile/internal/gc/ssa_test.go b/src/cmd/compile/internal/gc/ssa_test.go index d4dfa5d5bf..071522bc2f 100644 --- a/src/cmd/compile/internal/gc/ssa_test.go +++ b/src/cmd/compile/internal/gc/ssa_test.go @@ -51,3 +51,6 @@ func TestFP(t *testing.T) { runTest(t, "fp_ssa.go") } // TestArithmeticBoundary tests boundary results for arithmetic operations. func TestArithmeticBoundary(t *testing.T) { runTest(t, "arithBoundary_ssa.go") } + +// TestArithmeticConst tests results for arithmetic operations against constants. +func TestArithmeticConst(t *testing.T) { runTest(t, "arithConst_ssa.go") } diff --git a/src/cmd/compile/internal/gc/testdata/arithConst_ssa.go b/src/cmd/compile/internal/gc/testdata/arithConst_ssa.go new file mode 100644 index 0000000000..93420aee66 --- /dev/null +++ b/src/cmd/compile/internal/gc/testdata/arithConst_ssa.go @@ -0,0 +1,3979 @@ +package main + +import "fmt" + +func add_uint64_0_ssa(a uint64) uint64 { + switch { + } + return a + 0 +} +func add_0_uint64_ssa(a uint64) uint64 { + switch { + } + return 0 + a +} + +func add_uint64_1_ssa(a uint64) uint64 { + switch { + } + return a + 1 +} +func add_1_uint64_ssa(a uint64) uint64 { + switch { + } + return 1 + a +} + +func add_uint64_4294967296_ssa(a uint64) uint64 { + switch { + } + return a + 4294967296 +} +func add_4294967296_uint64_ssa(a uint64) uint64 { + switch { + } + return 4294967296 + a +} + +func add_uint64_18446744073709551615_ssa(a uint64) uint64 { + switch { + } + return a + 18446744073709551615 +} +func add_18446744073709551615_uint64_ssa(a uint64) uint64 { + switch { + } + return 18446744073709551615 + a +} + +func sub_uint64_0_ssa(a uint64) uint64 { + switch { + } + return a - 0 +} +func sub_0_uint64_ssa(a uint64) uint64 { + switch { + } + return 0 - a +} + +func sub_uint64_1_ssa(a uint64) uint64 { + switch { + } + return a - 1 +} +func sub_1_uint64_ssa(a uint64) uint64 { + switch { + } + return 1 - a +} + +func sub_uint64_4294967296_ssa(a uint64) uint64 { + switch { + } + return a - 4294967296 +} +func sub_4294967296_uint64_ssa(a uint64) uint64 { + switch { + } + return 4294967296 - a +} + +func sub_uint64_18446744073709551615_ssa(a uint64) uint64 { + switch { + } + return a - 18446744073709551615 +} +func sub_18446744073709551615_uint64_ssa(a uint64) uint64 { + switch { + } + return 18446744073709551615 - a +} + +func div_0_uint64_ssa(a uint64) uint64 { + switch { + } + return 0 / a +} + +func div_uint64_1_ssa(a uint64) uint64 { + switch { + } + return a / 1 +} +func div_1_uint64_ssa(a uint64) uint64 { + switch { + } + return 1 / a +} + +func div_uint64_4294967296_ssa(a uint64) uint64 { + switch { + } + return a / 4294967296 +} +func div_4294967296_uint64_ssa(a uint64) uint64 { + switch { + } + return 4294967296 / a +} + +func div_uint64_18446744073709551615_ssa(a uint64) uint64 { + switch { + } + return a / 18446744073709551615 +} +func div_18446744073709551615_uint64_ssa(a uint64) uint64 { + switch { + } + return 18446744073709551615 / a +} + +func mul_uint64_0_ssa(a uint64) uint64 { + switch { + } + return a * 0 +} +func mul_0_uint64_ssa(a uint64) uint64 { + switch { + } + return 0 * a +} + +func mul_uint64_1_ssa(a uint64) uint64 { + switch { + } + return a * 1 +} +func mul_1_uint64_ssa(a uint64) uint64 { + switch { + } + return 1 * a +} + +func mul_uint64_4294967296_ssa(a uint64) uint64 { + switch { + } + return a * 4294967296 +} +func mul_4294967296_uint64_ssa(a uint64) uint64 { + switch { + } + return 4294967296 * a +} + +func mul_uint64_18446744073709551615_ssa(a uint64) uint64 { + switch { + } + return a * 18446744073709551615 +} +func mul_18446744073709551615_uint64_ssa(a uint64) uint64 { + switch { + } + return 18446744073709551615 * a +} + +func add_int64_Neg9223372036854775808_ssa(a int64) int64 { + switch { + } + return a + -9223372036854775808 +} +func add_Neg9223372036854775808_int64_ssa(a int64) int64 { + switch { + } + return -9223372036854775808 + a +} + +func add_int64_Neg9223372036854775807_ssa(a int64) int64 { + switch { + } + return a + -9223372036854775807 +} +func add_Neg9223372036854775807_int64_ssa(a int64) int64 { + switch { + } + return -9223372036854775807 + a +} + +func add_int64_Neg4294967296_ssa(a int64) int64 { + switch { + } + return a + -4294967296 +} +func add_Neg4294967296_int64_ssa(a int64) int64 { + switch { + } + return -4294967296 + a +} + +func add_int64_Neg1_ssa(a int64) int64 { + switch { + } + return a + -1 +} +func add_Neg1_int64_ssa(a int64) int64 { + switch { + } + return -1 + a +} + +func add_int64_0_ssa(a int64) int64 { + switch { + } + return a + 0 +} +func add_0_int64_ssa(a int64) int64 { + switch { + } + return 0 + a +} + +func add_int64_1_ssa(a int64) int64 { + switch { + } + return a + 1 +} +func add_1_int64_ssa(a int64) int64 { + switch { + } + return 1 + a +} + +func add_int64_4294967296_ssa(a int64) int64 { + switch { + } + return a + 4294967296 +} +func add_4294967296_int64_ssa(a int64) int64 { + switch { + } + return 4294967296 + a +} + +func add_int64_9223372036854775806_ssa(a int64) int64 { + switch { + } + return a + 9223372036854775806 +} +func add_9223372036854775806_int64_ssa(a int64) int64 { + switch { + } + return 9223372036854775806 + a +} + +func add_int64_9223372036854775807_ssa(a int64) int64 { + switch { + } + return a + 9223372036854775807 +} +func add_9223372036854775807_int64_ssa(a int64) int64 { + switch { + } + return 9223372036854775807 + a +} + +func sub_int64_Neg9223372036854775808_ssa(a int64) int64 { + switch { + } + return a - -9223372036854775808 +} +func sub_Neg9223372036854775808_int64_ssa(a int64) int64 { + switch { + } + return -9223372036854775808 - a +} + +func sub_int64_Neg9223372036854775807_ssa(a int64) int64 { + switch { + } + return a - -9223372036854775807 +} +func sub_Neg9223372036854775807_int64_ssa(a int64) int64 { + switch { + } + return -9223372036854775807 - a +} + +func sub_int64_Neg4294967296_ssa(a int64) int64 { + switch { + } + return a - -4294967296 +} +func sub_Neg4294967296_int64_ssa(a int64) int64 { + switch { + } + return -4294967296 - a +} + +func sub_int64_Neg1_ssa(a int64) int64 { + switch { + } + return a - -1 +} +func sub_Neg1_int64_ssa(a int64) int64 { + switch { + } + return -1 - a +} + +func sub_int64_0_ssa(a int64) int64 { + switch { + } + return a - 0 +} +func sub_0_int64_ssa(a int64) int64 { + switch { + } + return 0 - a +} + +func sub_int64_1_ssa(a int64) int64 { + switch { + } + return a - 1 +} +func sub_1_int64_ssa(a int64) int64 { + switch { + } + return 1 - a +} + +func sub_int64_4294967296_ssa(a int64) int64 { + switch { + } + return a - 4294967296 +} +func sub_4294967296_int64_ssa(a int64) int64 { + switch { + } + return 4294967296 - a +} + +func sub_int64_9223372036854775806_ssa(a int64) int64 { + switch { + } + return a - 9223372036854775806 +} +func sub_9223372036854775806_int64_ssa(a int64) int64 { + switch { + } + return 9223372036854775806 - a +} + +func sub_int64_9223372036854775807_ssa(a int64) int64 { + switch { + } + return a - 9223372036854775807 +} +func sub_9223372036854775807_int64_ssa(a int64) int64 { + switch { + } + return 9223372036854775807 - a +} + +func div_int64_Neg9223372036854775808_ssa(a int64) int64 { + switch { + } + return a / -9223372036854775808 +} +func div_Neg9223372036854775808_int64_ssa(a int64) int64 { + switch { + } + return -9223372036854775808 / a +} + +func div_int64_Neg9223372036854775807_ssa(a int64) int64 { + switch { + } + return a / -9223372036854775807 +} +func div_Neg9223372036854775807_int64_ssa(a int64) int64 { + switch { + } + return -9223372036854775807 / a +} + +func div_int64_Neg4294967296_ssa(a int64) int64 { + switch { + } + return a / -4294967296 +} +func div_Neg4294967296_int64_ssa(a int64) int64 { + switch { + } + return -4294967296 / a +} + +func div_int64_Neg1_ssa(a int64) int64 { + switch { + } + return a / -1 +} +func div_Neg1_int64_ssa(a int64) int64 { + switch { + } + return -1 / a +} + +func div_0_int64_ssa(a int64) int64 { + switch { + } + return 0 / a +} + +func div_int64_1_ssa(a int64) int64 { + switch { + } + return a / 1 +} +func div_1_int64_ssa(a int64) int64 { + switch { + } + return 1 / a +} + +func div_int64_4294967296_ssa(a int64) int64 { + switch { + } + return a / 4294967296 +} +func div_4294967296_int64_ssa(a int64) int64 { + switch { + } + return 4294967296 / a +} + +func div_int64_9223372036854775806_ssa(a int64) int64 { + switch { + } + return a / 9223372036854775806 +} +func div_9223372036854775806_int64_ssa(a int64) int64 { + switch { + } + return 9223372036854775806 / a +} + +func div_int64_9223372036854775807_ssa(a int64) int64 { + switch { + } + return a / 9223372036854775807 +} +func div_9223372036854775807_int64_ssa(a int64) int64 { + switch { + } + return 9223372036854775807 / a +} + +func mul_int64_Neg9223372036854775808_ssa(a int64) int64 { + switch { + } + return a * -9223372036854775808 +} +func mul_Neg9223372036854775808_int64_ssa(a int64) int64 { + switch { + } + return -9223372036854775808 * a +} + +func mul_int64_Neg9223372036854775807_ssa(a int64) int64 { + switch { + } + return a * -9223372036854775807 +} +func mul_Neg9223372036854775807_int64_ssa(a int64) int64 { + switch { + } + return -9223372036854775807 * a +} + +func mul_int64_Neg4294967296_ssa(a int64) int64 { + switch { + } + return a * -4294967296 +} +func mul_Neg4294967296_int64_ssa(a int64) int64 { + switch { + } + return -4294967296 * a +} + +func mul_int64_Neg1_ssa(a int64) int64 { + switch { + } + return a * -1 +} +func mul_Neg1_int64_ssa(a int64) int64 { + switch { + } + return -1 * a +} + +func mul_int64_0_ssa(a int64) int64 { + switch { + } + return a * 0 +} +func mul_0_int64_ssa(a int64) int64 { + switch { + } + return 0 * a +} + +func mul_int64_1_ssa(a int64) int64 { + switch { + } + return a * 1 +} +func mul_1_int64_ssa(a int64) int64 { + switch { + } + return 1 * a +} + +func mul_int64_4294967296_ssa(a int64) int64 { + switch { + } + return a * 4294967296 +} +func mul_4294967296_int64_ssa(a int64) int64 { + switch { + } + return 4294967296 * a +} + +func mul_int64_9223372036854775806_ssa(a int64) int64 { + switch { + } + return a * 9223372036854775806 +} +func mul_9223372036854775806_int64_ssa(a int64) int64 { + switch { + } + return 9223372036854775806 * a +} + +func mul_int64_9223372036854775807_ssa(a int64) int64 { + switch { + } + return a * 9223372036854775807 +} +func mul_9223372036854775807_int64_ssa(a int64) int64 { + switch { + } + return 9223372036854775807 * a +} + +func add_uint32_0_ssa(a uint32) uint32 { + switch { + } + return a + 0 +} +func add_0_uint32_ssa(a uint32) uint32 { + switch { + } + return 0 + a +} + +func add_uint32_1_ssa(a uint32) uint32 { + switch { + } + return a + 1 +} +func add_1_uint32_ssa(a uint32) uint32 { + switch { + } + return 1 + a +} + +func add_uint32_4294967295_ssa(a uint32) uint32 { + switch { + } + return a + 4294967295 +} +func add_4294967295_uint32_ssa(a uint32) uint32 { + switch { + } + return 4294967295 + a +} + +func sub_uint32_0_ssa(a uint32) uint32 { + switch { + } + return a - 0 +} +func sub_0_uint32_ssa(a uint32) uint32 { + switch { + } + return 0 - a +} + +func sub_uint32_1_ssa(a uint32) uint32 { + switch { + } + return a - 1 +} +func sub_1_uint32_ssa(a uint32) uint32 { + switch { + } + return 1 - a +} + +func sub_uint32_4294967295_ssa(a uint32) uint32 { + switch { + } + return a - 4294967295 +} +func sub_4294967295_uint32_ssa(a uint32) uint32 { + switch { + } + return 4294967295 - a +} + +func div_0_uint32_ssa(a uint32) uint32 { + switch { + } + return 0 / a +} + +func div_uint32_1_ssa(a uint32) uint32 { + switch { + } + return a / 1 +} +func div_1_uint32_ssa(a uint32) uint32 { + switch { + } + return 1 / a +} + +func div_uint32_4294967295_ssa(a uint32) uint32 { + switch { + } + return a / 4294967295 +} +func div_4294967295_uint32_ssa(a uint32) uint32 { + switch { + } + return 4294967295 / a +} + +func mul_uint32_0_ssa(a uint32) uint32 { + switch { + } + return a * 0 +} +func mul_0_uint32_ssa(a uint32) uint32 { + switch { + } + return 0 * a +} + +func mul_uint32_1_ssa(a uint32) uint32 { + switch { + } + return a * 1 +} +func mul_1_uint32_ssa(a uint32) uint32 { + switch { + } + return 1 * a +} + +func mul_uint32_4294967295_ssa(a uint32) uint32 { + switch { + } + return a * 4294967295 +} +func mul_4294967295_uint32_ssa(a uint32) uint32 { + switch { + } + return 4294967295 * a +} + +func add_int32_Neg2147483648_ssa(a int32) int32 { + switch { + } + return a + -2147483648 +} +func add_Neg2147483648_int32_ssa(a int32) int32 { + switch { + } + return -2147483648 + a +} + +func add_int32_Neg2147483647_ssa(a int32) int32 { + switch { + } + return a + -2147483647 +} +func add_Neg2147483647_int32_ssa(a int32) int32 { + switch { + } + return -2147483647 + a +} + +func add_int32_Neg1_ssa(a int32) int32 { + switch { + } + return a + -1 +} +func add_Neg1_int32_ssa(a int32) int32 { + switch { + } + return -1 + a +} + +func add_int32_0_ssa(a int32) int32 { + switch { + } + return a + 0 +} +func add_0_int32_ssa(a int32) int32 { + switch { + } + return 0 + a +} + +func add_int32_1_ssa(a int32) int32 { + switch { + } + return a + 1 +} +func add_1_int32_ssa(a int32) int32 { + switch { + } + return 1 + a +} + +func add_int32_2147483647_ssa(a int32) int32 { + switch { + } + return a + 2147483647 +} +func add_2147483647_int32_ssa(a int32) int32 { + switch { + } + return 2147483647 + a +} + +func sub_int32_Neg2147483648_ssa(a int32) int32 { + switch { + } + return a - -2147483648 +} +func sub_Neg2147483648_int32_ssa(a int32) int32 { + switch { + } + return -2147483648 - a +} + +func sub_int32_Neg2147483647_ssa(a int32) int32 { + switch { + } + return a - -2147483647 +} +func sub_Neg2147483647_int32_ssa(a int32) int32 { + switch { + } + return -2147483647 - a +} + +func sub_int32_Neg1_ssa(a int32) int32 { + switch { + } + return a - -1 +} +func sub_Neg1_int32_ssa(a int32) int32 { + switch { + } + return -1 - a +} + +func sub_int32_0_ssa(a int32) int32 { + switch { + } + return a - 0 +} +func sub_0_int32_ssa(a int32) int32 { + switch { + } + return 0 - a +} + +func sub_int32_1_ssa(a int32) int32 { + switch { + } + return a - 1 +} +func sub_1_int32_ssa(a int32) int32 { + switch { + } + return 1 - a +} + +func sub_int32_2147483647_ssa(a int32) int32 { + switch { + } + return a - 2147483647 +} +func sub_2147483647_int32_ssa(a int32) int32 { + switch { + } + return 2147483647 - a +} + +func div_int32_Neg2147483648_ssa(a int32) int32 { + switch { + } + return a / -2147483648 +} +func div_Neg2147483648_int32_ssa(a int32) int32 { + switch { + } + return -2147483648 / a +} + +func div_int32_Neg2147483647_ssa(a int32) int32 { + switch { + } + return a / -2147483647 +} +func div_Neg2147483647_int32_ssa(a int32) int32 { + switch { + } + return -2147483647 / a +} + +func div_int32_Neg1_ssa(a int32) int32 { + switch { + } + return a / -1 +} +func div_Neg1_int32_ssa(a int32) int32 { + switch { + } + return -1 / a +} + +func div_0_int32_ssa(a int32) int32 { + switch { + } + return 0 / a +} + +func div_int32_1_ssa(a int32) int32 { + switch { + } + return a / 1 +} +func div_1_int32_ssa(a int32) int32 { + switch { + } + return 1 / a +} + +func div_int32_2147483647_ssa(a int32) int32 { + switch { + } + return a / 2147483647 +} +func div_2147483647_int32_ssa(a int32) int32 { + switch { + } + return 2147483647 / a +} + +func mul_int32_Neg2147483648_ssa(a int32) int32 { + switch { + } + return a * -2147483648 +} +func mul_Neg2147483648_int32_ssa(a int32) int32 { + switch { + } + return -2147483648 * a +} + +func mul_int32_Neg2147483647_ssa(a int32) int32 { + switch { + } + return a * -2147483647 +} +func mul_Neg2147483647_int32_ssa(a int32) int32 { + switch { + } + return -2147483647 * a +} + +func mul_int32_Neg1_ssa(a int32) int32 { + switch { + } + return a * -1 +} +func mul_Neg1_int32_ssa(a int32) int32 { + switch { + } + return -1 * a +} + +func mul_int32_0_ssa(a int32) int32 { + switch { + } + return a * 0 +} +func mul_0_int32_ssa(a int32) int32 { + switch { + } + return 0 * a +} + +func mul_int32_1_ssa(a int32) int32 { + switch { + } + return a * 1 +} +func mul_1_int32_ssa(a int32) int32 { + switch { + } + return 1 * a +} + +func mul_int32_2147483647_ssa(a int32) int32 { + switch { + } + return a * 2147483647 +} +func mul_2147483647_int32_ssa(a int32) int32 { + switch { + } + return 2147483647 * a +} + +func add_uint16_0_ssa(a uint16) uint16 { + switch { + } + return a + 0 +} +func add_0_uint16_ssa(a uint16) uint16 { + switch { + } + return 0 + a +} + +func add_uint16_1_ssa(a uint16) uint16 { + switch { + } + return a + 1 +} +func add_1_uint16_ssa(a uint16) uint16 { + switch { + } + return 1 + a +} + +func add_uint16_65535_ssa(a uint16) uint16 { + switch { + } + return a + 65535 +} +func add_65535_uint16_ssa(a uint16) uint16 { + switch { + } + return 65535 + a +} + +func sub_uint16_0_ssa(a uint16) uint16 { + switch { + } + return a - 0 +} +func sub_0_uint16_ssa(a uint16) uint16 { + switch { + } + return 0 - a +} + +func sub_uint16_1_ssa(a uint16) uint16 { + switch { + } + return a - 1 +} +func sub_1_uint16_ssa(a uint16) uint16 { + switch { + } + return 1 - a +} + +func sub_uint16_65535_ssa(a uint16) uint16 { + switch { + } + return a - 65535 +} +func sub_65535_uint16_ssa(a uint16) uint16 { + switch { + } + return 65535 - a +} + +func div_0_uint16_ssa(a uint16) uint16 { + switch { + } + return 0 / a +} + +func div_uint16_1_ssa(a uint16) uint16 { + switch { + } + return a / 1 +} +func div_1_uint16_ssa(a uint16) uint16 { + switch { + } + return 1 / a +} + +func div_uint16_65535_ssa(a uint16) uint16 { + switch { + } + return a / 65535 +} +func div_65535_uint16_ssa(a uint16) uint16 { + switch { + } + return 65535 / a +} + +func mul_uint16_0_ssa(a uint16) uint16 { + switch { + } + return a * 0 +} +func mul_0_uint16_ssa(a uint16) uint16 { + switch { + } + return 0 * a +} + +func mul_uint16_1_ssa(a uint16) uint16 { + switch { + } + return a * 1 +} +func mul_1_uint16_ssa(a uint16) uint16 { + switch { + } + return 1 * a +} + +func mul_uint16_65535_ssa(a uint16) uint16 { + switch { + } + return a * 65535 +} +func mul_65535_uint16_ssa(a uint16) uint16 { + switch { + } + return 65535 * a +} + +func add_int16_Neg32768_ssa(a int16) int16 { + switch { + } + return a + -32768 +} +func add_Neg32768_int16_ssa(a int16) int16 { + switch { + } + return -32768 + a +} + +func add_int16_Neg32767_ssa(a int16) int16 { + switch { + } + return a + -32767 +} +func add_Neg32767_int16_ssa(a int16) int16 { + switch { + } + return -32767 + a +} + +func add_int16_Neg1_ssa(a int16) int16 { + switch { + } + return a + -1 +} +func add_Neg1_int16_ssa(a int16) int16 { + switch { + } + return -1 + a +} + +func add_int16_0_ssa(a int16) int16 { + switch { + } + return a + 0 +} +func add_0_int16_ssa(a int16) int16 { + switch { + } + return 0 + a +} + +func add_int16_1_ssa(a int16) int16 { + switch { + } + return a + 1 +} +func add_1_int16_ssa(a int16) int16 { + switch { + } + return 1 + a +} + +func add_int16_32766_ssa(a int16) int16 { + switch { + } + return a + 32766 +} +func add_32766_int16_ssa(a int16) int16 { + switch { + } + return 32766 + a +} + +func add_int16_32767_ssa(a int16) int16 { + switch { + } + return a + 32767 +} +func add_32767_int16_ssa(a int16) int16 { + switch { + } + return 32767 + a +} + +func sub_int16_Neg32768_ssa(a int16) int16 { + switch { + } + return a - -32768 +} +func sub_Neg32768_int16_ssa(a int16) int16 { + switch { + } + return -32768 - a +} + +func sub_int16_Neg32767_ssa(a int16) int16 { + switch { + } + return a - -32767 +} +func sub_Neg32767_int16_ssa(a int16) int16 { + switch { + } + return -32767 - a +} + +func sub_int16_Neg1_ssa(a int16) int16 { + switch { + } + return a - -1 +} +func sub_Neg1_int16_ssa(a int16) int16 { + switch { + } + return -1 - a +} + +func sub_int16_0_ssa(a int16) int16 { + switch { + } + return a - 0 +} +func sub_0_int16_ssa(a int16) int16 { + switch { + } + return 0 - a +} + +func sub_int16_1_ssa(a int16) int16 { + switch { + } + return a - 1 +} +func sub_1_int16_ssa(a int16) int16 { + switch { + } + return 1 - a +} + +func sub_int16_32766_ssa(a int16) int16 { + switch { + } + return a - 32766 +} +func sub_32766_int16_ssa(a int16) int16 { + switch { + } + return 32766 - a +} + +func sub_int16_32767_ssa(a int16) int16 { + switch { + } + return a - 32767 +} +func sub_32767_int16_ssa(a int16) int16 { + switch { + } + return 32767 - a +} + +func div_int16_Neg32768_ssa(a int16) int16 { + switch { + } + return a / -32768 +} +func div_Neg32768_int16_ssa(a int16) int16 { + switch { + } + return -32768 / a +} + +func div_int16_Neg32767_ssa(a int16) int16 { + switch { + } + return a / -32767 +} +func div_Neg32767_int16_ssa(a int16) int16 { + switch { + } + return -32767 / a +} + +func div_int16_Neg1_ssa(a int16) int16 { + switch { + } + return a / -1 +} +func div_Neg1_int16_ssa(a int16) int16 { + switch { + } + return -1 / a +} + +func div_0_int16_ssa(a int16) int16 { + switch { + } + return 0 / a +} + +func div_int16_1_ssa(a int16) int16 { + switch { + } + return a / 1 +} +func div_1_int16_ssa(a int16) int16 { + switch { + } + return 1 / a +} + +func div_int16_32766_ssa(a int16) int16 { + switch { + } + return a / 32766 +} +func div_32766_int16_ssa(a int16) int16 { + switch { + } + return 32766 / a +} + +func div_int16_32767_ssa(a int16) int16 { + switch { + } + return a / 32767 +} +func div_32767_int16_ssa(a int16) int16 { + switch { + } + return 32767 / a +} + +func mul_int16_Neg32768_ssa(a int16) int16 { + switch { + } + return a * -32768 +} +func mul_Neg32768_int16_ssa(a int16) int16 { + switch { + } + return -32768 * a +} + +func mul_int16_Neg32767_ssa(a int16) int16 { + switch { + } + return a * -32767 +} +func mul_Neg32767_int16_ssa(a int16) int16 { + switch { + } + return -32767 * a +} + +func mul_int16_Neg1_ssa(a int16) int16 { + switch { + } + return a * -1 +} +func mul_Neg1_int16_ssa(a int16) int16 { + switch { + } + return -1 * a +} + +func mul_int16_0_ssa(a int16) int16 { + switch { + } + return a * 0 +} +func mul_0_int16_ssa(a int16) int16 { + switch { + } + return 0 * a +} + +func mul_int16_1_ssa(a int16) int16 { + switch { + } + return a * 1 +} +func mul_1_int16_ssa(a int16) int16 { + switch { + } + return 1 * a +} + +func mul_int16_32766_ssa(a int16) int16 { + switch { + } + return a * 32766 +} +func mul_32766_int16_ssa(a int16) int16 { + switch { + } + return 32766 * a +} + +func mul_int16_32767_ssa(a int16) int16 { + switch { + } + return a * 32767 +} +func mul_32767_int16_ssa(a int16) int16 { + switch { + } + return 32767 * a +} + +func add_uint8_0_ssa(a uint8) uint8 { + switch { + } + return a + 0 +} +func add_0_uint8_ssa(a uint8) uint8 { + switch { + } + return 0 + a +} + +func add_uint8_1_ssa(a uint8) uint8 { + switch { + } + return a + 1 +} +func add_1_uint8_ssa(a uint8) uint8 { + switch { + } + return 1 + a +} + +func add_uint8_255_ssa(a uint8) uint8 { + switch { + } + return a + 255 +} +func add_255_uint8_ssa(a uint8) uint8 { + switch { + } + return 255 + a +} + +func sub_uint8_0_ssa(a uint8) uint8 { + switch { + } + return a - 0 +} +func sub_0_uint8_ssa(a uint8) uint8 { + switch { + } + return 0 - a +} + +func sub_uint8_1_ssa(a uint8) uint8 { + switch { + } + return a - 1 +} +func sub_1_uint8_ssa(a uint8) uint8 { + switch { + } + return 1 - a +} + +func sub_uint8_255_ssa(a uint8) uint8 { + switch { + } + return a - 255 +} +func sub_255_uint8_ssa(a uint8) uint8 { + switch { + } + return 255 - a +} + +func div_0_uint8_ssa(a uint8) uint8 { + switch { + } + return 0 / a +} + +func div_uint8_1_ssa(a uint8) uint8 { + switch { + } + return a / 1 +} +func div_1_uint8_ssa(a uint8) uint8 { + switch { + } + return 1 / a +} + +func div_uint8_255_ssa(a uint8) uint8 { + switch { + } + return a / 255 +} +func div_255_uint8_ssa(a uint8) uint8 { + switch { + } + return 255 / a +} + +func mul_uint8_0_ssa(a uint8) uint8 { + switch { + } + return a * 0 +} +func mul_0_uint8_ssa(a uint8) uint8 { + switch { + } + return 0 * a +} + +func mul_uint8_1_ssa(a uint8) uint8 { + switch { + } + return a * 1 +} +func mul_1_uint8_ssa(a uint8) uint8 { + switch { + } + return 1 * a +} + +func mul_uint8_255_ssa(a uint8) uint8 { + switch { + } + return a * 255 +} +func mul_255_uint8_ssa(a uint8) uint8 { + switch { + } + return 255 * a +} + +func add_int8_Neg128_ssa(a int8) int8 { + switch { + } + return a + -128 +} +func add_Neg128_int8_ssa(a int8) int8 { + switch { + } + return -128 + a +} + +func add_int8_Neg127_ssa(a int8) int8 { + switch { + } + return a + -127 +} +func add_Neg127_int8_ssa(a int8) int8 { + switch { + } + return -127 + a +} + +func add_int8_Neg1_ssa(a int8) int8 { + switch { + } + return a + -1 +} +func add_Neg1_int8_ssa(a int8) int8 { + switch { + } + return -1 + a +} + +func add_int8_0_ssa(a int8) int8 { + switch { + } + return a + 0 +} +func add_0_int8_ssa(a int8) int8 { + switch { + } + return 0 + a +} + +func add_int8_1_ssa(a int8) int8 { + switch { + } + return a + 1 +} +func add_1_int8_ssa(a int8) int8 { + switch { + } + return 1 + a +} + +func add_int8_126_ssa(a int8) int8 { + switch { + } + return a + 126 +} +func add_126_int8_ssa(a int8) int8 { + switch { + } + return 126 + a +} + +func add_int8_127_ssa(a int8) int8 { + switch { + } + return a + 127 +} +func add_127_int8_ssa(a int8) int8 { + switch { + } + return 127 + a +} + +func sub_int8_Neg128_ssa(a int8) int8 { + switch { + } + return a - -128 +} +func sub_Neg128_int8_ssa(a int8) int8 { + switch { + } + return -128 - a +} + +func sub_int8_Neg127_ssa(a int8) int8 { + switch { + } + return a - -127 +} +func sub_Neg127_int8_ssa(a int8) int8 { + switch { + } + return -127 - a +} + +func sub_int8_Neg1_ssa(a int8) int8 { + switch { + } + return a - -1 +} +func sub_Neg1_int8_ssa(a int8) int8 { + switch { + } + return -1 - a +} + +func sub_int8_0_ssa(a int8) int8 { + switch { + } + return a - 0 +} +func sub_0_int8_ssa(a int8) int8 { + switch { + } + return 0 - a +} + +func sub_int8_1_ssa(a int8) int8 { + switch { + } + return a - 1 +} +func sub_1_int8_ssa(a int8) int8 { + switch { + } + return 1 - a +} + +func sub_int8_126_ssa(a int8) int8 { + switch { + } + return a - 126 +} +func sub_126_int8_ssa(a int8) int8 { + switch { + } + return 126 - a +} + +func sub_int8_127_ssa(a int8) int8 { + switch { + } + return a - 127 +} +func sub_127_int8_ssa(a int8) int8 { + switch { + } + return 127 - a +} + +func div_int8_Neg128_ssa(a int8) int8 { + switch { + } + return a / -128 +} +func div_Neg128_int8_ssa(a int8) int8 { + switch { + } + return -128 / a +} + +func div_int8_Neg127_ssa(a int8) int8 { + switch { + } + return a / -127 +} +func div_Neg127_int8_ssa(a int8) int8 { + switch { + } + return -127 / a +} + +func div_int8_Neg1_ssa(a int8) int8 { + switch { + } + return a / -1 +} +func div_Neg1_int8_ssa(a int8) int8 { + switch { + } + return -1 / a +} + +func div_0_int8_ssa(a int8) int8 { + switch { + } + return 0 / a +} + +func div_int8_1_ssa(a int8) int8 { + switch { + } + return a / 1 +} +func div_1_int8_ssa(a int8) int8 { + switch { + } + return 1 / a +} + +func div_int8_126_ssa(a int8) int8 { + switch { + } + return a / 126 +} +func div_126_int8_ssa(a int8) int8 { + switch { + } + return 126 / a +} + +func div_int8_127_ssa(a int8) int8 { + switch { + } + return a / 127 +} +func div_127_int8_ssa(a int8) int8 { + switch { + } + return 127 / a +} + +func mul_int8_Neg128_ssa(a int8) int8 { + switch { + } + return a * -128 +} +func mul_Neg128_int8_ssa(a int8) int8 { + switch { + } + return -128 * a +} + +func mul_int8_Neg127_ssa(a int8) int8 { + switch { + } + return a * -127 +} +func mul_Neg127_int8_ssa(a int8) int8 { + switch { + } + return -127 * a +} + +func mul_int8_Neg1_ssa(a int8) int8 { + switch { + } + return a * -1 +} +func mul_Neg1_int8_ssa(a int8) int8 { + switch { + } + return -1 * a +} + +func mul_int8_0_ssa(a int8) int8 { + switch { + } + return a * 0 +} +func mul_0_int8_ssa(a int8) int8 { + switch { + } + return 0 * a +} + +func mul_int8_1_ssa(a int8) int8 { + switch { + } + return a * 1 +} +func mul_1_int8_ssa(a int8) int8 { + switch { + } + return 1 * a +} + +func mul_int8_126_ssa(a int8) int8 { + switch { + } + return a * 126 +} +func mul_126_int8_ssa(a int8) int8 { + switch { + } + return 126 * a +} + +func mul_int8_127_ssa(a int8) int8 { + switch { + } + return a * 127 +} +func mul_127_int8_ssa(a int8) int8 { + switch { + } + return 127 * a +} + +var failed bool + +func main() { + + if got := div_0_uint64_ssa(1); got != 0 { + fmt.Printf("div_uint64 0/1 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_uint64_ssa(4294967296); got != 0 { + fmt.Printf("div_uint64 0/4294967296 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_uint64_ssa(18446744073709551615); got != 0 { + fmt.Printf("div_uint64 0/18446744073709551615 = %d, wanted 0\n", got) + failed = true + } + + if got := div_uint64_1_ssa(0); got != 0 { + fmt.Printf("div_uint64 0/1 = %d, wanted 0\n", got) + failed = true + } + + if got := div_1_uint64_ssa(1); got != 1 { + fmt.Printf("div_uint64 1/1 = %d, wanted 1\n", got) + failed = true + } + + if got := div_uint64_1_ssa(1); got != 1 { + fmt.Printf("div_uint64 1/1 = %d, wanted 1\n", got) + failed = true + } + + if got := div_1_uint64_ssa(4294967296); got != 0 { + fmt.Printf("div_uint64 1/4294967296 = %d, wanted 0\n", got) + failed = true + } + + if got := div_uint64_1_ssa(4294967296); got != 4294967296 { + fmt.Printf("div_uint64 4294967296/1 = %d, wanted 4294967296\n", got) + failed = true + } + + if got := div_1_uint64_ssa(18446744073709551615); got != 0 { + fmt.Printf("div_uint64 1/18446744073709551615 = %d, wanted 0\n", got) + failed = true + } + + if got := div_uint64_1_ssa(18446744073709551615); got != 18446744073709551615 { + fmt.Printf("div_uint64 18446744073709551615/1 = %d, wanted 18446744073709551615\n", got) + failed = true + } + + if got := div_uint64_4294967296_ssa(0); got != 0 { + fmt.Printf("div_uint64 0/4294967296 = %d, wanted 0\n", got) + failed = true + } + + if got := div_4294967296_uint64_ssa(1); got != 4294967296 { + fmt.Printf("div_uint64 4294967296/1 = %d, wanted 4294967296\n", got) + failed = true + } + + if got := div_uint64_4294967296_ssa(1); got != 0 { + fmt.Printf("div_uint64 1/4294967296 = %d, wanted 0\n", got) + failed = true + } + + if got := div_4294967296_uint64_ssa(4294967296); got != 1 { + fmt.Printf("div_uint64 4294967296/4294967296 = %d, wanted 1\n", got) + failed = true + } + + if got := div_uint64_4294967296_ssa(4294967296); got != 1 { + fmt.Printf("div_uint64 4294967296/4294967296 = %d, wanted 1\n", got) + failed = true + } + + if got := div_4294967296_uint64_ssa(18446744073709551615); got != 0 { + fmt.Printf("div_uint64 4294967296/18446744073709551615 = %d, wanted 0\n", got) + failed = true + } + + if got := div_uint64_4294967296_ssa(18446744073709551615); got != 4294967295 { + fmt.Printf("div_uint64 18446744073709551615/4294967296 = %d, wanted 4294967295\n", got) + failed = true + } + + if got := div_uint64_18446744073709551615_ssa(0); got != 0 { + fmt.Printf("div_uint64 0/18446744073709551615 = %d, wanted 0\n", got) + failed = true + } + + if got := div_18446744073709551615_uint64_ssa(1); got != 18446744073709551615 { + fmt.Printf("div_uint64 18446744073709551615/1 = %d, wanted 18446744073709551615\n", got) + failed = true + } + + if got := div_uint64_18446744073709551615_ssa(1); got != 0 { + fmt.Printf("div_uint64 1/18446744073709551615 = %d, wanted 0\n", got) + failed = true + } + + if got := div_18446744073709551615_uint64_ssa(4294967296); got != 4294967295 { + fmt.Printf("div_uint64 18446744073709551615/4294967296 = %d, wanted 4294967295\n", got) + failed = true + } + + if got := div_uint64_18446744073709551615_ssa(4294967296); got != 0 { + fmt.Printf("div_uint64 4294967296/18446744073709551615 = %d, wanted 0\n", got) + failed = true + } + + if got := div_18446744073709551615_uint64_ssa(18446744073709551615); got != 1 { + fmt.Printf("div_uint64 18446744073709551615/18446744073709551615 = %d, wanted 1\n", got) + failed = true + } + + if got := div_uint64_18446744073709551615_ssa(18446744073709551615); got != 1 { + fmt.Printf("div_uint64 18446744073709551615/18446744073709551615 = %d, wanted 1\n", got) + failed = true + } + + if got := div_Neg9223372036854775808_int64_ssa(-9223372036854775808); got != 1 { + fmt.Printf("div_int64 -9223372036854775808/-9223372036854775808 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int64_Neg9223372036854775808_ssa(-9223372036854775808); got != 1 { + fmt.Printf("div_int64 -9223372036854775808/-9223372036854775808 = %d, wanted 1\n", got) + failed = true + } + + if got := div_Neg9223372036854775808_int64_ssa(-9223372036854775807); got != 1 { + fmt.Printf("div_int64 -9223372036854775808/-9223372036854775807 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int64_Neg9223372036854775808_ssa(-9223372036854775807); got != 0 { + fmt.Printf("div_int64 -9223372036854775807/-9223372036854775808 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg9223372036854775808_int64_ssa(-4294967296); got != 2147483648 { + fmt.Printf("div_int64 -9223372036854775808/-4294967296 = %d, wanted 2147483648\n", got) + failed = true + } + + if got := div_int64_Neg9223372036854775808_ssa(-4294967296); got != 0 { + fmt.Printf("div_int64 -4294967296/-9223372036854775808 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg9223372036854775808_int64_ssa(-1); got != -9223372036854775808 { + fmt.Printf("div_int64 -9223372036854775808/-1 = %d, wanted -9223372036854775808\n", got) + failed = true + } + + if got := div_int64_Neg9223372036854775808_ssa(-1); got != 0 { + fmt.Printf("div_int64 -1/-9223372036854775808 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_Neg9223372036854775808_ssa(0); got != 0 { + fmt.Printf("div_int64 0/-9223372036854775808 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg9223372036854775808_int64_ssa(1); got != -9223372036854775808 { + fmt.Printf("div_int64 -9223372036854775808/1 = %d, wanted -9223372036854775808\n", got) + failed = true + } + + if got := div_int64_Neg9223372036854775808_ssa(1); got != 0 { + fmt.Printf("div_int64 1/-9223372036854775808 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg9223372036854775808_int64_ssa(4294967296); got != -2147483648 { + fmt.Printf("div_int64 -9223372036854775808/4294967296 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := div_int64_Neg9223372036854775808_ssa(4294967296); got != 0 { + fmt.Printf("div_int64 4294967296/-9223372036854775808 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg9223372036854775808_int64_ssa(9223372036854775806); got != -1 { + fmt.Printf("div_int64 -9223372036854775808/9223372036854775806 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int64_Neg9223372036854775808_ssa(9223372036854775806); got != 0 { + fmt.Printf("div_int64 9223372036854775806/-9223372036854775808 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg9223372036854775808_int64_ssa(9223372036854775807); got != -1 { + fmt.Printf("div_int64 -9223372036854775808/9223372036854775807 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int64_Neg9223372036854775808_ssa(9223372036854775807); got != 0 { + fmt.Printf("div_int64 9223372036854775807/-9223372036854775808 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg9223372036854775807_int64_ssa(-9223372036854775808); got != 0 { + fmt.Printf("div_int64 -9223372036854775807/-9223372036854775808 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_Neg9223372036854775807_ssa(-9223372036854775808); got != 1 { + fmt.Printf("div_int64 -9223372036854775808/-9223372036854775807 = %d, wanted 1\n", got) + failed = true + } + + if got := div_Neg9223372036854775807_int64_ssa(-9223372036854775807); got != 1 { + fmt.Printf("div_int64 -9223372036854775807/-9223372036854775807 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int64_Neg9223372036854775807_ssa(-9223372036854775807); got != 1 { + fmt.Printf("div_int64 -9223372036854775807/-9223372036854775807 = %d, wanted 1\n", got) + failed = true + } + + if got := div_Neg9223372036854775807_int64_ssa(-4294967296); got != 2147483647 { + fmt.Printf("div_int64 -9223372036854775807/-4294967296 = %d, wanted 2147483647\n", got) + failed = true + } + + if got := div_int64_Neg9223372036854775807_ssa(-4294967296); got != 0 { + fmt.Printf("div_int64 -4294967296/-9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg9223372036854775807_int64_ssa(-1); got != 9223372036854775807 { + fmt.Printf("div_int64 -9223372036854775807/-1 = %d, wanted 9223372036854775807\n", got) + failed = true + } + + if got := div_int64_Neg9223372036854775807_ssa(-1); got != 0 { + fmt.Printf("div_int64 -1/-9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_Neg9223372036854775807_ssa(0); got != 0 { + fmt.Printf("div_int64 0/-9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg9223372036854775807_int64_ssa(1); got != -9223372036854775807 { + fmt.Printf("div_int64 -9223372036854775807/1 = %d, wanted -9223372036854775807\n", got) + failed = true + } + + if got := div_int64_Neg9223372036854775807_ssa(1); got != 0 { + fmt.Printf("div_int64 1/-9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg9223372036854775807_int64_ssa(4294967296); got != -2147483647 { + fmt.Printf("div_int64 -9223372036854775807/4294967296 = %d, wanted -2147483647\n", got) + failed = true + } + + if got := div_int64_Neg9223372036854775807_ssa(4294967296); got != 0 { + fmt.Printf("div_int64 4294967296/-9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg9223372036854775807_int64_ssa(9223372036854775806); got != -1 { + fmt.Printf("div_int64 -9223372036854775807/9223372036854775806 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int64_Neg9223372036854775807_ssa(9223372036854775806); got != 0 { + fmt.Printf("div_int64 9223372036854775806/-9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg9223372036854775807_int64_ssa(9223372036854775807); got != -1 { + fmt.Printf("div_int64 -9223372036854775807/9223372036854775807 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int64_Neg9223372036854775807_ssa(9223372036854775807); got != -1 { + fmt.Printf("div_int64 9223372036854775807/-9223372036854775807 = %d, wanted -1\n", got) + failed = true + } + + if got := div_Neg4294967296_int64_ssa(-9223372036854775808); got != 0 { + fmt.Printf("div_int64 -4294967296/-9223372036854775808 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_Neg4294967296_ssa(-9223372036854775808); got != 2147483648 { + fmt.Printf("div_int64 -9223372036854775808/-4294967296 = %d, wanted 2147483648\n", got) + failed = true + } + + if got := div_Neg4294967296_int64_ssa(-9223372036854775807); got != 0 { + fmt.Printf("div_int64 -4294967296/-9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_Neg4294967296_ssa(-9223372036854775807); got != 2147483647 { + fmt.Printf("div_int64 -9223372036854775807/-4294967296 = %d, wanted 2147483647\n", got) + failed = true + } + + if got := div_Neg4294967296_int64_ssa(-4294967296); got != 1 { + fmt.Printf("div_int64 -4294967296/-4294967296 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int64_Neg4294967296_ssa(-4294967296); got != 1 { + fmt.Printf("div_int64 -4294967296/-4294967296 = %d, wanted 1\n", got) + failed = true + } + + if got := div_Neg4294967296_int64_ssa(-1); got != 4294967296 { + fmt.Printf("div_int64 -4294967296/-1 = %d, wanted 4294967296\n", got) + failed = true + } + + if got := div_int64_Neg4294967296_ssa(-1); got != 0 { + fmt.Printf("div_int64 -1/-4294967296 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_Neg4294967296_ssa(0); got != 0 { + fmt.Printf("div_int64 0/-4294967296 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg4294967296_int64_ssa(1); got != -4294967296 { + fmt.Printf("div_int64 -4294967296/1 = %d, wanted -4294967296\n", got) + failed = true + } + + if got := div_int64_Neg4294967296_ssa(1); got != 0 { + fmt.Printf("div_int64 1/-4294967296 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg4294967296_int64_ssa(4294967296); got != -1 { + fmt.Printf("div_int64 -4294967296/4294967296 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int64_Neg4294967296_ssa(4294967296); got != -1 { + fmt.Printf("div_int64 4294967296/-4294967296 = %d, wanted -1\n", got) + failed = true + } + + if got := div_Neg4294967296_int64_ssa(9223372036854775806); got != 0 { + fmt.Printf("div_int64 -4294967296/9223372036854775806 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_Neg4294967296_ssa(9223372036854775806); got != -2147483647 { + fmt.Printf("div_int64 9223372036854775806/-4294967296 = %d, wanted -2147483647\n", got) + failed = true + } + + if got := div_Neg4294967296_int64_ssa(9223372036854775807); got != 0 { + fmt.Printf("div_int64 -4294967296/9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_Neg4294967296_ssa(9223372036854775807); got != -2147483647 { + fmt.Printf("div_int64 9223372036854775807/-4294967296 = %d, wanted -2147483647\n", got) + failed = true + } + + if got := div_Neg1_int64_ssa(-9223372036854775808); got != 0 { + fmt.Printf("div_int64 -1/-9223372036854775808 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_Neg1_ssa(-9223372036854775808); got != -9223372036854775808 { + fmt.Printf("div_int64 -9223372036854775808/-1 = %d, wanted -9223372036854775808\n", got) + failed = true + } + + if got := div_Neg1_int64_ssa(-9223372036854775807); got != 0 { + fmt.Printf("div_int64 -1/-9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_Neg1_ssa(-9223372036854775807); got != 9223372036854775807 { + fmt.Printf("div_int64 -9223372036854775807/-1 = %d, wanted 9223372036854775807\n", got) + failed = true + } + + if got := div_Neg1_int64_ssa(-4294967296); got != 0 { + fmt.Printf("div_int64 -1/-4294967296 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_Neg1_ssa(-4294967296); got != 4294967296 { + fmt.Printf("div_int64 -4294967296/-1 = %d, wanted 4294967296\n", got) + failed = true + } + + if got := div_Neg1_int64_ssa(-1); got != 1 { + fmt.Printf("div_int64 -1/-1 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int64_Neg1_ssa(-1); got != 1 { + fmt.Printf("div_int64 -1/-1 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int64_Neg1_ssa(0); got != 0 { + fmt.Printf("div_int64 0/-1 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg1_int64_ssa(1); got != -1 { + fmt.Printf("div_int64 -1/1 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int64_Neg1_ssa(1); got != -1 { + fmt.Printf("div_int64 1/-1 = %d, wanted -1\n", got) + failed = true + } + + if got := div_Neg1_int64_ssa(4294967296); got != 0 { + fmt.Printf("div_int64 -1/4294967296 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_Neg1_ssa(4294967296); got != -4294967296 { + fmt.Printf("div_int64 4294967296/-1 = %d, wanted -4294967296\n", got) + failed = true + } + + if got := div_Neg1_int64_ssa(9223372036854775806); got != 0 { + fmt.Printf("div_int64 -1/9223372036854775806 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_Neg1_ssa(9223372036854775806); got != -9223372036854775806 { + fmt.Printf("div_int64 9223372036854775806/-1 = %d, wanted -9223372036854775806\n", got) + failed = true + } + + if got := div_Neg1_int64_ssa(9223372036854775807); got != 0 { + fmt.Printf("div_int64 -1/9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_Neg1_ssa(9223372036854775807); got != -9223372036854775807 { + fmt.Printf("div_int64 9223372036854775807/-1 = %d, wanted -9223372036854775807\n", got) + failed = true + } + + if got := div_0_int64_ssa(-9223372036854775808); got != 0 { + fmt.Printf("div_int64 0/-9223372036854775808 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_int64_ssa(-9223372036854775807); got != 0 { + fmt.Printf("div_int64 0/-9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_int64_ssa(-4294967296); got != 0 { + fmt.Printf("div_int64 0/-4294967296 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_int64_ssa(-1); got != 0 { + fmt.Printf("div_int64 0/-1 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_int64_ssa(1); got != 0 { + fmt.Printf("div_int64 0/1 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_int64_ssa(4294967296); got != 0 { + fmt.Printf("div_int64 0/4294967296 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_int64_ssa(9223372036854775806); got != 0 { + fmt.Printf("div_int64 0/9223372036854775806 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_int64_ssa(9223372036854775807); got != 0 { + fmt.Printf("div_int64 0/9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := div_1_int64_ssa(-9223372036854775808); got != 0 { + fmt.Printf("div_int64 1/-9223372036854775808 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_1_ssa(-9223372036854775808); got != -9223372036854775808 { + fmt.Printf("div_int64 -9223372036854775808/1 = %d, wanted -9223372036854775808\n", got) + failed = true + } + + if got := div_1_int64_ssa(-9223372036854775807); got != 0 { + fmt.Printf("div_int64 1/-9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_1_ssa(-9223372036854775807); got != -9223372036854775807 { + fmt.Printf("div_int64 -9223372036854775807/1 = %d, wanted -9223372036854775807\n", got) + failed = true + } + + if got := div_1_int64_ssa(-4294967296); got != 0 { + fmt.Printf("div_int64 1/-4294967296 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_1_ssa(-4294967296); got != -4294967296 { + fmt.Printf("div_int64 -4294967296/1 = %d, wanted -4294967296\n", got) + failed = true + } + + if got := div_1_int64_ssa(-1); got != -1 { + fmt.Printf("div_int64 1/-1 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int64_1_ssa(-1); got != -1 { + fmt.Printf("div_int64 -1/1 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int64_1_ssa(0); got != 0 { + fmt.Printf("div_int64 0/1 = %d, wanted 0\n", got) + failed = true + } + + if got := div_1_int64_ssa(1); got != 1 { + fmt.Printf("div_int64 1/1 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int64_1_ssa(1); got != 1 { + fmt.Printf("div_int64 1/1 = %d, wanted 1\n", got) + failed = true + } + + if got := div_1_int64_ssa(4294967296); got != 0 { + fmt.Printf("div_int64 1/4294967296 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_1_ssa(4294967296); got != 4294967296 { + fmt.Printf("div_int64 4294967296/1 = %d, wanted 4294967296\n", got) + failed = true + } + + if got := div_1_int64_ssa(9223372036854775806); got != 0 { + fmt.Printf("div_int64 1/9223372036854775806 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_1_ssa(9223372036854775806); got != 9223372036854775806 { + fmt.Printf("div_int64 9223372036854775806/1 = %d, wanted 9223372036854775806\n", got) + failed = true + } + + if got := div_1_int64_ssa(9223372036854775807); got != 0 { + fmt.Printf("div_int64 1/9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_1_ssa(9223372036854775807); got != 9223372036854775807 { + fmt.Printf("div_int64 9223372036854775807/1 = %d, wanted 9223372036854775807\n", got) + failed = true + } + + if got := div_4294967296_int64_ssa(-9223372036854775808); got != 0 { + fmt.Printf("div_int64 4294967296/-9223372036854775808 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_4294967296_ssa(-9223372036854775808); got != -2147483648 { + fmt.Printf("div_int64 -9223372036854775808/4294967296 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := div_4294967296_int64_ssa(-9223372036854775807); got != 0 { + fmt.Printf("div_int64 4294967296/-9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_4294967296_ssa(-9223372036854775807); got != -2147483647 { + fmt.Printf("div_int64 -9223372036854775807/4294967296 = %d, wanted -2147483647\n", got) + failed = true + } + + if got := div_4294967296_int64_ssa(-4294967296); got != -1 { + fmt.Printf("div_int64 4294967296/-4294967296 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int64_4294967296_ssa(-4294967296); got != -1 { + fmt.Printf("div_int64 -4294967296/4294967296 = %d, wanted -1\n", got) + failed = true + } + + if got := div_4294967296_int64_ssa(-1); got != -4294967296 { + fmt.Printf("div_int64 4294967296/-1 = %d, wanted -4294967296\n", got) + failed = true + } + + if got := div_int64_4294967296_ssa(-1); got != 0 { + fmt.Printf("div_int64 -1/4294967296 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_4294967296_ssa(0); got != 0 { + fmt.Printf("div_int64 0/4294967296 = %d, wanted 0\n", got) + failed = true + } + + if got := div_4294967296_int64_ssa(1); got != 4294967296 { + fmt.Printf("div_int64 4294967296/1 = %d, wanted 4294967296\n", got) + failed = true + } + + if got := div_int64_4294967296_ssa(1); got != 0 { + fmt.Printf("div_int64 1/4294967296 = %d, wanted 0\n", got) + failed = true + } + + if got := div_4294967296_int64_ssa(4294967296); got != 1 { + fmt.Printf("div_int64 4294967296/4294967296 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int64_4294967296_ssa(4294967296); got != 1 { + fmt.Printf("div_int64 4294967296/4294967296 = %d, wanted 1\n", got) + failed = true + } + + if got := div_4294967296_int64_ssa(9223372036854775806); got != 0 { + fmt.Printf("div_int64 4294967296/9223372036854775806 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_4294967296_ssa(9223372036854775806); got != 2147483647 { + fmt.Printf("div_int64 9223372036854775806/4294967296 = %d, wanted 2147483647\n", got) + failed = true + } + + if got := div_4294967296_int64_ssa(9223372036854775807); got != 0 { + fmt.Printf("div_int64 4294967296/9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_4294967296_ssa(9223372036854775807); got != 2147483647 { + fmt.Printf("div_int64 9223372036854775807/4294967296 = %d, wanted 2147483647\n", got) + failed = true + } + + if got := div_9223372036854775806_int64_ssa(-9223372036854775808); got != 0 { + fmt.Printf("div_int64 9223372036854775806/-9223372036854775808 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_9223372036854775806_ssa(-9223372036854775808); got != -1 { + fmt.Printf("div_int64 -9223372036854775808/9223372036854775806 = %d, wanted -1\n", got) + failed = true + } + + if got := div_9223372036854775806_int64_ssa(-9223372036854775807); got != 0 { + fmt.Printf("div_int64 9223372036854775806/-9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_9223372036854775806_ssa(-9223372036854775807); got != -1 { + fmt.Printf("div_int64 -9223372036854775807/9223372036854775806 = %d, wanted -1\n", got) + failed = true + } + + if got := div_9223372036854775806_int64_ssa(-4294967296); got != -2147483647 { + fmt.Printf("div_int64 9223372036854775806/-4294967296 = %d, wanted -2147483647\n", got) + failed = true + } + + if got := div_int64_9223372036854775806_ssa(-4294967296); got != 0 { + fmt.Printf("div_int64 -4294967296/9223372036854775806 = %d, wanted 0\n", got) + failed = true + } + + if got := div_9223372036854775806_int64_ssa(-1); got != -9223372036854775806 { + fmt.Printf("div_int64 9223372036854775806/-1 = %d, wanted -9223372036854775806\n", got) + failed = true + } + + if got := div_int64_9223372036854775806_ssa(-1); got != 0 { + fmt.Printf("div_int64 -1/9223372036854775806 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_9223372036854775806_ssa(0); got != 0 { + fmt.Printf("div_int64 0/9223372036854775806 = %d, wanted 0\n", got) + failed = true + } + + if got := div_9223372036854775806_int64_ssa(1); got != 9223372036854775806 { + fmt.Printf("div_int64 9223372036854775806/1 = %d, wanted 9223372036854775806\n", got) + failed = true + } + + if got := div_int64_9223372036854775806_ssa(1); got != 0 { + fmt.Printf("div_int64 1/9223372036854775806 = %d, wanted 0\n", got) + failed = true + } + + if got := div_9223372036854775806_int64_ssa(4294967296); got != 2147483647 { + fmt.Printf("div_int64 9223372036854775806/4294967296 = %d, wanted 2147483647\n", got) + failed = true + } + + if got := div_int64_9223372036854775806_ssa(4294967296); got != 0 { + fmt.Printf("div_int64 4294967296/9223372036854775806 = %d, wanted 0\n", got) + failed = true + } + + if got := div_9223372036854775806_int64_ssa(9223372036854775806); got != 1 { + fmt.Printf("div_int64 9223372036854775806/9223372036854775806 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int64_9223372036854775806_ssa(9223372036854775806); got != 1 { + fmt.Printf("div_int64 9223372036854775806/9223372036854775806 = %d, wanted 1\n", got) + failed = true + } + + if got := div_9223372036854775806_int64_ssa(9223372036854775807); got != 0 { + fmt.Printf("div_int64 9223372036854775806/9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_9223372036854775806_ssa(9223372036854775807); got != 1 { + fmt.Printf("div_int64 9223372036854775807/9223372036854775806 = %d, wanted 1\n", got) + failed = true + } + + if got := div_9223372036854775807_int64_ssa(-9223372036854775808); got != 0 { + fmt.Printf("div_int64 9223372036854775807/-9223372036854775808 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_9223372036854775807_ssa(-9223372036854775808); got != -1 { + fmt.Printf("div_int64 -9223372036854775808/9223372036854775807 = %d, wanted -1\n", got) + failed = true + } + + if got := div_9223372036854775807_int64_ssa(-9223372036854775807); got != -1 { + fmt.Printf("div_int64 9223372036854775807/-9223372036854775807 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int64_9223372036854775807_ssa(-9223372036854775807); got != -1 { + fmt.Printf("div_int64 -9223372036854775807/9223372036854775807 = %d, wanted -1\n", got) + failed = true + } + + if got := div_9223372036854775807_int64_ssa(-4294967296); got != -2147483647 { + fmt.Printf("div_int64 9223372036854775807/-4294967296 = %d, wanted -2147483647\n", got) + failed = true + } + + if got := div_int64_9223372036854775807_ssa(-4294967296); got != 0 { + fmt.Printf("div_int64 -4294967296/9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := div_9223372036854775807_int64_ssa(-1); got != -9223372036854775807 { + fmt.Printf("div_int64 9223372036854775807/-1 = %d, wanted -9223372036854775807\n", got) + failed = true + } + + if got := div_int64_9223372036854775807_ssa(-1); got != 0 { + fmt.Printf("div_int64 -1/9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_9223372036854775807_ssa(0); got != 0 { + fmt.Printf("div_int64 0/9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := div_9223372036854775807_int64_ssa(1); got != 9223372036854775807 { + fmt.Printf("div_int64 9223372036854775807/1 = %d, wanted 9223372036854775807\n", got) + failed = true + } + + if got := div_int64_9223372036854775807_ssa(1); got != 0 { + fmt.Printf("div_int64 1/9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := div_9223372036854775807_int64_ssa(4294967296); got != 2147483647 { + fmt.Printf("div_int64 9223372036854775807/4294967296 = %d, wanted 2147483647\n", got) + failed = true + } + + if got := div_int64_9223372036854775807_ssa(4294967296); got != 0 { + fmt.Printf("div_int64 4294967296/9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := div_9223372036854775807_int64_ssa(9223372036854775806); got != 1 { + fmt.Printf("div_int64 9223372036854775807/9223372036854775806 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int64_9223372036854775807_ssa(9223372036854775806); got != 0 { + fmt.Printf("div_int64 9223372036854775806/9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := div_9223372036854775807_int64_ssa(9223372036854775807); got != 1 { + fmt.Printf("div_int64 9223372036854775807/9223372036854775807 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int64_9223372036854775807_ssa(9223372036854775807); got != 1 { + fmt.Printf("div_int64 9223372036854775807/9223372036854775807 = %d, wanted 1\n", got) + failed = true + } + + if got := div_0_uint32_ssa(1); got != 0 { + fmt.Printf("div_uint32 0/1 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_uint32_ssa(4294967295); got != 0 { + fmt.Printf("div_uint32 0/4294967295 = %d, wanted 0\n", got) + failed = true + } + + if got := div_uint32_1_ssa(0); got != 0 { + fmt.Printf("div_uint32 0/1 = %d, wanted 0\n", got) + failed = true + } + + if got := div_1_uint32_ssa(1); got != 1 { + fmt.Printf("div_uint32 1/1 = %d, wanted 1\n", got) + failed = true + } + + if got := div_uint32_1_ssa(1); got != 1 { + fmt.Printf("div_uint32 1/1 = %d, wanted 1\n", got) + failed = true + } + + if got := div_1_uint32_ssa(4294967295); got != 0 { + fmt.Printf("div_uint32 1/4294967295 = %d, wanted 0\n", got) + failed = true + } + + if got := div_uint32_1_ssa(4294967295); got != 4294967295 { + fmt.Printf("div_uint32 4294967295/1 = %d, wanted 4294967295\n", got) + failed = true + } + + if got := div_uint32_4294967295_ssa(0); got != 0 { + fmt.Printf("div_uint32 0/4294967295 = %d, wanted 0\n", got) + failed = true + } + + if got := div_4294967295_uint32_ssa(1); got != 4294967295 { + fmt.Printf("div_uint32 4294967295/1 = %d, wanted 4294967295\n", got) + failed = true + } + + if got := div_uint32_4294967295_ssa(1); got != 0 { + fmt.Printf("div_uint32 1/4294967295 = %d, wanted 0\n", got) + failed = true + } + + if got := div_4294967295_uint32_ssa(4294967295); got != 1 { + fmt.Printf("div_uint32 4294967295/4294967295 = %d, wanted 1\n", got) + failed = true + } + + if got := div_uint32_4294967295_ssa(4294967295); got != 1 { + fmt.Printf("div_uint32 4294967295/4294967295 = %d, wanted 1\n", got) + failed = true + } + + if got := div_Neg2147483648_int32_ssa(-2147483648); got != 1 { + fmt.Printf("div_int32 -2147483648/-2147483648 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int32_Neg2147483648_ssa(-2147483648); got != 1 { + fmt.Printf("div_int32 -2147483648/-2147483648 = %d, wanted 1\n", got) + failed = true + } + + if got := div_Neg2147483648_int32_ssa(-2147483647); got != 1 { + fmt.Printf("div_int32 -2147483648/-2147483647 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int32_Neg2147483648_ssa(-2147483647); got != 0 { + fmt.Printf("div_int32 -2147483647/-2147483648 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg2147483648_int32_ssa(-1); got != -2147483648 { + fmt.Printf("div_int32 -2147483648/-1 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := div_int32_Neg2147483648_ssa(-1); got != 0 { + fmt.Printf("div_int32 -1/-2147483648 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int32_Neg2147483648_ssa(0); got != 0 { + fmt.Printf("div_int32 0/-2147483648 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg2147483648_int32_ssa(1); got != -2147483648 { + fmt.Printf("div_int32 -2147483648/1 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := div_int32_Neg2147483648_ssa(1); got != 0 { + fmt.Printf("div_int32 1/-2147483648 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg2147483648_int32_ssa(2147483647); got != -1 { + fmt.Printf("div_int32 -2147483648/2147483647 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int32_Neg2147483648_ssa(2147483647); got != 0 { + fmt.Printf("div_int32 2147483647/-2147483648 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg2147483647_int32_ssa(-2147483648); got != 0 { + fmt.Printf("div_int32 -2147483647/-2147483648 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int32_Neg2147483647_ssa(-2147483648); got != 1 { + fmt.Printf("div_int32 -2147483648/-2147483647 = %d, wanted 1\n", got) + failed = true + } + + if got := div_Neg2147483647_int32_ssa(-2147483647); got != 1 { + fmt.Printf("div_int32 -2147483647/-2147483647 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int32_Neg2147483647_ssa(-2147483647); got != 1 { + fmt.Printf("div_int32 -2147483647/-2147483647 = %d, wanted 1\n", got) + failed = true + } + + if got := div_Neg2147483647_int32_ssa(-1); got != 2147483647 { + fmt.Printf("div_int32 -2147483647/-1 = %d, wanted 2147483647\n", got) + failed = true + } + + if got := div_int32_Neg2147483647_ssa(-1); got != 0 { + fmt.Printf("div_int32 -1/-2147483647 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int32_Neg2147483647_ssa(0); got != 0 { + fmt.Printf("div_int32 0/-2147483647 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg2147483647_int32_ssa(1); got != -2147483647 { + fmt.Printf("div_int32 -2147483647/1 = %d, wanted -2147483647\n", got) + failed = true + } + + if got := div_int32_Neg2147483647_ssa(1); got != 0 { + fmt.Printf("div_int32 1/-2147483647 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg2147483647_int32_ssa(2147483647); got != -1 { + fmt.Printf("div_int32 -2147483647/2147483647 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int32_Neg2147483647_ssa(2147483647); got != -1 { + fmt.Printf("div_int32 2147483647/-2147483647 = %d, wanted -1\n", got) + failed = true + } + + if got := div_Neg1_int32_ssa(-2147483648); got != 0 { + fmt.Printf("div_int32 -1/-2147483648 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int32_Neg1_ssa(-2147483648); got != -2147483648 { + fmt.Printf("div_int32 -2147483648/-1 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := div_Neg1_int32_ssa(-2147483647); got != 0 { + fmt.Printf("div_int32 -1/-2147483647 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int32_Neg1_ssa(-2147483647); got != 2147483647 { + fmt.Printf("div_int32 -2147483647/-1 = %d, wanted 2147483647\n", got) + failed = true + } + + if got := div_Neg1_int32_ssa(-1); got != 1 { + fmt.Printf("div_int32 -1/-1 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int32_Neg1_ssa(-1); got != 1 { + fmt.Printf("div_int32 -1/-1 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int32_Neg1_ssa(0); got != 0 { + fmt.Printf("div_int32 0/-1 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg1_int32_ssa(1); got != -1 { + fmt.Printf("div_int32 -1/1 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int32_Neg1_ssa(1); got != -1 { + fmt.Printf("div_int32 1/-1 = %d, wanted -1\n", got) + failed = true + } + + if got := div_Neg1_int32_ssa(2147483647); got != 0 { + fmt.Printf("div_int32 -1/2147483647 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int32_Neg1_ssa(2147483647); got != -2147483647 { + fmt.Printf("div_int32 2147483647/-1 = %d, wanted -2147483647\n", got) + failed = true + } + + if got := div_0_int32_ssa(-2147483648); got != 0 { + fmt.Printf("div_int32 0/-2147483648 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_int32_ssa(-2147483647); got != 0 { + fmt.Printf("div_int32 0/-2147483647 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_int32_ssa(-1); got != 0 { + fmt.Printf("div_int32 0/-1 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_int32_ssa(1); got != 0 { + fmt.Printf("div_int32 0/1 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_int32_ssa(2147483647); got != 0 { + fmt.Printf("div_int32 0/2147483647 = %d, wanted 0\n", got) + failed = true + } + + if got := div_1_int32_ssa(-2147483648); got != 0 { + fmt.Printf("div_int32 1/-2147483648 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int32_1_ssa(-2147483648); got != -2147483648 { + fmt.Printf("div_int32 -2147483648/1 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := div_1_int32_ssa(-2147483647); got != 0 { + fmt.Printf("div_int32 1/-2147483647 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int32_1_ssa(-2147483647); got != -2147483647 { + fmt.Printf("div_int32 -2147483647/1 = %d, wanted -2147483647\n", got) + failed = true + } + + if got := div_1_int32_ssa(-1); got != -1 { + fmt.Printf("div_int32 1/-1 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int32_1_ssa(-1); got != -1 { + fmt.Printf("div_int32 -1/1 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int32_1_ssa(0); got != 0 { + fmt.Printf("div_int32 0/1 = %d, wanted 0\n", got) + failed = true + } + + if got := div_1_int32_ssa(1); got != 1 { + fmt.Printf("div_int32 1/1 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int32_1_ssa(1); got != 1 { + fmt.Printf("div_int32 1/1 = %d, wanted 1\n", got) + failed = true + } + + if got := div_1_int32_ssa(2147483647); got != 0 { + fmt.Printf("div_int32 1/2147483647 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int32_1_ssa(2147483647); got != 2147483647 { + fmt.Printf("div_int32 2147483647/1 = %d, wanted 2147483647\n", got) + failed = true + } + + if got := div_2147483647_int32_ssa(-2147483648); got != 0 { + fmt.Printf("div_int32 2147483647/-2147483648 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int32_2147483647_ssa(-2147483648); got != -1 { + fmt.Printf("div_int32 -2147483648/2147483647 = %d, wanted -1\n", got) + failed = true + } + + if got := div_2147483647_int32_ssa(-2147483647); got != -1 { + fmt.Printf("div_int32 2147483647/-2147483647 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int32_2147483647_ssa(-2147483647); got != -1 { + fmt.Printf("div_int32 -2147483647/2147483647 = %d, wanted -1\n", got) + failed = true + } + + if got := div_2147483647_int32_ssa(-1); got != -2147483647 { + fmt.Printf("div_int32 2147483647/-1 = %d, wanted -2147483647\n", got) + failed = true + } + + if got := div_int32_2147483647_ssa(-1); got != 0 { + fmt.Printf("div_int32 -1/2147483647 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int32_2147483647_ssa(0); got != 0 { + fmt.Printf("div_int32 0/2147483647 = %d, wanted 0\n", got) + failed = true + } + + if got := div_2147483647_int32_ssa(1); got != 2147483647 { + fmt.Printf("div_int32 2147483647/1 = %d, wanted 2147483647\n", got) + failed = true + } + + if got := div_int32_2147483647_ssa(1); got != 0 { + fmt.Printf("div_int32 1/2147483647 = %d, wanted 0\n", got) + failed = true + } + + if got := div_2147483647_int32_ssa(2147483647); got != 1 { + fmt.Printf("div_int32 2147483647/2147483647 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int32_2147483647_ssa(2147483647); got != 1 { + fmt.Printf("div_int32 2147483647/2147483647 = %d, wanted 1\n", got) + failed = true + } + + if got := div_0_uint16_ssa(1); got != 0 { + fmt.Printf("div_uint16 0/1 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_uint16_ssa(65535); got != 0 { + fmt.Printf("div_uint16 0/65535 = %d, wanted 0\n", got) + failed = true + } + + if got := div_uint16_1_ssa(0); got != 0 { + fmt.Printf("div_uint16 0/1 = %d, wanted 0\n", got) + failed = true + } + + if got := div_1_uint16_ssa(1); got != 1 { + fmt.Printf("div_uint16 1/1 = %d, wanted 1\n", got) + failed = true + } + + if got := div_uint16_1_ssa(1); got != 1 { + fmt.Printf("div_uint16 1/1 = %d, wanted 1\n", got) + failed = true + } + + if got := div_1_uint16_ssa(65535); got != 0 { + fmt.Printf("div_uint16 1/65535 = %d, wanted 0\n", got) + failed = true + } + + if got := div_uint16_1_ssa(65535); got != 65535 { + fmt.Printf("div_uint16 65535/1 = %d, wanted 65535\n", got) + failed = true + } + + if got := div_uint16_65535_ssa(0); got != 0 { + fmt.Printf("div_uint16 0/65535 = %d, wanted 0\n", got) + failed = true + } + + if got := div_65535_uint16_ssa(1); got != 65535 { + fmt.Printf("div_uint16 65535/1 = %d, wanted 65535\n", got) + failed = true + } + + if got := div_uint16_65535_ssa(1); got != 0 { + fmt.Printf("div_uint16 1/65535 = %d, wanted 0\n", got) + failed = true + } + + if got := div_65535_uint16_ssa(65535); got != 1 { + fmt.Printf("div_uint16 65535/65535 = %d, wanted 1\n", got) + failed = true + } + + if got := div_uint16_65535_ssa(65535); got != 1 { + fmt.Printf("div_uint16 65535/65535 = %d, wanted 1\n", got) + failed = true + } + + if got := div_Neg32768_int16_ssa(-32768); got != 1 { + fmt.Printf("div_int16 -32768/-32768 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int16_Neg32768_ssa(-32768); got != 1 { + fmt.Printf("div_int16 -32768/-32768 = %d, wanted 1\n", got) + failed = true + } + + if got := div_Neg32768_int16_ssa(-32767); got != 1 { + fmt.Printf("div_int16 -32768/-32767 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int16_Neg32768_ssa(-32767); got != 0 { + fmt.Printf("div_int16 -32767/-32768 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg32768_int16_ssa(-1); got != -32768 { + fmt.Printf("div_int16 -32768/-1 = %d, wanted -32768\n", got) + failed = true + } + + if got := div_int16_Neg32768_ssa(-1); got != 0 { + fmt.Printf("div_int16 -1/-32768 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int16_Neg32768_ssa(0); got != 0 { + fmt.Printf("div_int16 0/-32768 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg32768_int16_ssa(1); got != -32768 { + fmt.Printf("div_int16 -32768/1 = %d, wanted -32768\n", got) + failed = true + } + + if got := div_int16_Neg32768_ssa(1); got != 0 { + fmt.Printf("div_int16 1/-32768 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg32768_int16_ssa(32766); got != -1 { + fmt.Printf("div_int16 -32768/32766 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int16_Neg32768_ssa(32766); got != 0 { + fmt.Printf("div_int16 32766/-32768 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg32768_int16_ssa(32767); got != -1 { + fmt.Printf("div_int16 -32768/32767 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int16_Neg32768_ssa(32767); got != 0 { + fmt.Printf("div_int16 32767/-32768 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg32767_int16_ssa(-32768); got != 0 { + fmt.Printf("div_int16 -32767/-32768 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int16_Neg32767_ssa(-32768); got != 1 { + fmt.Printf("div_int16 -32768/-32767 = %d, wanted 1\n", got) + failed = true + } + + if got := div_Neg32767_int16_ssa(-32767); got != 1 { + fmt.Printf("div_int16 -32767/-32767 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int16_Neg32767_ssa(-32767); got != 1 { + fmt.Printf("div_int16 -32767/-32767 = %d, wanted 1\n", got) + failed = true + } + + if got := div_Neg32767_int16_ssa(-1); got != 32767 { + fmt.Printf("div_int16 -32767/-1 = %d, wanted 32767\n", got) + failed = true + } + + if got := div_int16_Neg32767_ssa(-1); got != 0 { + fmt.Printf("div_int16 -1/-32767 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int16_Neg32767_ssa(0); got != 0 { + fmt.Printf("div_int16 0/-32767 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg32767_int16_ssa(1); got != -32767 { + fmt.Printf("div_int16 -32767/1 = %d, wanted -32767\n", got) + failed = true + } + + if got := div_int16_Neg32767_ssa(1); got != 0 { + fmt.Printf("div_int16 1/-32767 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg32767_int16_ssa(32766); got != -1 { + fmt.Printf("div_int16 -32767/32766 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int16_Neg32767_ssa(32766); got != 0 { + fmt.Printf("div_int16 32766/-32767 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg32767_int16_ssa(32767); got != -1 { + fmt.Printf("div_int16 -32767/32767 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int16_Neg32767_ssa(32767); got != -1 { + fmt.Printf("div_int16 32767/-32767 = %d, wanted -1\n", got) + failed = true + } + + if got := div_Neg1_int16_ssa(-32768); got != 0 { + fmt.Printf("div_int16 -1/-32768 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int16_Neg1_ssa(-32768); got != -32768 { + fmt.Printf("div_int16 -32768/-1 = %d, wanted -32768\n", got) + failed = true + } + + if got := div_Neg1_int16_ssa(-32767); got != 0 { + fmt.Printf("div_int16 -1/-32767 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int16_Neg1_ssa(-32767); got != 32767 { + fmt.Printf("div_int16 -32767/-1 = %d, wanted 32767\n", got) + failed = true + } + + if got := div_Neg1_int16_ssa(-1); got != 1 { + fmt.Printf("div_int16 -1/-1 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int16_Neg1_ssa(-1); got != 1 { + fmt.Printf("div_int16 -1/-1 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int16_Neg1_ssa(0); got != 0 { + fmt.Printf("div_int16 0/-1 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg1_int16_ssa(1); got != -1 { + fmt.Printf("div_int16 -1/1 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int16_Neg1_ssa(1); got != -1 { + fmt.Printf("div_int16 1/-1 = %d, wanted -1\n", got) + failed = true + } + + if got := div_Neg1_int16_ssa(32766); got != 0 { + fmt.Printf("div_int16 -1/32766 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int16_Neg1_ssa(32766); got != -32766 { + fmt.Printf("div_int16 32766/-1 = %d, wanted -32766\n", got) + failed = true + } + + if got := div_Neg1_int16_ssa(32767); got != 0 { + fmt.Printf("div_int16 -1/32767 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int16_Neg1_ssa(32767); got != -32767 { + fmt.Printf("div_int16 32767/-1 = %d, wanted -32767\n", got) + failed = true + } + + if got := div_0_int16_ssa(-32768); got != 0 { + fmt.Printf("div_int16 0/-32768 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_int16_ssa(-32767); got != 0 { + fmt.Printf("div_int16 0/-32767 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_int16_ssa(-1); got != 0 { + fmt.Printf("div_int16 0/-1 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_int16_ssa(1); got != 0 { + fmt.Printf("div_int16 0/1 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_int16_ssa(32766); got != 0 { + fmt.Printf("div_int16 0/32766 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_int16_ssa(32767); got != 0 { + fmt.Printf("div_int16 0/32767 = %d, wanted 0\n", got) + failed = true + } + + if got := div_1_int16_ssa(-32768); got != 0 { + fmt.Printf("div_int16 1/-32768 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int16_1_ssa(-32768); got != -32768 { + fmt.Printf("div_int16 -32768/1 = %d, wanted -32768\n", got) + failed = true + } + + if got := div_1_int16_ssa(-32767); got != 0 { + fmt.Printf("div_int16 1/-32767 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int16_1_ssa(-32767); got != -32767 { + fmt.Printf("div_int16 -32767/1 = %d, wanted -32767\n", got) + failed = true + } + + if got := div_1_int16_ssa(-1); got != -1 { + fmt.Printf("div_int16 1/-1 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int16_1_ssa(-1); got != -1 { + fmt.Printf("div_int16 -1/1 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int16_1_ssa(0); got != 0 { + fmt.Printf("div_int16 0/1 = %d, wanted 0\n", got) + failed = true + } + + if got := div_1_int16_ssa(1); got != 1 { + fmt.Printf("div_int16 1/1 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int16_1_ssa(1); got != 1 { + fmt.Printf("div_int16 1/1 = %d, wanted 1\n", got) + failed = true + } + + if got := div_1_int16_ssa(32766); got != 0 { + fmt.Printf("div_int16 1/32766 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int16_1_ssa(32766); got != 32766 { + fmt.Printf("div_int16 32766/1 = %d, wanted 32766\n", got) + failed = true + } + + if got := div_1_int16_ssa(32767); got != 0 { + fmt.Printf("div_int16 1/32767 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int16_1_ssa(32767); got != 32767 { + fmt.Printf("div_int16 32767/1 = %d, wanted 32767\n", got) + failed = true + } + + if got := div_32766_int16_ssa(-32768); got != 0 { + fmt.Printf("div_int16 32766/-32768 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int16_32766_ssa(-32768); got != -1 { + fmt.Printf("div_int16 -32768/32766 = %d, wanted -1\n", got) + failed = true + } + + if got := div_32766_int16_ssa(-32767); got != 0 { + fmt.Printf("div_int16 32766/-32767 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int16_32766_ssa(-32767); got != -1 { + fmt.Printf("div_int16 -32767/32766 = %d, wanted -1\n", got) + failed = true + } + + if got := div_32766_int16_ssa(-1); got != -32766 { + fmt.Printf("div_int16 32766/-1 = %d, wanted -32766\n", got) + failed = true + } + + if got := div_int16_32766_ssa(-1); got != 0 { + fmt.Printf("div_int16 -1/32766 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int16_32766_ssa(0); got != 0 { + fmt.Printf("div_int16 0/32766 = %d, wanted 0\n", got) + failed = true + } + + if got := div_32766_int16_ssa(1); got != 32766 { + fmt.Printf("div_int16 32766/1 = %d, wanted 32766\n", got) + failed = true + } + + if got := div_int16_32766_ssa(1); got != 0 { + fmt.Printf("div_int16 1/32766 = %d, wanted 0\n", got) + failed = true + } + + if got := div_32766_int16_ssa(32766); got != 1 { + fmt.Printf("div_int16 32766/32766 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int16_32766_ssa(32766); got != 1 { + fmt.Printf("div_int16 32766/32766 = %d, wanted 1\n", got) + failed = true + } + + if got := div_32766_int16_ssa(32767); got != 0 { + fmt.Printf("div_int16 32766/32767 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int16_32766_ssa(32767); got != 1 { + fmt.Printf("div_int16 32767/32766 = %d, wanted 1\n", got) + failed = true + } + + if got := div_32767_int16_ssa(-32768); got != 0 { + fmt.Printf("div_int16 32767/-32768 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int16_32767_ssa(-32768); got != -1 { + fmt.Printf("div_int16 -32768/32767 = %d, wanted -1\n", got) + failed = true + } + + if got := div_32767_int16_ssa(-32767); got != -1 { + fmt.Printf("div_int16 32767/-32767 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int16_32767_ssa(-32767); got != -1 { + fmt.Printf("div_int16 -32767/32767 = %d, wanted -1\n", got) + failed = true + } + + if got := div_32767_int16_ssa(-1); got != -32767 { + fmt.Printf("div_int16 32767/-1 = %d, wanted -32767\n", got) + failed = true + } + + if got := div_int16_32767_ssa(-1); got != 0 { + fmt.Printf("div_int16 -1/32767 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int16_32767_ssa(0); got != 0 { + fmt.Printf("div_int16 0/32767 = %d, wanted 0\n", got) + failed = true + } + + if got := div_32767_int16_ssa(1); got != 32767 { + fmt.Printf("div_int16 32767/1 = %d, wanted 32767\n", got) + failed = true + } + + if got := div_int16_32767_ssa(1); got != 0 { + fmt.Printf("div_int16 1/32767 = %d, wanted 0\n", got) + failed = true + } + + if got := div_32767_int16_ssa(32766); got != 1 { + fmt.Printf("div_int16 32767/32766 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int16_32767_ssa(32766); got != 0 { + fmt.Printf("div_int16 32766/32767 = %d, wanted 0\n", got) + failed = true + } + + if got := div_32767_int16_ssa(32767); got != 1 { + fmt.Printf("div_int16 32767/32767 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int16_32767_ssa(32767); got != 1 { + fmt.Printf("div_int16 32767/32767 = %d, wanted 1\n", got) + failed = true + } + + if got := div_0_uint8_ssa(1); got != 0 { + fmt.Printf("div_uint8 0/1 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_uint8_ssa(255); got != 0 { + fmt.Printf("div_uint8 0/255 = %d, wanted 0\n", got) + failed = true + } + + if got := div_uint8_1_ssa(0); got != 0 { + fmt.Printf("div_uint8 0/1 = %d, wanted 0\n", got) + failed = true + } + + if got := div_1_uint8_ssa(1); got != 1 { + fmt.Printf("div_uint8 1/1 = %d, wanted 1\n", got) + failed = true + } + + if got := div_uint8_1_ssa(1); got != 1 { + fmt.Printf("div_uint8 1/1 = %d, wanted 1\n", got) + failed = true + } + + if got := div_1_uint8_ssa(255); got != 0 { + fmt.Printf("adiv_uint8 1/255 = %d, wanted 0\n", got) + failed = true + } + + if got := div_uint8_1_ssa(255); got != 255 { + fmt.Printf("div_uint8 255/1 = %d, wanted 255\n", got) + failed = true + } + + if got := div_uint8_255_ssa(0); got != 0 { + fmt.Printf("div_uint8 0/255 = %d, wanted 0\n", got) + failed = true + } + + if got := div_255_uint8_ssa(1); got != 255 { + fmt.Printf("div_uint8 255/1 = %d, wanted 255\n", got) + failed = true + } + + if got := div_uint8_255_ssa(1); got != 0 { + fmt.Printf("bdiv_uint8 1/255 = %d, wanted 0\n", got) + failed = true + } + + if got := div_255_uint8_ssa(255); got != 1 { + fmt.Printf("div_uint8 255/255 = %d, wanted 1\n", got) + failed = true + } + + if got := div_uint8_255_ssa(255); got != 1 { + fmt.Printf("div_uint8 255/255 = %d, wanted 1\n", got) + failed = true + } + + if got := div_Neg128_int8_ssa(-128); got != 1 { + fmt.Printf("div_int8 -128/-128 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int8_Neg128_ssa(-128); got != 1 { + fmt.Printf("div_int8 -128/-128 = %d, wanted 1\n", got) + failed = true + } + + if got := div_Neg128_int8_ssa(-127); got != 1 { + fmt.Printf("div_int8 -128/-127 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int8_Neg128_ssa(-127); got != 0 { + fmt.Printf("div_int8 -127/-128 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg128_int8_ssa(-1); got != -128 { + fmt.Printf("div_int8 -128/-1 = %d, wanted -128\n", got) + failed = true + } + + if got := div_int8_Neg128_ssa(-1); got != 0 { + fmt.Printf("div_int8 -1/-128 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int8_Neg128_ssa(0); got != 0 { + fmt.Printf("div_int8 0/-128 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg128_int8_ssa(1); got != -128 { + fmt.Printf("div_int8 -128/1 = %d, wanted -128\n", got) + failed = true + } + + if got := div_int8_Neg128_ssa(1); got != 0 { + fmt.Printf("div_int8 1/-128 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg128_int8_ssa(126); got != -1 { + fmt.Printf("div_int8 -128/126 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int8_Neg128_ssa(126); got != 0 { + fmt.Printf("div_int8 126/-128 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg128_int8_ssa(127); got != -1 { + fmt.Printf("div_int8 -128/127 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int8_Neg128_ssa(127); got != 0 { + fmt.Printf("div_int8 127/-128 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg127_int8_ssa(-128); got != 0 { + fmt.Printf("div_int8 -127/-128 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int8_Neg127_ssa(-128); got != 1 { + fmt.Printf("div_int8 -128/-127 = %d, wanted 1\n", got) + failed = true + } + + if got := div_Neg127_int8_ssa(-127); got != 1 { + fmt.Printf("div_int8 -127/-127 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int8_Neg127_ssa(-127); got != 1 { + fmt.Printf("div_int8 -127/-127 = %d, wanted 1\n", got) + failed = true + } + + if got := div_Neg127_int8_ssa(-1); got != 127 { + fmt.Printf("div_int8 -127/-1 = %d, wanted 127\n", got) + failed = true + } + + if got := div_int8_Neg127_ssa(-1); got != 0 { + fmt.Printf("div_int8 -1/-127 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int8_Neg127_ssa(0); got != 0 { + fmt.Printf("div_int8 0/-127 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg127_int8_ssa(1); got != -127 { + fmt.Printf("div_int8 -127/1 = %d, wanted -127\n", got) + failed = true + } + + if got := div_int8_Neg127_ssa(1); got != 0 { + fmt.Printf("div_int8 1/-127 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg127_int8_ssa(126); got != -1 { + fmt.Printf("div_int8 -127/126 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int8_Neg127_ssa(126); got != 0 { + fmt.Printf("div_int8 126/-127 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg127_int8_ssa(127); got != -1 { + fmt.Printf("div_int8 -127/127 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int8_Neg127_ssa(127); got != -1 { + fmt.Printf("div_int8 127/-127 = %d, wanted -1\n", got) + failed = true + } + + if got := div_Neg1_int8_ssa(-128); got != 0 { + fmt.Printf("div_int8 -1/-128 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int8_Neg1_ssa(-128); got != -128 { + fmt.Printf("div_int8 -128/-1 = %d, wanted -128\n", got) + failed = true + } + + if got := div_Neg1_int8_ssa(-127); got != 0 { + fmt.Printf("div_int8 -1/-127 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int8_Neg1_ssa(-127); got != 127 { + fmt.Printf("div_int8 -127/-1 = %d, wanted 127\n", got) + failed = true + } + + if got := div_Neg1_int8_ssa(-1); got != 1 { + fmt.Printf("div_int8 -1/-1 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int8_Neg1_ssa(-1); got != 1 { + fmt.Printf("div_int8 -1/-1 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int8_Neg1_ssa(0); got != 0 { + fmt.Printf("div_int8 0/-1 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg1_int8_ssa(1); got != -1 { + fmt.Printf("div_int8 -1/1 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int8_Neg1_ssa(1); got != -1 { + fmt.Printf("div_int8 1/-1 = %d, wanted -1\n", got) + failed = true + } + + if got := div_Neg1_int8_ssa(126); got != 0 { + fmt.Printf("div_int8 -1/126 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int8_Neg1_ssa(126); got != -126 { + fmt.Printf("div_int8 126/-1 = %d, wanted -126\n", got) + failed = true + } + + if got := div_Neg1_int8_ssa(127); got != 0 { + fmt.Printf("div_int8 -1/127 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int8_Neg1_ssa(127); got != -127 { + fmt.Printf("div_int8 127/-1 = %d, wanted -127\n", got) + failed = true + } + + if got := div_0_int8_ssa(-128); got != 0 { + fmt.Printf("div_int8 0/-128 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_int8_ssa(-127); got != 0 { + fmt.Printf("div_int8 0/-127 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_int8_ssa(-1); got != 0 { + fmt.Printf("div_int8 0/-1 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_int8_ssa(1); got != 0 { + fmt.Printf("div_int8 0/1 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_int8_ssa(126); got != 0 { + fmt.Printf("div_int8 0/126 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_int8_ssa(127); got != 0 { + fmt.Printf("div_int8 0/127 = %d, wanted 0\n", got) + failed = true + } + + if got := div_1_int8_ssa(-128); got != 0 { + fmt.Printf("div_int8 1/-128 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int8_1_ssa(-128); got != -128 { + fmt.Printf("div_int8 -128/1 = %d, wanted -128\n", got) + failed = true + } + + if got := div_1_int8_ssa(-127); got != 0 { + fmt.Printf("div_int8 1/-127 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int8_1_ssa(-127); got != -127 { + fmt.Printf("div_int8 -127/1 = %d, wanted -127\n", got) + failed = true + } + + if got := div_1_int8_ssa(-1); got != -1 { + fmt.Printf("div_int8 1/-1 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int8_1_ssa(-1); got != -1 { + fmt.Printf("div_int8 -1/1 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int8_1_ssa(0); got != 0 { + fmt.Printf("div_int8 0/1 = %d, wanted 0\n", got) + failed = true + } + + if got := div_1_int8_ssa(1); got != 1 { + fmt.Printf("div_int8 1/1 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int8_1_ssa(1); got != 1 { + fmt.Printf("div_int8 1/1 = %d, wanted 1\n", got) + failed = true + } + + if got := div_1_int8_ssa(126); got != 0 { + fmt.Printf("div_int8 1/126 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int8_1_ssa(126); got != 126 { + fmt.Printf("div_int8 126/1 = %d, wanted 126\n", got) + failed = true + } + + if got := div_1_int8_ssa(127); got != 0 { + fmt.Printf("div_int8 1/127 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int8_1_ssa(127); got != 127 { + fmt.Printf("div_int8 127/1 = %d, wanted 127\n", got) + failed = true + } + + if got := div_126_int8_ssa(-128); got != 0 { + fmt.Printf("div_int8 126/-128 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int8_126_ssa(-128); got != -1 { + fmt.Printf("div_int8 -128/126 = %d, wanted -1\n", got) + failed = true + } + + if got := div_126_int8_ssa(-127); got != 0 { + fmt.Printf("div_int8 126/-127 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int8_126_ssa(-127); got != -1 { + fmt.Printf("div_int8 -127/126 = %d, wanted -1\n", got) + failed = true + } + + if got := div_126_int8_ssa(-1); got != -126 { + fmt.Printf("div_int8 126/-1 = %d, wanted -126\n", got) + failed = true + } + + if got := div_int8_126_ssa(-1); got != 0 { + fmt.Printf("div_int8 -1/126 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int8_126_ssa(0); got != 0 { + fmt.Printf("div_int8 0/126 = %d, wanted 0\n", got) + failed = true + } + + if got := div_126_int8_ssa(1); got != 126 { + fmt.Printf("div_int8 126/1 = %d, wanted 126\n", got) + failed = true + } + + if got := div_int8_126_ssa(1); got != 0 { + fmt.Printf("div_int8 1/126 = %d, wanted 0\n", got) + failed = true + } + + if got := div_126_int8_ssa(126); got != 1 { + fmt.Printf("div_int8 126/126 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int8_126_ssa(126); got != 1 { + fmt.Printf("div_int8 126/126 = %d, wanted 1\n", got) + failed = true + } + + if got := div_126_int8_ssa(127); got != 0 { + fmt.Printf("div_int8 126/127 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int8_126_ssa(127); got != 1 { + fmt.Printf("div_int8 127/126 = %d, wanted 1\n", got) + failed = true + } + + if got := div_127_int8_ssa(-128); got != 0 { + fmt.Printf("div_int8 127/-128 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int8_127_ssa(-128); got != -1 { + fmt.Printf("div_int8 -128/127 = %d, wanted -1\n", got) + failed = true + } + + if got := div_127_int8_ssa(-127); got != -1 { + fmt.Printf("div_int8 127/-127 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int8_127_ssa(-127); got != -1 { + fmt.Printf("div_int8 -127/127 = %d, wanted -1\n", got) + failed = true + } + + if got := div_127_int8_ssa(-1); got != -127 { + fmt.Printf("div_int8 127/-1 = %d, wanted -127\n", got) + failed = true + } + + if got := div_int8_127_ssa(-1); got != 0 { + fmt.Printf("div_int8 -1/127 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int8_127_ssa(0); got != 0 { + fmt.Printf("div_int8 0/127 = %d, wanted 0\n", got) + failed = true + } + + if got := div_127_int8_ssa(1); got != 127 { + fmt.Printf("div_int8 127/1 = %d, wanted 127\n", got) + failed = true + } + + if got := div_int8_127_ssa(1); got != 0 { + fmt.Printf("div_int8 1/127 = %d, wanted 0\n", got) + failed = true + } + + if got := div_127_int8_ssa(126); got != 1 { + fmt.Printf("div_int8 127/126 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int8_127_ssa(126); got != 0 { + fmt.Printf("div_int8 126/127 = %d, wanted 0\n", got) + failed = true + } + + if got := div_127_int8_ssa(127); got != 1 { + fmt.Printf("div_int8 127/127 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int8_127_ssa(127); got != 1 { + fmt.Printf("div_int8 127/127 = %d, wanted 1\n", got) + failed = true + } + if failed { + panic("tests failed") + } +} diff --git a/src/cmd/compile/internal/gc/testdata/arith_ssa.go b/src/cmd/compile/internal/gc/testdata/arith_ssa.go index 2a56e2163f..f6f123c0be 100644 --- a/src/cmd/compile/internal/gc/testdata/arith_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/arith_ssa.go @@ -8,7 +8,7 @@ package main -// test64BitConstMulti tests that rewrite rules don't fold 64 bit constants +// test64BitConstMult tests that rewrite rules don't fold 64 bit constants // into multiply instructions. func test64BitConstMult() { want := int64(103079215109) diff --git a/src/cmd/compile/internal/ssa/TODO b/src/cmd/compile/internal/ssa/TODO index 1773dbbc98..9e52a67ed0 100644 --- a/src/cmd/compile/internal/ssa/TODO +++ b/src/cmd/compile/internal/ssa/TODO @@ -5,7 +5,7 @@ Coverage -------- - Floating point numbers - Complex numbers -- Integer division (HMUL & MOD) +- Integer division (MOD) - Fat objects (strings/slices/interfaces) vs. Phi - Defer? - Closure args @@ -50,6 +50,7 @@ Optimizations (better compiler) - Constant cache - Reuseable slices (e.g. []int of size NumValues()) cached in Func - Handle signed division overflow and sign extension earlier +- Implement 64 bit const division with high multiply, maybe in the frontend? Regalloc -------- diff --git a/src/cmd/compile/internal/ssa/gen/AMD64.rules b/src/cmd/compile/internal/ssa/gen/AMD64.rules index 0cde6f26d4..21f4d01296 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64.rules +++ b/src/cmd/compile/internal/ssa/gen/AMD64.rules @@ -45,6 +45,13 @@ (Div8 x y) -> (DIVW (SignExt8to16 x) (SignExt8to16 y)) (Div8u x y) -> (DIVWU (ZeroExt8to16 x) (ZeroExt8to16 y)) +(Hmul32 x y) -> (HMULL x y) +(Hmul32u x y) -> (HMULLU x y) +(Hmul16 x y) -> (HMULW x y) +(Hmul16u x y) -> (HMULWU x y) +(Hmul8 x y) -> (HMULB x y) +(Hmul8u x y) -> (HMULBU x y) + (And64 x y) -> (ANDQ x y) (And32 x y) -> (ANDL x y) (And16 x y) -> (ANDW x y) diff --git a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go index 220e5b01cd..24c8a199b5 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go @@ -101,6 +101,8 @@ func init() { gp21shift = regInfo{inputs: []regMask{gpsp, cx}, outputs: []regMask{gp &^ cx}, clobbers: flags} gp11div = regInfo{inputs: []regMask{ax, gpsp &^ dx}, outputs: []regMask{ax}, clobbers: dx | flags} + gp11hmul = regInfo{inputs: []regMask{ax, gpsp}, outputs: []regMask{dx}, + clobbers: ax | flags} gp2flags = regInfo{inputs: []regMask{gpsp, gpsp}, outputs: flagsonly} gp1flags = regInfo{inputs: []regMask{gpsp}, outputs: flagsonly} @@ -184,10 +186,16 @@ func init() { {name: "MULWconst", reg: gp11, asm: "IMULW"}, // arg0 * auxint {name: "MULBconst", reg: gp11, asm: "IMULW"}, // arg0 * auxint + {name: "HMULL", reg: gp11hmul, asm: "IMULL"}, // (arg0 * arg1) >> width + {name: "HMULW", reg: gp11hmul, asm: "IMULW"}, // (arg0 * arg1) >> width + {name: "HMULB", reg: gp11hmul, asm: "IMULB"}, // (arg0 * arg1) >> width + {name: "HMULLU", reg: gp11hmul, asm: "MULL"}, // (arg0 * arg1) >> width + {name: "HMULWU", reg: gp11hmul, asm: "MULW"}, // (arg0 * arg1) >> width + {name: "HMULBU", reg: gp11hmul, asm: "MULB"}, // (arg0 * arg1) >> width + {name: "DIVQ", reg: gp11div, asm: "IDIVQ"}, // arg0 / arg1 {name: "DIVL", reg: gp11div, asm: "IDIVL"}, // arg0 / arg1 {name: "DIVW", reg: gp11div, asm: "IDIVW"}, // arg0 / arg1 - {name: "DIVQU", reg: gp11div, asm: "DIVQ"}, // arg0 / arg1 {name: "DIVLU", reg: gp11div, asm: "DIVL"}, // arg0 / arg1 {name: "DIVWU", reg: gp11div, asm: "DIVW"}, // arg0 / arg1 diff --git a/src/cmd/compile/internal/ssa/gen/genericOps.go b/src/cmd/compile/internal/ssa/gen/genericOps.go index a0d8f8e000..44eed6aeba 100644 --- a/src/cmd/compile/internal/ssa/gen/genericOps.go +++ b/src/cmd/compile/internal/ssa/gen/genericOps.go @@ -37,6 +37,14 @@ var genericOps = []opData{ {name: "Div64F"}, // TODO: Div8, Div16, Div32, Div64 and unsigned + {name: "Hmul8"}, // (arg0 * arg1) >> width + {name: "Hmul8u"}, + {name: "Hmul16"}, + {name: "Hmul16u"}, + {name: "Hmul32"}, + {name: "Hmul32u"}, + // frontend currently doesn't generate a 64 bit hmul + {name: "Div8"}, // arg0 / arg1 {name: "Div8u"}, {name: "Div16"}, diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index 44fd6e3737..f8e5e623b6 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -93,6 +93,12 @@ const ( OpAMD64MULLconst OpAMD64MULWconst OpAMD64MULBconst + OpAMD64HMULL + OpAMD64HMULW + OpAMD64HMULB + OpAMD64HMULLU + OpAMD64HMULWU + OpAMD64HMULBU OpAMD64DIVQ OpAMD64DIVL OpAMD64DIVW @@ -245,6 +251,12 @@ const ( OpMul64F OpDiv32F OpDiv64F + OpHmul8 + OpHmul8u + OpHmul16 + OpHmul16u + OpHmul32 + OpHmul32u OpDiv8 OpDiv8u OpDiv16 @@ -977,6 +989,90 @@ var opcodeTable = [...]opInfo{ }, }, }, + { + name: "HMULL", + asm: x86.AIMULL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 1}, // .AX + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + clobbers: 8589934593, // .AX .FLAGS + outputs: []regMask{ + 4, // .DX + }, + }, + }, + { + name: "HMULW", + asm: x86.AIMULW, + reg: regInfo{ + inputs: []inputInfo{ + {0, 1}, // .AX + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + clobbers: 8589934593, // .AX .FLAGS + outputs: []regMask{ + 4, // .DX + }, + }, + }, + { + name: "HMULB", + asm: x86.AIMULB, + reg: regInfo{ + inputs: []inputInfo{ + {0, 1}, // .AX + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + clobbers: 8589934593, // .AX .FLAGS + outputs: []regMask{ + 4, // .DX + }, + }, + }, + { + name: "HMULLU", + asm: x86.AMULL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 1}, // .AX + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + clobbers: 8589934593, // .AX .FLAGS + outputs: []regMask{ + 4, // .DX + }, + }, + }, + { + name: "HMULWU", + asm: x86.AMULW, + reg: regInfo{ + inputs: []inputInfo{ + {0, 1}, // .AX + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + clobbers: 8589934593, // .AX .FLAGS + outputs: []regMask{ + 4, // .DX + }, + }, + }, + { + name: "HMULBU", + asm: x86.AMULB, + reg: regInfo{ + inputs: []inputInfo{ + {0, 1}, // .AX + {1, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + clobbers: 8589934593, // .AX .FLAGS + outputs: []regMask{ + 4, // .DX + }, + }, + }, { name: "DIVQ", asm: x86.AIDIVQ, @@ -2690,6 +2786,30 @@ var opcodeTable = [...]opInfo{ name: "Div64F", generic: true, }, + { + name: "Hmul8", + generic: true, + }, + { + name: "Hmul8u", + generic: true, + }, + { + name: "Hmul16", + generic: true, + }, + { + name: "Hmul16u", + generic: true, + }, + { + name: "Hmul32", + generic: true, + }, + { + name: "Hmul32u", + generic: true, + }, { name: "Div8", generic: true, diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go index 993838b537..4013611b88 100644 --- a/src/cmd/compile/internal/ssa/rewriteAMD64.go +++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go @@ -2335,6 +2335,114 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto end22eaafbcfe70447f79d9b3e6cc395bbd end22eaafbcfe70447f79d9b3e6cc395bbd: ; + case OpHmul16: + // match: (Hmul16 x y) + // cond: + // result: (HMULW x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64HMULW + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto end1b9ff394bb3b06fc109637656b6875f5 + end1b9ff394bb3b06fc109637656b6875f5: + ; + case OpHmul16u: + // match: (Hmul16u x y) + // cond: + // result: (HMULWU x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64HMULWU + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto endee9089e794a43f2ce1619a6ef61670f4 + endee9089e794a43f2ce1619a6ef61670f4: + ; + case OpHmul32: + // match: (Hmul32 x y) + // cond: + // result: (HMULL x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64HMULL + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto end7c83c91ef2634f0b1da4f49350b437b1 + end7c83c91ef2634f0b1da4f49350b437b1: + ; + case OpHmul32u: + // match: (Hmul32u x y) + // cond: + // result: (HMULLU x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64HMULLU + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto end3c4f36611dc8815aa2a63d4ec0eaa06d + end3c4f36611dc8815aa2a63d4ec0eaa06d: + ; + case OpHmul8: + // match: (Hmul8 x y) + // cond: + // result: (HMULB x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64HMULB + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto end51b2cc9f1ed15314e68fc81024f281a7 + end51b2cc9f1ed15314e68fc81024f281a7: + ; + case OpHmul8u: + // match: (Hmul8u x y) + // cond: + // result: (HMULBU x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64HMULBU + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto ende68d7b3a3c774cedc3522af9d635c39d + ende68d7b3a3c774cedc3522af9d635c39d: + ; case OpITab: // match: (ITab (Load ptr mem)) // cond: -- cgit v1.3 From 46e62f873a34b06348bdaf231f1b72367950732e Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Tue, 18 Aug 2015 14:17:30 -0700 Subject: [dev.ssa] cmd/compile: used Bounded field to fix empty range loops for i, v := range a { } Walk converts this to a regular for loop, like this: for i := 0, p := &a[0]; i < len(a); i++, p++ { v := *p } Unfortunately, &a[0] fails its bounds check when a is the empty slice (or string). The old compiler gets around this by marking &a[0] as Bounded, meaning "don't emit bounds checks for this index op". This change makes SSA honor that same mark. The SSA compiler hasn't implemented bounds check panics yet, so the failed bounds check just causes the current routine to return immediately. Fixes bytes package tests. Change-Id: Ibe838853ef4046c92f76adbded8cca3b1e449e0b Reviewed-on: https://go-review.googlesource.com/13685 Reviewed-by: Josh Bleecher Snyder --- src/cmd/compile/internal/gc/ssa.go | 12 +++++++++--- src/cmd/compile/internal/gc/testdata/ctl_ssa.go | 15 +++++++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index f2dd20bcb4..6a5ecbf04d 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -1313,7 +1313,9 @@ func (s *state) expr(n *Node) *ssa.Value { len = s.constInt(Types[TINT], n.Left.Type.Bound) elemtype = n.Left.Type.Type } - s.boundsCheck(i, len) + if !n.Bounded { + s.boundsCheck(i, len) + } return s.newValue2(ssa.OpArrayIndex, elemtype, a, i) } else { // slice p := s.addr(n) @@ -1530,7 +1532,9 @@ func (s *state) addr(n *Node) *ssa.Value { i := s.expr(n.Right) i = s.extendIndex(i) len := s.newValue1(ssa.OpSliceLen, Types[TUINTPTR], a) - s.boundsCheck(i, len) + if !n.Bounded { + s.boundsCheck(i, len) + } p := s.newValue1(ssa.OpSlicePtr, Ptrto(n.Left.Type.Type), a) return s.newValue2(ssa.OpPtrIndex, Ptrto(n.Left.Type.Type), p, i) } else { // array @@ -1538,7 +1542,9 @@ func (s *state) addr(n *Node) *ssa.Value { i := s.expr(n.Right) i = s.extendIndex(i) len := s.constInt(Types[TINT], n.Left.Type.Bound) - s.boundsCheck(i, len) + if !n.Bounded { + s.boundsCheck(i, len) + } return s.newValue2(ssa.OpPtrIndex, Ptrto(n.Left.Type.Type), a, i) } case OIND: diff --git a/src/cmd/compile/internal/gc/testdata/ctl_ssa.go b/src/cmd/compile/internal/gc/testdata/ctl_ssa.go index 7377c9aee8..f7c3b80799 100644 --- a/src/cmd/compile/internal/gc/testdata/ctl_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/ctl_ssa.go @@ -43,10 +43,25 @@ func testPhiControl() { } } +func emptyRange_ssa(b []byte) bool { + for _, x := range b { + _ = x + } + return true +} + +func testEmptyRange() { + if !emptyRange_ssa([]byte{}) { + println("emptyRange_ssa([]byte{})=false, want true") + failed = true + } +} + var failed = false func main() { testPhiControl() + testEmptyRange() if failed { panic("failed") } -- cgit v1.3 From 9f954db170dff18a33fbd333082cd8758851f936 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Tue, 18 Aug 2015 10:26:28 -0700 Subject: [dev.ssa] cmd/compile: add decompose pass Decompose breaks compound objects up into pieces that can be operated on by the target architecture. The decompose pass only does phi ops, the rest is done by the rewrite rules in generic.rules. Compound objects include strings,slices,interfaces,structs,arrays. Arrays aren't decomposed because of indexing (we could support constant indexes, but dynamic indexes can't be handled using SSA). Structs will come in a subsequent CL. TODO: after this pass we have lost the association between, e.g., a string's pointer and its size. It would be nice if we could keep that information around for debugging info somehow. Change-Id: I6379ab962a7beef62297d0f68c421f22aa0a0901 Reviewed-on: https://go-review.googlesource.com/13683 Reviewed-by: Josh Bleecher Snyder --- src/cmd/compile/internal/gc/ssa.go | 56 ++- .../compile/internal/gc/testdata/compound_ssa.go | 91 ++++ src/cmd/compile/internal/gc/type.go | 4 + src/cmd/compile/internal/ssa/compile.go | 3 + src/cmd/compile/internal/ssa/decompose.go | 93 +++++ src/cmd/compile/internal/ssa/gen/generic.rules | 84 +++- src/cmd/compile/internal/ssa/gen/genericOps.go | 8 +- src/cmd/compile/internal/ssa/opGen.go | 20 + src/cmd/compile/internal/ssa/rewritegeneric.go | 459 +++++++++++++++------ src/cmd/compile/internal/ssa/type.go | 30 +- src/cmd/compile/internal/ssa/type_test.go | 30 +- 11 files changed, 712 insertions(+), 166 deletions(-) create mode 100644 src/cmd/compile/internal/gc/testdata/compound_ssa.go create mode 100644 src/cmd/compile/internal/ssa/decompose.go (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 1fb5485183..a324ed2a42 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -1072,7 +1072,15 @@ func (s *state) expr(n *Node) *ssa.Value { case CTBOOL: return s.entryNewValue0A(ssa.OpConstBool, n.Type, n.Val().U) case CTNIL: - return s.entryNewValue0(ssa.OpConstNil, n.Type) + t := n.Type + switch { + case t.IsSlice(): + return s.entryNewValue0(ssa.OpConstSlice, t) + case t.IsInterface(): + return s.entryNewValue0(ssa.OpConstInterface, t) + default: + return s.entryNewValue0(ssa.OpConstNil, t) + } case CTFLT: f := n.Val().U.(*Mpflt) switch n.Type.Size() { @@ -1470,6 +1478,10 @@ func (s *state) zeroVal(t *Type) *ssa.Value { return s.entryNewValue0(ssa.OpConstNil, t) case t.IsBoolean(): return s.entryNewValue0A(ssa.OpConstBool, t, false) // TODO: store bools as 0/1 in AuxInt? + case t.IsInterface(): + return s.entryNewValue0(ssa.OpConstInterface, t) + case t.IsSlice(): + return s.entryNewValue0(ssa.OpConstSlice, t) } s.Unimplementedf("zero for type %v not implemented", t) return nil @@ -1582,11 +1594,47 @@ func canSSA(n *Node) bool { if n.Class == PPARAMOUT { return false } - if Isfat(n.Type) { + return canSSAType(n.Type) + // TODO: try to make more variables SSAable? +} + +// canSSA reports whether variables of type t are SSA-able. +func canSSAType(t *Type) bool { + dowidth(t) + if t.Width > int64(4*Widthptr) { + // 4*Widthptr is an arbitrary constant. We want it + // to be at least 3*Widthptr so slices can be registerized. + // Too big and we'll introduce too much register pressure. return false } - return true - // TODO: try to make more variables SSAable. + switch t.Etype { + case TARRAY: + if Isslice(t) { + return true + } + // We can't do arrays because dynamic indexing is + // not supported on SSA variables. + // TODO: maybe allow if length is <=1? All indexes + // are constant? Might be good for the arrays + // introduced by the compiler for variadic functions. + return false + case TSTRUCT: + if countfield(t) > 4 { + // 4 is an arbitrary constant. Same reasoning + // as above, lots of small fields would waste + // register space needed by other values. + return false + } + for t1 := t.Type; t1 != nil; t1 = t1.Down { + if !canSSAType(t1.Type) { + return false + } + } + return false // until it is implemented + //return true + default: + return true + } } // nilCheck generates nil pointer checking code. diff --git a/src/cmd/compile/internal/gc/testdata/compound_ssa.go b/src/cmd/compile/internal/gc/testdata/compound_ssa.go new file mode 100644 index 0000000000..9b84ce4b11 --- /dev/null +++ b/src/cmd/compile/internal/gc/testdata/compound_ssa.go @@ -0,0 +1,91 @@ +// run + +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Test compound objects + +package main + +import "fmt" + +func string_ssa(a, b string, x bool) string { + s := "" + if x { + s = a + } else { + s = b + } + return s +} + +func testString() { + a := "foo" + b := "barz" + if want, got := a, string_ssa(a, b, true); got != want { + fmt.Printf("string_ssa(%v, %v, true) = %v, want %v\n", a, b, got, want) + failed = true + } + if want, got := b, string_ssa(a, b, false); got != want { + fmt.Printf("string_ssa(%v, %v, false) = %v, want %v\n", a, b, got, want) + failed = true + } +} + +func slice_ssa(a, b []byte, x bool) []byte { + var s []byte + if x { + s = a + } else { + s = b + } + return s +} + +func testSlice() { + a := []byte{3, 4, 5} + b := []byte{7, 8, 9} + if want, got := byte(3), slice_ssa(a, b, true)[0]; got != want { + fmt.Printf("slice_ssa(%v, %v, true) = %v, want %v\n", a, b, got, want) + failed = true + } + if want, got := byte(7), slice_ssa(a, b, false)[0]; got != want { + fmt.Printf("slice_ssa(%v, %v, false) = %v, want %v\n", a, b, got, want) + failed = true + } +} + +func interface_ssa(a, b interface{}, x bool) interface{} { + var s interface{} + if x { + s = a + } else { + s = b + } + return s +} + +func testInterface() { + a := interface{}(3) + b := interface{}(4) + if want, got := 3, interface_ssa(a, b, true).(int); got != want { + fmt.Printf("interface_ssa(%v, %v, true) = %v, want %v\n", a, b, got, want) + failed = true + } + if want, got := 4, interface_ssa(a, b, false).(int); got != want { + fmt.Printf("interface_ssa(%v, %v, false) = %v, want %v\n", a, b, got, want) + failed = true + } +} + +var failed = false + +func main() { + testString() + testSlice() + testInterface() + if failed { + panic("failed") + } +} diff --git a/src/cmd/compile/internal/gc/type.go b/src/cmd/compile/internal/gc/type.go index f60d01b3bb..bcad025ba6 100644 --- a/src/cmd/compile/internal/gc/type.go +++ b/src/cmd/compile/internal/gc/type.go @@ -68,6 +68,10 @@ func (t *Type) IsSlice() bool { return t.Etype == TARRAY && t.Bound < 0 } +func (t *Type) IsInterface() bool { + return t.Etype == TINTER +} + func (t *Type) Elem() ssa.Type { return t.Type } diff --git a/src/cmd/compile/internal/ssa/compile.go b/src/cmd/compile/internal/ssa/compile.go index e85fb10e00..7413e721fe 100644 --- a/src/cmd/compile/internal/ssa/compile.go +++ b/src/cmd/compile/internal/ssa/compile.go @@ -60,6 +60,7 @@ type pass struct { var passes = [...]pass{ {"phielim", phielim}, {"copyelim", copyelim}, + {"decompose", decompose}, {"early deadcode", deadcode}, // remove generated dead code to avoid doing pointless work during opt {"opt", opt}, {"opt deadcode", deadcode}, // remove any blocks orphaned during opt @@ -103,6 +104,8 @@ var passOrder = [...]constraint{ // tighten will be most effective when as many values have been removed as possible {"generic deadcode", "tighten"}, {"generic cse", "tighten"}, + // don't run optimization pass until we've decomposed compound objects + {"decompose", "opt"}, // don't layout blocks until critical edges have been removed {"critical", "layout"}, // regalloc requires the removal of all critical edges diff --git a/src/cmd/compile/internal/ssa/decompose.go b/src/cmd/compile/internal/ssa/decompose.go new file mode 100644 index 0000000000..534ffc269e --- /dev/null +++ b/src/cmd/compile/internal/ssa/decompose.go @@ -0,0 +1,93 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ssa + +// decompose converts phi ops on compound types into phi +// ops on simple types. +// (The remaining compound ops are decomposed with rewrite rules.) +func decompose(f *Func) { + for _, b := range f.Blocks { + for _, v := range b.Values { + if v.Op != OpPhi { + continue + } + switch { + case v.Type.IsString(): + decomposeStringPhi(v) + case v.Type.IsSlice(): + decomposeSlicePhi(v) + case v.Type.IsInterface(): + decomposeInterfacePhi(v) + //case v.Type.IsStruct(): + // decomposeStructPhi(v) + case v.Type.Size() > f.Config.IntSize: + f.Unimplementedf("undecomposed type %s", v.Type) + } + } + } + // TODO: decompose complex? + // TODO: decompose 64-bit ops on 32-bit archs? +} + +func decomposeStringPhi(v *Value) { + fe := v.Block.Func.Config.fe + ptrType := fe.TypeBytePtr() + lenType := fe.TypeUintptr() + + ptr := v.Block.NewValue0(v.Line, OpPhi, ptrType) + len := v.Block.NewValue0(v.Line, OpPhi, lenType) + for _, a := range v.Args { + ptr.AddArg(a.Block.NewValue1(v.Line, OpStringPtr, ptrType, a)) + len.AddArg(a.Block.NewValue1(v.Line, OpStringLen, lenType, a)) + } + v.Op = OpStringMake + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(ptr) + v.AddArg(len) +} + +func decomposeSlicePhi(v *Value) { + fe := v.Block.Func.Config.fe + ptrType := fe.TypeBytePtr() + lenType := fe.TypeUintptr() + + ptr := v.Block.NewValue0(v.Line, OpPhi, ptrType) + len := v.Block.NewValue0(v.Line, OpPhi, lenType) + cap := v.Block.NewValue0(v.Line, OpPhi, lenType) + for _, a := range v.Args { + ptr.AddArg(a.Block.NewValue1(v.Line, OpSlicePtr, ptrType, a)) + len.AddArg(a.Block.NewValue1(v.Line, OpSliceLen, lenType, a)) + cap.AddArg(a.Block.NewValue1(v.Line, OpSliceCap, lenType, a)) + } + v.Op = OpSliceMake + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(ptr) + v.AddArg(len) + v.AddArg(cap) +} + +func decomposeInterfacePhi(v *Value) { + ptrType := v.Block.Func.Config.fe.TypeBytePtr() + + itab := v.Block.NewValue0(v.Line, OpPhi, ptrType) + data := v.Block.NewValue0(v.Line, OpPhi, ptrType) + for _, a := range v.Args { + itab.AddArg(a.Block.NewValue1(v.Line, OpITab, ptrType, a)) + data.AddArg(a.Block.NewValue1(v.Line, OpIData, ptrType, a)) + } + v.Op = OpIMake + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(itab) + v.AddArg(data) +} +func decomposeStructPhi(v *Value) { + // TODO +} diff --git a/src/cmd/compile/internal/ssa/gen/generic.rules b/src/cmd/compile/internal/ssa/gen/generic.rules index db66a457c3..7be00569ea 100644 --- a/src/cmd/compile/internal/ssa/gen/generic.rules +++ b/src/cmd/compile/internal/ssa/gen/generic.rules @@ -59,36 +59,90 @@ (Com32 (Com32 x)) -> x (Com64 (Com64 x)) -> x -// tear apart slices -// TODO: anything that generates a slice needs to go in here. -(SlicePtr (Load ptr mem)) -> (Load ptr mem) -(SliceLen (Load ptr mem)) -> (Load (AddPtr ptr (ConstPtr [config.PtrSize])) mem) -(SliceCap (Load ptr mem)) -> (Load (AddPtr ptr (ConstPtr [config.PtrSize*2])) mem) - // slice and interface comparisons // the frontend ensures that we can only compare against nil // start by putting nil on the right to simplify the other rules (EqFat x y) && x.Op == OpConstNil && y.Op != OpConstNil -> (EqFat y x) (NeqFat x y) && x.Op == OpConstNil && y.Op != OpConstNil -> (NeqFat y x) // it suffices to check the first word (backing array for slices, dynamic type for interfaces) -(EqFat (Load ptr mem) (ConstNil)) -> (EqPtr (Load ptr mem) (ConstPtr [0])) -(NeqFat (Load ptr mem) (ConstNil)) -> (NeqPtr (Load ptr mem) (ConstPtr [0])) +(EqFat (Load ptr mem) (ConstNil)) -> (EqPtr (Load ptr mem) (ConstPtr [0])) +(NeqFat (Load ptr mem) (ConstNil)) -> (NeqPtr (Load ptr mem) (ConstPtr [0])) // indexing operations // Note: bounds check has already been done (ArrayIndex (Load ptr mem) idx) -> (Load (PtrIndex ptr idx) mem) -(PtrIndex ptr idx) -> (AddPtr ptr (MulPtr idx (ConstPtr [t.Elem().Size()]))) +(PtrIndex ptr idx) -> (AddPtr ptr (MulPtr idx (ConstPtr [t.Elem().Size()]))) (StructSelect [idx] (Load ptr mem)) -> (Load (OffPtr [idx] ptr) mem) -// big-object moves -(Store [size] dst (Load src mem) mem) && size > config.IntSize -> (Move [size] dst src mem) - // string ops -(ConstString {s}) -> (StringMake (Addr {config.fe.StringData(s.(string))} (SB )) (ConstPtr [int64(len(s.(string)))])) -(Load ptr mem) && t.IsString() -> (StringMake (Load ptr mem) (Load (OffPtr [config.PtrSize] ptr) mem)) (StringPtr (StringMake ptr _)) -> ptr (StringLen (StringMake _ len)) -> len -(Store [2*config.PtrSize] dst str mem) && str.Type.IsString() -> (Store [config.PtrSize] (OffPtr [config.PtrSize] dst) (StringLen str) (Store [config.PtrSize] dst (StringPtr str) mem)) +(ConstString {s}) -> + (StringMake + (Addr {config.fe.StringData(s.(string))} + (SB )) + (ConstPtr [int64(len(s.(string)))])) +(Load ptr mem) && t.IsString() -> + (StringMake + (Load ptr mem) + (Load + (OffPtr [config.PtrSize] ptr) + mem)) +(Store [2*config.PtrSize] dst (StringMake ptr len) mem) -> + (Store [config.PtrSize] + (OffPtr [config.PtrSize] dst) + len + (Store [config.PtrSize] dst ptr mem)) + +// slice ops +(SlicePtr (SliceMake ptr _ _ )) -> ptr +(SliceLen (SliceMake _ len _)) -> len +(SliceCap (SliceMake _ _ cap)) -> cap +(ConstSlice) -> + (SliceMake + (ConstNil ) + (ConstPtr ) + (ConstPtr )) + +(Load ptr mem) && t.IsSlice() -> + (SliceMake + (Load ptr mem) + (Load + (OffPtr [config.PtrSize] ptr) + mem) + (Load + (OffPtr [2*config.PtrSize] ptr) + mem)) +(Store [3*config.PtrSize] dst (SliceMake ptr len cap) mem) -> + (Store [config.PtrSize] + (OffPtr [2*config.PtrSize] dst) + cap + (Store [config.PtrSize] + (OffPtr [config.PtrSize] dst) + len + (Store [config.PtrSize] dst ptr mem))) + +// interface ops +(ITab (IMake itab _)) -> itab +(IData (IMake _ data)) -> data +(ConstInterface) -> + (IMake + (ConstNil ) + (ConstNil )) +(Load ptr mem) && t.IsInterface() -> + (IMake + (Load ptr mem) + (Load + (OffPtr [config.PtrSize] ptr) + mem)) +(Store [2*config.PtrSize] dst (IMake itab data) mem) -> + (Store [config.PtrSize] + (OffPtr [config.PtrSize] dst) + data + (Store [config.PtrSize] dst itab mem)) + +// big-object moves (TODO: remove?) +(Store [size] dst (Load src mem) mem) && size > config.IntSize -> (Move [size] dst src mem) (If (IsNonNil (GetG)) yes no) -> (Plain nil yes) diff --git a/src/cmd/compile/internal/ssa/gen/genericOps.go b/src/cmd/compile/internal/ssa/gen/genericOps.go index 2024788c5d..5b8b064bb5 100644 --- a/src/cmd/compile/internal/ssa/gen/genericOps.go +++ b/src/cmd/compile/internal/ssa/gen/genericOps.go @@ -229,7 +229,9 @@ var genericOps = []opData{ {name: "Const64"}, {name: "Const32F"}, {name: "Const64F"}, - {name: "ConstPtr"}, // pointer-sized integer constant + {name: "ConstPtr"}, // pointer-sized integer constant + {name: "ConstInterface"}, // nil interface + {name: "ConstSlice"}, // nil slice // TODO: Const32F, ... // Constant-like things @@ -305,7 +307,9 @@ var genericOps = []opData{ {name: "StringLen"}, // len(arg0) // Interfaces - {name: "ITab"}, // arg0=interface, returns itable field + {name: "IMake"}, // arg0=itab, arg1=data + {name: "ITab"}, // arg0=interface, returns itable field + {name: "IData"}, // arg0=interface, returns data field // Spill&restore ops for the register allocator. These are // semantically identical to OpCopy; they do not take/return diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index 003aacffbb..17d4edb221 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -396,6 +396,8 @@ const ( OpConst32F OpConst64F OpConstPtr + OpConstInterface + OpConstSlice OpArg OpAddr OpSP @@ -442,7 +444,9 @@ const ( OpStringMake OpStringPtr OpStringLen + OpIMake OpITab + OpIData OpStoreReg OpLoadReg OpFwdRef @@ -3374,6 +3378,14 @@ var opcodeTable = [...]opInfo{ name: "ConstPtr", generic: true, }, + { + name: "ConstInterface", + generic: true, + }, + { + name: "ConstSlice", + generic: true, + }, { name: "Arg", generic: true, @@ -3558,10 +3570,18 @@ var opcodeTable = [...]opInfo{ name: "StringLen", generic: true, }, + { + name: "IMake", + generic: true, + }, { name: "ITab", generic: true, }, + { + name: "IData", + generic: true, + }, { name: "StoreReg", generic: true, diff --git a/src/cmd/compile/internal/ssa/rewritegeneric.go b/src/cmd/compile/internal/ssa/rewritegeneric.go index 4c278cb168..bd53e05230 100644 --- a/src/cmd/compile/internal/ssa/rewritegeneric.go +++ b/src/cmd/compile/internal/ssa/rewritegeneric.go @@ -237,10 +237,53 @@ func rewriteValuegeneric(v *Value, config *Config) bool { goto end4d92ff3ba567d9afd38fc9ca113602ad end4d92ff3ba567d9afd38fc9ca113602ad: ; + case OpConstInterface: + // match: (ConstInterface) + // cond: + // result: (IMake (ConstNil ) (ConstNil )) + { + v.Op = OpIMake + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpConstNil, TypeInvalid) + v0.Type = config.fe.TypeBytePtr() + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpConstNil, TypeInvalid) + v1.Type = config.fe.TypeBytePtr() + v.AddArg(v1) + return true + } + goto end0367bd8f20a320cc41568f2b28657f6b + end0367bd8f20a320cc41568f2b28657f6b: + ; + case OpConstSlice: + // match: (ConstSlice) + // cond: + // result: (SliceMake (ConstNil ) (ConstPtr ) (ConstPtr )) + { + v.Op = OpSliceMake + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpConstNil, TypeInvalid) + v0.Type = config.fe.TypeBytePtr() + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpConstPtr, TypeInvalid) + v1.Type = config.fe.TypeUintptr() + v.AddArg(v1) + v2 := b.NewValue0(v.Line, OpConstPtr, TypeInvalid) + v2.Type = config.fe.TypeUintptr() + v.AddArg(v2) + return true + } + goto endfd2d8ffcd55eaf8a5092a20c3ae61ba3 + endfd2d8ffcd55eaf8a5092a20c3ae61ba3: + ; case OpConstString: // match: (ConstString {s}) // cond: - // result: (StringMake (Addr {config.fe.StringData(s.(string))} (SB )) (ConstPtr [int64(len(s.(string)))])) + // result: (StringMake (Addr {config.fe.StringData(s.(string))} (SB )) (ConstPtr [int64(len(s.(string)))])) { s := v.Aux v.Op = OpStringMake @@ -248,20 +291,20 @@ func rewriteValuegeneric(v *Value, config *Config) bool { v.Aux = nil v.resetArgs() v0 := b.NewValue0(v.Line, OpAddr, TypeInvalid) - v0.Type = config.Frontend().TypeBytePtr() + v0.Type = config.fe.TypeBytePtr() v0.Aux = config.fe.StringData(s.(string)) v1 := b.NewValue0(v.Line, OpSB, TypeInvalid) - v1.Type = config.Frontend().TypeUintptr() + v1.Type = config.fe.TypeUintptr() v0.AddArg(v1) v.AddArg(v0) v2 := b.NewValue0(v.Line, OpConstPtr, TypeInvalid) - v2.Type = config.Frontend().TypeUintptr() + v2.Type = config.fe.TypeUintptr() v2.AuxInt = int64(len(s.(string))) v.AddArg(v2) return true } - goto end68cc91679848c7c30bd8b0a8ed533843 - end68cc91679848c7c30bd8b0a8ed533843: + goto end51a3d96f2d304db9a52f36ee6b29c14e + end51a3d96f2d304db9a52f36ee6b29c14e: ; case OpEq16: // match: (Eq16 x x) @@ -362,33 +405,73 @@ func rewriteValuegeneric(v *Value, config *Config) bool { ; // match: (EqFat (Load ptr mem) (ConstNil)) // cond: - // result: (EqPtr (Load ptr mem) (ConstPtr [0])) + // result: (EqPtr (Load ptr mem) (ConstPtr [0])) { if v.Args[0].Op != OpLoad { - goto end540dc8dfbc66adcd3db2d7e819c534f6 + goto ende10070e5ddd3dc059674d25ccc6a63b5 } ptr := v.Args[0].Args[0] mem := v.Args[0].Args[1] if v.Args[1].Op != OpConstNil { - goto end540dc8dfbc66adcd3db2d7e819c534f6 + goto ende10070e5ddd3dc059674d25ccc6a63b5 } v.Op = OpEqPtr v.AuxInt = 0 v.Aux = nil v.resetArgs() v0 := b.NewValue0(v.Line, OpLoad, TypeInvalid) - v0.Type = config.Frontend().TypeUintptr() + v0.Type = config.fe.TypeUintptr() v0.AddArg(ptr) v0.AddArg(mem) v.AddArg(v0) v1 := b.NewValue0(v.Line, OpConstPtr, TypeInvalid) - v1.Type = config.Frontend().TypeUintptr() + v1.Type = config.fe.TypeUintptr() v1.AuxInt = 0 v.AddArg(v1) return true } - goto end540dc8dfbc66adcd3db2d7e819c534f6 - end540dc8dfbc66adcd3db2d7e819c534f6: + goto ende10070e5ddd3dc059674d25ccc6a63b5 + ende10070e5ddd3dc059674d25ccc6a63b5: + ; + case OpIData: + // match: (IData (IMake _ data)) + // cond: + // result: data + { + if v.Args[0].Op != OpIMake { + goto endbfa1bb944cdc07933effb16a35152e12 + } + data := v.Args[0].Args[1] + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = data.Type + v.AddArg(data) + return true + } + goto endbfa1bb944cdc07933effb16a35152e12 + endbfa1bb944cdc07933effb16a35152e12: + ; + case OpITab: + // match: (ITab (IMake itab _)) + // cond: + // result: itab + { + if v.Args[0].Op != OpIMake { + goto endfcbb9414a776ff9c8512da3e0f4d8fbd + } + itab := v.Args[0].Args[0] + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = itab.Type + v.AddArg(itab) + return true + } + goto endfcbb9414a776ff9c8512da3e0f4d8fbd + endfcbb9414a776ff9c8512da3e0f4d8fbd: ; case OpIsInBounds: // match: (IsInBounds (Const32 [c]) (Const32 [d])) @@ -488,36 +571,111 @@ func rewriteValuegeneric(v *Value, config *Config) bool { case OpLoad: // match: (Load ptr mem) // cond: t.IsString() - // result: (StringMake (Load ptr mem) (Load (OffPtr [config.PtrSize] ptr) mem)) + // result: (StringMake (Load ptr mem) (Load (OffPtr [config.PtrSize] ptr) mem)) { t := v.Type ptr := v.Args[0] mem := v.Args[1] if !(t.IsString()) { - goto end18afa4a6fdd6d0b92ed292840898c8f6 + goto end7c75255555bf9dd796298d9f6eaf9cf2 } v.Op = OpStringMake v.AuxInt = 0 v.Aux = nil v.resetArgs() v0 := b.NewValue0(v.Line, OpLoad, TypeInvalid) - v0.Type = config.Frontend().TypeBytePtr() + v0.Type = config.fe.TypeBytePtr() + v0.AddArg(ptr) + v0.AddArg(mem) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpLoad, TypeInvalid) + v1.Type = config.fe.TypeUintptr() + v2 := b.NewValue0(v.Line, OpOffPtr, TypeInvalid) + v2.Type = config.fe.TypeUintptr().PtrTo() + v2.AuxInt = config.PtrSize + v2.AddArg(ptr) + v1.AddArg(v2) + v1.AddArg(mem) + v.AddArg(v1) + return true + } + goto end7c75255555bf9dd796298d9f6eaf9cf2 + end7c75255555bf9dd796298d9f6eaf9cf2: + ; + // match: (Load ptr mem) + // cond: t.IsSlice() + // result: (SliceMake (Load ptr mem) (Load (OffPtr [config.PtrSize] ptr) mem) (Load (OffPtr [2*config.PtrSize] ptr) mem)) + { + t := v.Type + ptr := v.Args[0] + mem := v.Args[1] + if !(t.IsSlice()) { + goto end12c46556d962198680eb3238859e3016 + } + v.Op = OpSliceMake + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpLoad, TypeInvalid) + v0.Type = config.fe.TypeBytePtr() v0.AddArg(ptr) v0.AddArg(mem) v.AddArg(v0) v1 := b.NewValue0(v.Line, OpLoad, TypeInvalid) - v1.Type = config.Frontend().TypeUintptr() + v1.Type = config.fe.TypeUintptr() v2 := b.NewValue0(v.Line, OpOffPtr, TypeInvalid) - v2.Type = config.Frontend().TypeBytePtr() + v2.Type = config.fe.TypeUintptr().PtrTo() v2.AuxInt = config.PtrSize v2.AddArg(ptr) v1.AddArg(v2) v1.AddArg(mem) v.AddArg(v1) + v3 := b.NewValue0(v.Line, OpLoad, TypeInvalid) + v3.Type = config.fe.TypeUintptr() + v4 := b.NewValue0(v.Line, OpOffPtr, TypeInvalid) + v4.Type = config.fe.TypeUintptr().PtrTo() + v4.AuxInt = 2 * config.PtrSize + v4.AddArg(ptr) + v3.AddArg(v4) + v3.AddArg(mem) + v.AddArg(v3) return true } - goto end18afa4a6fdd6d0b92ed292840898c8f6 - end18afa4a6fdd6d0b92ed292840898c8f6: + goto end12c46556d962198680eb3238859e3016 + end12c46556d962198680eb3238859e3016: + ; + // match: (Load ptr mem) + // cond: t.IsInterface() + // result: (IMake (Load ptr mem) (Load (OffPtr [config.PtrSize] ptr) mem)) + { + t := v.Type + ptr := v.Args[0] + mem := v.Args[1] + if !(t.IsInterface()) { + goto end12671c83ebe3ccbc8e53383765ee7675 + } + v.Op = OpIMake + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpLoad, TypeInvalid) + v0.Type = config.fe.TypeBytePtr() + v0.AddArg(ptr) + v0.AddArg(mem) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpLoad, TypeInvalid) + v1.Type = config.fe.TypeBytePtr() + v2 := b.NewValue0(v.Line, OpOffPtr, TypeInvalid) + v2.Type = config.fe.TypeBytePtr().PtrTo() + v2.AuxInt = config.PtrSize + v2.AddArg(ptr) + v1.AddArg(v2) + v1.AddArg(mem) + v.AddArg(v1) + return true + } + goto end12671c83ebe3ccbc8e53383765ee7675 + end12671c83ebe3ccbc8e53383765ee7675: ; case OpMul64: // match: (Mul64 (Const64 [c]) (Const64 [d])) @@ -664,33 +822,33 @@ func rewriteValuegeneric(v *Value, config *Config) bool { ; // match: (NeqFat (Load ptr mem) (ConstNil)) // cond: - // result: (NeqPtr (Load ptr mem) (ConstPtr [0])) + // result: (NeqPtr (Load ptr mem) (ConstPtr [0])) { if v.Args[0].Op != OpLoad { - goto end67d723bb0f39a5c897816abcf411e5cf + goto end423eea941d60473e73140e25f5818bfb } ptr := v.Args[0].Args[0] mem := v.Args[0].Args[1] if v.Args[1].Op != OpConstNil { - goto end67d723bb0f39a5c897816abcf411e5cf + goto end423eea941d60473e73140e25f5818bfb } v.Op = OpNeqPtr v.AuxInt = 0 v.Aux = nil v.resetArgs() v0 := b.NewValue0(v.Line, OpLoad, TypeInvalid) - v0.Type = config.Frontend().TypeUintptr() + v0.Type = config.fe.TypeUintptr() v0.AddArg(ptr) v0.AddArg(mem) v.AddArg(v0) v1 := b.NewValue0(v.Line, OpConstPtr, TypeInvalid) - v1.Type = config.Frontend().TypeUintptr() + v1.Type = config.fe.TypeUintptr() v1.AuxInt = 0 v.AddArg(v1) return true } - goto end67d723bb0f39a5c897816abcf411e5cf - end67d723bb0f39a5c897816abcf411e5cf: + goto end423eea941d60473e73140e25f5818bfb + end423eea941d60473e73140e25f5818bfb: ; case OpOr16: // match: (Or16 x x) @@ -775,7 +933,7 @@ func rewriteValuegeneric(v *Value, config *Config) bool { case OpPtrIndex: // match: (PtrIndex ptr idx) // cond: - // result: (AddPtr ptr (MulPtr idx (ConstPtr [t.Elem().Size()]))) + // result: (AddPtr ptr (MulPtr idx (ConstPtr [t.Elem().Size()]))) { t := v.Type ptr := v.Args[0] @@ -786,96 +944,201 @@ func rewriteValuegeneric(v *Value, config *Config) bool { v.resetArgs() v.AddArg(ptr) v0 := b.NewValue0(v.Line, OpMulPtr, TypeInvalid) - v0.Type = config.Frontend().TypeUintptr() + v0.Type = config.fe.TypeUintptr() v0.AddArg(idx) v1 := b.NewValue0(v.Line, OpConstPtr, TypeInvalid) - v1.Type = config.Frontend().TypeUintptr() + v1.Type = config.fe.TypeUintptr() v1.AuxInt = t.Elem().Size() v0.AddArg(v1) v.AddArg(v0) return true } - goto endf7546737f42c76a99699f241d41f491a - endf7546737f42c76a99699f241d41f491a: + goto end1e1c5ef80c11231f89a5439cdda98359 + end1e1c5ef80c11231f89a5439cdda98359: ; case OpSliceCap: - // match: (SliceCap (Load ptr mem)) + // match: (SliceCap (SliceMake _ _ cap)) // cond: - // result: (Load (AddPtr ptr (ConstPtr [config.PtrSize*2])) mem) + // result: cap { - if v.Args[0].Op != OpLoad { - goto end6696811bf6bd45e505d24c1a15c68e70 + if v.Args[0].Op != OpSliceMake { + goto end1bd11616743632b33b410964667fb3c6 } - ptr := v.Args[0].Args[0] - mem := v.Args[0].Args[1] - v.Op = OpLoad + cap := v.Args[0].Args[2] + v.Op = OpCopy v.AuxInt = 0 v.Aux = nil v.resetArgs() - v0 := b.NewValue0(v.Line, OpAddPtr, TypeInvalid) - v0.Type = ptr.Type - v0.AddArg(ptr) - v1 := b.NewValue0(v.Line, OpConstPtr, TypeInvalid) - v1.Type = config.Frontend().TypeUintptr() - v1.AuxInt = config.PtrSize * 2 - v0.AddArg(v1) - v.AddArg(v0) - v.AddArg(mem) + v.Type = cap.Type + v.AddArg(cap) return true } - goto end6696811bf6bd45e505d24c1a15c68e70 - end6696811bf6bd45e505d24c1a15c68e70: + goto end1bd11616743632b33b410964667fb3c6 + end1bd11616743632b33b410964667fb3c6: ; case OpSliceLen: - // match: (SliceLen (Load ptr mem)) + // match: (SliceLen (SliceMake _ len _)) // cond: - // result: (Load (AddPtr ptr (ConstPtr [config.PtrSize])) mem) + // result: len { - if v.Args[0].Op != OpLoad { - goto end9844ce3e290e81355493141e653e37d5 + if v.Args[0].Op != OpSliceMake { + goto endebb2090199d13e4c2ae52fb3e778f7fd } - ptr := v.Args[0].Args[0] - mem := v.Args[0].Args[1] - v.Op = OpLoad + len := v.Args[0].Args[1] + v.Op = OpCopy v.AuxInt = 0 v.Aux = nil v.resetArgs() - v0 := b.NewValue0(v.Line, OpAddPtr, TypeInvalid) - v0.Type = ptr.Type - v0.AddArg(ptr) - v1 := b.NewValue0(v.Line, OpConstPtr, TypeInvalid) - v1.Type = config.Frontend().TypeUintptr() - v1.AuxInt = config.PtrSize - v0.AddArg(v1) - v.AddArg(v0) - v.AddArg(mem) + v.Type = len.Type + v.AddArg(len) return true } - goto end9844ce3e290e81355493141e653e37d5 - end9844ce3e290e81355493141e653e37d5: + goto endebb2090199d13e4c2ae52fb3e778f7fd + endebb2090199d13e4c2ae52fb3e778f7fd: ; case OpSlicePtr: - // match: (SlicePtr (Load ptr mem)) + // match: (SlicePtr (SliceMake ptr _ _ )) // cond: - // result: (Load ptr mem) + // result: ptr { - if v.Args[0].Op != OpLoad { - goto end459613b83f95b65729d45c2ed663a153 + if v.Args[0].Op != OpSliceMake { + goto end526acc0a705137a5d25577499206720b } ptr := v.Args[0].Args[0] - mem := v.Args[0].Args[1] - v.Op = OpLoad + v.Op = OpCopy v.AuxInt = 0 v.Aux = nil v.resetArgs() + v.Type = ptr.Type v.AddArg(ptr) - v.AddArg(mem) return true } - goto end459613b83f95b65729d45c2ed663a153 - end459613b83f95b65729d45c2ed663a153: + goto end526acc0a705137a5d25577499206720b + end526acc0a705137a5d25577499206720b: ; case OpStore: + // match: (Store [2*config.PtrSize] dst (StringMake ptr len) mem) + // cond: + // result: (Store [config.PtrSize] (OffPtr [config.PtrSize] dst) len (Store [config.PtrSize] dst ptr mem)) + { + if v.AuxInt != 2*config.PtrSize { + goto end25ae4fc3dc01583a4adc45067d49940a + } + dst := v.Args[0] + if v.Args[1].Op != OpStringMake { + goto end25ae4fc3dc01583a4adc45067d49940a + } + ptr := v.Args[1].Args[0] + len := v.Args[1].Args[1] + mem := v.Args[2] + v.Op = OpStore + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = config.PtrSize + v0 := b.NewValue0(v.Line, OpOffPtr, TypeInvalid) + v0.Type = config.fe.TypeUintptr().PtrTo() + v0.AuxInt = config.PtrSize + v0.AddArg(dst) + v.AddArg(v0) + v.AddArg(len) + v1 := b.NewValue0(v.Line, OpStore, TypeInvalid) + v1.Type = TypeMem + v1.AuxInt = config.PtrSize + v1.AddArg(dst) + v1.AddArg(ptr) + v1.AddArg(mem) + v.AddArg(v1) + return true + } + goto end25ae4fc3dc01583a4adc45067d49940a + end25ae4fc3dc01583a4adc45067d49940a: + ; + // match: (Store [3*config.PtrSize] dst (SliceMake ptr len cap) mem) + // cond: + // result: (Store [config.PtrSize] (OffPtr [2*config.PtrSize] dst) cap (Store [config.PtrSize] (OffPtr [config.PtrSize] dst) len (Store [config.PtrSize] dst ptr mem))) + { + if v.AuxInt != 3*config.PtrSize { + goto end39ab85d51c8cd7f5d54e3eea4fb79a96 + } + dst := v.Args[0] + if v.Args[1].Op != OpSliceMake { + goto end39ab85d51c8cd7f5d54e3eea4fb79a96 + } + ptr := v.Args[1].Args[0] + len := v.Args[1].Args[1] + cap := v.Args[1].Args[2] + mem := v.Args[2] + v.Op = OpStore + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = config.PtrSize + v0 := b.NewValue0(v.Line, OpOffPtr, TypeInvalid) + v0.Type = config.fe.TypeUintptr().PtrTo() + v0.AuxInt = 2 * config.PtrSize + v0.AddArg(dst) + v.AddArg(v0) + v.AddArg(cap) + v1 := b.NewValue0(v.Line, OpStore, TypeInvalid) + v1.Type = TypeMem + v1.AuxInt = config.PtrSize + v2 := b.NewValue0(v.Line, OpOffPtr, TypeInvalid) + v2.Type = config.fe.TypeUintptr().PtrTo() + v2.AuxInt = config.PtrSize + v2.AddArg(dst) + v1.AddArg(v2) + v1.AddArg(len) + v3 := b.NewValue0(v.Line, OpStore, TypeInvalid) + v3.Type = TypeMem + v3.AuxInt = config.PtrSize + v3.AddArg(dst) + v3.AddArg(ptr) + v3.AddArg(mem) + v1.AddArg(v3) + v.AddArg(v1) + return true + } + goto end39ab85d51c8cd7f5d54e3eea4fb79a96 + end39ab85d51c8cd7f5d54e3eea4fb79a96: + ; + // match: (Store [2*config.PtrSize] dst (IMake itab data) mem) + // cond: + // result: (Store [config.PtrSize] (OffPtr [config.PtrSize] dst) data (Store [config.PtrSize] dst itab mem)) + { + if v.AuxInt != 2*config.PtrSize { + goto end63b77ae78d92c05d496202e8b6b96ff3 + } + dst := v.Args[0] + if v.Args[1].Op != OpIMake { + goto end63b77ae78d92c05d496202e8b6b96ff3 + } + itab := v.Args[1].Args[0] + data := v.Args[1].Args[1] + mem := v.Args[2] + v.Op = OpStore + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = config.PtrSize + v0 := b.NewValue0(v.Line, OpOffPtr, TypeInvalid) + v0.Type = config.fe.TypeBytePtr().PtrTo() + v0.AuxInt = config.PtrSize + v0.AddArg(dst) + v.AddArg(v0) + v.AddArg(data) + v1 := b.NewValue0(v.Line, OpStore, TypeInvalid) + v1.Type = TypeMem + v1.AuxInt = config.PtrSize + v1.AddArg(dst) + v1.AddArg(itab) + v1.AddArg(mem) + v.AddArg(v1) + return true + } + goto end63b77ae78d92c05d496202e8b6b96ff3 + end63b77ae78d92c05d496202e8b6b96ff3: + ; // match: (Store [size] dst (Load src mem) mem) // cond: size > config.IntSize // result: (Move [size] dst src mem) @@ -906,48 +1169,6 @@ func rewriteValuegeneric(v *Value, config *Config) bool { goto enda18a7163888e2f4fca9f38bae56cef42 enda18a7163888e2f4fca9f38bae56cef42: ; - // match: (Store [2*config.PtrSize] dst str mem) - // cond: str.Type.IsString() - // result: (Store [config.PtrSize] (OffPtr [config.PtrSize] dst) (StringLen str) (Store [config.PtrSize] dst (StringPtr str) mem)) - { - if v.AuxInt != 2*config.PtrSize { - goto end6942df62f9cb570a99ab97a5aeebfd2d - } - dst := v.Args[0] - str := v.Args[1] - mem := v.Args[2] - if !(str.Type.IsString()) { - goto end6942df62f9cb570a99ab97a5aeebfd2d - } - v.Op = OpStore - v.AuxInt = 0 - v.Aux = nil - v.resetArgs() - v.AuxInt = config.PtrSize - v0 := b.NewValue0(v.Line, OpOffPtr, TypeInvalid) - v0.Type = config.Frontend().TypeBytePtr() - v0.AuxInt = config.PtrSize - v0.AddArg(dst) - v.AddArg(v0) - v1 := b.NewValue0(v.Line, OpStringLen, TypeInvalid) - v1.Type = config.Frontend().TypeUintptr() - v1.AddArg(str) - v.AddArg(v1) - v2 := b.NewValue0(v.Line, OpStore, TypeInvalid) - v2.AuxInt = config.PtrSize - v2.Type = TypeMem - v2.AddArg(dst) - v3 := b.NewValue0(v.Line, OpStringPtr, TypeInvalid) - v3.Type = config.Frontend().TypeBytePtr() - v3.AddArg(str) - v2.AddArg(v3) - v2.AddArg(mem) - v.AddArg(v2) - return true - } - goto end6942df62f9cb570a99ab97a5aeebfd2d - end6942df62f9cb570a99ab97a5aeebfd2d: - ; case OpStringLen: // match: (StringLen (StringMake _ len)) // cond: diff --git a/src/cmd/compile/internal/ssa/type.go b/src/cmd/compile/internal/ssa/type.go index d6e8384cf0..c6cc889420 100644 --- a/src/cmd/compile/internal/ssa/type.go +++ b/src/cmd/compile/internal/ssa/type.go @@ -18,6 +18,8 @@ type Type interface { IsFloat() bool IsPtr() bool IsString() bool + IsSlice() bool + IsInterface() bool IsMemory() bool // special ssa-package-only types IsFlags() bool @@ -36,19 +38,21 @@ type CompilerType struct { Flags bool } -func (t *CompilerType) Size() int64 { return 0 } -func (t *CompilerType) Alignment() int64 { return 0 } -func (t *CompilerType) IsBoolean() bool { return false } -func (t *CompilerType) IsInteger() bool { return false } -func (t *CompilerType) IsSigned() bool { return false } -func (t *CompilerType) IsFloat() bool { return false } -func (t *CompilerType) IsPtr() bool { return false } -func (t *CompilerType) IsString() bool { return false } -func (t *CompilerType) IsMemory() bool { return t.Memory } -func (t *CompilerType) IsFlags() bool { return t.Flags } -func (t *CompilerType) String() string { return t.Name } -func (t *CompilerType) Elem() Type { panic("not implemented") } -func (t *CompilerType) PtrTo() Type { panic("not implemented") } +func (t *CompilerType) Size() int64 { return 0 } +func (t *CompilerType) Alignment() int64 { return 0 } +func (t *CompilerType) IsBoolean() bool { return false } +func (t *CompilerType) IsInteger() bool { return false } +func (t *CompilerType) IsSigned() bool { return false } +func (t *CompilerType) IsFloat() bool { return false } +func (t *CompilerType) IsPtr() bool { return false } +func (t *CompilerType) IsString() bool { return false } +func (t *CompilerType) IsSlice() bool { return false } +func (t *CompilerType) IsInterface() bool { return false } +func (t *CompilerType) IsMemory() bool { return t.Memory } +func (t *CompilerType) IsFlags() bool { return t.Flags } +func (t *CompilerType) String() string { return t.Name } +func (t *CompilerType) Elem() Type { panic("not implemented") } +func (t *CompilerType) PtrTo() Type { panic("not implemented") } func (t *CompilerType) Equal(u Type) bool { x, ok := u.(*CompilerType) diff --git a/src/cmd/compile/internal/ssa/type_test.go b/src/cmd/compile/internal/ssa/type_test.go index 29bd5cd131..3dfa5f7c0b 100644 --- a/src/cmd/compile/internal/ssa/type_test.go +++ b/src/cmd/compile/internal/ssa/type_test.go @@ -14,24 +14,28 @@ type TypeImpl struct { Float bool Ptr bool string bool + slice bool + inter bool Elem_ Type Name string } -func (t *TypeImpl) Size() int64 { return t.Size_ } -func (t *TypeImpl) Alignment() int64 { return t.Align } -func (t *TypeImpl) IsBoolean() bool { return t.Boolean } -func (t *TypeImpl) IsInteger() bool { return t.Integer } -func (t *TypeImpl) IsSigned() bool { return t.Signed } -func (t *TypeImpl) IsFloat() bool { return t.Float } -func (t *TypeImpl) IsPtr() bool { return t.Ptr } -func (t *TypeImpl) IsString() bool { return t.string } -func (t *TypeImpl) IsMemory() bool { return false } -func (t *TypeImpl) IsFlags() bool { return false } -func (t *TypeImpl) String() string { return t.Name } -func (t *TypeImpl) Elem() Type { return t.Elem_ } -func (t *TypeImpl) PtrTo() Type { panic("not implemented") } +func (t *TypeImpl) Size() int64 { return t.Size_ } +func (t *TypeImpl) Alignment() int64 { return t.Align } +func (t *TypeImpl) IsBoolean() bool { return t.Boolean } +func (t *TypeImpl) IsInteger() bool { return t.Integer } +func (t *TypeImpl) IsSigned() bool { return t.Signed } +func (t *TypeImpl) IsFloat() bool { return t.Float } +func (t *TypeImpl) IsPtr() bool { return t.Ptr } +func (t *TypeImpl) IsString() bool { return t.string } +func (t *TypeImpl) IsSlice() bool { return t.slice } +func (t *TypeImpl) IsInterface() bool { return t.inter } +func (t *TypeImpl) IsMemory() bool { return false } +func (t *TypeImpl) IsFlags() bool { return false } +func (t *TypeImpl) String() string { return t.Name } +func (t *TypeImpl) Elem() Type { return t.Elem_ } +func (t *TypeImpl) PtrTo() Type { panic("not implemented") } func (t *TypeImpl) Equal(u Type) bool { x, ok := u.(*TypeImpl) -- cgit v1.3 From 57d9e7e3c4553ae9b6e59cabe95659cc8014efa9 Mon Sep 17 00:00:00 2001 From: Todd Neal Date: Tue, 18 Aug 2015 19:51:44 -0500 Subject: [dev.ssa] cmd/compile/internal/ssa: implement OMOD Change-Id: Iec954c4daefef4ab3fa2c98bfb2c70b2dea8dffb Reviewed-on: https://go-review.googlesource.com/13743 Reviewed-by: Keith Randall --- src/cmd/compile/internal/gc/ssa.go | 74 ++- .../internal/gc/testdata/arithBoundary_ssa.go | 626 ++++++++++++--------- .../internal/gc/testdata/gen/arithBoundaryGen.go | 214 +++++++ src/cmd/compile/internal/ssa/gen/AMD64.rules | 9 + src/cmd/compile/internal/ssa/gen/AMD64Ops.go | 9 + src/cmd/compile/internal/ssa/gen/genericOps.go | 10 +- src/cmd/compile/internal/ssa/opGen.go | 130 +++++ src/cmd/compile/internal/ssa/rewriteAMD64.go | 156 +++++ 8 files changed, 936 insertions(+), 292 deletions(-) create mode 100644 src/cmd/compile/internal/gc/testdata/gen/arithBoundaryGen.go (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index a324ed2a42..6d3359ad0e 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -795,6 +795,15 @@ var opToSSA = map[opAndType]ssa.Op{ opAndType{ODIV, TINT64}: ssa.OpDiv64, opAndType{ODIV, TUINT64}: ssa.OpDiv64u, + opAndType{OMOD, TINT8}: ssa.OpMod8, + opAndType{OMOD, TUINT8}: ssa.OpMod8u, + opAndType{OMOD, TINT16}: ssa.OpMod16, + opAndType{OMOD, TUINT16}: ssa.OpMod16u, + opAndType{OMOD, TINT32}: ssa.OpMod32, + opAndType{OMOD, TUINT32}: ssa.OpMod32u, + opAndType{OMOD, TINT64}: ssa.OpMod64, + opAndType{OMOD, TUINT64}: ssa.OpMod64u, + opAndType{OAND, TINT8}: ssa.OpAnd8, opAndType{OAND, TUINT8}: ssa.OpAnd8, opAndType{OAND, TINT16}: ssa.OpAnd16, @@ -1216,7 +1225,7 @@ func (s *state) expr(n *Node) *ssa.Value { a := s.expr(n.Left) b := s.expr(n.Right) return s.newValue2(s.ssaOp(n.Op, n.Left.Type), Types[TBOOL], a, b) - case OADD, OAND, OMUL, OOR, OSUB, ODIV, OXOR, OHMUL: + case OADD, OAND, OMUL, OOR, OSUB, ODIV, OMOD, OHMUL, OXOR: a := s.expr(n.Left) b := s.expr(n.Right) return s.newValue2(s.ssaOp(n.Op, n.Type), a.Type, a, b) @@ -2099,57 +2108,58 @@ func genValue(v *ssa.Value) { opregreg(v.Op.Asm(), r, y) case ssa.OpAMD64DIVQ, ssa.OpAMD64DIVL, ssa.OpAMD64DIVW, - ssa.OpAMD64DIVQU, ssa.OpAMD64DIVLU, ssa.OpAMD64DIVWU: + ssa.OpAMD64DIVQU, ssa.OpAMD64DIVLU, ssa.OpAMD64DIVWU, + ssa.OpAMD64MODQ, ssa.OpAMD64MODL, ssa.OpAMD64MODW, + ssa.OpAMD64MODQU, ssa.OpAMD64MODLU, ssa.OpAMD64MODWU: // Arg[0] is already in AX as it's the only register we allow // and AX is the only output x := regnum(v.Args[1]) // CPU faults upon signed overflow, which occurs when most - // negative int is divided by -1. So we check for division - // by -1 and negate the input. + // negative int is divided by -1. var j *obj.Prog if v.Op == ssa.OpAMD64DIVQ || v.Op == ssa.OpAMD64DIVL || - v.Op == ssa.OpAMD64DIVW { + v.Op == ssa.OpAMD64DIVW || v.Op == ssa.OpAMD64MODQ || + v.Op == ssa.OpAMD64MODL || v.Op == ssa.OpAMD64MODW { var c *obj.Prog switch v.Op { - case ssa.OpAMD64DIVQ: + case ssa.OpAMD64DIVQ, ssa.OpAMD64MODQ: c = Prog(x86.ACMPQ) - case ssa.OpAMD64DIVL: + j = Prog(x86.AJEQ) + // go ahead and sign extend to save doing it later + Prog(x86.ACQO) + + case ssa.OpAMD64DIVL, ssa.OpAMD64MODL: c = Prog(x86.ACMPL) - case ssa.OpAMD64DIVW: + j = Prog(x86.AJEQ) + Prog(x86.ACDQ) + + case ssa.OpAMD64DIVW, ssa.OpAMD64MODW: c = Prog(x86.ACMPW) + j = Prog(x86.AJEQ) + Prog(x86.ACWD) } c.From.Type = obj.TYPE_REG c.From.Reg = x c.To.Type = obj.TYPE_CONST c.To.Offset = -1 - j = Prog(x86.AJEQ) j.To.Type = obj.TYPE_BRANCH } - // dividend is ax, so we sign extend to - // dx:ax for DIV input - switch v.Op { - case ssa.OpAMD64DIVQU: - fallthrough - case ssa.OpAMD64DIVLU: - fallthrough - case ssa.OpAMD64DIVWU: + // for unsigned ints, we sign extend by setting DX = 0 + // signed ints were sign extended above + if v.Op == ssa.OpAMD64DIVQU || v.Op == ssa.OpAMD64MODQU || + v.Op == ssa.OpAMD64DIVLU || v.Op == ssa.OpAMD64MODLU || + v.Op == ssa.OpAMD64DIVWU || v.Op == ssa.OpAMD64MODWU { c := Prog(x86.AXORQ) c.From.Type = obj.TYPE_REG c.From.Reg = x86.REG_DX c.To.Type = obj.TYPE_REG c.To.Reg = x86.REG_DX - case ssa.OpAMD64DIVQ: - Prog(x86.ACQO) - case ssa.OpAMD64DIVL: - Prog(x86.ACDQ) - case ssa.OpAMD64DIVW: - Prog(x86.ACWD) } p := Prog(v.Op.Asm()) @@ -2161,9 +2171,21 @@ func genValue(v *ssa.Value) { j2 := Prog(obj.AJMP) j2.To.Type = obj.TYPE_BRANCH - n := Prog(x86.ANEGQ) - n.To.Type = obj.TYPE_REG - n.To.Reg = x86.REG_AX + var n *obj.Prog + if v.Op == ssa.OpAMD64DIVQ || v.Op == ssa.OpAMD64DIVL || + v.Op == ssa.OpAMD64DIVW { + // n * -1 = -n + n = Prog(x86.ANEGQ) + n.To.Type = obj.TYPE_REG + n.To.Reg = x86.REG_AX + } else { + // n % -1 == 0 + n = Prog(x86.AXORQ) + n.From.Type = obj.TYPE_REG + n.From.Reg = x86.REG_DX + n.To.Type = obj.TYPE_REG + n.To.Reg = x86.REG_DX + } j.To.Val = n j2.To.Val = Pc diff --git a/src/cmd/compile/internal/gc/testdata/arithBoundary_ssa.go b/src/cmd/compile/internal/gc/testdata/arithBoundary_ssa.go index 8f84026a5d..9f1b9a4a60 100644 --- a/src/cmd/compile/internal/gc/testdata/arithBoundary_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/arithBoundary_ssa.go @@ -3,464 +3,504 @@ package main import "fmt" type utd64 struct { - a, b uint64 - add, sub, mul, div uint64 + a, b uint64 + add, sub, mul, div, mod uint64 } type itd64 struct { - a, b int64 - add, sub, mul, div int64 + a, b int64 + add, sub, mul, div, mod int64 } type utd32 struct { - a, b uint32 - add, sub, mul, div uint32 + a, b uint32 + add, sub, mul, div, mod uint32 } type itd32 struct { - a, b int32 - add, sub, mul, div int32 + a, b int32 + add, sub, mul, div, mod int32 } type utd16 struct { - a, b uint16 - add, sub, mul, div uint16 + a, b uint16 + add, sub, mul, div, mod uint16 } type itd16 struct { - a, b int16 - add, sub, mul, div int16 + a, b int16 + add, sub, mul, div, mod int16 } type utd8 struct { - a, b uint8 - add, sub, mul, div uint8 + a, b uint8 + add, sub, mul, div, mod uint8 } type itd8 struct { - a, b int8 - add, sub, mul, div int8 + a, b int8 + add, sub, mul, div, mod int8 } func add_uint64_ssa(a, b uint64) uint64 { switch { - } + } // prevent inlining return a + b } func sub_uint64_ssa(a, b uint64) uint64 { switch { - } + } // prevent inlining return a - b } func div_uint64_ssa(a, b uint64) uint64 { switch { - } + } // prevent inlining return a / b } +func mod_uint64_ssa(a, b uint64) uint64 { + switch { + } // prevent inlining + return a % b +} func mul_uint64_ssa(a, b uint64) uint64 { switch { - } + } // prevent inlining return a * b } func add_int64_ssa(a, b int64) int64 { switch { - } + } // prevent inlining return a + b } func sub_int64_ssa(a, b int64) int64 { switch { - } + } // prevent inlining return a - b } func div_int64_ssa(a, b int64) int64 { switch { - } + } // prevent inlining return a / b } +func mod_int64_ssa(a, b int64) int64 { + switch { + } // prevent inlining + return a % b +} func mul_int64_ssa(a, b int64) int64 { switch { - } + } // prevent inlining return a * b } func add_uint32_ssa(a, b uint32) uint32 { switch { - } + } // prevent inlining return a + b } func sub_uint32_ssa(a, b uint32) uint32 { switch { - } + } // prevent inlining return a - b } func div_uint32_ssa(a, b uint32) uint32 { switch { - } + } // prevent inlining return a / b } +func mod_uint32_ssa(a, b uint32) uint32 { + switch { + } // prevent inlining + return a % b +} func mul_uint32_ssa(a, b uint32) uint32 { switch { - } + } // prevent inlining return a * b } func add_int32_ssa(a, b int32) int32 { switch { - } + } // prevent inlining return a + b } func sub_int32_ssa(a, b int32) int32 { switch { - } + } // prevent inlining return a - b } func div_int32_ssa(a, b int32) int32 { switch { - } + } // prevent inlining return a / b } +func mod_int32_ssa(a, b int32) int32 { + switch { + } // prevent inlining + return a % b +} func mul_int32_ssa(a, b int32) int32 { switch { - } + } // prevent inlining return a * b } func add_uint16_ssa(a, b uint16) uint16 { switch { - } + } // prevent inlining return a + b } func sub_uint16_ssa(a, b uint16) uint16 { switch { - } + } // prevent inlining return a - b } func div_uint16_ssa(a, b uint16) uint16 { switch { - } + } // prevent inlining return a / b } +func mod_uint16_ssa(a, b uint16) uint16 { + switch { + } // prevent inlining + return a % b +} func mul_uint16_ssa(a, b uint16) uint16 { switch { - } + } // prevent inlining return a * b } func add_int16_ssa(a, b int16) int16 { switch { - } + } // prevent inlining return a + b } func sub_int16_ssa(a, b int16) int16 { switch { - } + } // prevent inlining return a - b } func div_int16_ssa(a, b int16) int16 { switch { - } + } // prevent inlining return a / b } +func mod_int16_ssa(a, b int16) int16 { + switch { + } // prevent inlining + return a % b +} func mul_int16_ssa(a, b int16) int16 { switch { - } + } // prevent inlining return a * b } func add_uint8_ssa(a, b uint8) uint8 { switch { - } + } // prevent inlining return a + b } func sub_uint8_ssa(a, b uint8) uint8 { switch { - } + } // prevent inlining return a - b } func div_uint8_ssa(a, b uint8) uint8 { switch { - } + } // prevent inlining return a / b } +func mod_uint8_ssa(a, b uint8) uint8 { + switch { + } // prevent inlining + return a % b +} func mul_uint8_ssa(a, b uint8) uint8 { switch { - } + } // prevent inlining return a * b } func add_int8_ssa(a, b int8) int8 { switch { - } + } // prevent inlining return a + b } func sub_int8_ssa(a, b int8) int8 { switch { - } + } // prevent inlining return a - b } func div_int8_ssa(a, b int8) int8 { switch { - } + } // prevent inlining return a / b } +func mod_int8_ssa(a, b int8) int8 { + switch { + } // prevent inlining + return a % b +} func mul_int8_ssa(a, b int8) int8 { switch { - } + } // prevent inlining return a * b } var uint64_data []utd64 = []utd64{utd64{a: 0, b: 0, add: 0, sub: 0, mul: 0}, - utd64{a: 0, b: 1, add: 1, sub: 18446744073709551615, mul: 0, div: 0}, - utd64{a: 0, b: 4294967296, add: 4294967296, sub: 18446744069414584320, mul: 0, div: 0}, - utd64{a: 0, b: 18446744073709551615, add: 18446744073709551615, sub: 1, mul: 0, div: 0}, + utd64{a: 0, b: 1, add: 1, sub: 18446744073709551615, mul: 0, div: 0, mod: 0}, + utd64{a: 0, b: 4294967296, add: 4294967296, sub: 18446744069414584320, mul: 0, div: 0, mod: 0}, + utd64{a: 0, b: 18446744073709551615, add: 18446744073709551615, sub: 1, mul: 0, div: 0, mod: 0}, utd64{a: 1, b: 0, add: 1, sub: 1, mul: 0}, - utd64{a: 1, b: 1, add: 2, sub: 0, mul: 1, div: 1}, - utd64{a: 1, b: 4294967296, add: 4294967297, sub: 18446744069414584321, mul: 4294967296, div: 0}, - utd64{a: 1, b: 18446744073709551615, add: 0, sub: 2, mul: 18446744073709551615, div: 0}, + utd64{a: 1, b: 1, add: 2, sub: 0, mul: 1, div: 1, mod: 0}, + utd64{a: 1, b: 4294967296, add: 4294967297, sub: 18446744069414584321, mul: 4294967296, div: 0, mod: 1}, + utd64{a: 1, b: 18446744073709551615, add: 0, sub: 2, mul: 18446744073709551615, div: 0, mod: 1}, utd64{a: 4294967296, b: 0, add: 4294967296, sub: 4294967296, mul: 0}, - utd64{a: 4294967296, b: 1, add: 4294967297, sub: 4294967295, mul: 4294967296, div: 4294967296}, - utd64{a: 4294967296, b: 4294967296, add: 8589934592, sub: 0, mul: 0, div: 1}, - utd64{a: 4294967296, b: 18446744073709551615, add: 4294967295, sub: 4294967297, mul: 18446744069414584320, div: 0}, + utd64{a: 4294967296, b: 1, add: 4294967297, sub: 4294967295, mul: 4294967296, div: 4294967296, mod: 0}, + utd64{a: 4294967296, b: 4294967296, add: 8589934592, sub: 0, mul: 0, div: 1, mod: 0}, + utd64{a: 4294967296, b: 18446744073709551615, add: 4294967295, sub: 4294967297, mul: 18446744069414584320, div: 0, mod: 4294967296}, utd64{a: 18446744073709551615, b: 0, add: 18446744073709551615, sub: 18446744073709551615, mul: 0}, - utd64{a: 18446744073709551615, b: 1, add: 0, sub: 18446744073709551614, mul: 18446744073709551615, div: 18446744073709551615}, - utd64{a: 18446744073709551615, b: 4294967296, add: 4294967295, sub: 18446744069414584319, mul: 18446744069414584320, div: 4294967295}, - utd64{a: 18446744073709551615, b: 18446744073709551615, add: 18446744073709551614, sub: 0, mul: 1, div: 1}, -} -var int64_data []itd64 = []itd64{itd64{a: -9223372036854775808, b: -9223372036854775808, add: 0, sub: 0, mul: 0, div: 1}, - itd64{a: -9223372036854775808, b: -9223372036854775807, add: 1, sub: -1, mul: -9223372036854775808, div: 1}, - itd64{a: -9223372036854775808, b: -4294967296, add: 9223372032559808512, sub: -9223372032559808512, mul: 0, div: 2147483648}, - itd64{a: -9223372036854775808, b: -1, add: 9223372036854775807, sub: -9223372036854775807, mul: -9223372036854775808, div: -9223372036854775808}, + utd64{a: 18446744073709551615, b: 1, add: 0, sub: 18446744073709551614, mul: 18446744073709551615, div: 18446744073709551615, mod: 0}, + utd64{a: 18446744073709551615, b: 4294967296, add: 4294967295, sub: 18446744069414584319, mul: 18446744069414584320, div: 4294967295, mod: 4294967295}, + utd64{a: 18446744073709551615, b: 18446744073709551615, add: 18446744073709551614, sub: 0, mul: 1, div: 1, mod: 0}, +} +var int64_data []itd64 = []itd64{itd64{a: -9223372036854775808, b: -9223372036854775808, add: 0, sub: 0, mul: 0, div: 1, mod: 0}, + itd64{a: -9223372036854775808, b: -9223372036854775807, add: 1, sub: -1, mul: -9223372036854775808, div: 1, mod: -1}, + itd64{a: -9223372036854775808, b: -4294967296, add: 9223372032559808512, sub: -9223372032559808512, mul: 0, div: 2147483648, mod: 0}, + itd64{a: -9223372036854775808, b: -1, add: 9223372036854775807, sub: -9223372036854775807, mul: -9223372036854775808, div: -9223372036854775808, mod: 0}, itd64{a: -9223372036854775808, b: 0, add: -9223372036854775808, sub: -9223372036854775808, mul: 0}, - itd64{a: -9223372036854775808, b: 1, add: -9223372036854775807, sub: 9223372036854775807, mul: -9223372036854775808, div: -9223372036854775808}, - itd64{a: -9223372036854775808, b: 4294967296, add: -9223372032559808512, sub: 9223372032559808512, mul: 0, div: -2147483648}, - itd64{a: -9223372036854775808, b: 9223372036854775806, add: -2, sub: 2, mul: 0, div: -1}, - itd64{a: -9223372036854775808, b: 9223372036854775807, add: -1, sub: 1, mul: -9223372036854775808, div: -1}, - itd64{a: -9223372036854775807, b: -9223372036854775808, add: 1, sub: 1, mul: -9223372036854775808, div: 0}, - itd64{a: -9223372036854775807, b: -9223372036854775807, add: 2, sub: 0, mul: 1, div: 1}, - itd64{a: -9223372036854775807, b: -4294967296, add: 9223372032559808513, sub: -9223372032559808511, mul: -4294967296, div: 2147483647}, - itd64{a: -9223372036854775807, b: -1, add: -9223372036854775808, sub: -9223372036854775806, mul: 9223372036854775807, div: 9223372036854775807}, + itd64{a: -9223372036854775808, b: 1, add: -9223372036854775807, sub: 9223372036854775807, mul: -9223372036854775808, div: -9223372036854775808, mod: 0}, + itd64{a: -9223372036854775808, b: 4294967296, add: -9223372032559808512, sub: 9223372032559808512, mul: 0, div: -2147483648, mod: 0}, + itd64{a: -9223372036854775808, b: 9223372036854775806, add: -2, sub: 2, mul: 0, div: -1, mod: -2}, + itd64{a: -9223372036854775808, b: 9223372036854775807, add: -1, sub: 1, mul: -9223372036854775808, div: -1, mod: -1}, + itd64{a: -9223372036854775807, b: -9223372036854775808, add: 1, sub: 1, mul: -9223372036854775808, div: 0, mod: -9223372036854775807}, + itd64{a: -9223372036854775807, b: -9223372036854775807, add: 2, sub: 0, mul: 1, div: 1, mod: 0}, + itd64{a: -9223372036854775807, b: -4294967296, add: 9223372032559808513, sub: -9223372032559808511, mul: -4294967296, div: 2147483647, mod: -4294967295}, + itd64{a: -9223372036854775807, b: -1, add: -9223372036854775808, sub: -9223372036854775806, mul: 9223372036854775807, div: 9223372036854775807, mod: 0}, itd64{a: -9223372036854775807, b: 0, add: -9223372036854775807, sub: -9223372036854775807, mul: 0}, - itd64{a: -9223372036854775807, b: 1, add: -9223372036854775806, sub: -9223372036854775808, mul: -9223372036854775807, div: -9223372036854775807}, - itd64{a: -9223372036854775807, b: 4294967296, add: -9223372032559808511, sub: 9223372032559808513, mul: 4294967296, div: -2147483647}, - itd64{a: -9223372036854775807, b: 9223372036854775806, add: -1, sub: 3, mul: 9223372036854775806, div: -1}, - itd64{a: -9223372036854775807, b: 9223372036854775807, add: 0, sub: 2, mul: -1, div: -1}, - itd64{a: -4294967296, b: -9223372036854775808, add: 9223372032559808512, sub: 9223372032559808512, mul: 0, div: 0}, - itd64{a: -4294967296, b: -9223372036854775807, add: 9223372032559808513, sub: 9223372032559808511, mul: -4294967296, div: 0}, - itd64{a: -4294967296, b: -4294967296, add: -8589934592, sub: 0, mul: 0, div: 1}, - itd64{a: -4294967296, b: -1, add: -4294967297, sub: -4294967295, mul: 4294967296, div: 4294967296}, + itd64{a: -9223372036854775807, b: 1, add: -9223372036854775806, sub: -9223372036854775808, mul: -9223372036854775807, div: -9223372036854775807, mod: 0}, + itd64{a: -9223372036854775807, b: 4294967296, add: -9223372032559808511, sub: 9223372032559808513, mul: 4294967296, div: -2147483647, mod: -4294967295}, + itd64{a: -9223372036854775807, b: 9223372036854775806, add: -1, sub: 3, mul: 9223372036854775806, div: -1, mod: -1}, + itd64{a: -9223372036854775807, b: 9223372036854775807, add: 0, sub: 2, mul: -1, div: -1, mod: 0}, + itd64{a: -4294967296, b: -9223372036854775808, add: 9223372032559808512, sub: 9223372032559808512, mul: 0, div: 0, mod: -4294967296}, + itd64{a: -4294967296, b: -9223372036854775807, add: 9223372032559808513, sub: 9223372032559808511, mul: -4294967296, div: 0, mod: -4294967296}, + itd64{a: -4294967296, b: -4294967296, add: -8589934592, sub: 0, mul: 0, div: 1, mod: 0}, + itd64{a: -4294967296, b: -1, add: -4294967297, sub: -4294967295, mul: 4294967296, div: 4294967296, mod: 0}, itd64{a: -4294967296, b: 0, add: -4294967296, sub: -4294967296, mul: 0}, - itd64{a: -4294967296, b: 1, add: -4294967295, sub: -4294967297, mul: -4294967296, div: -4294967296}, - itd64{a: -4294967296, b: 4294967296, add: 0, sub: -8589934592, mul: 0, div: -1}, - itd64{a: -4294967296, b: 9223372036854775806, add: 9223372032559808510, sub: 9223372032559808514, mul: 8589934592, div: 0}, - itd64{a: -4294967296, b: 9223372036854775807, add: 9223372032559808511, sub: 9223372032559808513, mul: 4294967296, div: 0}, - itd64{a: -1, b: -9223372036854775808, add: 9223372036854775807, sub: 9223372036854775807, mul: -9223372036854775808, div: 0}, - itd64{a: -1, b: -9223372036854775807, add: -9223372036854775808, sub: 9223372036854775806, mul: 9223372036854775807, div: 0}, - itd64{a: -1, b: -4294967296, add: -4294967297, sub: 4294967295, mul: 4294967296, div: 0}, - itd64{a: -1, b: -1, add: -2, sub: 0, mul: 1, div: 1}, + itd64{a: -4294967296, b: 1, add: -4294967295, sub: -4294967297, mul: -4294967296, div: -4294967296, mod: 0}, + itd64{a: -4294967296, b: 4294967296, add: 0, sub: -8589934592, mul: 0, div: -1, mod: 0}, + itd64{a: -4294967296, b: 9223372036854775806, add: 9223372032559808510, sub: 9223372032559808514, mul: 8589934592, div: 0, mod: -4294967296}, + itd64{a: -4294967296, b: 9223372036854775807, add: 9223372032559808511, sub: 9223372032559808513, mul: 4294967296, div: 0, mod: -4294967296}, + itd64{a: -1, b: -9223372036854775808, add: 9223372036854775807, sub: 9223372036854775807, mul: -9223372036854775808, div: 0, mod: -1}, + itd64{a: -1, b: -9223372036854775807, add: -9223372036854775808, sub: 9223372036854775806, mul: 9223372036854775807, div: 0, mod: -1}, + itd64{a: -1, b: -4294967296, add: -4294967297, sub: 4294967295, mul: 4294967296, div: 0, mod: -1}, + itd64{a: -1, b: -1, add: -2, sub: 0, mul: 1, div: 1, mod: 0}, itd64{a: -1, b: 0, add: -1, sub: -1, mul: 0}, - itd64{a: -1, b: 1, add: 0, sub: -2, mul: -1, div: -1}, - itd64{a: -1, b: 4294967296, add: 4294967295, sub: -4294967297, mul: -4294967296, div: 0}, - itd64{a: -1, b: 9223372036854775806, add: 9223372036854775805, sub: -9223372036854775807, mul: -9223372036854775806, div: 0}, - itd64{a: -1, b: 9223372036854775807, add: 9223372036854775806, sub: -9223372036854775808, mul: -9223372036854775807, div: 0}, - itd64{a: 0, b: -9223372036854775808, add: -9223372036854775808, sub: -9223372036854775808, mul: 0, div: 0}, - itd64{a: 0, b: -9223372036854775807, add: -9223372036854775807, sub: 9223372036854775807, mul: 0, div: 0}, - itd64{a: 0, b: -4294967296, add: -4294967296, sub: 4294967296, mul: 0, div: 0}, - itd64{a: 0, b: -1, add: -1, sub: 1, mul: 0, div: 0}, + itd64{a: -1, b: 1, add: 0, sub: -2, mul: -1, div: -1, mod: 0}, + itd64{a: -1, b: 4294967296, add: 4294967295, sub: -4294967297, mul: -4294967296, div: 0, mod: -1}, + itd64{a: -1, b: 9223372036854775806, add: 9223372036854775805, sub: -9223372036854775807, mul: -9223372036854775806, div: 0, mod: -1}, + itd64{a: -1, b: 9223372036854775807, add: 9223372036854775806, sub: -9223372036854775808, mul: -9223372036854775807, div: 0, mod: -1}, + itd64{a: 0, b: -9223372036854775808, add: -9223372036854775808, sub: -9223372036854775808, mul: 0, div: 0, mod: 0}, + itd64{a: 0, b: -9223372036854775807, add: -9223372036854775807, sub: 9223372036854775807, mul: 0, div: 0, mod: 0}, + itd64{a: 0, b: -4294967296, add: -4294967296, sub: 4294967296, mul: 0, div: 0, mod: 0}, + itd64{a: 0, b: -1, add: -1, sub: 1, mul: 0, div: 0, mod: 0}, itd64{a: 0, b: 0, add: 0, sub: 0, mul: 0}, - itd64{a: 0, b: 1, add: 1, sub: -1, mul: 0, div: 0}, - itd64{a: 0, b: 4294967296, add: 4294967296, sub: -4294967296, mul: 0, div: 0}, - itd64{a: 0, b: 9223372036854775806, add: 9223372036854775806, sub: -9223372036854775806, mul: 0, div: 0}, - itd64{a: 0, b: 9223372036854775807, add: 9223372036854775807, sub: -9223372036854775807, mul: 0, div: 0}, - itd64{a: 1, b: -9223372036854775808, add: -9223372036854775807, sub: -9223372036854775807, mul: -9223372036854775808, div: 0}, - itd64{a: 1, b: -9223372036854775807, add: -9223372036854775806, sub: -9223372036854775808, mul: -9223372036854775807, div: 0}, - itd64{a: 1, b: -4294967296, add: -4294967295, sub: 4294967297, mul: -4294967296, div: 0}, - itd64{a: 1, b: -1, add: 0, sub: 2, mul: -1, div: -1}, + itd64{a: 0, b: 1, add: 1, sub: -1, mul: 0, div: 0, mod: 0}, + itd64{a: 0, b: 4294967296, add: 4294967296, sub: -4294967296, mul: 0, div: 0, mod: 0}, + itd64{a: 0, b: 9223372036854775806, add: 9223372036854775806, sub: -9223372036854775806, mul: 0, div: 0, mod: 0}, + itd64{a: 0, b: 9223372036854775807, add: 9223372036854775807, sub: -9223372036854775807, mul: 0, div: 0, mod: 0}, + itd64{a: 1, b: -9223372036854775808, add: -9223372036854775807, sub: -9223372036854775807, mul: -9223372036854775808, div: 0, mod: 1}, + itd64{a: 1, b: -9223372036854775807, add: -9223372036854775806, sub: -9223372036854775808, mul: -9223372036854775807, div: 0, mod: 1}, + itd64{a: 1, b: -4294967296, add: -4294967295, sub: 4294967297, mul: -4294967296, div: 0, mod: 1}, + itd64{a: 1, b: -1, add: 0, sub: 2, mul: -1, div: -1, mod: 0}, itd64{a: 1, b: 0, add: 1, sub: 1, mul: 0}, - itd64{a: 1, b: 1, add: 2, sub: 0, mul: 1, div: 1}, - itd64{a: 1, b: 4294967296, add: 4294967297, sub: -4294967295, mul: 4294967296, div: 0}, - itd64{a: 1, b: 9223372036854775806, add: 9223372036854775807, sub: -9223372036854775805, mul: 9223372036854775806, div: 0}, - itd64{a: 1, b: 9223372036854775807, add: -9223372036854775808, sub: -9223372036854775806, mul: 9223372036854775807, div: 0}, - itd64{a: 4294967296, b: -9223372036854775808, add: -9223372032559808512, sub: -9223372032559808512, mul: 0, div: 0}, - itd64{a: 4294967296, b: -9223372036854775807, add: -9223372032559808511, sub: -9223372032559808513, mul: 4294967296, div: 0}, - itd64{a: 4294967296, b: -4294967296, add: 0, sub: 8589934592, mul: 0, div: -1}, - itd64{a: 4294967296, b: -1, add: 4294967295, sub: 4294967297, mul: -4294967296, div: -4294967296}, + itd64{a: 1, b: 1, add: 2, sub: 0, mul: 1, div: 1, mod: 0}, + itd64{a: 1, b: 4294967296, add: 4294967297, sub: -4294967295, mul: 4294967296, div: 0, mod: 1}, + itd64{a: 1, b: 9223372036854775806, add: 9223372036854775807, sub: -9223372036854775805, mul: 9223372036854775806, div: 0, mod: 1}, + itd64{a: 1, b: 9223372036854775807, add: -9223372036854775808, sub: -9223372036854775806, mul: 9223372036854775807, div: 0, mod: 1}, + itd64{a: 4294967296, b: -9223372036854775808, add: -9223372032559808512, sub: -9223372032559808512, mul: 0, div: 0, mod: 4294967296}, + itd64{a: 4294967296, b: -9223372036854775807, add: -9223372032559808511, sub: -9223372032559808513, mul: 4294967296, div: 0, mod: 4294967296}, + itd64{a: 4294967296, b: -4294967296, add: 0, sub: 8589934592, mul: 0, div: -1, mod: 0}, + itd64{a: 4294967296, b: -1, add: 4294967295, sub: 4294967297, mul: -4294967296, div: -4294967296, mod: 0}, itd64{a: 4294967296, b: 0, add: 4294967296, sub: 4294967296, mul: 0}, - itd64{a: 4294967296, b: 1, add: 4294967297, sub: 4294967295, mul: 4294967296, div: 4294967296}, - itd64{a: 4294967296, b: 4294967296, add: 8589934592, sub: 0, mul: 0, div: 1}, - itd64{a: 4294967296, b: 9223372036854775806, add: -9223372032559808514, sub: -9223372032559808510, mul: -8589934592, div: 0}, - itd64{a: 4294967296, b: 9223372036854775807, add: -9223372032559808513, sub: -9223372032559808511, mul: -4294967296, div: 0}, - itd64{a: 9223372036854775806, b: -9223372036854775808, add: -2, sub: -2, mul: 0, div: 0}, - itd64{a: 9223372036854775806, b: -9223372036854775807, add: -1, sub: -3, mul: 9223372036854775806, div: 0}, - itd64{a: 9223372036854775806, b: -4294967296, add: 9223372032559808510, sub: -9223372032559808514, mul: 8589934592, div: -2147483647}, - itd64{a: 9223372036854775806, b: -1, add: 9223372036854775805, sub: 9223372036854775807, mul: -9223372036854775806, div: -9223372036854775806}, + itd64{a: 4294967296, b: 1, add: 4294967297, sub: 4294967295, mul: 4294967296, div: 4294967296, mod: 0}, + itd64{a: 4294967296, b: 4294967296, add: 8589934592, sub: 0, mul: 0, div: 1, mod: 0}, + itd64{a: 4294967296, b: 9223372036854775806, add: -9223372032559808514, sub: -9223372032559808510, mul: -8589934592, div: 0, mod: 4294967296}, + itd64{a: 4294967296, b: 9223372036854775807, add: -9223372032559808513, sub: -9223372032559808511, mul: -4294967296, div: 0, mod: 4294967296}, + itd64{a: 9223372036854775806, b: -9223372036854775808, add: -2, sub: -2, mul: 0, div: 0, mod: 9223372036854775806}, + itd64{a: 9223372036854775806, b: -9223372036854775807, add: -1, sub: -3, mul: 9223372036854775806, div: 0, mod: 9223372036854775806}, + itd64{a: 9223372036854775806, b: -4294967296, add: 9223372032559808510, sub: -9223372032559808514, mul: 8589934592, div: -2147483647, mod: 4294967294}, + itd64{a: 9223372036854775806, b: -1, add: 9223372036854775805, sub: 9223372036854775807, mul: -9223372036854775806, div: -9223372036854775806, mod: 0}, itd64{a: 9223372036854775806, b: 0, add: 9223372036854775806, sub: 9223372036854775806, mul: 0}, - itd64{a: 9223372036854775806, b: 1, add: 9223372036854775807, sub: 9223372036854775805, mul: 9223372036854775806, div: 9223372036854775806}, - itd64{a: 9223372036854775806, b: 4294967296, add: -9223372032559808514, sub: 9223372032559808510, mul: -8589934592, div: 2147483647}, - itd64{a: 9223372036854775806, b: 9223372036854775806, add: -4, sub: 0, mul: 4, div: 1}, - itd64{a: 9223372036854775806, b: 9223372036854775807, add: -3, sub: -1, mul: -9223372036854775806, div: 0}, - itd64{a: 9223372036854775807, b: -9223372036854775808, add: -1, sub: -1, mul: -9223372036854775808, div: 0}, - itd64{a: 9223372036854775807, b: -9223372036854775807, add: 0, sub: -2, mul: -1, div: -1}, - itd64{a: 9223372036854775807, b: -4294967296, add: 9223372032559808511, sub: -9223372032559808513, mul: 4294967296, div: -2147483647}, - itd64{a: 9223372036854775807, b: -1, add: 9223372036854775806, sub: -9223372036854775808, mul: -9223372036854775807, div: -9223372036854775807}, + itd64{a: 9223372036854775806, b: 1, add: 9223372036854775807, sub: 9223372036854775805, mul: 9223372036854775806, div: 9223372036854775806, mod: 0}, + itd64{a: 9223372036854775806, b: 4294967296, add: -9223372032559808514, sub: 9223372032559808510, mul: -8589934592, div: 2147483647, mod: 4294967294}, + itd64{a: 9223372036854775806, b: 9223372036854775806, add: -4, sub: 0, mul: 4, div: 1, mod: 0}, + itd64{a: 9223372036854775806, b: 9223372036854775807, add: -3, sub: -1, mul: -9223372036854775806, div: 0, mod: 9223372036854775806}, + itd64{a: 9223372036854775807, b: -9223372036854775808, add: -1, sub: -1, mul: -9223372036854775808, div: 0, mod: 9223372036854775807}, + itd64{a: 9223372036854775807, b: -9223372036854775807, add: 0, sub: -2, mul: -1, div: -1, mod: 0}, + itd64{a: 9223372036854775807, b: -4294967296, add: 9223372032559808511, sub: -9223372032559808513, mul: 4294967296, div: -2147483647, mod: 4294967295}, + itd64{a: 9223372036854775807, b: -1, add: 9223372036854775806, sub: -9223372036854775808, mul: -9223372036854775807, div: -9223372036854775807, mod: 0}, itd64{a: 9223372036854775807, b: 0, add: 9223372036854775807, sub: 9223372036854775807, mul: 0}, - itd64{a: 9223372036854775807, b: 1, add: -9223372036854775808, sub: 9223372036854775806, mul: 9223372036854775807, div: 9223372036854775807}, - itd64{a: 9223372036854775807, b: 4294967296, add: -9223372032559808513, sub: 9223372032559808511, mul: -4294967296, div: 2147483647}, - itd64{a: 9223372036854775807, b: 9223372036854775806, add: -3, sub: 1, mul: -9223372036854775806, div: 1}, - itd64{a: 9223372036854775807, b: 9223372036854775807, add: -2, sub: 0, mul: 1, div: 1}, + itd64{a: 9223372036854775807, b: 1, add: -9223372036854775808, sub: 9223372036854775806, mul: 9223372036854775807, div: 9223372036854775807, mod: 0}, + itd64{a: 9223372036854775807, b: 4294967296, add: -9223372032559808513, sub: 9223372032559808511, mul: -4294967296, div: 2147483647, mod: 4294967295}, + itd64{a: 9223372036854775807, b: 9223372036854775806, add: -3, sub: 1, mul: -9223372036854775806, div: 1, mod: 1}, + itd64{a: 9223372036854775807, b: 9223372036854775807, add: -2, sub: 0, mul: 1, div: 1, mod: 0}, } var uint32_data []utd32 = []utd32{utd32{a: 0, b: 0, add: 0, sub: 0, mul: 0}, - utd32{a: 0, b: 1, add: 1, sub: 4294967295, mul: 0, div: 0}, - utd32{a: 0, b: 4294967295, add: 4294967295, sub: 1, mul: 0, div: 0}, + utd32{a: 0, b: 1, add: 1, sub: 4294967295, mul: 0, div: 0, mod: 0}, + utd32{a: 0, b: 4294967295, add: 4294967295, sub: 1, mul: 0, div: 0, mod: 0}, utd32{a: 1, b: 0, add: 1, sub: 1, mul: 0}, - utd32{a: 1, b: 1, add: 2, sub: 0, mul: 1, div: 1}, - utd32{a: 1, b: 4294967295, add: 0, sub: 2, mul: 4294967295, div: 0}, + utd32{a: 1, b: 1, add: 2, sub: 0, mul: 1, div: 1, mod: 0}, + utd32{a: 1, b: 4294967295, add: 0, sub: 2, mul: 4294967295, div: 0, mod: 1}, utd32{a: 4294967295, b: 0, add: 4294967295, sub: 4294967295, mul: 0}, - utd32{a: 4294967295, b: 1, add: 0, sub: 4294967294, mul: 4294967295, div: 4294967295}, - utd32{a: 4294967295, b: 4294967295, add: 4294967294, sub: 0, mul: 1, div: 1}, + utd32{a: 4294967295, b: 1, add: 0, sub: 4294967294, mul: 4294967295, div: 4294967295, mod: 0}, + utd32{a: 4294967295, b: 4294967295, add: 4294967294, sub: 0, mul: 1, div: 1, mod: 0}, } -var int32_data []itd32 = []itd32{itd32{a: -2147483648, b: -2147483648, add: 0, sub: 0, mul: 0, div: 1}, - itd32{a: -2147483648, b: -2147483647, add: 1, sub: -1, mul: -2147483648, div: 1}, - itd32{a: -2147483648, b: -1, add: 2147483647, sub: -2147483647, mul: -2147483648, div: -2147483648}, +var int32_data []itd32 = []itd32{itd32{a: -2147483648, b: -2147483648, add: 0, sub: 0, mul: 0, div: 1, mod: 0}, + itd32{a: -2147483648, b: -2147483647, add: 1, sub: -1, mul: -2147483648, div: 1, mod: -1}, + itd32{a: -2147483648, b: -1, add: 2147483647, sub: -2147483647, mul: -2147483648, div: -2147483648, mod: 0}, itd32{a: -2147483648, b: 0, add: -2147483648, sub: -2147483648, mul: 0}, - itd32{a: -2147483648, b: 1, add: -2147483647, sub: 2147483647, mul: -2147483648, div: -2147483648}, - itd32{a: -2147483648, b: 2147483647, add: -1, sub: 1, mul: -2147483648, div: -1}, - itd32{a: -2147483647, b: -2147483648, add: 1, sub: 1, mul: -2147483648, div: 0}, - itd32{a: -2147483647, b: -2147483647, add: 2, sub: 0, mul: 1, div: 1}, - itd32{a: -2147483647, b: -1, add: -2147483648, sub: -2147483646, mul: 2147483647, div: 2147483647}, + itd32{a: -2147483648, b: 1, add: -2147483647, sub: 2147483647, mul: -2147483648, div: -2147483648, mod: 0}, + itd32{a: -2147483648, b: 2147483647, add: -1, sub: 1, mul: -2147483648, div: -1, mod: -1}, + itd32{a: -2147483647, b: -2147483648, add: 1, sub: 1, mul: -2147483648, div: 0, mod: -2147483647}, + itd32{a: -2147483647, b: -2147483647, add: 2, sub: 0, mul: 1, div: 1, mod: 0}, + itd32{a: -2147483647, b: -1, add: -2147483648, sub: -2147483646, mul: 2147483647, div: 2147483647, mod: 0}, itd32{a: -2147483647, b: 0, add: -2147483647, sub: -2147483647, mul: 0}, - itd32{a: -2147483647, b: 1, add: -2147483646, sub: -2147483648, mul: -2147483647, div: -2147483647}, - itd32{a: -2147483647, b: 2147483647, add: 0, sub: 2, mul: -1, div: -1}, - itd32{a: -1, b: -2147483648, add: 2147483647, sub: 2147483647, mul: -2147483648, div: 0}, - itd32{a: -1, b: -2147483647, add: -2147483648, sub: 2147483646, mul: 2147483647, div: 0}, - itd32{a: -1, b: -1, add: -2, sub: 0, mul: 1, div: 1}, + itd32{a: -2147483647, b: 1, add: -2147483646, sub: -2147483648, mul: -2147483647, div: -2147483647, mod: 0}, + itd32{a: -2147483647, b: 2147483647, add: 0, sub: 2, mul: -1, div: -1, mod: 0}, + itd32{a: -1, b: -2147483648, add: 2147483647, sub: 2147483647, mul: -2147483648, div: 0, mod: -1}, + itd32{a: -1, b: -2147483647, add: -2147483648, sub: 2147483646, mul: 2147483647, div: 0, mod: -1}, + itd32{a: -1, b: -1, add: -2, sub: 0, mul: 1, div: 1, mod: 0}, itd32{a: -1, b: 0, add: -1, sub: -1, mul: 0}, - itd32{a: -1, b: 1, add: 0, sub: -2, mul: -1, div: -1}, - itd32{a: -1, b: 2147483647, add: 2147483646, sub: -2147483648, mul: -2147483647, div: 0}, - itd32{a: 0, b: -2147483648, add: -2147483648, sub: -2147483648, mul: 0, div: 0}, - itd32{a: 0, b: -2147483647, add: -2147483647, sub: 2147483647, mul: 0, div: 0}, - itd32{a: 0, b: -1, add: -1, sub: 1, mul: 0, div: 0}, + itd32{a: -1, b: 1, add: 0, sub: -2, mul: -1, div: -1, mod: 0}, + itd32{a: -1, b: 2147483647, add: 2147483646, sub: -2147483648, mul: -2147483647, div: 0, mod: -1}, + itd32{a: 0, b: -2147483648, add: -2147483648, sub: -2147483648, mul: 0, div: 0, mod: 0}, + itd32{a: 0, b: -2147483647, add: -2147483647, sub: 2147483647, mul: 0, div: 0, mod: 0}, + itd32{a: 0, b: -1, add: -1, sub: 1, mul: 0, div: 0, mod: 0}, itd32{a: 0, b: 0, add: 0, sub: 0, mul: 0}, - itd32{a: 0, b: 1, add: 1, sub: -1, mul: 0, div: 0}, - itd32{a: 0, b: 2147483647, add: 2147483647, sub: -2147483647, mul: 0, div: 0}, - itd32{a: 1, b: -2147483648, add: -2147483647, sub: -2147483647, mul: -2147483648, div: 0}, - itd32{a: 1, b: -2147483647, add: -2147483646, sub: -2147483648, mul: -2147483647, div: 0}, - itd32{a: 1, b: -1, add: 0, sub: 2, mul: -1, div: -1}, + itd32{a: 0, b: 1, add: 1, sub: -1, mul: 0, div: 0, mod: 0}, + itd32{a: 0, b: 2147483647, add: 2147483647, sub: -2147483647, mul: 0, div: 0, mod: 0}, + itd32{a: 1, b: -2147483648, add: -2147483647, sub: -2147483647, mul: -2147483648, div: 0, mod: 1}, + itd32{a: 1, b: -2147483647, add: -2147483646, sub: -2147483648, mul: -2147483647, div: 0, mod: 1}, + itd32{a: 1, b: -1, add: 0, sub: 2, mul: -1, div: -1, mod: 0}, itd32{a: 1, b: 0, add: 1, sub: 1, mul: 0}, - itd32{a: 1, b: 1, add: 2, sub: 0, mul: 1, div: 1}, - itd32{a: 1, b: 2147483647, add: -2147483648, sub: -2147483646, mul: 2147483647, div: 0}, - itd32{a: 2147483647, b: -2147483648, add: -1, sub: -1, mul: -2147483648, div: 0}, - itd32{a: 2147483647, b: -2147483647, add: 0, sub: -2, mul: -1, div: -1}, - itd32{a: 2147483647, b: -1, add: 2147483646, sub: -2147483648, mul: -2147483647, div: -2147483647}, + itd32{a: 1, b: 1, add: 2, sub: 0, mul: 1, div: 1, mod: 0}, + itd32{a: 1, b: 2147483647, add: -2147483648, sub: -2147483646, mul: 2147483647, div: 0, mod: 1}, + itd32{a: 2147483647, b: -2147483648, add: -1, sub: -1, mul: -2147483648, div: 0, mod: 2147483647}, + itd32{a: 2147483647, b: -2147483647, add: 0, sub: -2, mul: -1, div: -1, mod: 0}, + itd32{a: 2147483647, b: -1, add: 2147483646, sub: -2147483648, mul: -2147483647, div: -2147483647, mod: 0}, itd32{a: 2147483647, b: 0, add: 2147483647, sub: 2147483647, mul: 0}, - itd32{a: 2147483647, b: 1, add: -2147483648, sub: 2147483646, mul: 2147483647, div: 2147483647}, - itd32{a: 2147483647, b: 2147483647, add: -2, sub: 0, mul: 1, div: 1}, + itd32{a: 2147483647, b: 1, add: -2147483648, sub: 2147483646, mul: 2147483647, div: 2147483647, mod: 0}, + itd32{a: 2147483647, b: 2147483647, add: -2, sub: 0, mul: 1, div: 1, mod: 0}, } var uint16_data []utd16 = []utd16{utd16{a: 0, b: 0, add: 0, sub: 0, mul: 0}, - utd16{a: 0, b: 1, add: 1, sub: 65535, mul: 0, div: 0}, - utd16{a: 0, b: 65535, add: 65535, sub: 1, mul: 0, div: 0}, + utd16{a: 0, b: 1, add: 1, sub: 65535, mul: 0, div: 0, mod: 0}, + utd16{a: 0, b: 65535, add: 65535, sub: 1, mul: 0, div: 0, mod: 0}, utd16{a: 1, b: 0, add: 1, sub: 1, mul: 0}, - utd16{a: 1, b: 1, add: 2, sub: 0, mul: 1, div: 1}, - utd16{a: 1, b: 65535, add: 0, sub: 2, mul: 65535, div: 0}, + utd16{a: 1, b: 1, add: 2, sub: 0, mul: 1, div: 1, mod: 0}, + utd16{a: 1, b: 65535, add: 0, sub: 2, mul: 65535, div: 0, mod: 1}, utd16{a: 65535, b: 0, add: 65535, sub: 65535, mul: 0}, - utd16{a: 65535, b: 1, add: 0, sub: 65534, mul: 65535, div: 65535}, - utd16{a: 65535, b: 65535, add: 65534, sub: 0, mul: 1, div: 1}, + utd16{a: 65535, b: 1, add: 0, sub: 65534, mul: 65535, div: 65535, mod: 0}, + utd16{a: 65535, b: 65535, add: 65534, sub: 0, mul: 1, div: 1, mod: 0}, } -var int16_data []itd16 = []itd16{itd16{a: -32768, b: -32768, add: 0, sub: 0, mul: 0, div: 1}, - itd16{a: -32768, b: -32767, add: 1, sub: -1, mul: -32768, div: 1}, - itd16{a: -32768, b: -1, add: 32767, sub: -32767, mul: -32768, div: -32768}, +var int16_data []itd16 = []itd16{itd16{a: -32768, b: -32768, add: 0, sub: 0, mul: 0, div: 1, mod: 0}, + itd16{a: -32768, b: -32767, add: 1, sub: -1, mul: -32768, div: 1, mod: -1}, + itd16{a: -32768, b: -1, add: 32767, sub: -32767, mul: -32768, div: -32768, mod: 0}, itd16{a: -32768, b: 0, add: -32768, sub: -32768, mul: 0}, - itd16{a: -32768, b: 1, add: -32767, sub: 32767, mul: -32768, div: -32768}, - itd16{a: -32768, b: 32766, add: -2, sub: 2, mul: 0, div: -1}, - itd16{a: -32768, b: 32767, add: -1, sub: 1, mul: -32768, div: -1}, - itd16{a: -32767, b: -32768, add: 1, sub: 1, mul: -32768, div: 0}, - itd16{a: -32767, b: -32767, add: 2, sub: 0, mul: 1, div: 1}, - itd16{a: -32767, b: -1, add: -32768, sub: -32766, mul: 32767, div: 32767}, + itd16{a: -32768, b: 1, add: -32767, sub: 32767, mul: -32768, div: -32768, mod: 0}, + itd16{a: -32768, b: 32766, add: -2, sub: 2, mul: 0, div: -1, mod: -2}, + itd16{a: -32768, b: 32767, add: -1, sub: 1, mul: -32768, div: -1, mod: -1}, + itd16{a: -32767, b: -32768, add: 1, sub: 1, mul: -32768, div: 0, mod: -32767}, + itd16{a: -32767, b: -32767, add: 2, sub: 0, mul: 1, div: 1, mod: 0}, + itd16{a: -32767, b: -1, add: -32768, sub: -32766, mul: 32767, div: 32767, mod: 0}, itd16{a: -32767, b: 0, add: -32767, sub: -32767, mul: 0}, - itd16{a: -32767, b: 1, add: -32766, sub: -32768, mul: -32767, div: -32767}, - itd16{a: -32767, b: 32766, add: -1, sub: 3, mul: 32766, div: -1}, - itd16{a: -32767, b: 32767, add: 0, sub: 2, mul: -1, div: -1}, - itd16{a: -1, b: -32768, add: 32767, sub: 32767, mul: -32768, div: 0}, - itd16{a: -1, b: -32767, add: -32768, sub: 32766, mul: 32767, div: 0}, - itd16{a: -1, b: -1, add: -2, sub: 0, mul: 1, div: 1}, + itd16{a: -32767, b: 1, add: -32766, sub: -32768, mul: -32767, div: -32767, mod: 0}, + itd16{a: -32767, b: 32766, add: -1, sub: 3, mul: 32766, div: -1, mod: -1}, + itd16{a: -32767, b: 32767, add: 0, sub: 2, mul: -1, div: -1, mod: 0}, + itd16{a: -1, b: -32768, add: 32767, sub: 32767, mul: -32768, div: 0, mod: -1}, + itd16{a: -1, b: -32767, add: -32768, sub: 32766, mul: 32767, div: 0, mod: -1}, + itd16{a: -1, b: -1, add: -2, sub: 0, mul: 1, div: 1, mod: 0}, itd16{a: -1, b: 0, add: -1, sub: -1, mul: 0}, - itd16{a: -1, b: 1, add: 0, sub: -2, mul: -1, div: -1}, - itd16{a: -1, b: 32766, add: 32765, sub: -32767, mul: -32766, div: 0}, - itd16{a: -1, b: 32767, add: 32766, sub: -32768, mul: -32767, div: 0}, - itd16{a: 0, b: -32768, add: -32768, sub: -32768, mul: 0, div: 0}, - itd16{a: 0, b: -32767, add: -32767, sub: 32767, mul: 0, div: 0}, - itd16{a: 0, b: -1, add: -1, sub: 1, mul: 0, div: 0}, + itd16{a: -1, b: 1, add: 0, sub: -2, mul: -1, div: -1, mod: 0}, + itd16{a: -1, b: 32766, add: 32765, sub: -32767, mul: -32766, div: 0, mod: -1}, + itd16{a: -1, b: 32767, add: 32766, sub: -32768, mul: -32767, div: 0, mod: -1}, + itd16{a: 0, b: -32768, add: -32768, sub: -32768, mul: 0, div: 0, mod: 0}, + itd16{a: 0, b: -32767, add: -32767, sub: 32767, mul: 0, div: 0, mod: 0}, + itd16{a: 0, b: -1, add: -1, sub: 1, mul: 0, div: 0, mod: 0}, itd16{a: 0, b: 0, add: 0, sub: 0, mul: 0}, - itd16{a: 0, b: 1, add: 1, sub: -1, mul: 0, div: 0}, - itd16{a: 0, b: 32766, add: 32766, sub: -32766, mul: 0, div: 0}, - itd16{a: 0, b: 32767, add: 32767, sub: -32767, mul: 0, div: 0}, - itd16{a: 1, b: -32768, add: -32767, sub: -32767, mul: -32768, div: 0}, - itd16{a: 1, b: -32767, add: -32766, sub: -32768, mul: -32767, div: 0}, - itd16{a: 1, b: -1, add: 0, sub: 2, mul: -1, div: -1}, + itd16{a: 0, b: 1, add: 1, sub: -1, mul: 0, div: 0, mod: 0}, + itd16{a: 0, b: 32766, add: 32766, sub: -32766, mul: 0, div: 0, mod: 0}, + itd16{a: 0, b: 32767, add: 32767, sub: -32767, mul: 0, div: 0, mod: 0}, + itd16{a: 1, b: -32768, add: -32767, sub: -32767, mul: -32768, div: 0, mod: 1}, + itd16{a: 1, b: -32767, add: -32766, sub: -32768, mul: -32767, div: 0, mod: 1}, + itd16{a: 1, b: -1, add: 0, sub: 2, mul: -1, div: -1, mod: 0}, itd16{a: 1, b: 0, add: 1, sub: 1, mul: 0}, - itd16{a: 1, b: 1, add: 2, sub: 0, mul: 1, div: 1}, - itd16{a: 1, b: 32766, add: 32767, sub: -32765, mul: 32766, div: 0}, - itd16{a: 1, b: 32767, add: -32768, sub: -32766, mul: 32767, div: 0}, - itd16{a: 32766, b: -32768, add: -2, sub: -2, mul: 0, div: 0}, - itd16{a: 32766, b: -32767, add: -1, sub: -3, mul: 32766, div: 0}, - itd16{a: 32766, b: -1, add: 32765, sub: 32767, mul: -32766, div: -32766}, + itd16{a: 1, b: 1, add: 2, sub: 0, mul: 1, div: 1, mod: 0}, + itd16{a: 1, b: 32766, add: 32767, sub: -32765, mul: 32766, div: 0, mod: 1}, + itd16{a: 1, b: 32767, add: -32768, sub: -32766, mul: 32767, div: 0, mod: 1}, + itd16{a: 32766, b: -32768, add: -2, sub: -2, mul: 0, div: 0, mod: 32766}, + itd16{a: 32766, b: -32767, add: -1, sub: -3, mul: 32766, div: 0, mod: 32766}, + itd16{a: 32766, b: -1, add: 32765, sub: 32767, mul: -32766, div: -32766, mod: 0}, itd16{a: 32766, b: 0, add: 32766, sub: 32766, mul: 0}, - itd16{a: 32766, b: 1, add: 32767, sub: 32765, mul: 32766, div: 32766}, - itd16{a: 32766, b: 32766, add: -4, sub: 0, mul: 4, div: 1}, - itd16{a: 32766, b: 32767, add: -3, sub: -1, mul: -32766, div: 0}, - itd16{a: 32767, b: -32768, add: -1, sub: -1, mul: -32768, div: 0}, - itd16{a: 32767, b: -32767, add: 0, sub: -2, mul: -1, div: -1}, - itd16{a: 32767, b: -1, add: 32766, sub: -32768, mul: -32767, div: -32767}, + itd16{a: 32766, b: 1, add: 32767, sub: 32765, mul: 32766, div: 32766, mod: 0}, + itd16{a: 32766, b: 32766, add: -4, sub: 0, mul: 4, div: 1, mod: 0}, + itd16{a: 32766, b: 32767, add: -3, sub: -1, mul: -32766, div: 0, mod: 32766}, + itd16{a: 32767, b: -32768, add: -1, sub: -1, mul: -32768, div: 0, mod: 32767}, + itd16{a: 32767, b: -32767, add: 0, sub: -2, mul: -1, div: -1, mod: 0}, + itd16{a: 32767, b: -1, add: 32766, sub: -32768, mul: -32767, div: -32767, mod: 0}, itd16{a: 32767, b: 0, add: 32767, sub: 32767, mul: 0}, - itd16{a: 32767, b: 1, add: -32768, sub: 32766, mul: 32767, div: 32767}, - itd16{a: 32767, b: 32766, add: -3, sub: 1, mul: -32766, div: 1}, - itd16{a: 32767, b: 32767, add: -2, sub: 0, mul: 1, div: 1}, + itd16{a: 32767, b: 1, add: -32768, sub: 32766, mul: 32767, div: 32767, mod: 0}, + itd16{a: 32767, b: 32766, add: -3, sub: 1, mul: -32766, div: 1, mod: 1}, + itd16{a: 32767, b: 32767, add: -2, sub: 0, mul: 1, div: 1, mod: 0}, } var uint8_data []utd8 = []utd8{utd8{a: 0, b: 0, add: 0, sub: 0, mul: 0}, - utd8{a: 0, b: 1, add: 1, sub: 255, mul: 0, div: 0}, - utd8{a: 0, b: 255, add: 255, sub: 1, mul: 0, div: 0}, + utd8{a: 0, b: 1, add: 1, sub: 255, mul: 0, div: 0, mod: 0}, + utd8{a: 0, b: 255, add: 255, sub: 1, mul: 0, div: 0, mod: 0}, utd8{a: 1, b: 0, add: 1, sub: 1, mul: 0}, - utd8{a: 1, b: 1, add: 2, sub: 0, mul: 1, div: 1}, - utd8{a: 1, b: 255, add: 0, sub: 2, mul: 255, div: 0}, + utd8{a: 1, b: 1, add: 2, sub: 0, mul: 1, div: 1, mod: 0}, + utd8{a: 1, b: 255, add: 0, sub: 2, mul: 255, div: 0, mod: 1}, utd8{a: 255, b: 0, add: 255, sub: 255, mul: 0}, - utd8{a: 255, b: 1, add: 0, sub: 254, mul: 255, div: 255}, - utd8{a: 255, b: 255, add: 254, sub: 0, mul: 1, div: 1}, + utd8{a: 255, b: 1, add: 0, sub: 254, mul: 255, div: 255, mod: 0}, + utd8{a: 255, b: 255, add: 254, sub: 0, mul: 1, div: 1, mod: 0}, } -var int8_data []itd8 = []itd8{itd8{a: -128, b: -128, add: 0, sub: 0, mul: 0, div: 1}, - itd8{a: -128, b: -127, add: 1, sub: -1, mul: -128, div: 1}, - itd8{a: -128, b: -1, add: 127, sub: -127, mul: -128, div: -128}, +var int8_data []itd8 = []itd8{itd8{a: -128, b: -128, add: 0, sub: 0, mul: 0, div: 1, mod: 0}, + itd8{a: -128, b: -127, add: 1, sub: -1, mul: -128, div: 1, mod: -1}, + itd8{a: -128, b: -1, add: 127, sub: -127, mul: -128, div: -128, mod: 0}, itd8{a: -128, b: 0, add: -128, sub: -128, mul: 0}, - itd8{a: -128, b: 1, add: -127, sub: 127, mul: -128, div: -128}, - itd8{a: -128, b: 126, add: -2, sub: 2, mul: 0, div: -1}, - itd8{a: -128, b: 127, add: -1, sub: 1, mul: -128, div: -1}, - itd8{a: -127, b: -128, add: 1, sub: 1, mul: -128, div: 0}, - itd8{a: -127, b: -127, add: 2, sub: 0, mul: 1, div: 1}, - itd8{a: -127, b: -1, add: -128, sub: -126, mul: 127, div: 127}, + itd8{a: -128, b: 1, add: -127, sub: 127, mul: -128, div: -128, mod: 0}, + itd8{a: -128, b: 126, add: -2, sub: 2, mul: 0, div: -1, mod: -2}, + itd8{a: -128, b: 127, add: -1, sub: 1, mul: -128, div: -1, mod: -1}, + itd8{a: -127, b: -128, add: 1, sub: 1, mul: -128, div: 0, mod: -127}, + itd8{a: -127, b: -127, add: 2, sub: 0, mul: 1, div: 1, mod: 0}, + itd8{a: -127, b: -1, add: -128, sub: -126, mul: 127, div: 127, mod: 0}, itd8{a: -127, b: 0, add: -127, sub: -127, mul: 0}, - itd8{a: -127, b: 1, add: -126, sub: -128, mul: -127, div: -127}, - itd8{a: -127, b: 126, add: -1, sub: 3, mul: 126, div: -1}, - itd8{a: -127, b: 127, add: 0, sub: 2, mul: -1, div: -1}, - itd8{a: -1, b: -128, add: 127, sub: 127, mul: -128, div: 0}, - itd8{a: -1, b: -127, add: -128, sub: 126, mul: 127, div: 0}, - itd8{a: -1, b: -1, add: -2, sub: 0, mul: 1, div: 1}, + itd8{a: -127, b: 1, add: -126, sub: -128, mul: -127, div: -127, mod: 0}, + itd8{a: -127, b: 126, add: -1, sub: 3, mul: 126, div: -1, mod: -1}, + itd8{a: -127, b: 127, add: 0, sub: 2, mul: -1, div: -1, mod: 0}, + itd8{a: -1, b: -128, add: 127, sub: 127, mul: -128, div: 0, mod: -1}, + itd8{a: -1, b: -127, add: -128, sub: 126, mul: 127, div: 0, mod: -1}, + itd8{a: -1, b: -1, add: -2, sub: 0, mul: 1, div: 1, mod: 0}, itd8{a: -1, b: 0, add: -1, sub: -1, mul: 0}, - itd8{a: -1, b: 1, add: 0, sub: -2, mul: -1, div: -1}, - itd8{a: -1, b: 126, add: 125, sub: -127, mul: -126, div: 0}, - itd8{a: -1, b: 127, add: 126, sub: -128, mul: -127, div: 0}, - itd8{a: 0, b: -128, add: -128, sub: -128, mul: 0, div: 0}, - itd8{a: 0, b: -127, add: -127, sub: 127, mul: 0, div: 0}, - itd8{a: 0, b: -1, add: -1, sub: 1, mul: 0, div: 0}, + itd8{a: -1, b: 1, add: 0, sub: -2, mul: -1, div: -1, mod: 0}, + itd8{a: -1, b: 126, add: 125, sub: -127, mul: -126, div: 0, mod: -1}, + itd8{a: -1, b: 127, add: 126, sub: -128, mul: -127, div: 0, mod: -1}, + itd8{a: 0, b: -128, add: -128, sub: -128, mul: 0, div: 0, mod: 0}, + itd8{a: 0, b: -127, add: -127, sub: 127, mul: 0, div: 0, mod: 0}, + itd8{a: 0, b: -1, add: -1, sub: 1, mul: 0, div: 0, mod: 0}, itd8{a: 0, b: 0, add: 0, sub: 0, mul: 0}, - itd8{a: 0, b: 1, add: 1, sub: -1, mul: 0, div: 0}, - itd8{a: 0, b: 126, add: 126, sub: -126, mul: 0, div: 0}, - itd8{a: 0, b: 127, add: 127, sub: -127, mul: 0, div: 0}, - itd8{a: 1, b: -128, add: -127, sub: -127, mul: -128, div: 0}, - itd8{a: 1, b: -127, add: -126, sub: -128, mul: -127, div: 0}, - itd8{a: 1, b: -1, add: 0, sub: 2, mul: -1, div: -1}, + itd8{a: 0, b: 1, add: 1, sub: -1, mul: 0, div: 0, mod: 0}, + itd8{a: 0, b: 126, add: 126, sub: -126, mul: 0, div: 0, mod: 0}, + itd8{a: 0, b: 127, add: 127, sub: -127, mul: 0, div: 0, mod: 0}, + itd8{a: 1, b: -128, add: -127, sub: -127, mul: -128, div: 0, mod: 1}, + itd8{a: 1, b: -127, add: -126, sub: -128, mul: -127, div: 0, mod: 1}, + itd8{a: 1, b: -1, add: 0, sub: 2, mul: -1, div: -1, mod: 0}, itd8{a: 1, b: 0, add: 1, sub: 1, mul: 0}, - itd8{a: 1, b: 1, add: 2, sub: 0, mul: 1, div: 1}, - itd8{a: 1, b: 126, add: 127, sub: -125, mul: 126, div: 0}, - itd8{a: 1, b: 127, add: -128, sub: -126, mul: 127, div: 0}, - itd8{a: 126, b: -128, add: -2, sub: -2, mul: 0, div: 0}, - itd8{a: 126, b: -127, add: -1, sub: -3, mul: 126, div: 0}, - itd8{a: 126, b: -1, add: 125, sub: 127, mul: -126, div: -126}, + itd8{a: 1, b: 1, add: 2, sub: 0, mul: 1, div: 1, mod: 0}, + itd8{a: 1, b: 126, add: 127, sub: -125, mul: 126, div: 0, mod: 1}, + itd8{a: 1, b: 127, add: -128, sub: -126, mul: 127, div: 0, mod: 1}, + itd8{a: 126, b: -128, add: -2, sub: -2, mul: 0, div: 0, mod: 126}, + itd8{a: 126, b: -127, add: -1, sub: -3, mul: 126, div: 0, mod: 126}, + itd8{a: 126, b: -1, add: 125, sub: 127, mul: -126, div: -126, mod: 0}, itd8{a: 126, b: 0, add: 126, sub: 126, mul: 0}, - itd8{a: 126, b: 1, add: 127, sub: 125, mul: 126, div: 126}, - itd8{a: 126, b: 126, add: -4, sub: 0, mul: 4, div: 1}, - itd8{a: 126, b: 127, add: -3, sub: -1, mul: -126, div: 0}, - itd8{a: 127, b: -128, add: -1, sub: -1, mul: -128, div: 0}, - itd8{a: 127, b: -127, add: 0, sub: -2, mul: -1, div: -1}, - itd8{a: 127, b: -1, add: 126, sub: -128, mul: -127, div: -127}, + itd8{a: 126, b: 1, add: 127, sub: 125, mul: 126, div: 126, mod: 0}, + itd8{a: 126, b: 126, add: -4, sub: 0, mul: 4, div: 1, mod: 0}, + itd8{a: 126, b: 127, add: -3, sub: -1, mul: -126, div: 0, mod: 126}, + itd8{a: 127, b: -128, add: -1, sub: -1, mul: -128, div: 0, mod: 127}, + itd8{a: 127, b: -127, add: 0, sub: -2, mul: -1, div: -1, mod: 0}, + itd8{a: 127, b: -1, add: 126, sub: -128, mul: -127, div: -127, mod: 0}, itd8{a: 127, b: 0, add: 127, sub: 127, mul: 0}, - itd8{a: 127, b: 1, add: -128, sub: 126, mul: 127, div: 127}, - itd8{a: 127, b: 126, add: -3, sub: 1, mul: -126, div: 1}, - itd8{a: 127, b: 127, add: -2, sub: 0, mul: 1, div: 1}, + itd8{a: 127, b: 1, add: -128, sub: 126, mul: 127, div: 127, mod: 0}, + itd8{a: 127, b: 126, add: -3, sub: 1, mul: -126, div: 1, mod: 1}, + itd8{a: 127, b: 127, add: -2, sub: 0, mul: 1, div: 1, mod: 0}, } var failed bool @@ -481,6 +521,13 @@ func main() { failed = true } + } + if v.b != 0 { + if got := mod_uint64_ssa(v.a, v.b); got != v.mod { + fmt.Printf("mod_uint64 %d%%%d = %d, wanted %d\n", v.a, v.b, got, v.mod) + failed = true + } + } if got := mul_uint64_ssa(v.a, v.b); got != v.mul { fmt.Printf("mul_uint64 %d*%d = %d, wanted %d\n", v.a, v.b, got, v.mul) @@ -502,6 +549,13 @@ func main() { failed = true } + } + if v.b != 0 { + if got := mod_int64_ssa(v.a, v.b); got != v.mod { + fmt.Printf("mod_int64 %d%%%d = %d, wanted %d\n", v.a, v.b, got, v.mod) + failed = true + } + } if got := mul_int64_ssa(v.a, v.b); got != v.mul { fmt.Printf("mul_int64 %d*%d = %d, wanted %d\n", v.a, v.b, got, v.mul) @@ -523,6 +577,13 @@ func main() { failed = true } + } + if v.b != 0 { + if got := mod_uint32_ssa(v.a, v.b); got != v.mod { + fmt.Printf("mod_uint32 %d%%%d = %d, wanted %d\n", v.a, v.b, got, v.mod) + failed = true + } + } if got := mul_uint32_ssa(v.a, v.b); got != v.mul { fmt.Printf("mul_uint32 %d*%d = %d, wanted %d\n", v.a, v.b, got, v.mul) @@ -544,6 +605,13 @@ func main() { failed = true } + } + if v.b != 0 { + if got := mod_int32_ssa(v.a, v.b); got != v.mod { + fmt.Printf("mod_int32 %d%%%d = %d, wanted %d\n", v.a, v.b, got, v.mod) + failed = true + } + } if got := mul_int32_ssa(v.a, v.b); got != v.mul { fmt.Printf("mul_int32 %d*%d = %d, wanted %d\n", v.a, v.b, got, v.mul) @@ -565,6 +633,13 @@ func main() { failed = true } + } + if v.b != 0 { + if got := mod_uint16_ssa(v.a, v.b); got != v.mod { + fmt.Printf("mod_uint16 %d%%%d = %d, wanted %d\n", v.a, v.b, got, v.mod) + failed = true + } + } if got := mul_uint16_ssa(v.a, v.b); got != v.mul { fmt.Printf("mul_uint16 %d*%d = %d, wanted %d\n", v.a, v.b, got, v.mul) @@ -586,6 +661,13 @@ func main() { failed = true } + } + if v.b != 0 { + if got := mod_int16_ssa(v.a, v.b); got != v.mod { + fmt.Printf("mod_int16 %d%%%d = %d, wanted %d\n", v.a, v.b, got, v.mod) + failed = true + } + } if got := mul_int16_ssa(v.a, v.b); got != v.mul { fmt.Printf("mul_int16 %d*%d = %d, wanted %d\n", v.a, v.b, got, v.mul) @@ -607,6 +689,13 @@ func main() { failed = true } + } + if v.b != 0 { + if got := mod_uint8_ssa(v.a, v.b); got != v.mod { + fmt.Printf("mod_uint8 %d%%%d = %d, wanted %d\n", v.a, v.b, got, v.mod) + failed = true + } + } if got := mul_uint8_ssa(v.a, v.b); got != v.mul { fmt.Printf("mul_uint8 %d*%d = %d, wanted %d\n", v.a, v.b, got, v.mul) @@ -628,6 +717,13 @@ func main() { failed = true } + } + if v.b != 0 { + if got := mod_int8_ssa(v.a, v.b); got != v.mod { + fmt.Printf("mod_int8 %d%%%d = %d, wanted %d\n", v.a, v.b, got, v.mod) + failed = true + } + } if got := mul_int8_ssa(v.a, v.b); got != v.mul { fmt.Printf("mul_int8 %d*%d = %d, wanted %d\n", v.a, v.b, got, v.mul) diff --git a/src/cmd/compile/internal/gc/testdata/gen/arithBoundaryGen.go b/src/cmd/compile/internal/gc/testdata/gen/arithBoundaryGen.go new file mode 100644 index 0000000000..19bb04b6f1 --- /dev/null +++ b/src/cmd/compile/internal/gc/testdata/gen/arithBoundaryGen.go @@ -0,0 +1,214 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This program generates a test to verify that the standard arithmetic +// operators properly handle some special cases. The test file should be +// generated with a known working version of go. +// launch with `go run arithBoundaryGen.go` a file called arithBoundary_ssa.go +// will be written into the parent directory containing the tests + +package main + +import ( + "bytes" + "fmt" + "go/format" + "io/ioutil" + "log" + "text/template" +) + +// used for interpolation in a text template +type tmplData struct { + Name, Stype, Symbol string +} + +// used to work around an issue with the mod symbol being +// interpreted as part of a format string +func (s tmplData) SymFirst() string { + return string(s.Symbol[0]) +} + +// ucast casts an unsigned int to the size in s +func ucast(i uint64, s sizedTestData) uint64 { + switch s.name { + case "uint32": + return uint64(uint32(i)) + case "uint16": + return uint64(uint16(i)) + case "uint8": + return uint64(uint8(i)) + } + return i +} + +// icast casts a signed int to the size in s +func icast(i int64, s sizedTestData) int64 { + switch s.name { + case "int32": + return int64(int32(i)) + case "int16": + return int64(int16(i)) + case "int8": + return int64(int8(i)) + } + return i +} + +type sizedTestData struct { + name string + sn string + u []uint64 + i []int64 +} + +// values to generate tests. these should include the smallest and largest values, along +// with any other values that might cause issues. we generate n^2 tests for each size to +// cover all cases. +var szs = []sizedTestData{ + sizedTestData{name: "uint64", sn: "64", u: []uint64{0, 1, 4294967296, 0xffffFFFFffffFFFF}}, + sizedTestData{name: "int64", sn: "64", i: []int64{-0x8000000000000000, -0x7FFFFFFFFFFFFFFF, + -4294967296, -1, 0, 1, 4294967296, 0x7FFFFFFFFFFFFFFE, 0x7FFFFFFFFFFFFFFF}}, + + sizedTestData{name: "uint32", sn: "32", u: []uint64{0, 1, 4294967295}}, + sizedTestData{name: "int32", sn: "32", i: []int64{-0x80000000, -0x7FFFFFFF, -1, 0, + 1, 0x7FFFFFFF}}, + + sizedTestData{name: "uint16", sn: "16", u: []uint64{0, 1, 65535}}, + sizedTestData{name: "int16", sn: "16", i: []int64{-32768, -32767, -1, 0, 1, 32766, 32767}}, + + sizedTestData{name: "uint8", sn: "8", u: []uint64{0, 1, 255}}, + sizedTestData{name: "int8", sn: "8", i: []int64{-128, -127, -1, 0, 1, 126, 127}}, +} + +type op struct { + name, symbol string +} + +// ops that we will be generating tests for +var ops = []op{op{"add", "+"}, op{"sub", "-"}, op{"div", "/"}, op{"mod", "%%"}, op{"mul", "*"}} + +func main() { + + w := new(bytes.Buffer) + fmt.Fprintf(w, "package main;\n") + fmt.Fprintf(w, "import \"fmt\"\n") + + for _, sz := range []int{64, 32, 16, 8} { + fmt.Fprintf(w, "type utd%d struct {\n", sz) + fmt.Fprintf(w, " a,b uint%d\n", sz) + fmt.Fprintf(w, " add,sub,mul,div,mod uint%d\n", sz) + fmt.Fprintf(w, "}\n") + + fmt.Fprintf(w, "type itd%d struct {\n", sz) + fmt.Fprintf(w, " a,b int%d\n", sz) + fmt.Fprintf(w, " add,sub,mul,div,mod int%d\n", sz) + fmt.Fprintf(w, "}\n") + } + + // the function being tested + testFunc, err := template.New("testFunc").Parse( + `func {{.Name}}_{{.Stype}}_ssa(a, b {{.Stype}}) {{.Stype}} { + switch{} // prevent inlining + return a {{.SymFirst}} b +} +`) + if err != nil { + panic(err) + } + + // generate our functions to be tested + for _, s := range szs { + for _, o := range ops { + fd := tmplData{o.name, s.name, o.symbol} + err = testFunc.Execute(w, fd) + if err != nil { + panic(err) + } + } + } + + // generate the test data + for _, s := range szs { + if len(s.u) > 0 { + fmt.Fprintf(w, "var %s_data []utd%s = []utd%s{", s.name, s.sn, s.sn) + for _, i := range s.u { + for _, j := range s.u { + fmt.Fprintf(w, "utd%s{a: %d, b: %d, add: %d, sub: %d, mul: %d", s.sn, i, j, ucast(i+j, s), ucast(i-j, s), ucast(i*j, s)) + if j != 0 { + fmt.Fprintf(w, ", div: %d, mod: %d", ucast(i/j, s), ucast(i%j, s)) + } + fmt.Fprint(w, "},\n") + } + } + fmt.Fprintf(w, "}\n") + } else { + // TODO: clean up this duplication + fmt.Fprintf(w, "var %s_data []itd%s = []itd%s{", s.name, s.sn, s.sn) + for _, i := range s.i { + for _, j := range s.i { + fmt.Fprintf(w, "itd%s{a: %d, b: %d, add: %d, sub: %d, mul: %d", s.sn, i, j, icast(i+j, s), icast(i-j, s), icast(i*j, s)) + if j != 0 { + fmt.Fprintf(w, ", div: %d, mod: %d", icast(i/j, s), icast(i%j, s)) + } + fmt.Fprint(w, "},\n") + } + } + fmt.Fprintf(w, "}\n") + } + } + + fmt.Fprintf(w, "var failed bool\n\n") + fmt.Fprintf(w, "func main() {\n\n") + + verify, err := template.New("tst").Parse( + `if got := {{.Name}}_{{.Stype}}_ssa(v.a, v.b); got != v.{{.Name}} { + fmt.Printf("{{.Name}}_{{.Stype}} %d{{.Symbol}}%d = %d, wanted %d\n",v.a,v.b,got,v.{{.Name}}) + failed = true +} +`) + + for _, s := range szs { + fmt.Fprintf(w, "for _, v := range %s_data {\n", s.name) + + for _, o := range ops { + // avoid generating tests that divide by zero + if o.name == "div" || o.name == "mod" { + fmt.Fprint(w, "if v.b != 0 {") + } + + err = verify.Execute(w, tmplData{o.name, s.name, o.symbol}) + + if o.name == "div" || o.name == "mod" { + fmt.Fprint(w, "\n}\n") + } + + if err != nil { + panic(err) + } + + } + fmt.Fprint(w, " }\n") + } + + fmt.Fprintf(w, `if failed { + panic("tests failed") + } +`) + fmt.Fprintf(w, "}\n") + + // gofmt result + b := w.Bytes() + src, err := format.Source(b) + if err != nil { + fmt.Printf("%s\n", b) + panic(err) + } + + // write to file + err = ioutil.WriteFile("../arithBoundary_ssa.go", src, 0666) + if err != nil { + log.Fatalf("can't write output: %v\n", err) + } +} diff --git a/src/cmd/compile/internal/ssa/gen/AMD64.rules b/src/cmd/compile/internal/ssa/gen/AMD64.rules index 919336e869..582528801a 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64.rules +++ b/src/cmd/compile/internal/ssa/gen/AMD64.rules @@ -52,6 +52,15 @@ (Hmul8 x y) -> (HMULB x y) (Hmul8u x y) -> (HMULBU x y) +(Mod64 x y) -> (MODQ x y) +(Mod64u x y) -> (MODQU x y) +(Mod32 x y) -> (MODL x y) +(Mod32u x y) -> (MODLU x y) +(Mod16 x y) -> (MODW x y) +(Mod16u x y) -> (MODWU x y) +(Mod8 x y) -> (MODW (SignExt8to16 x) (SignExt8to16 y)) +(Mod8u x y) -> (MODWU (ZeroExt8to16 x) (ZeroExt8to16 y)) + (And64 x y) -> (ANDQ x y) (And32 x y) -> (ANDL x y) (And16 x y) -> (ANDW x y) diff --git a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go index b218c66a64..7469601fc7 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go @@ -103,6 +103,8 @@ func init() { clobbers: dx | flags} gp11hmul = regInfo{inputs: []regMask{ax, gpsp}, outputs: []regMask{dx}, clobbers: ax | flags} + gp11mod = regInfo{inputs: []regMask{ax, gpsp &^ dx}, outputs: []regMask{dx}, + clobbers: ax | flags} gp10 = regInfo{inputs: []regMask{gp}} gp2flags = regInfo{inputs: []regMask{gpsp, gpsp}, outputs: flagsonly} @@ -202,6 +204,13 @@ func init() { {name: "DIVLU", reg: gp11div, asm: "DIVL"}, // arg0 / arg1 {name: "DIVWU", reg: gp11div, asm: "DIVW"}, // arg0 / arg1 + {name: "MODQ", reg: gp11mod, asm: "IDIVQ"}, // arg0 % arg1 + {name: "MODL", reg: gp11mod, asm: "IDIVL"}, // arg0 % arg1 + {name: "MODW", reg: gp11mod, asm: "IDIVW"}, // arg0 % arg1 + {name: "MODQU", reg: gp11mod, asm: "DIVQ"}, // arg0 % arg1 + {name: "MODLU", reg: gp11mod, asm: "DIVL"}, // arg0 % arg1 + {name: "MODWU", reg: gp11mod, asm: "DIVW"}, // arg0 % arg1 + {name: "ANDQ", reg: gp21, asm: "ANDQ"}, // arg0 & arg1 {name: "ANDL", reg: gp21, asm: "ANDL"}, // arg0 & arg1 {name: "ANDW", reg: gp21, asm: "ANDW"}, // arg0 & arg1 diff --git a/src/cmd/compile/internal/ssa/gen/genericOps.go b/src/cmd/compile/internal/ssa/gen/genericOps.go index 5b8b064bb5..78524a5e6b 100644 --- a/src/cmd/compile/internal/ssa/gen/genericOps.go +++ b/src/cmd/compile/internal/ssa/gen/genericOps.go @@ -35,7 +35,6 @@ var genericOps = []opData{ {name: "Div32F"}, // arg0 / arg1 {name: "Div64F"}, - // TODO: Div8, Div16, Div32, Div64 and unsigned {name: "Hmul8"}, // (arg0 * arg1) >> width {name: "Hmul8u"}, @@ -54,6 +53,15 @@ var genericOps = []opData{ {name: "Div64"}, {name: "Div64u"}, + {name: "Mod8"}, // arg0 % arg1 + {name: "Mod8u"}, + {name: "Mod16"}, + {name: "Mod16u"}, + {name: "Mod32"}, + {name: "Mod32u"}, + {name: "Mod64"}, + {name: "Mod64u"}, + {name: "And8"}, // arg0 & arg1 {name: "And16"}, {name: "And32"}, diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index a2e087246d..11fc3180cf 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -105,6 +105,12 @@ const ( OpAMD64DIVQU OpAMD64DIVLU OpAMD64DIVWU + OpAMD64MODQ + OpAMD64MODL + OpAMD64MODW + OpAMD64MODQU + OpAMD64MODLU + OpAMD64MODWU OpAMD64ANDQ OpAMD64ANDL OpAMD64ANDW @@ -267,6 +273,14 @@ const ( OpDiv32u OpDiv64 OpDiv64u + OpMod8 + OpMod8u + OpMod16 + OpMod16u + OpMod32 + OpMod32u + OpMod64 + OpMod64u OpAnd8 OpAnd16 OpAnd32 @@ -1165,6 +1179,90 @@ var opcodeTable = [...]opInfo{ }, }, }, + { + name: "MODQ", + asm: x86.AIDIVQ, + reg: regInfo{ + inputs: []inputInfo{ + {0, 1}, // .AX + {1, 65531}, // .AX .CX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + clobbers: 8589934593, // .AX .FLAGS + outputs: []regMask{ + 4, // .DX + }, + }, + }, + { + name: "MODL", + asm: x86.AIDIVL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 1}, // .AX + {1, 65531}, // .AX .CX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + clobbers: 8589934593, // .AX .FLAGS + outputs: []regMask{ + 4, // .DX + }, + }, + }, + { + name: "MODW", + asm: x86.AIDIVW, + reg: regInfo{ + inputs: []inputInfo{ + {0, 1}, // .AX + {1, 65531}, // .AX .CX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + clobbers: 8589934593, // .AX .FLAGS + outputs: []regMask{ + 4, // .DX + }, + }, + }, + { + name: "MODQU", + asm: x86.ADIVQ, + reg: regInfo{ + inputs: []inputInfo{ + {0, 1}, // .AX + {1, 65531}, // .AX .CX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + clobbers: 8589934593, // .AX .FLAGS + outputs: []regMask{ + 4, // .DX + }, + }, + }, + { + name: "MODLU", + asm: x86.ADIVL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 1}, // .AX + {1, 65531}, // .AX .CX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + clobbers: 8589934593, // .AX .FLAGS + outputs: []regMask{ + 4, // .DX + }, + }, + }, + { + name: "MODWU", + asm: x86.ADIVW, + reg: regInfo{ + inputs: []inputInfo{ + {0, 1}, // .AX + {1, 65531}, // .AX .CX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + clobbers: 8589934593, // .AX .FLAGS + outputs: []regMask{ + 4, // .DX + }, + }, + }, { name: "ANDQ", asm: x86.AANDQ, @@ -2852,6 +2950,38 @@ var opcodeTable = [...]opInfo{ name: "Div64u", generic: true, }, + { + name: "Mod8", + generic: true, + }, + { + name: "Mod8u", + generic: true, + }, + { + name: "Mod16", + generic: true, + }, + { + name: "Mod16u", + generic: true, + }, + { + name: "Mod32", + generic: true, + }, + { + name: "Mod32u", + generic: true, + }, + { + name: "Mod64", + generic: true, + }, + { + name: "Mod64u", + generic: true, + }, { name: "And8", generic: true, diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go index 4265cfcb84..3b2b7f03a7 100644 --- a/src/cmd/compile/internal/ssa/rewriteAMD64.go +++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go @@ -4734,6 +4734,162 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto end61dbc9d9e93dd6946a20a1f475b3f74b end61dbc9d9e93dd6946a20a1f475b3f74b: ; + case OpMod16: + // match: (Mod16 x y) + // cond: + // result: (MODW x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64MODW + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto end036bac694be9fe0d6b00b86c2e625990 + end036bac694be9fe0d6b00b86c2e625990: + ; + case OpMod16u: + // match: (Mod16u x y) + // cond: + // result: (MODWU x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64MODWU + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto enda75d900097f1510ca1c6df786bef0c24 + enda75d900097f1510ca1c6df786bef0c24: + ; + case OpMod32: + // match: (Mod32 x y) + // cond: + // result: (MODL x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64MODL + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto end12c8c0ecf3296810b8217cd4e40f7707 + end12c8c0ecf3296810b8217cd4e40f7707: + ; + case OpMod32u: + // match: (Mod32u x y) + // cond: + // result: (MODLU x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64MODLU + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto end1f0892076cfd58733a08d3ab175a3c1c + end1f0892076cfd58733a08d3ab175a3c1c: + ; + case OpMod64: + // match: (Mod64 x y) + // cond: + // result: (MODQ x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64MODQ + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto endaae75f449baf5dc108be4e0439af97f2 + endaae75f449baf5dc108be4e0439af97f2: + ; + case OpMod64u: + // match: (Mod64u x y) + // cond: + // result: (MODQU x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64MODQU + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto end0d4c8b9df77e59289fb14e2496559d1d + end0d4c8b9df77e59289fb14e2496559d1d: + ; + case OpMod8: + // match: (Mod8 x y) + // cond: + // result: (MODW (SignExt8to16 x) (SignExt8to16 y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64MODW + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpSignExt8to16, TypeInvalid) + v0.Type = config.Frontend().TypeInt16() + v0.AddArg(x) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpSignExt8to16, TypeInvalid) + v1.Type = config.Frontend().TypeInt16() + v1.AddArg(y) + v.AddArg(v1) + return true + } + goto end13bfd4e75ea363f7b6926fa05136e193 + end13bfd4e75ea363f7b6926fa05136e193: + ; + case OpMod8u: + // match: (Mod8u x y) + // cond: + // result: (MODWU (ZeroExt8to16 x) (ZeroExt8to16 y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64MODWU + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpZeroExt8to16, TypeInvalid) + v0.Type = config.Frontend().TypeUInt16() + v0.AddArg(x) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpZeroExt8to16, TypeInvalid) + v1.Type = config.Frontend().TypeUInt16() + v1.AddArg(y) + v.AddArg(v1) + return true + } + goto end4c0e16e55b5f8f6d19811fc8d07eacf2 + end4c0e16e55b5f8f6d19811fc8d07eacf2: + ; case OpMove: // match: (Move [size] dst src mem) // cond: -- cgit v1.3 From 4282588694de58b86df17af7366a5f00903af24b Mon Sep 17 00:00:00 2001 From: David Chase Date: Thu, 20 Aug 2015 15:14:20 -0400 Subject: [dev.ssa] cmd/compile: add [u]int and FP to FP conversions Change-Id: I8c17f706a3e0f1fa2d754bfb4ccd1f7a027cb3db Reviewed-on: https://go-review.googlesource.com/13744 Reviewed-by: Keith Randall --- src/cmd/compile/internal/gc/ssa.go | 195 ++++++++++++++++++++++++- src/cmd/compile/internal/gc/testdata/fp_ssa.go | 140 ++++++++++++++++++ src/cmd/compile/internal/ssa/gen/AMD64.rules | 13 ++ src/cmd/compile/internal/ssa/gen/AMD64Ops.go | 18 ++- src/cmd/compile/internal/ssa/gen/genericOps.go | 11 ++ src/cmd/compile/internal/ssa/opGen.go | 180 +++++++++++++++++++++++ src/cmd/compile/internal/ssa/rewriteAMD64.go | 160 ++++++++++++++++++++ 7 files changed, 708 insertions(+), 9 deletions(-) (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 0f0610e139..8e44ede318 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -1217,6 +1217,84 @@ func (s *state) expr(n *Node) *ssa.Value { } return s.newValue1(op, n.Type, x) } + + var op1, op2 ssa.Op + if ft.IsInteger() && tt.IsFloat() { + // signed 1, 2, 4, 8, unsigned 6, 7, 9, 13 + signedSize := ft.Size() + it := TINT32 // intermediate type in conversion, int32 or int64 + if !ft.IsSigned() { + signedSize += 5 + } + switch signedSize { + case 1: + op1 = ssa.OpSignExt8to32 + case 2: + op1 = ssa.OpSignExt16to32 + case 4: + op1 = ssa.OpCopy + case 8: + op1 = ssa.OpCopy + it = TINT64 + case 6: + op1 = ssa.OpZeroExt8to32 + case 7: + op1 = ssa.OpZeroExt16to32 + case 9: + // Go wide to dodge the unsignedness correction + op1 = ssa.OpZeroExt32to64 + it = TINT64 + case 13: + // unsigned 64, there is branchy correction code + // because there is only signed-integer to FP + // conversion in the (AMD64) instructions set. + // Branchy correction code *may* be amenable to + // optimization, and it can be cleanly expressed + // in SSA, so do it here. + if tt.Size() == 4 { + return s.uint64Tofloat32(n, x, ft, tt) + } + if tt.Size() == 8 { + return s.uint64Tofloat64(n, x, ft, tt) + } + + default: + s.Fatalf("weird integer to float sign extension %s -> %s", ft, tt) + + } + if tt.Size() == 4 { + if it == TINT64 { + op2 = ssa.OpCvt64to32F + } else { + op2 = ssa.OpCvt32to32F + } + } else { + if it == TINT64 { + op2 = ssa.OpCvt64to64F + } else { + op2 = ssa.OpCvt32to64F + } + } + if op1 == ssa.OpCopy { + return s.newValue1(op2, n.Type, x) + } + return s.newValue1(op2, n.Type, s.newValue1(op1, Types[it], x)) + } + if ft.IsFloat() && tt.IsFloat() { + var op ssa.Op + if ft.Size() == tt.Size() { + op = ssa.OpCopy + } else if ft.Size() == 4 && tt.Size() == 8 { + op = ssa.OpCvt32Fto64F + } else if ft.Size() == 8 && tt.Size() == 4 { + op = ssa.OpCvt64Fto32F + } else { + s.Fatalf("weird float conversion %s -> %s", ft, tt) + } + return s.newValue1(op, n.Type, x) + } + // TODO: Still lack float-to-int + s.Unimplementedf("unhandled OCONV %s -> %s", Econv(int(n.Left.Type.Etype), 0), Econv(int(n.Type.Etype), 0)) return nil @@ -1709,6 +1787,112 @@ func (s *state) boundsCheck(idx, len *ssa.Value) { s.startBlock(bNext) } +type u2fcvtTab struct { + geq, cvt2F, and, rsh, or, add ssa.Op + one func(*state, ssa.Type, int64) *ssa.Value +} + +var u64_f64 u2fcvtTab = u2fcvtTab{ + geq: ssa.OpGeq64, + cvt2F: ssa.OpCvt64to64F, + and: ssa.OpAnd64, + rsh: ssa.OpRsh64Ux64, + or: ssa.OpOr64, + add: ssa.OpAdd64F, + one: (*state).constInt64, +} + +var u64_f32 u2fcvtTab = u2fcvtTab{ + geq: ssa.OpGeq64, + cvt2F: ssa.OpCvt64to32F, + and: ssa.OpAnd64, + rsh: ssa.OpRsh64Ux64, + or: ssa.OpOr64, + add: ssa.OpAdd32F, + one: (*state).constInt64, +} + +// Excess generality on a machine with 64-bit integer registers. +// Not used on AMD64. +var u32_f32 u2fcvtTab = u2fcvtTab{ + geq: ssa.OpGeq32, + cvt2F: ssa.OpCvt32to32F, + and: ssa.OpAnd32, + rsh: ssa.OpRsh32Ux32, + or: ssa.OpOr32, + add: ssa.OpAdd32F, + one: func(s *state, t ssa.Type, x int64) *ssa.Value { + return s.constInt32(t, int32(x)) + }, +} + +func (s *state) uint64Tofloat64(n *Node, x *ssa.Value, ft, tt *Type) *ssa.Value { + return s.uintTofloat(&u64_f64, n, x, ft, tt) +} + +func (s *state) uint64Tofloat32(n *Node, x *ssa.Value, ft, tt *Type) *ssa.Value { + return s.uintTofloat(&u64_f32, n, x, ft, tt) +} + +func (s *state) uintTofloat(cvttab *u2fcvtTab, n *Node, x *ssa.Value, ft, tt *Type) *ssa.Value { + // if x >= 0 { + // result = (floatY) x + // } else { + // y = uintX(x) ; y = x & 1 + // z = uintX(x) ; z = z >> 1 + // z = z >> 1 + // z = z | y + // result = (floatY) z + // z = z + z + // } + // + // Code borrowed from old code generator. + // What's going on: large 64-bit "unsigned" looks like + // negative number to hardware's integer-to-float + // conversion. However, because the mantissa is only + // 63 bits, we don't need the LSB, so instead we do an + // unsigned right shift (divide by two), convert, and + // double. However, before we do that, we need to be + // sure that we do not lose a "1" if that made the + // difference in the resulting rounding. Therefore, we + // preserve it, and OR (not ADD) it back in. The case + // that matters is when the eleven discarded bits are + // equal to 10000000001; that rounds up, and the 1 cannot + // be lost else it would round down if the LSB of the + // candidate mantissa is 0. + cmp := s.newValue2(cvttab.geq, Types[TBOOL], x, s.zeroVal(ft)) + b := s.endBlock() + b.Kind = ssa.BlockIf + b.Control = cmp + b.Likely = ssa.BranchLikely + + bThen := s.f.NewBlock(ssa.BlockPlain) + bElse := s.f.NewBlock(ssa.BlockPlain) + bAfter := s.f.NewBlock(ssa.BlockPlain) + + addEdge(b, bThen) + s.startBlock(bThen) + a0 := s.newValue1(cvttab.cvt2F, tt, x) + s.vars[n] = a0 + s.endBlock() + addEdge(bThen, bAfter) + + addEdge(b, bElse) + s.startBlock(bElse) + one := cvttab.one(s, ft, 1) + y := s.newValue2(cvttab.and, ft, x, one) + z := s.newValue2(cvttab.rsh, ft, x, one) + z = s.newValue2(cvttab.or, ft, z, y) + a := s.newValue1(cvttab.cvt2F, tt, z) + a1 := s.newValue2(cvttab.add, tt, a, a) + s.vars[n] = a1 + s.endBlock() + addEdge(bElse, bAfter) + + s.startBlock(bAfter) + return s.variable(n, n.Type) +} + // checkgoto checks that a goto from from to to does not // jump into a block or jump over variable declarations. // It is a copy of checkgoto in the pre-SSA backend, @@ -2425,12 +2609,11 @@ func genValue(v *ssa.Value) { p.To.Scale = 4 p.To.Index = regnum(v.Args[1]) addAux(&p.To, v) - case ssa.OpAMD64MOVLQSX, ssa.OpAMD64MOVWQSX, ssa.OpAMD64MOVBQSX, ssa.OpAMD64MOVLQZX, ssa.OpAMD64MOVWQZX, ssa.OpAMD64MOVBQZX: - p := Prog(v.Op.Asm()) - p.From.Type = obj.TYPE_REG - p.From.Reg = regnum(v.Args[0]) - p.To.Type = obj.TYPE_REG - p.To.Reg = regnum(v) + case ssa.OpAMD64MOVLQSX, ssa.OpAMD64MOVWQSX, ssa.OpAMD64MOVBQSX, ssa.OpAMD64MOVLQZX, ssa.OpAMD64MOVWQZX, ssa.OpAMD64MOVBQZX, + ssa.OpAMD64CVTSL2SS, ssa.OpAMD64CVTSL2SD, ssa.OpAMD64CVTSQ2SS, ssa.OpAMD64CVTSQ2SD, + ssa.OpAMD64CVTSS2SL, ssa.OpAMD64CVTSD2SL, ssa.OpAMD64CVTSS2SQ, ssa.OpAMD64CVTSD2SQ, + ssa.OpAMD64CVTSS2SD, ssa.OpAMD64CVTSD2SS: + opregreg(v.Op.Asm(), regnum(v), regnum(v.Args[0])) case ssa.OpAMD64MOVXzero: nb := v.AuxInt offset := int64(0) diff --git a/src/cmd/compile/internal/gc/testdata/fp_ssa.go b/src/cmd/compile/internal/gc/testdata/fp_ssa.go index 73366cdfa8..1a52100d6b 100644 --- a/src/cmd/compile/internal/gc/testdata/fp_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/fp_ssa.go @@ -31,10 +31,43 @@ func fail32(s string, f func(a, b float32) float32, a, b, e float32) int { func expect64(s string, x, expected float64) int { if x != expected { println("Expected", expected, "for", s, ", got", x) + return 1 } return 0 } +func expect32(s string, x, expected float32) int { + if x != expected { + println("Expected", expected, "for", s, ", got", x) + return 1 + } + return 0 +} + +func expectAll64(s string, expected, a, b, c, d, e, f, g, h, i float64) int { + fails := 0 + fails += expect64(s+":a", a, expected) + fails += expect64(s+":b", b, expected) + fails += expect64(s+":c", c, expected) + fails += expect64(s+":d", d, expected) + fails += expect64(s+":e", e, expected) + fails += expect64(s+":f", f, expected) + fails += expect64(s+":g", g, expected) + return fails +} + +func expectAll32(s string, expected, a, b, c, d, e, f, g, h, i float32) int { + fails := 0 + fails += expect32(s+":a", a, expected) + fails += expect32(s+":b", b, expected) + fails += expect32(s+":c", c, expected) + fails += expect32(s+":d", d, expected) + fails += expect32(s+":e", e, expected) + fails += expect32(s+":f", f, expected) + fails += expect32(s+":g", g, expected) + return fails +} + // manysub_ssa is designed to tickle bugs that depend on register // pressure or unfriendly operand ordering in registers (and at // least once it succeeded in this). @@ -107,6 +140,111 @@ func div32_ssa(a, b float32) float32 { return a / b } +func conv2Float64_ssa(a int8, b uint8, c int16, d uint16, + e int32, f uint32, g int64, h uint64, i float32) (aa, bb, cc, dd, ee, ff, gg, hh, ii float64) { + switch { + } + aa = float64(a) + bb = float64(b) + cc = float64(c) + hh = float64(h) + dd = float64(d) + ee = float64(e) + ff = float64(f) + gg = float64(g) + ii = float64(i) + return +} + +func conv2Float32_ssa(a int8, b uint8, c int16, d uint16, + e int32, f uint32, g int64, h uint64, i float64) (aa, bb, cc, dd, ee, ff, gg, hh, ii float32) { + switch { + } + aa = float32(a) + bb = float32(b) + cc = float32(c) + dd = float32(d) + ee = float32(e) + ff = float32(f) + gg = float32(g) + hh = float32(h) + ii = float32(i) + return +} + +func integer2floatConversions() int { + fails := 0 + { + a, b, c, d, e, f, g, h, i := conv2Float64_ssa(0, 0, 0, 0, 0, 0, 0, 0, 0) + fails += expectAll64("zero64", 0, a, b, c, d, e, f, g, h, i) + } + { + a, b, c, d, e, f, g, h, i := conv2Float64_ssa(1, 1, 1, 1, 1, 1, 1, 1, 1) + fails += expectAll64("one64", 1, a, b, c, d, e, f, g, h, i) + } + { + a, b, c, d, e, f, g, h, i := conv2Float32_ssa(0, 0, 0, 0, 0, 0, 0, 0, 0) + fails += expectAll32("zero32", 0, a, b, c, d, e, f, g, h, i) + } + { + a, b, c, d, e, f, g, h, i := conv2Float32_ssa(1, 1, 1, 1, 1, 1, 1, 1, 1) + fails += expectAll32("one32", 1, a, b, c, d, e, f, g, h, i) + } + { + // Check maximum values + a, b, c, d, e, f, g, h, i := conv2Float64_ssa(127, 255, 32767, 65535, 0x7fffffff, 0xffffffff, 0x7fffFFFFffffFFFF, 0xffffFFFFffffFFFF, 3.402823E38) + fails += expect64("a", a, 127) + fails += expect64("b", b, 255) + fails += expect64("c", c, 32767) + fails += expect64("d", d, 65535) + fails += expect64("e", e, float64(int32(0x7fffffff))) + fails += expect64("f", f, float64(uint32(0xffffffff))) + fails += expect64("g", g, float64(int64(0x7fffffffffffffff))) + fails += expect64("h", h, float64(uint64(0xffffffffffffffff))) + fails += expect64("i", i, float64(float32(3.402823E38))) + } + { + // Check minimum values (and tweaks for unsigned) + a, b, c, d, e, f, g, h, i := conv2Float64_ssa(-128, 254, -32768, 65534, ^0x7fffffff, 0xfffffffe, ^0x7fffFFFFffffFFFF, 0xffffFFFFffffF401, 1.5E-45) + fails += expect64("a", a, -128) + fails += expect64("b", b, 254) + fails += expect64("c", c, -32768) + fails += expect64("d", d, 65534) + fails += expect64("e", e, float64(^int32(0x7fffffff))) + fails += expect64("f", f, float64(uint32(0xfffffffe))) + fails += expect64("g", g, float64(^int64(0x7fffffffffffffff))) + fails += expect64("h", h, float64(uint64(0xfffffffffffff401))) + fails += expect64("i", i, float64(float32(1.5E-45))) + } + { + // Check maximum values + a, b, c, d, e, f, g, h, i := conv2Float32_ssa(127, 255, 32767, 65535, 0x7fffffff, 0xffffffff, 0x7fffFFFFffffFFFF, 0xffffFFFFffffFFFF, 3.402823E38) + fails += expect32("a", a, 127) + fails += expect32("b", b, 255) + fails += expect32("c", c, 32767) + fails += expect32("d", d, 65535) + fails += expect32("e", e, float32(int32(0x7fffffff))) + fails += expect32("f", f, float32(uint32(0xffffffff))) + fails += expect32("g", g, float32(int64(0x7fffffffffffffff))) + fails += expect32("h", h, float32(uint64(0xffffffffffffffff))) + fails += expect32("i", i, float32(float64(3.402823E38))) + } + { + // Check minimum values (and tweaks for unsigned) + a, b, c, d, e, f, g, h, i := conv2Float32_ssa(-128, 254, -32768, 65534, ^0x7fffffff, 0xfffffffe, ^0x7fffFFFFffffFFFF, 0xffffFFFFffffF401, 1.5E-45) + fails += expect32("a", a, -128) + fails += expect32("b", b, 254) + fails += expect32("c", c, -32768) + fails += expect32("d", d, 65534) + fails += expect32("e", e, float32(^int32(0x7fffffff))) + fails += expect32("f", f, float32(uint32(0xfffffffe))) + fails += expect32("g", g, float32(^int64(0x7fffffffffffffff))) + fails += expect32("h", h, float32(uint64(0xfffffffffffff401))) + fails += expect32("i", i, float32(float64(1.5E-45))) + } + return fails +} + func main() { a := 3.0 @@ -157,6 +295,8 @@ func main() { fails += expect64("dc", dc, -9.0) fails += expect64("dd", dd, 44.0) + fails += integer2floatConversions() + if fails > 0 { fmt.Printf("Saw %v failures\n", fails) panic("Failed.") diff --git a/src/cmd/compile/internal/ssa/gen/AMD64.rules b/src/cmd/compile/internal/ssa/gen/AMD64.rules index c59da55dbf..86b443c10d 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64.rules +++ b/src/cmd/compile/internal/ssa/gen/AMD64.rules @@ -101,6 +101,19 @@ (ZeroExt16to64 x) -> (MOVWQZX x) (ZeroExt32to64 x) -> (MOVLQZX x) +(Cvt32to32F x) -> (CVTSL2SS x) +(Cvt32to64F x) -> (CVTSL2SD x) +(Cvt64to32F x) -> (CVTSQ2SS x) +(Cvt64to64F x) -> (CVTSQ2SD x) + +(Cvt32Fto32 x) -> (CVTSS2SL x) +(Cvt32Fto64 x) -> (CVTSS2SQ x) +(Cvt64Fto32 x) -> (CVTSD2SL x) +(Cvt64Fto64 x) -> (CVTSD2SQ x) + +(Cvt32Fto64F x) -> (CVTSS2SD x) +(Cvt64Fto32F x) -> (CVTSD2SS x) + // Because we ignore high parts of registers, truncates are just copies. (Trunc16to8 x) -> x (Trunc32to8 x) -> x diff --git a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go index 3ee802ec9f..8b8da225d1 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go @@ -120,13 +120,14 @@ func init() { gpstoreconst = regInfo{inputs: []regMask{gpspsb, 0}} gpstoreidx = regInfo{inputs: []regMask{gpspsb, gpsp, gpsp, 0}} - // fp11 = regInfo{inputs: fponly, outputs: fponly} fp01 = regInfo{inputs: []regMask{}, outputs: fponly} fp21 = regInfo{inputs: []regMask{fp, fp}, outputs: fponly} fp21x15 = regInfo{inputs: []regMask{fp &^ x15, fp &^ x15}, clobbers: x15, outputs: []regMask{fp &^ x15}} - // fp2flags = regInfo{inputs: []regMask{fp, fp}, outputs: flagsonly} - // fp1flags = regInfo{inputs: fponly, outputs: flagsonly} + + fpgp = regInfo{inputs: fponly, outputs: gponly} + gpfp = regInfo{inputs: gponly, outputs: fponly} + fp11 = regInfo{inputs: fponly, outputs: fponly} fpload = regInfo{inputs: []regMask{gpspsb, 0}, outputs: fponly} fploadidx = regInfo{inputs: []regMask{gpspsb, gpsp, 0}, outputs: fponly} @@ -328,6 +329,17 @@ func init() { {name: "MOVLconst", reg: gp01, asm: "MOVL"}, // 32 low bits of auxint {name: "MOVQconst", reg: gp01, asm: "MOVQ"}, // auxint + {name: "CVTSD2SL", reg: fpgp, asm: "CVTSD2SL"}, // convert float64 to int32 + {name: "CVTSD2SQ", reg: fpgp, asm: "CVTSD2SQ"}, // convert float64 to int64 + {name: "CVTSS2SL", reg: fpgp, asm: "CVTSS2SL"}, // convert float32 to int32 + {name: "CVTSS2SQ", reg: fpgp, asm: "CVTSS2SQ"}, // convert float32 to int64 + {name: "CVTSL2SS", reg: gpfp, asm: "CVTSL2SS"}, // convert int32 to float32 + {name: "CVTSL2SD", reg: gpfp, asm: "CVTSL2SD"}, // convert int32 to float64 + {name: "CVTSQ2SS", reg: gpfp, asm: "CVTSQ2SS"}, // convert int64 to float32 + {name: "CVTSQ2SD", reg: gpfp, asm: "CVTSQ2SD"}, // convert int64 to float64 + {name: "CVTSD2SS", reg: fp11, asm: "CVTSD2SS"}, // convert float64 to float32 + {name: "CVTSS2SD", reg: fp11, asm: "CVTSS2SD"}, // convert float32 to float64 + {name: "LEAQ", reg: gp11sb}, // arg0 + auxint + offset encoded in aux {name: "LEAQ1", reg: gp21sb}, // arg0 + arg1 + auxint {name: "LEAQ2", reg: gp21sb}, // arg0 + 2*arg1 + auxint diff --git a/src/cmd/compile/internal/ssa/gen/genericOps.go b/src/cmd/compile/internal/ssa/gen/genericOps.go index 78524a5e6b..4a65a87ea8 100644 --- a/src/cmd/compile/internal/ssa/gen/genericOps.go +++ b/src/cmd/compile/internal/ssa/gen/genericOps.go @@ -287,6 +287,17 @@ var genericOps = []opData{ {name: "Trunc64to16"}, {name: "Trunc64to32"}, + {name: "Cvt32to32F"}, + {name: "Cvt32to64F"}, + {name: "Cvt64to32F"}, + {name: "Cvt64to64F"}, + {name: "Cvt32Fto32"}, + {name: "Cvt32Fto64"}, + {name: "Cvt64Fto32"}, + {name: "Cvt64Fto64"}, + {name: "Cvt32Fto64F"}, + {name: "Cvt64Fto32F"}, + // Automatically inserted safety checks {name: "IsNonNil"}, // arg0 != nil {name: "IsInBounds"}, // 0 <= arg0 < arg1 diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index 5346f757fb..aa51cbc301 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -209,6 +209,16 @@ const ( OpAMD64MOVWconst OpAMD64MOVLconst OpAMD64MOVQconst + OpAMD64CVTSD2SL + OpAMD64CVTSD2SQ + OpAMD64CVTSS2SL + OpAMD64CVTSS2SQ + OpAMD64CVTSL2SS + OpAMD64CVTSL2SD + OpAMD64CVTSQ2SS + OpAMD64CVTSQ2SD + OpAMD64CVTSD2SS + OpAMD64CVTSS2SD OpAMD64LEAQ OpAMD64LEAQ1 OpAMD64LEAQ2 @@ -441,6 +451,16 @@ const ( OpTrunc64to8 OpTrunc64to16 OpTrunc64to32 + OpCvt32to32F + OpCvt32to64F + OpCvt64to32F + OpCvt64to64F + OpCvt32Fto32 + OpCvt32Fto64 + OpCvt64Fto32 + OpCvt64Fto64 + OpCvt32Fto64F + OpCvt64Fto32F OpIsNonNil OpIsInBounds OpPanicNilCheck @@ -2521,6 +2541,126 @@ var opcodeTable = [...]opInfo{ }, }, }, + { + name: "CVTSD2SL", + asm: x86.ACVTSD2SL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 4294901760}, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + }, + outputs: []regMask{ + 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + }, + }, + { + name: "CVTSD2SQ", + asm: x86.ACVTSD2SQ, + reg: regInfo{ + inputs: []inputInfo{ + {0, 4294901760}, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + }, + outputs: []regMask{ + 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + }, + }, + { + name: "CVTSS2SL", + asm: x86.ACVTSS2SL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 4294901760}, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + }, + outputs: []regMask{ + 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + }, + }, + { + name: "CVTSS2SQ", + asm: x86.ACVTSS2SQ, + reg: regInfo{ + inputs: []inputInfo{ + {0, 4294901760}, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + }, + outputs: []regMask{ + 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + }, + }, + { + name: "CVTSL2SS", + asm: x86.ACVTSL2SS, + reg: regInfo{ + inputs: []inputInfo{ + {0, 65519}, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + outputs: []regMask{ + 4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + }, + }, + }, + { + name: "CVTSL2SD", + asm: x86.ACVTSL2SD, + reg: regInfo{ + inputs: []inputInfo{ + {0, 65519}, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + outputs: []regMask{ + 4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + }, + }, + }, + { + name: "CVTSQ2SS", + asm: x86.ACVTSQ2SS, + reg: regInfo{ + inputs: []inputInfo{ + {0, 65519}, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + outputs: []regMask{ + 4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + }, + }, + }, + { + name: "CVTSQ2SD", + asm: x86.ACVTSQ2SD, + reg: regInfo{ + inputs: []inputInfo{ + {0, 65519}, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + outputs: []regMask{ + 4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + }, + }, + }, + { + name: "CVTSD2SS", + asm: x86.ACVTSD2SS, + reg: regInfo{ + inputs: []inputInfo{ + {0, 4294901760}, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + }, + outputs: []regMask{ + 4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + }, + }, + }, + { + name: "CVTSS2SD", + asm: x86.ACVTSS2SD, + reg: regInfo{ + inputs: []inputInfo{ + {0, 4294901760}, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + }, + outputs: []regMask{ + 4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + }, + }, + }, { name: "LEAQ", reg: regInfo{ @@ -3606,6 +3746,46 @@ var opcodeTable = [...]opInfo{ name: "Trunc64to32", generic: true, }, + { + name: "Cvt32to32F", + generic: true, + }, + { + name: "Cvt32to64F", + generic: true, + }, + { + name: "Cvt64to32F", + generic: true, + }, + { + name: "Cvt64to64F", + generic: true, + }, + { + name: "Cvt32Fto32", + generic: true, + }, + { + name: "Cvt32Fto64", + generic: true, + }, + { + name: "Cvt64Fto32", + generic: true, + }, + { + name: "Cvt64Fto64", + generic: true, + }, + { + name: "Cvt32Fto64F", + generic: true, + }, + { + name: "Cvt64Fto32F", + generic: true, + }, { name: "IsNonNil", generic: true, diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go index f9690a37db..b50fecda2e 100644 --- a/src/cmd/compile/internal/ssa/rewriteAMD64.go +++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go @@ -1688,6 +1688,166 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto endc395c0a53eeccf597e225a07b53047d1 endc395c0a53eeccf597e225a07b53047d1: ; + case OpCvt32Fto32: + // match: (Cvt32Fto32 x) + // cond: + // result: (CVTSS2SL x) + { + x := v.Args[0] + v.Op = OpAMD64CVTSS2SL + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto endad55e2986dea26975574ee27f4976d5e + endad55e2986dea26975574ee27f4976d5e: + ; + case OpCvt32Fto64: + // match: (Cvt32Fto64 x) + // cond: + // result: (CVTSS2SQ x) + { + x := v.Args[0] + v.Op = OpAMD64CVTSS2SQ + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto end227800dc831e0b4ef80fa315133c0991 + end227800dc831e0b4ef80fa315133c0991: + ; + case OpCvt32Fto64F: + // match: (Cvt32Fto64F x) + // cond: + // result: (CVTSS2SD x) + { + x := v.Args[0] + v.Op = OpAMD64CVTSS2SD + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto end0bf5d6f8d182ee2b3ab7d7c2f8ff7790 + end0bf5d6f8d182ee2b3ab7d7c2f8ff7790: + ; + case OpCvt32to32F: + // match: (Cvt32to32F x) + // cond: + // result: (CVTSL2SS x) + { + x := v.Args[0] + v.Op = OpAMD64CVTSL2SS + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto ende0bdea2b21aecdb8399d6fd80ddc97d6 + ende0bdea2b21aecdb8399d6fd80ddc97d6: + ; + case OpCvt32to64F: + // match: (Cvt32to64F x) + // cond: + // result: (CVTSL2SD x) + { + x := v.Args[0] + v.Op = OpAMD64CVTSL2SD + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto ende06cbe745112bcf0e6612788ef71c958 + ende06cbe745112bcf0e6612788ef71c958: + ; + case OpCvt64Fto32: + // match: (Cvt64Fto32 x) + // cond: + // result: (CVTSD2SL x) + { + x := v.Args[0] + v.Op = OpAMD64CVTSD2SL + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto end1ce5fd52f29d5a42d1aa08d7ac53e49e + end1ce5fd52f29d5a42d1aa08d7ac53e49e: + ; + case OpCvt64Fto32F: + // match: (Cvt64Fto32F x) + // cond: + // result: (CVTSD2SS x) + { + x := v.Args[0] + v.Op = OpAMD64CVTSD2SS + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto endfd70158a96824ced99712d606c607d94 + endfd70158a96824ced99712d606c607d94: + ; + case OpCvt64Fto64: + // match: (Cvt64Fto64 x) + // cond: + // result: (CVTSD2SQ x) + { + x := v.Args[0] + v.Op = OpAMD64CVTSD2SQ + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto end8239c11ce860dc3b5417d4d2ae59386a + end8239c11ce860dc3b5417d4d2ae59386a: + ; + case OpCvt64to32F: + // match: (Cvt64to32F x) + // cond: + // result: (CVTSQ2SS x) + { + x := v.Args[0] + v.Op = OpAMD64CVTSQ2SS + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto endfecc08b8a8cbd2bf3be21a077c4d0d40 + endfecc08b8a8cbd2bf3be21a077c4d0d40: + ; + case OpCvt64to64F: + // match: (Cvt64to64F x) + // cond: + // result: (CVTSQ2SD x) + { + x := v.Args[0] + v.Op = OpAMD64CVTSQ2SD + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto endf74ce5df659f385f75c61187b515a5d0 + endf74ce5df659f385f75c61187b515a5d0: + ; case OpDiv16: // match: (Div16 x y) // cond: -- cgit v1.3 From 8e601b23cd77f687407a358d2baba672f5a8e4d6 Mon Sep 17 00:00:00 2001 From: David Chase Date: Tue, 18 Aug 2015 14:39:26 -0400 Subject: [dev.ssa] cmd/compile: add FP comparison ops Basic ops, no particular optimization in the pattern matching yet (e.g. x!=x for Nan detection, x cmp constant, etc.) Change-Id: I0043564081d6dc0eede876c4a9eb3c33cbd1521c Reviewed-on: https://go-review.googlesource.com/13704 Reviewed-by: Keith Randall --- src/cmd/compile/internal/gc/ssa.go | 188 ++++- src/cmd/compile/internal/gc/testdata/fp_ssa.go | 1039 ++++++++++++++++++++++-- src/cmd/compile/internal/ssa/fuse.go | 2 +- src/cmd/compile/internal/ssa/gen/AMD64.rules | 39 +- src/cmd/compile/internal/ssa/gen/AMD64Ops.go | 30 +- src/cmd/compile/internal/ssa/gen/genericOps.go | 12 + src/cmd/compile/internal/ssa/gen/main.go | 4 +- src/cmd/compile/internal/ssa/opGen.go | 184 ++++- src/cmd/compile/internal/ssa/rewriteAMD64.go | 424 ++++++++++ 9 files changed, 1804 insertions(+), 118 deletions(-) (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 8e44ede318..676de23115 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -848,6 +848,8 @@ var opToSSA = map[opAndType]ssa.Op{ opAndType{OEQ, TCHAN}: ssa.OpEqPtr, opAndType{OEQ, TUINTPTR}: ssa.OpEqPtr, opAndType{OEQ, TUNSAFEPTR}: ssa.OpEqPtr, + opAndType{OEQ, TFLOAT64}: ssa.OpEq64F, + opAndType{OEQ, TFLOAT32}: ssa.OpEq32F, opAndType{ONE, TBOOL}: ssa.OpNeq8, opAndType{ONE, TINT8}: ssa.OpNeq8, @@ -866,42 +868,52 @@ var opToSSA = map[opAndType]ssa.Op{ opAndType{ONE, TCHAN}: ssa.OpNeqPtr, opAndType{ONE, TUINTPTR}: ssa.OpNeqPtr, opAndType{ONE, TUNSAFEPTR}: ssa.OpNeqPtr, - - opAndType{OLT, TINT8}: ssa.OpLess8, - opAndType{OLT, TUINT8}: ssa.OpLess8U, - opAndType{OLT, TINT16}: ssa.OpLess16, - opAndType{OLT, TUINT16}: ssa.OpLess16U, - opAndType{OLT, TINT32}: ssa.OpLess32, - opAndType{OLT, TUINT32}: ssa.OpLess32U, - opAndType{OLT, TINT64}: ssa.OpLess64, - opAndType{OLT, TUINT64}: ssa.OpLess64U, - - opAndType{OGT, TINT8}: ssa.OpGreater8, - opAndType{OGT, TUINT8}: ssa.OpGreater8U, - opAndType{OGT, TINT16}: ssa.OpGreater16, - opAndType{OGT, TUINT16}: ssa.OpGreater16U, - opAndType{OGT, TINT32}: ssa.OpGreater32, - opAndType{OGT, TUINT32}: ssa.OpGreater32U, - opAndType{OGT, TINT64}: ssa.OpGreater64, - opAndType{OGT, TUINT64}: ssa.OpGreater64U, - - opAndType{OLE, TINT8}: ssa.OpLeq8, - opAndType{OLE, TUINT8}: ssa.OpLeq8U, - opAndType{OLE, TINT16}: ssa.OpLeq16, - opAndType{OLE, TUINT16}: ssa.OpLeq16U, - opAndType{OLE, TINT32}: ssa.OpLeq32, - opAndType{OLE, TUINT32}: ssa.OpLeq32U, - opAndType{OLE, TINT64}: ssa.OpLeq64, - opAndType{OLE, TUINT64}: ssa.OpLeq64U, - - opAndType{OGE, TINT8}: ssa.OpGeq8, - opAndType{OGE, TUINT8}: ssa.OpGeq8U, - opAndType{OGE, TINT16}: ssa.OpGeq16, - opAndType{OGE, TUINT16}: ssa.OpGeq16U, - opAndType{OGE, TINT32}: ssa.OpGeq32, - opAndType{OGE, TUINT32}: ssa.OpGeq32U, - opAndType{OGE, TINT64}: ssa.OpGeq64, - opAndType{OGE, TUINT64}: ssa.OpGeq64U, + opAndType{ONE, TFLOAT64}: ssa.OpNeq64F, + opAndType{ONE, TFLOAT32}: ssa.OpNeq32F, + + opAndType{OLT, TINT8}: ssa.OpLess8, + opAndType{OLT, TUINT8}: ssa.OpLess8U, + opAndType{OLT, TINT16}: ssa.OpLess16, + opAndType{OLT, TUINT16}: ssa.OpLess16U, + opAndType{OLT, TINT32}: ssa.OpLess32, + opAndType{OLT, TUINT32}: ssa.OpLess32U, + opAndType{OLT, TINT64}: ssa.OpLess64, + opAndType{OLT, TUINT64}: ssa.OpLess64U, + opAndType{OLT, TFLOAT64}: ssa.OpLess64F, + opAndType{OLT, TFLOAT32}: ssa.OpLess32F, + + opAndType{OGT, TINT8}: ssa.OpGreater8, + opAndType{OGT, TUINT8}: ssa.OpGreater8U, + opAndType{OGT, TINT16}: ssa.OpGreater16, + opAndType{OGT, TUINT16}: ssa.OpGreater16U, + opAndType{OGT, TINT32}: ssa.OpGreater32, + opAndType{OGT, TUINT32}: ssa.OpGreater32U, + opAndType{OGT, TINT64}: ssa.OpGreater64, + opAndType{OGT, TUINT64}: ssa.OpGreater64U, + opAndType{OGT, TFLOAT64}: ssa.OpGreater64F, + opAndType{OGT, TFLOAT32}: ssa.OpGreater32F, + + opAndType{OLE, TINT8}: ssa.OpLeq8, + opAndType{OLE, TUINT8}: ssa.OpLeq8U, + opAndType{OLE, TINT16}: ssa.OpLeq16, + opAndType{OLE, TUINT16}: ssa.OpLeq16U, + opAndType{OLE, TINT32}: ssa.OpLeq32, + opAndType{OLE, TUINT32}: ssa.OpLeq32U, + opAndType{OLE, TINT64}: ssa.OpLeq64, + opAndType{OLE, TUINT64}: ssa.OpLeq64U, + opAndType{OLE, TFLOAT64}: ssa.OpLeq64F, + opAndType{OLE, TFLOAT32}: ssa.OpLeq32F, + + opAndType{OGE, TINT8}: ssa.OpGeq8, + opAndType{OGE, TUINT8}: ssa.OpGeq8U, + opAndType{OGE, TINT16}: ssa.OpGeq16, + opAndType{OGE, TUINT16}: ssa.OpGeq16U, + opAndType{OGE, TINT32}: ssa.OpGeq32, + opAndType{OGE, TUINT32}: ssa.OpGeq32U, + opAndType{OGE, TINT64}: ssa.OpGeq64, + opAndType{OGE, TUINT64}: ssa.OpGeq64U, + opAndType{OGE, TFLOAT64}: ssa.OpGeq64F, + opAndType{OGE, TFLOAT32}: ssa.OpGeq32F, opAndType{OLROT, TUINT8}: ssa.OpLrot8, opAndType{OLROT, TUINT16}: ssa.OpLrot16, @@ -2198,7 +2210,7 @@ func genssa(f *ssa.Func, ptxt *obj.Prog, gcargs, gclocals *Sym) { } // opregreg emits instructions for -// dest := dest op src +// dest := dest(To) op src(From) // and also returns the created obj.Prog so it // may be further adjusted (offset, scale, etc). func opregreg(op int, dest, src int16) *obj.Prog { @@ -2522,11 +2534,11 @@ func genValue(v *ssa.Value) { p.To.Reg = regnum(v) case ssa.OpAMD64CMPQ, ssa.OpAMD64CMPL, ssa.OpAMD64CMPW, ssa.OpAMD64CMPB, ssa.OpAMD64TESTQ, ssa.OpAMD64TESTL, ssa.OpAMD64TESTW, ssa.OpAMD64TESTB: - p := Prog(v.Op.Asm()) - p.From.Type = obj.TYPE_REG - p.From.Reg = regnum(v.Args[0]) - p.To.Type = obj.TYPE_REG - p.To.Reg = regnum(v.Args[1]) + opregreg(v.Op.Asm(), regnum(v.Args[1]), regnum(v.Args[0])) + case ssa.OpAMD64UCOMISS, ssa.OpAMD64UCOMISD: + // Go assembler has swapped operands for UCOMISx relative to CMP, + // must account for that right here. + opregreg(v.Op.Asm(), regnum(v.Args[0]), regnum(v.Args[1])) case ssa.OpAMD64CMPQconst, ssa.OpAMD64CMPLconst, ssa.OpAMD64CMPWconst, ssa.OpAMD64CMPBconst, ssa.OpAMD64TESTQconst, ssa.OpAMD64TESTLconst, ssa.OpAMD64TESTWconst, ssa.OpAMD64TESTBconst: p := Prog(v.Op.Asm()) @@ -2763,11 +2775,34 @@ func genValue(v *ssa.Value) { case ssa.OpAMD64SETEQ, ssa.OpAMD64SETNE, ssa.OpAMD64SETL, ssa.OpAMD64SETLE, ssa.OpAMD64SETG, ssa.OpAMD64SETGE, + ssa.OpAMD64SETGF, ssa.OpAMD64SETGEF, ssa.OpAMD64SETB, ssa.OpAMD64SETBE, + ssa.OpAMD64SETORD, ssa.OpAMD64SETNAN, ssa.OpAMD64SETA, ssa.OpAMD64SETAE: p := Prog(v.Op.Asm()) p.To.Type = obj.TYPE_REG p.To.Reg = regnum(v) + + case ssa.OpAMD64SETNEF: + p := Prog(v.Op.Asm()) + p.To.Type = obj.TYPE_REG + p.To.Reg = regnum(v) + q := Prog(x86.ASETPS) + q.To.Type = obj.TYPE_REG + q.To.Reg = x86.REG_AX + // TODO AORQ copied from old code generator, why not AORB? + opregreg(x86.AORQ, regnum(v), x86.REG_AX) + + case ssa.OpAMD64SETEQF: + p := Prog(v.Op.Asm()) + p.To.Type = obj.TYPE_REG + p.To.Reg = regnum(v) + q := Prog(x86.ASETPC) + q.To.Type = obj.TYPE_REG + q.To.Reg = x86.REG_AX + // TODO AANDQ copied from old code generator, why not AANDB? + opregreg(x86.AANDQ, regnum(v), x86.REG_AX) + case ssa.OpAMD64InvertFlags: v.Fatalf("InvertFlags should never make it to codegen %v", v) case ssa.OpAMD64REPSTOSQ: @@ -2808,7 +2843,9 @@ func movZero(as int, width int64, nbytes int64, offset int64, regnum int16) (nle return nleft, offset } -var blockJump = [...]struct{ asm, invasm int }{ +var blockJump = [...]struct { + asm, invasm int +}{ ssa.BlockAMD64EQ: {x86.AJEQ, x86.AJNE}, ssa.BlockAMD64NE: {x86.AJNE, x86.AJEQ}, ssa.BlockAMD64LT: {x86.AJLT, x86.AJGE}, @@ -2819,6 +2856,63 @@ var blockJump = [...]struct{ asm, invasm int }{ ssa.BlockAMD64UGE: {x86.AJCC, x86.AJCS}, ssa.BlockAMD64UGT: {x86.AJHI, x86.AJLS}, ssa.BlockAMD64ULE: {x86.AJLS, x86.AJHI}, + ssa.BlockAMD64ORD: {x86.AJPC, x86.AJPS}, + ssa.BlockAMD64NAN: {x86.AJPS, x86.AJPC}, +} + +type floatingEQNEJump struct { + jump, index int +} + +var eqfJumps = [2][2]floatingEQNEJump{ + {{x86.AJNE, 1}, {x86.AJPS, 1}}, // next == b.Succs[0] + {{x86.AJNE, 1}, {x86.AJPC, 0}}, // next == b.Succs[1] +} +var nefJumps = [2][2]floatingEQNEJump{ + {{x86.AJNE, 0}, {x86.AJPC, 1}}, // next == b.Succs[0] + {{x86.AJNE, 0}, {x86.AJPS, 0}}, // next == b.Succs[1] +} + +func oneFPJump(b *ssa.Block, jumps *floatingEQNEJump, likely ssa.BranchPrediction, branches []branch) []branch { + p := Prog(jumps.jump) + p.To.Type = obj.TYPE_BRANCH + to := jumps.index + branches = append(branches, branch{p, b.Succs[to]}) + if to == 1 { + likely = -likely + } + // liblink reorders the instruction stream as it sees fit. + // Pass along what we know so liblink can make use of it. + // TODO: Once we've fully switched to SSA, + // make liblink leave our output alone. + switch likely { + case ssa.BranchUnlikely: + p.From.Type = obj.TYPE_CONST + p.From.Offset = 0 + case ssa.BranchLikely: + p.From.Type = obj.TYPE_CONST + p.From.Offset = 1 + } + return branches +} + +func genFPJump(b, next *ssa.Block, jumps *[2][2]floatingEQNEJump, branches []branch) []branch { + likely := b.Likely + switch next { + case b.Succs[0]: + branches = oneFPJump(b, &jumps[0][0], likely, branches) + branches = oneFPJump(b, &jumps[0][1], likely, branches) + case b.Succs[1]: + branches = oneFPJump(b, &jumps[1][0], likely, branches) + branches = oneFPJump(b, &jumps[1][1], likely, branches) + default: + branches = oneFPJump(b, &jumps[1][0], likely, branches) + branches = oneFPJump(b, &jumps[1][1], likely, branches) + q := Prog(obj.AJMP) + q.To.Type = obj.TYPE_BRANCH + branches = append(branches, branch{q, b.Succs[1]}) + } + return branches } func genBlock(b, next *ssa.Block, branches []branch) []branch { @@ -2849,12 +2943,18 @@ func genBlock(b, next *ssa.Block, branches []branch) []branch { p.To.Type = obj.TYPE_BRANCH branches = append(branches, branch{p, b.Succs[0]}) } + + case ssa.BlockAMD64EQF: + branches = genFPJump(b, next, &eqfJumps, branches) + + case ssa.BlockAMD64NEF: + branches = genFPJump(b, next, &nefJumps, branches) + case ssa.BlockAMD64EQ, ssa.BlockAMD64NE, ssa.BlockAMD64LT, ssa.BlockAMD64GE, ssa.BlockAMD64LE, ssa.BlockAMD64GT, ssa.BlockAMD64ULT, ssa.BlockAMD64UGT, ssa.BlockAMD64ULE, ssa.BlockAMD64UGE: - jmp := blockJump[b.Kind] likely := b.Likely var p *obj.Prog diff --git a/src/cmd/compile/internal/gc/testdata/fp_ssa.go b/src/cmd/compile/internal/gc/testdata/fp_ssa.go index 1a52100d6b..95e3cf9196 100644 --- a/src/cmd/compile/internal/gc/testdata/fp_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/fp_ssa.go @@ -10,64 +10,6 @@ package main import "fmt" -func fail64(s string, f func(a, b float64) float64, a, b, e float64) int { - d := f(a, b) - if d != e { - fmt.Printf("For (float64) %v %v %v, expected %v, got %v\n", a, s, b, e, d) - return 1 - } - return 0 -} - -func fail32(s string, f func(a, b float32) float32, a, b, e float32) int { - d := f(a, b) - if d != e { - fmt.Printf("For (float32) %v %v %v, expected %v, got %v\n", a, s, b, e, d) - return 1 - } - return 0 -} - -func expect64(s string, x, expected float64) int { - if x != expected { - println("Expected", expected, "for", s, ", got", x) - return 1 - } - return 0 -} - -func expect32(s string, x, expected float32) int { - if x != expected { - println("Expected", expected, "for", s, ", got", x) - return 1 - } - return 0 -} - -func expectAll64(s string, expected, a, b, c, d, e, f, g, h, i float64) int { - fails := 0 - fails += expect64(s+":a", a, expected) - fails += expect64(s+":b", b, expected) - fails += expect64(s+":c", c, expected) - fails += expect64(s+":d", d, expected) - fails += expect64(s+":e", e, expected) - fails += expect64(s+":f", f, expected) - fails += expect64(s+":g", g, expected) - return fails -} - -func expectAll32(s string, expected, a, b, c, d, e, f, g, h, i float32) int { - fails := 0 - fails += expect32(s+":a", a, expected) - fails += expect32(s+":b", b, expected) - fails += expect32(s+":c", c, expected) - fails += expect32(s+":d", d, expected) - fails += expect32(s+":e", e, expected) - fails += expect32(s+":f", f, expected) - fails += expect32(s+":g", g, expected) - return fails -} - // manysub_ssa is designed to tickle bugs that depend on register // pressure or unfriendly operand ordering in registers (and at // least once it succeeded in this). @@ -245,6 +187,952 @@ func integer2floatConversions() int { return fails } +const ( + aa = 0x1000000000000000 + ab = 0x100000000000000 + ac = 0x10000000000000 + ad = 0x1000000000000 + ba = 0x100000000000 + bb = 0x10000000000 + bc = 0x1000000000 + bd = 0x100000000 + ca = 0x10000000 + cb = 0x1000000 + cc = 0x100000 + cd = 0x10000 + da = 0x1000 + db = 0x100 + dc = 0x10 + dd = 0x1 +) + +func compares64_ssa(a, b, c, d float64) (lt, le, eq, ne, ge, gt uint64) { + + switch { + } + + if a < a { + lt += aa + } + if a < b { + lt += ab + } + if a < c { + lt += ac + } + if a < d { + lt += ad + } + + if b < a { + lt += ba + } + if b < b { + lt += bb + } + if b < c { + lt += bc + } + if b < d { + lt += bd + } + + if c < a { + lt += ca + } + if c < b { + lt += cb + } + if c < c { + lt += cc + } + if c < d { + lt += cd + } + + if d < a { + lt += da + } + if d < b { + lt += db + } + if d < c { + lt += dc + } + if d < d { + lt += dd + } + + if a <= a { + le += aa + } + if a <= b { + le += ab + } + if a <= c { + le += ac + } + if a <= d { + le += ad + } + + if b <= a { + le += ba + } + if b <= b { + le += bb + } + if b <= c { + le += bc + } + if b <= d { + le += bd + } + + if c <= a { + le += ca + } + if c <= b { + le += cb + } + if c <= c { + le += cc + } + if c <= d { + le += cd + } + + if d <= a { + le += da + } + if d <= b { + le += db + } + if d <= c { + le += dc + } + if d <= d { + le += dd + } + + if a == a { + eq += aa + } + if a == b { + eq += ab + } + if a == c { + eq += ac + } + if a == d { + eq += ad + } + + if b == a { + eq += ba + } + if b == b { + eq += bb + } + if b == c { + eq += bc + } + if b == d { + eq += bd + } + + if c == a { + eq += ca + } + if c == b { + eq += cb + } + if c == c { + eq += cc + } + if c == d { + eq += cd + } + + if d == a { + eq += da + } + if d == b { + eq += db + } + if d == c { + eq += dc + } + if d == d { + eq += dd + } + + if a != a { + ne += aa + } + if a != b { + ne += ab + } + if a != c { + ne += ac + } + if a != d { + ne += ad + } + + if b != a { + ne += ba + } + if b != b { + ne += bb + } + if b != c { + ne += bc + } + if b != d { + ne += bd + } + + if c != a { + ne += ca + } + if c != b { + ne += cb + } + if c != c { + ne += cc + } + if c != d { + ne += cd + } + + if d != a { + ne += da + } + if d != b { + ne += db + } + if d != c { + ne += dc + } + if d != d { + ne += dd + } + + if a >= a { + ge += aa + } + if a >= b { + ge += ab + } + if a >= c { + ge += ac + } + if a >= d { + ge += ad + } + + if b >= a { + ge += ba + } + if b >= b { + ge += bb + } + if b >= c { + ge += bc + } + if b >= d { + ge += bd + } + + if c >= a { + ge += ca + } + if c >= b { + ge += cb + } + if c >= c { + ge += cc + } + if c >= d { + ge += cd + } + + if d >= a { + ge += da + } + if d >= b { + ge += db + } + if d >= c { + ge += dc + } + if d >= d { + ge += dd + } + + if a > a { + gt += aa + } + if a > b { + gt += ab + } + if a > c { + gt += ac + } + if a > d { + gt += ad + } + + if b > a { + gt += ba + } + if b > b { + gt += bb + } + if b > c { + gt += bc + } + if b > d { + gt += bd + } + + if c > a { + gt += ca + } + if c > b { + gt += cb + } + if c > c { + gt += cc + } + if c > d { + gt += cd + } + + if d > a { + gt += da + } + if d > b { + gt += db + } + if d > c { + gt += dc + } + if d > d { + gt += dd + } + + return +} + +func compares32_ssa(a, b, c, d float32) (lt, le, eq, ne, ge, gt uint64) { + + switch { + } + + if a < a { + lt += aa + } + if a < b { + lt += ab + } + if a < c { + lt += ac + } + if a < d { + lt += ad + } + + if b < a { + lt += ba + } + if b < b { + lt += bb + } + if b < c { + lt += bc + } + if b < d { + lt += bd + } + + if c < a { + lt += ca + } + if c < b { + lt += cb + } + if c < c { + lt += cc + } + if c < d { + lt += cd + } + + if d < a { + lt += da + } + if d < b { + lt += db + } + if d < c { + lt += dc + } + if d < d { + lt += dd + } + + if a <= a { + le += aa + } + if a <= b { + le += ab + } + if a <= c { + le += ac + } + if a <= d { + le += ad + } + + if b <= a { + le += ba + } + if b <= b { + le += bb + } + if b <= c { + le += bc + } + if b <= d { + le += bd + } + + if c <= a { + le += ca + } + if c <= b { + le += cb + } + if c <= c { + le += cc + } + if c <= d { + le += cd + } + + if d <= a { + le += da + } + if d <= b { + le += db + } + if d <= c { + le += dc + } + if d <= d { + le += dd + } + + if a == a { + eq += aa + } + if a == b { + eq += ab + } + if a == c { + eq += ac + } + if a == d { + eq += ad + } + + if b == a { + eq += ba + } + if b == b { + eq += bb + } + if b == c { + eq += bc + } + if b == d { + eq += bd + } + + if c == a { + eq += ca + } + if c == b { + eq += cb + } + if c == c { + eq += cc + } + if c == d { + eq += cd + } + + if d == a { + eq += da + } + if d == b { + eq += db + } + if d == c { + eq += dc + } + if d == d { + eq += dd + } + + if a != a { + ne += aa + } + if a != b { + ne += ab + } + if a != c { + ne += ac + } + if a != d { + ne += ad + } + + if b != a { + ne += ba + } + if b != b { + ne += bb + } + if b != c { + ne += bc + } + if b != d { + ne += bd + } + + if c != a { + ne += ca + } + if c != b { + ne += cb + } + if c != c { + ne += cc + } + if c != d { + ne += cd + } + + if d != a { + ne += da + } + if d != b { + ne += db + } + if d != c { + ne += dc + } + if d != d { + ne += dd + } + + if a >= a { + ge += aa + } + if a >= b { + ge += ab + } + if a >= c { + ge += ac + } + if a >= d { + ge += ad + } + + if b >= a { + ge += ba + } + if b >= b { + ge += bb + } + if b >= c { + ge += bc + } + if b >= d { + ge += bd + } + + if c >= a { + ge += ca + } + if c >= b { + ge += cb + } + if c >= c { + ge += cc + } + if c >= d { + ge += cd + } + + if d >= a { + ge += da + } + if d >= b { + ge += db + } + if d >= c { + ge += dc + } + if d >= d { + ge += dd + } + + if a > a { + gt += aa + } + if a > b { + gt += ab + } + if a > c { + gt += ac + } + if a > d { + gt += ad + } + + if b > a { + gt += ba + } + if b > b { + gt += bb + } + if b > c { + gt += bc + } + if b > d { + gt += bd + } + + if c > a { + gt += ca + } + if c > b { + gt += cb + } + if c > c { + gt += cc + } + if c > d { + gt += cd + } + + if d > a { + gt += da + } + if d > b { + gt += db + } + if d > c { + gt += dc + } + if d > d { + gt += dd + } + + return +} + +func le64_ssa(x, y float64) bool { + switch { + } + return x <= y +} +func ge64_ssa(x, y float64) bool { + switch { + } + return x >= y +} +func lt64_ssa(x, y float64) bool { + switch { + } + return x < y +} +func gt64_ssa(x, y float64) bool { + switch { + } + return x > y +} +func eq64_ssa(x, y float64) bool { + switch { + } + return x == y +} +func ne64_ssa(x, y float64) bool { + switch { + } + return x != y +} + +func eqbr64_ssa(x, y float64) float64 { + switch { + } + if x == y { + return 17 + } + return 42 +} +func nebr64_ssa(x, y float64) float64 { + switch { + } + if x != y { + return 17 + } + return 42 +} +func gebr64_ssa(x, y float64) float64 { + switch { + } + if x >= y { + return 17 + } + return 42 +} +func lebr64_ssa(x, y float64) float64 { + switch { + } + if x <= y { + return 17 + } + return 42 +} +func ltbr64_ssa(x, y float64) float64 { + switch { + } + if x < y { + return 17 + } + return 42 +} +func gtbr64_ssa(x, y float64) float64 { + switch { + } + if x > y { + return 17 + } + return 42 +} + +func le32_ssa(x, y float32) bool { + switch { + } + return x <= y +} +func ge32_ssa(x, y float32) bool { + switch { + } + return x >= y +} +func lt32_ssa(x, y float32) bool { + switch { + } + return x < y +} +func gt32_ssa(x, y float32) bool { + switch { + } + return x > y +} +func eq32_ssa(x, y float32) bool { + switch { + } + return x == y +} +func ne32_ssa(x, y float32) bool { + switch { + } + return x != y +} + +func eqbr32_ssa(x, y float32) float32 { + switch { + } + if x == y { + return 17 + } + return 42 +} +func nebr32_ssa(x, y float32) float32 { + switch { + } + if x != y { + return 17 + } + return 42 +} +func gebr32_ssa(x, y float32) float32 { + switch { + } + if x >= y { + return 17 + } + return 42 +} +func lebr32_ssa(x, y float32) float32 { + switch { + } + if x <= y { + return 17 + } + return 42 +} +func ltbr32_ssa(x, y float32) float32 { + switch { + } + if x < y { + return 17 + } + return 42 +} +func gtbr32_ssa(x, y float32) float32 { + switch { + } + if x > y { + return 17 + } + return 42 +} + +func fail64(s string, f func(a, b float64) float64, a, b, e float64) int { + d := f(a, b) + if d != e { + fmt.Printf("For (float64) %v %v %v, expected %v, got %v\n", a, s, b, e, d) + return 1 + } + return 0 +} + +func fail64bool(s string, f func(a, b float64) bool, a, b float64, e bool) int { + d := f(a, b) + if d != e { + fmt.Printf("For (float64) %v %v %v, expected %v, got %v\n", a, s, b, e, d) + return 1 + } + return 0 +} + +func fail32(s string, f func(a, b float32) float32, a, b, e float32) int { + d := f(a, b) + if d != e { + fmt.Printf("For (float32) %v %v %v, expected %v, got %v\n", a, s, b, e, d) + return 1 + } + return 0 +} + +func fail32bool(s string, f func(a, b float32) bool, a, b float32, e bool) int { + d := f(a, b) + if d != e { + fmt.Printf("For (float32) %v %v %v, expected %v, got %v\n", a, s, b, e, d) + return 1 + } + return 0 +} + +func expect64(s string, x, expected float64) int { + if x != expected { + println("Expected", expected, "for", s, ", got", x) + return 1 + } + return 0 +} + +func expect32(s string, x, expected float32) int { + if x != expected { + println("Expected", expected, "for", s, ", got", x) + return 1 + } + return 0 +} + +func expectUint64(s string, x, expected uint64) int { + if x != expected { + fmt.Printf("Expected 0x%016x for %s, got 0x%016x\n", expected, s, x) + return 1 + } + return 0 +} + +func expectAll64(s string, expected, a, b, c, d, e, f, g, h, i float64) int { + fails := 0 + fails += expect64(s+":a", a, expected) + fails += expect64(s+":b", b, expected) + fails += expect64(s+":c", c, expected) + fails += expect64(s+":d", d, expected) + fails += expect64(s+":e", e, expected) + fails += expect64(s+":f", f, expected) + fails += expect64(s+":g", g, expected) + return fails +} + +func expectAll32(s string, expected, a, b, c, d, e, f, g, h, i float32) int { + fails := 0 + fails += expect32(s+":a", a, expected) + fails += expect32(s+":b", b, expected) + fails += expect32(s+":c", c, expected) + fails += expect32(s+":d", d, expected) + fails += expect32(s+":e", e, expected) + fails += expect32(s+":f", f, expected) + fails += expect32(s+":g", g, expected) + return fails +} + +var ev64 [2]float64 = [2]float64{42.0, 17.0} +var ev32 [2]float32 = [2]float32{42.0, 17.0} + +func cmpOpTest(s string, + f func(a, b float64) bool, + g func(a, b float64) float64, + ff func(a, b float32) bool, + gg func(a, b float32) float32, + zero, one, inf, nan float64, result uint) int { + fails := 0 + fails += fail64bool(s, f, zero, zero, result>>16&1 == 1) + fails += fail64bool(s, f, zero, one, result>>12&1 == 1) + fails += fail64bool(s, f, zero, inf, result>>8&1 == 1) + fails += fail64bool(s, f, zero, nan, result>>4&1 == 1) + fails += fail64bool(s, f, nan, nan, result&1 == 1) + + fails += fail64(s, g, zero, zero, ev64[result>>16&1]) + fails += fail64(s, g, zero, one, ev64[result>>12&1]) + fails += fail64(s, g, zero, inf, ev64[result>>8&1]) + fails += fail64(s, g, zero, nan, ev64[result>>4&1]) + fails += fail64(s, g, nan, nan, ev64[result>>0&1]) + + { + zero := float32(zero) + one := float32(one) + inf := float32(inf) + nan := float32(nan) + fails += fail32bool(s, ff, zero, zero, (result>>16)&1 == 1) + fails += fail32bool(s, ff, zero, one, (result>>12)&1 == 1) + fails += fail32bool(s, ff, zero, inf, (result>>8)&1 == 1) + fails += fail32bool(s, ff, zero, nan, (result>>4)&1 == 1) + fails += fail32bool(s, ff, nan, nan, result&1 == 1) + + fails += fail32(s, gg, zero, zero, ev32[(result>>16)&1]) + fails += fail32(s, gg, zero, one, ev32[(result>>12)&1]) + fails += fail32(s, gg, zero, inf, ev32[(result>>8)&1]) + fails += fail32(s, gg, zero, nan, ev32[(result>>4)&1]) + fails += fail32(s, gg, nan, nan, ev32[(result>>0)&1]) + } + + return fails +} + func main() { a := 3.0 @@ -273,6 +1161,8 @@ func main() { // but should not underflow in float and in fact is exactly representable. fails += fail64("*", mul64_ssa, dtiny, dtiny, 1.9636373861190906e-90) + // Intended to create register pressure which forces + // asymmetric op into different code paths. aa, ab, ac, ad, ba, bb, bc, bd, ca, cb, cc, cd, da, db, dc, dd := manysub_ssa(1000.0, 100.0, 10.0, 1.0) fails += expect64("aa", aa, 11.0) @@ -297,6 +1187,39 @@ func main() { fails += integer2floatConversions() + var zero64 float64 = 0.0 + var one64 float64 = 1.0 + var inf64 float64 = 1.0 / zero64 + var nan64 float64 = sub64_ssa(inf64, inf64) + + fails += cmpOpTest("!=", ne64_ssa, nebr64_ssa, ne32_ssa, nebr32_ssa, zero64, one64, inf64, nan64, 0x01111) + fails += cmpOpTest("==", eq64_ssa, eqbr64_ssa, eq32_ssa, eqbr32_ssa, zero64, one64, inf64, nan64, 0x10000) + fails += cmpOpTest("<=", le64_ssa, lebr64_ssa, le32_ssa, lebr32_ssa, zero64, one64, inf64, nan64, 0x11100) + fails += cmpOpTest("<", lt64_ssa, ltbr64_ssa, lt32_ssa, ltbr32_ssa, zero64, one64, inf64, nan64, 0x01100) + fails += cmpOpTest(">", gt64_ssa, gtbr64_ssa, gt32_ssa, gtbr32_ssa, zero64, one64, inf64, nan64, 0x00000) + fails += cmpOpTest(">=", ge64_ssa, gebr64_ssa, ge32_ssa, gebr32_ssa, zero64, one64, inf64, nan64, 0x10000) + + { + lt, le, eq, ne, ge, gt := compares64_ssa(0.0, 1.0, inf64, nan64) + fails += expectUint64("lt", lt, 0x0110001000000000) + fails += expectUint64("le", le, 0x1110011000100000) + fails += expectUint64("eq", eq, 0x1000010000100000) + fails += expectUint64("ne", ne, 0x0111101111011111) + fails += expectUint64("ge", ge, 0x1000110011100000) + fails += expectUint64("gt", gt, 0x0000100011000000) + // fmt.Printf("lt=0x%016x, le=0x%016x, eq=0x%016x, ne=0x%016x, ge=0x%016x, gt=0x%016x\n", + // lt, le, eq, ne, ge, gt) + } + { + lt, le, eq, ne, ge, gt := compares32_ssa(0.0, 1.0, float32(inf64), float32(nan64)) + fails += expectUint64("lt", lt, 0x0110001000000000) + fails += expectUint64("le", le, 0x1110011000100000) + fails += expectUint64("eq", eq, 0x1000010000100000) + fails += expectUint64("ne", ne, 0x0111101111011111) + fails += expectUint64("ge", ge, 0x1000110011100000) + fails += expectUint64("gt", gt, 0x0000100011000000) + } + if fails > 0 { fmt.Printf("Saw %v failures\n", fails) panic("Failed.") diff --git a/src/cmd/compile/internal/ssa/fuse.go b/src/cmd/compile/internal/ssa/fuse.go index e6bd44d573..e390fc4998 100644 --- a/src/cmd/compile/internal/ssa/fuse.go +++ b/src/cmd/compile/internal/ssa/fuse.go @@ -35,7 +35,7 @@ func fuse(f *Func) { } // trash b, just in case - b.Kind = blockInvalid + b.Kind = BlockInvalid b.Values = nil b.Preds = nil b.Succs = nil diff --git a/src/cmd/compile/internal/ssa/gen/AMD64.rules b/src/cmd/compile/internal/ssa/gen/AMD64.rules index 86b443c10d..ff89a7e899 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64.rules +++ b/src/cmd/compile/internal/ssa/gen/AMD64.rules @@ -198,53 +198,67 @@ (Less32 x y) -> (SETL (CMPL x y)) (Less16 x y) -> (SETL (CMPW x y)) (Less8 x y) -> (SETL (CMPB x y)) - (Less64U x y) -> (SETB (CMPQ x y)) (Less32U x y) -> (SETB (CMPL x y)) (Less16U x y) -> (SETB (CMPW x y)) (Less8U x y) -> (SETB (CMPB x y)) +// Use SETGF with reversed operands to dodge NaN case +(Less64F x y) -> (SETGF (UCOMISD y x)) +(Less32F x y) -> (SETGF (UCOMISS y x)) (Leq64 x y) -> (SETLE (CMPQ x y)) (Leq32 x y) -> (SETLE (CMPL x y)) (Leq16 x y) -> (SETLE (CMPW x y)) (Leq8 x y) -> (SETLE (CMPB x y)) - (Leq64U x y) -> (SETBE (CMPQ x y)) (Leq32U x y) -> (SETBE (CMPL x y)) (Leq16U x y) -> (SETBE (CMPW x y)) (Leq8U x y) -> (SETBE (CMPB x y)) +// Use SETGEF with reversed operands to dodge NaN case +(Leq64F x y) -> (SETGEF (UCOMISD y x)) +(Leq32F x y) -> (SETGEF (UCOMISS y x)) (Greater64 x y) -> (SETG (CMPQ x y)) (Greater32 x y) -> (SETG (CMPL x y)) (Greater16 x y) -> (SETG (CMPW x y)) (Greater8 x y) -> (SETG (CMPB x y)) - (Greater64U x y) -> (SETA (CMPQ x y)) (Greater32U x y) -> (SETA (CMPL x y)) (Greater16U x y) -> (SETA (CMPW x y)) (Greater8U x y) -> (SETA (CMPB x y)) +// Note Go assembler gets UCOMISx operand order wrong, but it is right here +// Bug is accommodated at generation of assembly language. +(Greater64F x y) -> (SETGF (UCOMISD x y)) +(Greater32F x y) -> (SETGF (UCOMISS x y)) (Geq64 x y) -> (SETGE (CMPQ x y)) (Geq32 x y) -> (SETGE (CMPL x y)) (Geq16 x y) -> (SETGE (CMPW x y)) (Geq8 x y) -> (SETGE (CMPB x y)) - (Geq64U x y) -> (SETAE (CMPQ x y)) (Geq32U x y) -> (SETAE (CMPL x y)) (Geq16U x y) -> (SETAE (CMPW x y)) (Geq8U x y) -> (SETAE (CMPB x y)) +// Note Go assembler gets UCOMISx operand order wrong, but it is right here +// Bug is accommodated at generation of assembly language. +(Geq64F x y) -> (SETGEF (UCOMISD x y)) +(Geq32F x y) -> (SETGEF (UCOMISS x y)) (Eq64 x y) -> (SETEQ (CMPQ x y)) (Eq32 x y) -> (SETEQ (CMPL x y)) (Eq16 x y) -> (SETEQ (CMPW x y)) (Eq8 x y) -> (SETEQ (CMPB x y)) (EqPtr x y) -> (SETEQ (CMPQ x y)) +(Eq64F x y) -> (SETEQF (UCOMISD x y)) +(Eq32F x y) -> (SETEQF (UCOMISS x y)) (Neq64 x y) -> (SETNE (CMPQ x y)) (Neq32 x y) -> (SETNE (CMPL x y)) (Neq16 x y) -> (SETNE (CMPW x y)) (Neq8 x y) -> (SETNE (CMPB x y)) (NeqPtr x y) -> (SETNE (CMPQ x y)) +(Neq64F x y) -> (SETNEF (UCOMISD x y)) +(Neq32F x y) -> (SETNEF (UCOMISS x y)) (Load ptr mem) && (is64BitInt(t) || isPtr(t)) -> (MOVQload ptr mem) (Load ptr mem) && is32BitInt(t) -> (MOVLload ptr mem) @@ -304,6 +318,12 @@ (If (SETA cmp) yes no) -> (UGT cmp yes no) (If (SETAE cmp) yes no) -> (UGE cmp yes no) +// Special case for floating point - LF/LEF not generated +(If (SETGF cmp) yes no) -> (UGT cmp yes no) +(If (SETGEF cmp) yes no) -> (UGE cmp yes no) +(If (SETEQF cmp) yes no) -> (EQF cmp yes no) +(If (SETNEF cmp) yes no) -> (EQF cmp yes no) + (If cond yes no) -> (NE (TESTB cond cond) yes no) (NE (TESTB (SETL cmp)) yes no) -> (LT cmp yes no) @@ -317,6 +337,16 @@ (NE (TESTB (SETA cmp)) yes no) -> (UGT cmp yes no) (NE (TESTB (SETAE cmp)) yes no) -> (UGE cmp yes no) +// Special case for floating point - LF/LEF not generated +(NE (TESTB (SETGF cmp)) yes no) -> (UGT cmp yes no) +(NE (TESTB (SETGEF cmp)) yes no) -> (UGE cmp yes no) +(NE (TESTB (SETEQF cmp)) yes no) -> (EQF cmp yes no) +(NE (TESTB (SETNEF cmp)) yes no) -> (NEF cmp yes no) + +// Disabled because it interferes with the pattern match above and makes worse code. +// (SETNEF x) -> (ORQ (SETNE x) (SETNAN x)) +// (SETEQF x) -> (ANDQ (SETEQ x) (SETORD x)) + (StaticCall [argwid] {target} mem) -> (CALLstatic [argwid] {target} mem) (ClosureCall [argwid] entry closure mem) -> (CALLclosure [argwid] entry closure mem) @@ -519,7 +549,6 @@ (MOVSDstore [off1] {sym1} (LEAQ8 [off2] {sym2} ptr idx) val mem) && canMergeSym(sym1, sym2) -> (MOVSDstoreidx8 [addOff(off1, off2)] {mergeSym(sym1,sym2)} ptr idx val mem) - (ADDQconst [0] x) -> x // lower Zero instructions with word sizes diff --git a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go index 8b8da225d1..e610458c92 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go @@ -83,7 +83,6 @@ func init() { flags = buildReg("FLAGS") callerSave = gp | fp | flags ) - // Common slices of register masks var ( gponly = []regMask{gp} @@ -110,8 +109,9 @@ func init() { gp2flags = regInfo{inputs: []regMask{gpsp, gpsp}, outputs: flagsonly} gp1flags = regInfo{inputs: []regMask{gpsp}, outputs: flagsonly} - flagsgp = regInfo{inputs: flagsonly, outputs: gponly, clobbers: flags} + flagsgp = regInfo{inputs: flagsonly, outputs: gponly} readflags = regInfo{inputs: flagsonly, outputs: gponly} + flagsgpax = regInfo{inputs: flagsonly, clobbers: ax, outputs: []regMask{gp &^ ax}} gpload = regInfo{inputs: []regMask{gpspsb, 0}, outputs: gponly} gploadidx = regInfo{inputs: []regMask{gpspsb, gpsp, 0}, outputs: gponly} @@ -124,10 +124,11 @@ func init() { fp21 = regInfo{inputs: []regMask{fp, fp}, outputs: fponly} fp21x15 = regInfo{inputs: []regMask{fp &^ x15, fp &^ x15}, clobbers: x15, outputs: []regMask{fp &^ x15}} - - fpgp = regInfo{inputs: fponly, outputs: gponly} - gpfp = regInfo{inputs: gponly, outputs: fponly} - fp11 = regInfo{inputs: fponly, outputs: fponly} + fpgp = regInfo{inputs: fponly, outputs: gponly} + gpfp = regInfo{inputs: gponly, outputs: fponly} + fp11 = regInfo{inputs: fponly, outputs: fponly} + fp2flags = regInfo{inputs: []regMask{fp, fp}, outputs: flagsonly} + // fp1flags = regInfo{inputs: fponly, outputs: flagsonly} fpload = regInfo{inputs: []regMask{gpspsb, 0}, outputs: fponly} fploadidx = regInfo{inputs: []regMask{gpspsb, gpsp, 0}, outputs: fponly} @@ -249,6 +250,9 @@ func init() { {name: "CMPWconst", reg: gp1flags, asm: "CMPW"}, // arg0 compare to auxint {name: "CMPBconst", reg: gp1flags, asm: "CMPB"}, // arg0 compare to auxint + {name: "UCOMISS", reg: fp2flags, asm: "UCOMISS"}, // arg0 compare to arg1, f32 + {name: "UCOMISD", reg: fp2flags, asm: "UCOMISD"}, // arg0 compare to arg1, f64 + {name: "TESTQ", reg: gp2flags, asm: "TESTQ"}, // (arg0 & arg1) compare to 0 {name: "TESTL", reg: gp2flags, asm: "TESTL"}, // (arg0 & arg1) compare to 0 {name: "TESTW", reg: gp2flags, asm: "TESTW"}, // (arg0 & arg1) compare to 0 @@ -316,6 +320,16 @@ func init() { {name: "SETBE", reg: readflags, asm: "SETLS"}, // extract unsigned <= condition from arg0 {name: "SETA", reg: readflags, asm: "SETHI"}, // extract unsigned > condition from arg0 {name: "SETAE", reg: readflags, asm: "SETCC"}, // extract unsigned >= condition from arg0 + // Need different opcodes for floating point conditions because + // any comparison involving a NaN is always FALSE and thus + // the patterns for inverting conditions cannot be used. + {name: "SETEQF", reg: flagsgpax, asm: "SETEQ"}, // extract == condition from arg0 + {name: "SETNEF", reg: flagsgpax, asm: "SETNE"}, // extract != condition from arg0 + {name: "SETORD", reg: flagsgp, asm: "SETPC"}, // extract "ordered" (No Nan present) condition from arg0 + {name: "SETNAN", reg: flagsgp, asm: "SETPS"}, // extract "unordered" (Nan present) condition from arg0 + + {name: "SETGF", reg: flagsgp, asm: "SETHI"}, // extract floating > condition from arg0 + {name: "SETGEF", reg: flagsgp, asm: "SETCC"}, // extract floating >= condition from arg0 {name: "MOVBQSX", reg: gp11nf, asm: "MOVBQSX"}, // sign extend arg0 from int8 to int64 {name: "MOVBQZX", reg: gp11nf, asm: "MOVBQZX"}, // zero extend arg0 from int8 to int64 @@ -395,6 +409,10 @@ func init() { {name: "ULE"}, {name: "UGT"}, {name: "UGE"}, + {name: "EQF"}, + {name: "NEF"}, + {name: "ORD"}, // FP, ordered comparison (parity zero) + {name: "NAN"}, // FP, unordered comparison (parity one) } archs = append(archs, arch{"AMD64", AMD64ops, AMD64blocks, regNamesAMD64}) diff --git a/src/cmd/compile/internal/ssa/gen/genericOps.go b/src/cmd/compile/internal/ssa/gen/genericOps.go index 4a65a87ea8..a0040d3017 100644 --- a/src/cmd/compile/internal/ssa/gen/genericOps.go +++ b/src/cmd/compile/internal/ssa/gen/genericOps.go @@ -161,6 +161,8 @@ var genericOps = []opData{ {name: "Eq64"}, {name: "EqPtr"}, {name: "EqFat"}, // slice/interface; arg0 or arg1 is nil; other cases handled by frontend + {name: "Eq32F"}, + {name: "Eq64F"}, {name: "Neq8"}, // arg0 != arg1 {name: "Neq16"}, @@ -168,6 +170,8 @@ var genericOps = []opData{ {name: "Neq64"}, {name: "NeqPtr"}, {name: "NeqFat"}, // slice/interface; arg0 or arg1 is nil; other cases handled by frontend + {name: "Neq32F"}, + {name: "Neq64F"}, {name: "Less8"}, // arg0 < arg1 {name: "Less8U"}, @@ -177,6 +181,8 @@ var genericOps = []opData{ {name: "Less32U"}, {name: "Less64"}, {name: "Less64U"}, + {name: "Less32F"}, + {name: "Less64F"}, {name: "Leq8"}, // arg0 <= arg1 {name: "Leq8U"}, @@ -186,6 +192,8 @@ var genericOps = []opData{ {name: "Leq32U"}, {name: "Leq64"}, {name: "Leq64U"}, + {name: "Leq32F"}, + {name: "Leq64F"}, {name: "Greater8"}, // arg0 > arg1 {name: "Greater8U"}, @@ -195,6 +203,8 @@ var genericOps = []opData{ {name: "Greater32U"}, {name: "Greater64"}, {name: "Greater64U"}, + {name: "Greater32F"}, + {name: "Greater64F"}, {name: "Geq8"}, // arg0 <= arg1 {name: "Geq8U"}, @@ -204,6 +214,8 @@ var genericOps = []opData{ {name: "Geq32U"}, {name: "Geq64"}, {name: "Geq64U"}, + {name: "Geq32F"}, + {name: "Geq64F"}, // 1-input ops {name: "Not"}, // !arg0 diff --git a/src/cmd/compile/internal/ssa/gen/main.go b/src/cmd/compile/internal/ssa/gen/main.go index 6620c0a1d0..1383566e3a 100644 --- a/src/cmd/compile/internal/ssa/gen/main.go +++ b/src/cmd/compile/internal/ssa/gen/main.go @@ -76,7 +76,7 @@ func genOp() { // generate Block* declarations fmt.Fprintln(w, "const (") - fmt.Fprintln(w, "blockInvalid BlockKind = iota") + fmt.Fprintln(w, "BlockInvalid BlockKind = iota") for _, a := range archs { fmt.Fprintln(w) for _, d := range a.blocks { @@ -87,7 +87,7 @@ func genOp() { // generate block kind string method fmt.Fprintln(w, "var blockString = [...]string{") - fmt.Fprintln(w, "blockInvalid:\"BlockInvalid\",") + fmt.Fprintln(w, "BlockInvalid:\"BlockInvalid\",") for _, a := range archs { fmt.Fprintln(w) for _, b := range a.blocks { diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index aa51cbc301..4eccb463da 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -5,7 +5,7 @@ package ssa import "cmd/internal/obj/x86" const ( - blockInvalid BlockKind = iota + BlockInvalid BlockKind = iota BlockAMD64EQ BlockAMD64NE @@ -17,6 +17,10 @@ const ( BlockAMD64ULE BlockAMD64UGT BlockAMD64UGE + BlockAMD64EQF + BlockAMD64NEF + BlockAMD64ORD + BlockAMD64NAN BlockExit BlockDead @@ -26,7 +30,7 @@ const ( ) var blockString = [...]string{ - blockInvalid: "BlockInvalid", + BlockInvalid: "BlockInvalid", BlockAMD64EQ: "EQ", BlockAMD64NE: "NE", @@ -38,6 +42,10 @@ var blockString = [...]string{ BlockAMD64ULE: "ULE", BlockAMD64UGT: "UGT", BlockAMD64UGE: "UGE", + BlockAMD64EQF: "EQF", + BlockAMD64NEF: "NEF", + BlockAMD64ORD: "ORD", + BlockAMD64NAN: "NAN", BlockExit: "Exit", BlockDead: "Dead", @@ -143,6 +151,8 @@ const ( OpAMD64CMPLconst OpAMD64CMPWconst OpAMD64CMPBconst + OpAMD64UCOMISS + OpAMD64UCOMISD OpAMD64TESTQ OpAMD64TESTL OpAMD64TESTW @@ -199,6 +209,12 @@ const ( OpAMD64SETBE OpAMD64SETA OpAMD64SETAE + OpAMD64SETEQF + OpAMD64SETNEF + OpAMD64SETORD + OpAMD64SETNAN + OpAMD64SETGF + OpAMD64SETGEF OpAMD64MOVBQSX OpAMD64MOVBQZX OpAMD64MOVWQSX @@ -361,12 +377,16 @@ const ( OpEq64 OpEqPtr OpEqFat + OpEq32F + OpEq64F OpNeq8 OpNeq16 OpNeq32 OpNeq64 OpNeqPtr OpNeqFat + OpNeq32F + OpNeq64F OpLess8 OpLess8U OpLess16 @@ -375,6 +395,8 @@ const ( OpLess32U OpLess64 OpLess64U + OpLess32F + OpLess64F OpLeq8 OpLeq8U OpLeq16 @@ -383,6 +405,8 @@ const ( OpLeq32U OpLeq64 OpLeq64U + OpLeq32F + OpLeq64F OpGreater8 OpGreater8U OpGreater16 @@ -391,6 +415,8 @@ const ( OpGreater32U OpGreater64 OpGreater64U + OpGreater32F + OpGreater64F OpGeq8 OpGeq8U OpGeq16 @@ -399,6 +425,8 @@ const ( OpGeq32U OpGeq64 OpGeq64U + OpGeq32F + OpGeq64F OpNot OpNeg8 OpNeg16 @@ -1707,6 +1735,32 @@ var opcodeTable = [...]opInfo{ }, }, }, + { + name: "UCOMISS", + asm: x86.AUCOMISS, + reg: regInfo{ + inputs: []inputInfo{ + {0, 4294901760}, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + {1, 4294901760}, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + }, + outputs: []regMask{ + 8589934592, // .FLAGS + }, + }, + }, + { + name: "UCOMISD", + asm: x86.AUCOMISD, + reg: regInfo{ + inputs: []inputInfo{ + {0, 4294901760}, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + {1, 4294901760}, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + }, + outputs: []regMask{ + 8589934592, // .FLAGS + }, + }, + }, { name: "TESTQ", asm: x86.ATESTQ, @@ -2432,6 +2486,84 @@ var opcodeTable = [...]opInfo{ }, }, }, + { + name: "SETEQF", + asm: x86.ASETEQ, + reg: regInfo{ + inputs: []inputInfo{ + {0, 8589934592}, // .FLAGS + }, + clobbers: 8589934593, // .AX .FLAGS + outputs: []regMask{ + 65518, // .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + }, + }, + { + name: "SETNEF", + asm: x86.ASETNE, + reg: regInfo{ + inputs: []inputInfo{ + {0, 8589934592}, // .FLAGS + }, + clobbers: 8589934593, // .AX .FLAGS + outputs: []regMask{ + 65518, // .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + }, + }, + { + name: "SETORD", + asm: x86.ASETPC, + reg: regInfo{ + inputs: []inputInfo{ + {0, 8589934592}, // .FLAGS + }, + clobbers: 8589934592, // .FLAGS + outputs: []regMask{ + 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + }, + }, + { + name: "SETNAN", + asm: x86.ASETPS, + reg: regInfo{ + inputs: []inputInfo{ + {0, 8589934592}, // .FLAGS + }, + clobbers: 8589934592, // .FLAGS + outputs: []regMask{ + 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + }, + }, + { + name: "SETGF", + asm: x86.ASETHI, + reg: regInfo{ + inputs: []inputInfo{ + {0, 8589934592}, // .FLAGS + }, + clobbers: 8589934592, // .FLAGS + outputs: []regMask{ + 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + }, + }, + { + name: "SETGEF", + asm: x86.ASETCC, + reg: regInfo{ + inputs: []inputInfo{ + {0, 8589934592}, // .FLAGS + }, + clobbers: 8589934592, // .FLAGS + outputs: []regMask{ + 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + }, + }, { name: "MOVBQSX", asm: x86.AMOVBQSX, @@ -3386,6 +3518,14 @@ var opcodeTable = [...]opInfo{ name: "EqFat", generic: true, }, + { + name: "Eq32F", + generic: true, + }, + { + name: "Eq64F", + generic: true, + }, { name: "Neq8", generic: true, @@ -3410,6 +3550,14 @@ var opcodeTable = [...]opInfo{ name: "NeqFat", generic: true, }, + { + name: "Neq32F", + generic: true, + }, + { + name: "Neq64F", + generic: true, + }, { name: "Less8", generic: true, @@ -3442,6 +3590,14 @@ var opcodeTable = [...]opInfo{ name: "Less64U", generic: true, }, + { + name: "Less32F", + generic: true, + }, + { + name: "Less64F", + generic: true, + }, { name: "Leq8", generic: true, @@ -3474,6 +3630,14 @@ var opcodeTable = [...]opInfo{ name: "Leq64U", generic: true, }, + { + name: "Leq32F", + generic: true, + }, + { + name: "Leq64F", + generic: true, + }, { name: "Greater8", generic: true, @@ -3506,6 +3670,14 @@ var opcodeTable = [...]opInfo{ name: "Greater64U", generic: true, }, + { + name: "Greater32F", + generic: true, + }, + { + name: "Greater64F", + generic: true, + }, { name: "Geq8", generic: true, @@ -3538,6 +3710,14 @@ var opcodeTable = [...]opInfo{ name: "Geq64U", generic: true, }, + { + name: "Geq32F", + generic: true, + }, + { + name: "Geq64F", + generic: true, + }, { name: "Not", generic: true, diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go index b50fecda2e..dc6dce995b 100644 --- a/src/cmd/compile/internal/ssa/rewriteAMD64.go +++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go @@ -2082,6 +2082,27 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto end4d77d0b016f93817fd6e5f60fa0e7ef2 end4d77d0b016f93817fd6e5f60fa0e7ef2: ; + case OpEq32F: + // match: (Eq32F x y) + // cond: + // result: (SETEQF (UCOMISS x y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETEQF + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64UCOMISS, TypeInvalid) + v0.Type = TypeFlags + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + return true + } + goto end034925b03df528b1ffec9fafdcd56c8e + end034925b03df528b1ffec9fafdcd56c8e: + ; case OpEq64: // match: (Eq64 x y) // cond: @@ -2103,6 +2124,27 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto endae6c62e4e20b4f62694b6ee40dbd9211 endae6c62e4e20b4f62694b6ee40dbd9211: ; + case OpEq64F: + // match: (Eq64F x y) + // cond: + // result: (SETEQF (UCOMISD x y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETEQF + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64UCOMISD, TypeInvalid) + v0.Type = TypeFlags + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + return true + } + goto end62b2fb60187571e6ab0c53696ef7d030 + end62b2fb60187571e6ab0c53696ef7d030: + ; case OpEq8: // match: (Eq8 x y) // cond: @@ -2208,6 +2250,27 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto end713c3dfa0f7247dcc232bcfc916fb044 end713c3dfa0f7247dcc232bcfc916fb044: ; + case OpGeq32F: + // match: (Geq32F x y) + // cond: + // result: (SETGEF (UCOMISS x y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETGEF + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64UCOMISS, TypeInvalid) + v0.Type = TypeFlags + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + return true + } + goto end5847ac7f2e264fba4c408ebb60c1e8a5 + end5847ac7f2e264fba4c408ebb60c1e8a5: + ; case OpGeq32U: // match: (Geq32U x y) // cond: @@ -2250,6 +2313,27 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto end63f44e3fec8d92723b5bde42d6d7eea0 end63f44e3fec8d92723b5bde42d6d7eea0: ; + case OpGeq64F: + // match: (Geq64F x y) + // cond: + // result: (SETGEF (UCOMISD x y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETGEF + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64UCOMISD, TypeInvalid) + v0.Type = TypeFlags + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + return true + } + goto endb40fbc46a8fc04fef95182771e2933c2 + endb40fbc46a8fc04fef95182771e2933c2: + ; case OpGeq64U: // match: (Geq64U x y) // cond: @@ -2390,6 +2474,27 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto endbf0b2b1368aadff48969a7386eee5795 endbf0b2b1368aadff48969a7386eee5795: ; + case OpGreater32F: + // match: (Greater32F x y) + // cond: + // result: (SETGF (UCOMISS x y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETGF + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64UCOMISS, TypeInvalid) + v0.Type = TypeFlags + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + return true + } + goto endb65b042358784f18002ae59ea6f2c51a + endb65b042358784f18002ae59ea6f2c51a: + ; case OpGreater32U: // match: (Greater32U x y) // cond: @@ -2432,6 +2537,27 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto endaef0cfa5e27e23cf5e527061cf251069 endaef0cfa5e27e23cf5e527061cf251069: ; + case OpGreater64F: + // match: (Greater64F x y) + // cond: + // result: (SETGF (UCOMISD x y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETGF + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64UCOMISD, TypeInvalid) + v0.Type = TypeFlags + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + return true + } + goto end1a6ca23bbb3e885473865e3b3ea501e7 + end1a6ca23bbb3e885473865e3b3ea501e7: + ; case OpGreater64U: // match: (Greater64U x y) // cond: @@ -2728,6 +2854,27 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto endf422ecc8da0033e22242de9c67112537 endf422ecc8da0033e22242de9c67112537: ; + case OpLeq32F: + // match: (Leq32F x y) + // cond: + // result: (SETGEF (UCOMISS y x)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETGEF + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64UCOMISS, TypeInvalid) + v0.Type = TypeFlags + v0.AddArg(y) + v0.AddArg(x) + v.AddArg(v0) + return true + } + goto end98f7b2e6e15ce282d044c812454fe77f + end98f7b2e6e15ce282d044c812454fe77f: + ; case OpLeq32U: // match: (Leq32U x y) // cond: @@ -2770,6 +2917,27 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto endf03da5e28dccdb4797671f39e824fb10 endf03da5e28dccdb4797671f39e824fb10: ; + case OpLeq64F: + // match: (Leq64F x y) + // cond: + // result: (SETGEF (UCOMISD y x)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETGEF + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64UCOMISD, TypeInvalid) + v0.Type = TypeFlags + v0.AddArg(y) + v0.AddArg(x) + v.AddArg(v0) + return true + } + goto end7efa164f4e4f5a395f547b1885b7eef4 + end7efa164f4e4f5a395f547b1885b7eef4: + ; case OpLeq64U: // match: (Leq64U x y) // cond: @@ -2896,6 +3064,27 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto end8da8d2030c0a323a84503c1240c566ae end8da8d2030c0a323a84503c1240c566ae: ; + case OpLess32F: + // match: (Less32F x y) + // cond: + // result: (SETGF (UCOMISS y x)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETGF + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64UCOMISS, TypeInvalid) + v0.Type = TypeFlags + v0.AddArg(y) + v0.AddArg(x) + v.AddArg(v0) + return true + } + goto end54f94ce87c18a1ed2beb8d0161bea907 + end54f94ce87c18a1ed2beb8d0161bea907: + ; case OpLess32U: // match: (Less32U x y) // cond: @@ -2938,6 +3127,27 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto endf8e7a24c25692045bbcfd2c9356d1a8c endf8e7a24c25692045bbcfd2c9356d1a8c: ; + case OpLess64F: + // match: (Less64F x y) + // cond: + // result: (SETGF (UCOMISD y x)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETGF + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64UCOMISD, TypeInvalid) + v0.Type = TypeFlags + v0.AddArg(y) + v0.AddArg(x) + v.AddArg(v0) + return true + } + goto end92720155a95cbfae47ea469583c4d3c7 + end92720155a95cbfae47ea469583c4d3c7: + ; case OpLess64U: // match: (Less64U x y) // cond: @@ -5902,6 +6112,27 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto end39c4bf6d063f8a0b6f0064c96ce25173 end39c4bf6d063f8a0b6f0064c96ce25173: ; + case OpNeq32F: + // match: (Neq32F x y) + // cond: + // result: (SETNEF (UCOMISS x y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETNEF + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64UCOMISS, TypeInvalid) + v0.Type = TypeFlags + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + return true + } + goto end4eb0af70b64b789e55d83c15e426b0c5 + end4eb0af70b64b789e55d83c15e426b0c5: + ; case OpNeq64: // match: (Neq64 x y) // cond: @@ -5923,6 +6154,27 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto end8ab0bcb910c0d3213dd8726fbcc4848e end8ab0bcb910c0d3213dd8726fbcc4848e: ; + case OpNeq64F: + // match: (Neq64F x y) + // cond: + // result: (SETNEF (UCOMISD x y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETNEF + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64UCOMISD, TypeInvalid) + v0.Type = TypeFlags + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + return true + } + goto end73beb54a015a226bc2e83bdd39e7ee46 + end73beb54a015a226bc2e83bdd39e7ee46: + ; case OpNeq8: // match: (Neq8 x y) // cond: @@ -10358,6 +10610,86 @@ func rewriteBlockAMD64(b *Block) bool { } goto end9bea9963c3c5dfb97249a5feb8287f94 end9bea9963c3c5dfb97249a5feb8287f94: + ; + // match: (If (SETGF cmp) yes no) + // cond: + // result: (UGT cmp yes no) + { + v := b.Control + if v.Op != OpAMD64SETGF { + goto enda72d68674cfa26b5982a43756bca6767 + } + cmp := v.Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockAMD64UGT + b.Control = cmp + b.Succs[0] = yes + b.Succs[1] = no + return true + } + goto enda72d68674cfa26b5982a43756bca6767 + enda72d68674cfa26b5982a43756bca6767: + ; + // match: (If (SETGEF cmp) yes no) + // cond: + // result: (UGE cmp yes no) + { + v := b.Control + if v.Op != OpAMD64SETGEF { + goto endccc171c1d66dd60ac0275d1f78259315 + } + cmp := v.Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockAMD64UGE + b.Control = cmp + b.Succs[0] = yes + b.Succs[1] = no + return true + } + goto endccc171c1d66dd60ac0275d1f78259315 + endccc171c1d66dd60ac0275d1f78259315: + ; + // match: (If (SETEQF cmp) yes no) + // cond: + // result: (EQF cmp yes no) + { + v := b.Control + if v.Op != OpAMD64SETEQF { + goto end58cb74d05266a79003ebdd733afb66fa + } + cmp := v.Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockAMD64EQF + b.Control = cmp + b.Succs[0] = yes + b.Succs[1] = no + return true + } + goto end58cb74d05266a79003ebdd733afb66fa + end58cb74d05266a79003ebdd733afb66fa: + ; + // match: (If (SETNEF cmp) yes no) + // cond: + // result: (EQF cmp yes no) + { + v := b.Control + if v.Op != OpAMD64SETNEF { + goto endfe25939ca97349543bc2d2ce4f97ba41 + } + cmp := v.Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockAMD64EQF + b.Control = cmp + b.Succs[0] = yes + b.Succs[1] = no + return true + } + goto endfe25939ca97349543bc2d2ce4f97ba41 + endfe25939ca97349543bc2d2ce4f97ba41: ; // match: (If cond yes no) // cond: @@ -10652,6 +10984,98 @@ func rewriteBlockAMD64(b *Block) bool { } goto endbd122fd599aeb9e60881a0fa735e2fde endbd122fd599aeb9e60881a0fa735e2fde: + ; + // match: (NE (TESTB (SETGF cmp)) yes no) + // cond: + // result: (UGT cmp yes no) + { + v := b.Control + if v.Op != OpAMD64TESTB { + goto endb2499521f7f351e24757f8c918c3598e + } + if v.Args[0].Op != OpAMD64SETGF { + goto endb2499521f7f351e24757f8c918c3598e + } + cmp := v.Args[0].Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockAMD64UGT + b.Control = cmp + b.Succs[0] = yes + b.Succs[1] = no + return true + } + goto endb2499521f7f351e24757f8c918c3598e + endb2499521f7f351e24757f8c918c3598e: + ; + // match: (NE (TESTB (SETGEF cmp)) yes no) + // cond: + // result: (UGE cmp yes no) + { + v := b.Control + if v.Op != OpAMD64TESTB { + goto end20461774babea665c4ca7c4f790a7209 + } + if v.Args[0].Op != OpAMD64SETGEF { + goto end20461774babea665c4ca7c4f790a7209 + } + cmp := v.Args[0].Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockAMD64UGE + b.Control = cmp + b.Succs[0] = yes + b.Succs[1] = no + return true + } + goto end20461774babea665c4ca7c4f790a7209 + end20461774babea665c4ca7c4f790a7209: + ; + // match: (NE (TESTB (SETEQF cmp)) yes no) + // cond: + // result: (EQF cmp yes no) + { + v := b.Control + if v.Op != OpAMD64TESTB { + goto end236616ef13d489b78736cda7bcc1d168 + } + if v.Args[0].Op != OpAMD64SETEQF { + goto end236616ef13d489b78736cda7bcc1d168 + } + cmp := v.Args[0].Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockAMD64EQF + b.Control = cmp + b.Succs[0] = yes + b.Succs[1] = no + return true + } + goto end236616ef13d489b78736cda7bcc1d168 + end236616ef13d489b78736cda7bcc1d168: + ; + // match: (NE (TESTB (SETNEF cmp)) yes no) + // cond: + // result: (NEF cmp yes no) + { + v := b.Control + if v.Op != OpAMD64TESTB { + goto endc992f3c266b16cb5f6aa98faa8f55600 + } + if v.Args[0].Op != OpAMD64SETNEF { + goto endc992f3c266b16cb5f6aa98faa8f55600 + } + cmp := v.Args[0].Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockAMD64NEF + b.Control = cmp + b.Succs[0] = yes + b.Succs[1] = no + return true + } + goto endc992f3c266b16cb5f6aa98faa8f55600 + endc992f3c266b16cb5f6aa98faa8f55600: ; // match: (NE (InvertFlags cmp) yes no) // cond: -- cgit v1.3 From 3526cf586be92cb4c741aed54ccfd37cf00ddfc5 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Mon, 24 Aug 2015 23:52:03 -0700 Subject: [dev.ssa] cmd/compile: implement OSLICESTR Add a new function and generic operation to handle bounds checking for slices. Unlike the index bounds checking the index can be equal to the upper bound. Do gc-friendly slicing that generates proper code for 0-length result slices. This is a takeover of Alexandru's original change, (https://go-review.googlesource.com/#/c/12764/) submittable now that the decompose phase is in. Change-Id: I17d164cf42ed7839f84ca949c6ad3289269c9160 Reviewed-on: https://go-review.googlesource.com/13903 Reviewed-by: David Chase --- src/cmd/compile/internal/gc/ssa.go | 86 +++++++++++++++++++- src/cmd/compile/internal/gc/testdata/string_ssa.go | 92 ++++++++++++++++++++++ src/cmd/compile/internal/ssa/gen/AMD64.rules | 2 + src/cmd/compile/internal/ssa/gen/genericOps.go | 7 +- src/cmd/compile/internal/ssa/opGen.go | 12 ++- src/cmd/compile/internal/ssa/rewriteAMD64.go | 39 +++++++++ 6 files changed, 234 insertions(+), 4 deletions(-) create mode 100644 src/cmd/compile/internal/gc/testdata/string_ssa.go (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 676de23115..ce20e7bdfd 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -1465,6 +1465,71 @@ func (s *state) expr(n *Node) *ssa.Value { a := s.expr(n.Left) return s.newValue1(ssa.OpITab, n.Type, a) + case OSLICESTR: + // Evaluate the string once. + str := s.expr(n.Left) + ptr := s.newValue1(ssa.OpStringPtr, Ptrto(Types[TUINT8]), str) + len := s.newValue1(ssa.OpStringLen, Types[TINT], str) + zero := s.constInt(Types[TINT], 0) + + // Evaluate the slice indexes. + var low, high *ssa.Value + if n.Right.Left == nil { + low = zero + } else { + low = s.expr(n.Right.Left) + } + if n.Right.Right == nil { + high = len + } else { + high = s.expr(n.Right.Right) + } + + // Panic if slice indices are not in bounds. + s.sliceBoundsCheck(low, high) + s.sliceBoundsCheck(high, len) + + // Generate the following code assuming that indexes are in bounds. + // The conditional is to make sure that we don't generate a string + // that points to the next object in memory. + // rlen = (SubPtr high low) + // p = ptr + // if rlen != 0 { + // p = (AddPtr ptr low) + // } + // result = (StringMake p size) + rlen := s.newValue2(ssa.OpSubPtr, Types[TINT], high, low) + + // Use n as the "variable" for p. + s.vars[n] = ptr + + // Generate code to test the resulting slice length. + var cmp *ssa.Value + if s.config.IntSize == 8 { + cmp = s.newValue2(ssa.OpNeq64, Types[TBOOL], rlen, zero) + } else { + cmp = s.newValue2(ssa.OpNeq32, Types[TBOOL], rlen, zero) + } + + b := s.endBlock() + b.Kind = ssa.BlockIf + b.Likely = ssa.BranchLikely + b.Control = cmp + + // Generate code for non-zero length slice case. + nz := s.f.NewBlock(ssa.BlockPlain) + addEdge(b, nz) + s.startBlock(nz) + s.vars[n] = s.newValue2(ssa.OpAddPtr, Ptrto(Types[TUINT8]), ptr, low) + s.endBlock() + + // All done. + merge := s.f.NewBlock(ssa.BlockPlain) + addEdge(b, merge) + addEdge(nz, merge) + s.startBlock(merge) + return s.newValue2(ssa.OpStringMake, Types[TSTRING], s.variable(n, Ptrto(Types[TUINT8])), rlen) + case OCALLFUNC, OCALLMETH: left := n.Left static := left.Op == ONAME && left.Class == PFUNC @@ -1782,6 +1847,25 @@ func (s *state) boundsCheck(idx, len *ssa.Value) { // bounds check cmp := s.newValue2(ssa.OpIsInBounds, Types[TBOOL], idx, len) + s.check(cmp, ssa.OpPanicIndexCheck) +} + +// sliceBoundsCheck generates slice bounds checking code. Checks if 0 <= idx <= len, branches to exit if not. +// Starts a new block on return. +func (s *state) sliceBoundsCheck(idx, len *ssa.Value) { + if Debug['B'] != 0 { + return + } + // TODO: convert index to full width? + // TODO: if index is 64-bit and we're compiling to 32-bit, check that high 32 bits are zero. + + // bounds check + cmp := s.newValue2(ssa.OpIsSliceInBounds, Types[TBOOL], idx, len) + s.check(cmp, ssa.OpPanicSliceCheck) +} + +// If cmp (a bool) is true, panic using the given op. +func (s *state) check(cmp *ssa.Value, panicOp ssa.Op) { b := s.endBlock() b.Kind = ssa.BlockIf b.Control = cmp @@ -1794,7 +1878,7 @@ func (s *state) boundsCheck(idx, len *ssa.Value) { s.startBlock(bPanic) // The panic check takes/returns memory to ensure that the right // memory state is observed if the panic happens. - s.vars[&memvar] = s.newValue1(ssa.OpPanicIndexCheck, ssa.TypeMem, s.mem()) + s.vars[&memvar] = s.newValue1(panicOp, ssa.TypeMem, s.mem()) s.endBlock() s.startBlock(bNext) } diff --git a/src/cmd/compile/internal/gc/testdata/string_ssa.go b/src/cmd/compile/internal/gc/testdata/string_ssa.go new file mode 100644 index 0000000000..5987412933 --- /dev/null +++ b/src/cmd/compile/internal/gc/testdata/string_ssa.go @@ -0,0 +1,92 @@ +// string_ssa.go tests string operations. +package main + +var failed = false + +func testStringSlice1_ssa(a string, i, j int) string { + switch { // prevent inlining + } + return a[i:] +} + +func testStringSlice2_ssa(a string, i, j int) string { + switch { // prevent inlining + } + return a[:j] +} + +func testStringSlice12_ssa(a string, i, j int) string { + switch { // prevent inlining + } + return a[i:j] +} + +func testStringSlice() { + tests := [...]struct { + fn func(string, int, int) string + s string + low, high int + want string + }{ + // -1 means the value is not used. + {testStringSlice1_ssa, "foobar", 0, -1, "foobar"}, + {testStringSlice1_ssa, "foobar", 3, -1, "bar"}, + {testStringSlice1_ssa, "foobar", 6, -1, ""}, + {testStringSlice2_ssa, "foobar", -1, 0, ""}, + {testStringSlice2_ssa, "foobar", -1, 3, "foo"}, + {testStringSlice2_ssa, "foobar", -1, 6, "foobar"}, + {testStringSlice12_ssa, "foobar", 0, 6, "foobar"}, + {testStringSlice12_ssa, "foobar", 0, 0, ""}, + {testStringSlice12_ssa, "foobar", 6, 6, ""}, + {testStringSlice12_ssa, "foobar", 1, 5, "ooba"}, + {testStringSlice12_ssa, "foobar", 3, 3, ""}, + {testStringSlice12_ssa, "", 0, 0, ""}, + } + + for i, t := range tests { + if got := t.fn(t.s, t.low, t.high); t.want != got { + println("#", i, " ", t.s, "[", t.low, ":", t.high, "] = ", got, " want ", t.want) + failed = true + } + } +} + +type prefix struct { + prefix string +} + +func (p *prefix) slice_ssa() { + p.prefix = p.prefix[:3] +} + +func testStructSlice() { + switch { + } + p := &prefix{"prefix"} + p.slice_ssa() + if "pre" != p.prefix { + println("wrong field slice: wanted %s got %s", "pre", p.prefix) + } +} + +func testStringSlicePanic() { + defer func() { + if r := recover(); r != nil { + println("paniced as expected") + } + }() + + str := "foobar" + println("got ", testStringSlice12_ssa(str, 3, 9)) + println("expected to panic, but didn't") + failed = true +} + +func main() { + testStringSlice() + testStringSlicePanic() + + if failed { + panic("failed") + } +} diff --git a/src/cmd/compile/internal/ssa/gen/AMD64.rules b/src/cmd/compile/internal/ssa/gen/AMD64.rules index ff89a7e899..f0b9288dd5 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64.rules +++ b/src/cmd/compile/internal/ssa/gen/AMD64.rules @@ -19,6 +19,7 @@ (Add64F x y) -> (ADDSD x y) (Sub64 x y) -> (SUBQ x y) +(SubPtr x y) -> (SUBQ x y) (Sub32 x y) -> (SUBL x y) (Sub16 x y) -> (SUBW x y) (Sub8 x y) -> (SUBB x y) @@ -279,6 +280,7 @@ // checks (IsNonNil p) -> (SETNE (TESTQ p p)) (IsInBounds idx len) -> (SETB (CMPQ idx len)) +(IsSliceInBounds idx len) -> (SETBE (CMPQ idx len)) (PanicNilCheck ptr mem) -> (LoweredPanicNilCheck ptr mem) (PanicIndexCheck mem) -> (LoweredPanicIndexCheck mem) diff --git a/src/cmd/compile/internal/ssa/gen/genericOps.go b/src/cmd/compile/internal/ssa/gen/genericOps.go index a0040d3017..66bb6596fa 100644 --- a/src/cmd/compile/internal/ssa/gen/genericOps.go +++ b/src/cmd/compile/internal/ssa/gen/genericOps.go @@ -21,9 +21,11 @@ var genericOps = []opData{ {name: "Sub16"}, {name: "Sub32"}, {name: "Sub64"}, + {name: "SubPtr"}, {name: "Sub32F"}, {name: "Sub64F"}, // TODO: Sub64C, Sub128C + // TODO: Sub32F, Sub64F, Sub64C, Sub128C {name: "Mul8"}, // arg0 * arg1 {name: "Mul16"}, @@ -311,8 +313,9 @@ var genericOps = []opData{ {name: "Cvt64Fto32F"}, // Automatically inserted safety checks - {name: "IsNonNil"}, // arg0 != nil - {name: "IsInBounds"}, // 0 <= arg0 < arg1 + {name: "IsNonNil"}, // arg0 != nil + {name: "IsInBounds"}, // 0 <= arg0 < arg1 + {name: "IsSliceInBounds"}, // 0 <= arg0 <= arg1 // Pseudo-ops {name: "PanicNilCheck"}, // trigger a dereference fault; arg0=nil ptr, arg1=mem, returns mem diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index 4eccb463da..8d99d57df7 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -274,6 +274,7 @@ const ( OpSub16 OpSub32 OpSub64 + OpSubPtr OpSub32F OpSub64F OpMul8 @@ -491,6 +492,7 @@ const ( OpCvt64Fto32F OpIsNonNil OpIsInBounds + OpIsSliceInBounds OpPanicNilCheck OpPanicIndexCheck OpPanicSliceCheck @@ -2335,6 +2337,7 @@ var opcodeTable = [...]opInfo{ inputs: []inputInfo{ {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -2631,7 +2634,6 @@ var opcodeTable = [...]opInfo{ inputs: []inputInfo{ {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, - clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -3106,6 +3108,10 @@ var opcodeTable = [...]opInfo{ name: "Sub64", generic: true, }, + { + name: "SubPtr", + generic: true, + }, { name: "Sub32F", generic: true, @@ -3974,6 +3980,10 @@ var opcodeTable = [...]opInfo{ name: "IsInBounds", generic: true, }, + { + name: "IsSliceInBounds", + generic: true, + }, { name: "PanicNilCheck", generic: true, diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go index dc6dce995b..c0213d8632 100644 --- a/src/cmd/compile/internal/ssa/rewriteAMD64.go +++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go @@ -2791,6 +2791,27 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto endff508c3726edfb573abc6128c177e76c endff508c3726edfb573abc6128c177e76c: ; + case OpIsSliceInBounds: + // match: (IsSliceInBounds idx len) + // cond: + // result: (SETBE (CMPQ idx len)) + { + idx := v.Args[0] + len := v.Args[1] + v.Op = OpAMD64SETBE + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64CMPQ, TypeInvalid) + v0.Type = TypeFlags + v0.AddArg(idx) + v0.AddArg(len) + v.AddArg(v0) + return true + } + goto end41f8211150e3a4ef36a1b5168013f96f + end41f8211150e3a4ef36a1b5168013f96f: + ; case OpLeq16: // match: (Leq16 x y) // cond: @@ -9579,6 +9600,24 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto end7d33bf9bdfa505f96b930563eca7955f end7d33bf9bdfa505f96b930563eca7955f: ; + case OpSubPtr: + // match: (SubPtr x y) + // cond: + // result: (SUBQ x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SUBQ + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto end748f63f755afe0b97a8f3cf7e4d9cbfe + end748f63f755afe0b97a8f3cf7e4d9cbfe: + ; case OpTrunc16to8: // match: (Trunc16to8 x) // cond: -- cgit v1.3 From 7cadf23afb3c54f36758d09710b87a0a9db4b4b9 Mon Sep 17 00:00:00 2001 From: Todd Neal Date: Tue, 25 Aug 2015 22:49:59 -0500 Subject: [dev.ssa] cmd/compile: fix phi floats The code previously always used AX causing errors. For now, just switch off the type in order to at least generate valid code. Change-Id: Iaf13120a24b62456b9b33c04ab31f2d5104b381b Reviewed-on: https://go-review.googlesource.com/13943 Reviewed-by: David Chase --- src/cmd/compile/internal/gc/testdata/fp_ssa.go | 46 ++++++++++++++++++++++++++ src/cmd/compile/internal/ssa/regalloc.go | 20 ++++++++--- 2 files changed, 62 insertions(+), 4 deletions(-) (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/testdata/fp_ssa.go b/src/cmd/compile/internal/gc/testdata/fp_ssa.go index 95e3cf9196..5eb65035d4 100644 --- a/src/cmd/compile/internal/gc/testdata/fp_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/fp_ssa.go @@ -35,6 +35,52 @@ func manysub_ssa(a, b, c, d float64) (aa, ab, ac, ad, ba, bb, bc, bd, ca, cb, cc return } +// fpspill_ssa attempts to trigger a bug where phis with floating point values +// were stored in non-fp registers causing an error in doasm. +func fpspill_ssa(a int) float64 { + switch { + } + + ret := -1.0 + switch a { + case 0: + ret = 1.0 + case 1: + ret = 1.1 + case 2: + ret = 1.2 + case 3: + ret = 1.3 + case 4: + ret = 1.4 + case 5: + ret = 1.5 + case 6: + ret = 1.6 + case 7: + ret = 1.7 + case 8: + ret = 1.8 + case 9: + ret = 1.9 + case 10: + ret = 1.10 + case 11: + ret = 1.11 + case 12: + ret = 1.12 + case 13: + ret = 1.13 + case 14: + ret = 1.14 + case 15: + ret = 1.15 + case 16: + ret = 1.16 + } + return ret +} + func add64_ssa(a, b float64) float64 { switch { } diff --git a/src/cmd/compile/internal/ssa/regalloc.go b/src/cmd/compile/internal/ssa/regalloc.go index b62f9042b6..b098ea1a19 100644 --- a/src/cmd/compile/internal/ssa/regalloc.go +++ b/src/cmd/compile/internal/ssa/regalloc.go @@ -550,6 +550,16 @@ func (s *regAllocState) setState(state []regState) { } } +// compatReg returns a register compatible with the a value and is used when +// spilling/loading. +// TODO: choose a better default register (set of reg by type?). +func compatReg(v *Value) regMask { + if v.Type.IsFloat() { + return 1 << 16 // X0 + } + return 1 << 0 // AX +} + func (s *regAllocState) regalloc(f *Func) { liveset := newSparseSet(f.NumValues()) argset := newSparseSet(f.NumValues()) @@ -836,10 +846,11 @@ func (s *regAllocState) regalloc(f *Func) { if !argset.contains(v.ID) { continue } + // This stack-based phi is the argument of some other // phi in this block. We must make a copy of its // value so that we don't clobber it prematurely. - c := s.allocValToReg(v, s.values[v.ID].regs|1<<0, false) + c := s.allocValToReg(v, s.values[v.ID].regs|compatReg(v), false) d := p.NewValue1(v.Line, OpStoreReg, v.Type, c) s.values[v.ID].spill2 = d } @@ -848,9 +859,10 @@ func (s *regAllocState) regalloc(f *Func) { // we might need a register to do the assignment. for _, v := range stackPhis { // Load phi arg into a register, then store it with a StoreReg. - // If already in a register, use that. If not, use register 0. - // TODO: choose a better default register (set of reg by type?). - c := s.allocValToReg(v.Args[i], s.values[v.Args[i].ID].regs|1<<0, false) + // If already in a register, use that. If not, pick a compatible + // register. + w := v.Args[i] + c := s.allocValToReg(w, s.values[w.ID].regs|compatReg(w), false) v.Args[i] = p.NewValue1(v.Line, OpStoreReg, v.Type, c) } // Figure out what value goes in each register. -- cgit v1.3 From e0e4068c6e6cebb586bbffa36962c7fc6cb595e0 Mon Sep 17 00:00:00 2001 From: Todd Neal Date: Wed, 26 Aug 2015 18:40:52 -0500 Subject: [dev.ssa] cmd/compile: implement len(map) Implement len(map) values. Change-Id: If92be96ec9a7a86aeb3ce566d6758aab01c2fa7d Reviewed-on: https://go-review.googlesource.com/13961 Reviewed-by: Keith Randall --- src/cmd/compile/internal/gc/ssa.go | 38 ++++++++++++++++- src/cmd/compile/internal/gc/testdata/map_ssa.go | 47 ++++++++++++++++++++++ src/cmd/compile/internal/gc/testdata/string_ssa.go | 4 ++ 3 files changed, 87 insertions(+), 2 deletions(-) create mode 100644 src/cmd/compile/internal/gc/testdata/map_ssa.go (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 0c0a6a36da..d672eb58e0 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -1440,8 +1440,7 @@ func (s *state) expr(n *Node) *ssa.Value { case n.Left.Type.IsString(): // string; not reachable for OCAP return s.newValue1(ssa.OpStringLen, Types[TINT], s.expr(n.Left)) case n.Left.Type.IsMap(): - s.Unimplementedf("unhandled len(map)") - return nil + return s.lenMap(n, s.expr(n.Left)) case n.Left.Type.IsChan(): if n.Op == OCAP { s.Unimplementedf("unhandled cap(chan)") @@ -1998,6 +1997,41 @@ func (s *state) uintTofloat(cvttab *u2fcvtTab, n *Node, x *ssa.Value, ft, tt *Ty return s.variable(n, n.Type) } +func (s *state) lenMap(n *Node, x *ssa.Value) *ssa.Value { + // if n == nil { + // return 0 + // } else { + // return *((*int)n) + // } + lenType := n.Type + cmp := s.newValue2(ssa.OpEqPtr, Types[TBOOL], x, s.zeroVal(lenType)) + b := s.endBlock() + b.Kind = ssa.BlockIf + b.Control = cmp + b.Likely = ssa.BranchUnlikely + + bThen := s.f.NewBlock(ssa.BlockPlain) + bElse := s.f.NewBlock(ssa.BlockPlain) + bAfter := s.f.NewBlock(ssa.BlockPlain) + + // length of a nil map is zero + addEdge(b, bThen) + s.startBlock(bThen) + s.vars[n] = s.zeroVal(lenType) + s.endBlock() + addEdge(bThen, bAfter) + + // the length is stored in the first word + addEdge(b, bElse) + s.startBlock(bElse) + s.vars[n] = s.newValue2(ssa.OpLoad, lenType, x, s.mem()) + s.endBlock() + addEdge(bElse, bAfter) + + s.startBlock(bAfter) + return s.variable(n, lenType) +} + // checkgoto checks that a goto from from to to does not // jump into a block or jump over variable declarations. // It is a copy of checkgoto in the pre-SSA backend, diff --git a/src/cmd/compile/internal/gc/testdata/map_ssa.go b/src/cmd/compile/internal/gc/testdata/map_ssa.go new file mode 100644 index 0000000000..41c949a9f2 --- /dev/null +++ b/src/cmd/compile/internal/gc/testdata/map_ssa.go @@ -0,0 +1,47 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// map_ssa.go tests map operations. +package main + +import "fmt" + +var failed = false + +func lenMap_ssa(v map[int]int) int { + switch { // prevent inlining + + } + return len(v) +} + +func testLenMap() { + + v := make(map[int]int) + v[0] = 0 + v[1] = 0 + v[2] = 0 + + if want, got := 3, lenMap_ssa(v); got != want { + fmt.Printf("expected len(map) = %d, got %d", want, got) + failed = true + } +} + +func testLenNilMap() { + + var v map[int]int + if want, got := 0, lenMap_ssa(v); got != want { + fmt.Printf("expected len(nil) = %d, got %d", want, got) + failed = true + } +} +func main() { + testLenMap() + testLenNilMap() + + if failed { + panic("failed") + } +} diff --git a/src/cmd/compile/internal/gc/testdata/string_ssa.go b/src/cmd/compile/internal/gc/testdata/string_ssa.go index 5987412933..efc734e1a2 100644 --- a/src/cmd/compile/internal/gc/testdata/string_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/string_ssa.go @@ -1,3 +1,7 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + // string_ssa.go tests string operations. package main -- cgit v1.3 From 525785885e42b26e6936e5d91386518218cff4d7 Mon Sep 17 00:00:00 2001 From: David Chase Date: Fri, 28 Aug 2015 14:24:10 -0400 Subject: [dev.ssa] cmd/compile: add compose/decompose for complex, phi, constants Still to do: arithmetic Change-Id: I31fd23b34980c9ed4b4e304b8597134b2ba6ca5c Reviewed-on: https://go-review.googlesource.com/14024 Reviewed-by: Keith Randall --- src/cmd/compile/internal/gc/ssa.go | 37 +++++ .../compile/internal/gc/testdata/compound_ssa.go | 54 +++++++ src/cmd/compile/internal/gc/type.go | 4 + src/cmd/compile/internal/ssa/config.go | 2 + src/cmd/compile/internal/ssa/decompose.go | 27 ++++ src/cmd/compile/internal/ssa/export_test.go | 2 + src/cmd/compile/internal/ssa/gen/generic.rules | 30 ++++ src/cmd/compile/internal/ssa/gen/genericOps.go | 5 + src/cmd/compile/internal/ssa/opGen.go | 25 ++- src/cmd/compile/internal/ssa/rewritegeneric.go | 180 +++++++++++++++++++++ src/cmd/compile/internal/ssa/type.go | 4 +- src/cmd/compile/internal/ssa/type_test.go | 26 +-- 12 files changed, 377 insertions(+), 19 deletions(-) (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index d672eb58e0..94fdf0e489 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -1113,6 +1113,29 @@ func (s *state) expr(n *Node) *ssa.Value { s.Fatalf("bad float size %d", n.Type.Size()) return nil } + case CTCPLX: + c := n.Val().U.(*Mpcplx) + r := &c.Real + i := &c.Imag + switch n.Type.Size() { + case 8: + { + pt := Types[TFLOAT32] + return s.newValue2(ssa.OpComplexMake, n.Type, + s.constFloat32(pt, mpgetflt32(r)), + s.constFloat32(pt, mpgetflt32(i))) + } + case 16: + { + pt := Types[TFLOAT64] + return s.newValue2(ssa.OpComplexMake, n.Type, + s.constFloat32(pt, mpgetflt(r)), + s.constFloat32(pt, mpgetflt(i))) + } + default: + s.Fatalf("bad float size %d", n.Type.Size()) + return nil + } default: s.Unimplementedf("unhandled OLITERAL %v", n.Val().Ctype()) @@ -1654,6 +1677,18 @@ func (s *state) zeroVal(t *Type) *ssa.Value { default: s.Fatalf("bad sized float type %s", t) } + case t.IsComplex(): + switch t.Size() { + case 8: + z := s.constFloat32(Types[TFLOAT32], 0) + return s.newValue2(ssa.OpComplexMake, t, z, z) + case 16: + z := s.constFloat64(Types[TFLOAT64], 0) + return s.newValue2(ssa.OpComplexMake, t, z, z) + default: + s.Fatalf("bad sized complex type %s", t) + } + case t.IsString(): return s.entryNewValue0A(ssa.OpConstString, t, "") case t.IsPtr(): @@ -3328,6 +3363,8 @@ func (s *ssaExport) TypeUInt8() ssa.Type { return Types[TUINT8] } func (s *ssaExport) TypeUInt16() ssa.Type { return Types[TUINT16] } func (s *ssaExport) TypeUInt32() ssa.Type { return Types[TUINT32] } func (s *ssaExport) TypeUInt64() ssa.Type { return Types[TUINT64] } +func (s *ssaExport) TypeFloat32() ssa.Type { return Types[TFLOAT32] } +func (s *ssaExport) TypeFloat64() ssa.Type { return Types[TFLOAT64] } func (s *ssaExport) TypeInt() ssa.Type { return Types[TINT] } func (s *ssaExport) TypeUintptr() ssa.Type { return Types[TUINTPTR] } func (s *ssaExport) TypeString() ssa.Type { return Types[TSTRING] } diff --git a/src/cmd/compile/internal/gc/testdata/compound_ssa.go b/src/cmd/compile/internal/gc/testdata/compound_ssa.go index 9b84ce4b11..b0e4962f5e 100644 --- a/src/cmd/compile/internal/gc/testdata/compound_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/compound_ssa.go @@ -33,6 +33,58 @@ func testString() { } } +func complex64_ssa(a, b complex64, x bool) complex64 { + switch { + } + var c complex64 + if x { + c = a + } else { + c = b + } + return c +} + +func complex128_ssa(a, b complex128, x bool) complex128 { + switch { + } + var c complex128 + if x { + c = a + } else { + c = b + } + return c +} + +func testComplex64() { + var a complex64 = 1 + 2i + var b complex64 = 3 + 4i + + if want, got := a, complex64_ssa(a, b, true); got != want { + fmt.Printf("complex64_ssa(%v, %v, true) = %v, want %v\n", a, b, got, want) + failed = true + } + if want, got := b, complex64_ssa(a, b, false); got != want { + fmt.Printf("complex64_ssa(%v, %v, true) = %v, want %v\n", a, b, got, want) + failed = true + } +} + +func testComplex128() { + var a complex128 = 1 + 2i + var b complex128 = 3 + 4i + + if want, got := a, complex128_ssa(a, b, true); got != want { + fmt.Printf("complex128_ssa(%v, %v, true) = %v, want %v\n", a, b, got, want) + failed = true + } + if want, got := b, complex128_ssa(a, b, false); got != want { + fmt.Printf("complex128_ssa(%v, %v, true) = %v, want %v\n", a, b, got, want) + failed = true + } +} + func slice_ssa(a, b []byte, x bool) []byte { var s []byte if x { @@ -85,6 +137,8 @@ func main() { testString() testSlice() testInterface() + testComplex64() + testComplex128() if failed { panic("failed") } diff --git a/src/cmd/compile/internal/gc/type.go b/src/cmd/compile/internal/gc/type.go index e2d8925839..cdd9b3f14a 100644 --- a/src/cmd/compile/internal/gc/type.go +++ b/src/cmd/compile/internal/gc/type.go @@ -59,6 +59,10 @@ func (t *Type) IsFloat() bool { return t.Etype == TFLOAT32 || t.Etype == TFLOAT64 } +func (t *Type) IsComplex() bool { + return t.Etype == TCOMPLEX64 || t.Etype == TCOMPLEX128 +} + func (t *Type) IsPtr() bool { return t.Etype == TPTR32 || t.Etype == TPTR64 || t.Etype == TUNSAFEPTR || t.Etype == TMAP || t.Etype == TCHAN || t.Etype == TFUNC diff --git a/src/cmd/compile/internal/ssa/config.go b/src/cmd/compile/internal/ssa/config.go index ad6441117c..865066870d 100644 --- a/src/cmd/compile/internal/ssa/config.go +++ b/src/cmd/compile/internal/ssa/config.go @@ -27,6 +27,8 @@ type TypeSource interface { TypeUInt32() Type TypeUInt64() Type TypeInt() Type + TypeFloat32() Type + TypeFloat64() Type TypeUintptr() Type TypeString() Type TypeBytePtr() Type // TODO: use unsafe.Pointer instead? diff --git a/src/cmd/compile/internal/ssa/decompose.go b/src/cmd/compile/internal/ssa/decompose.go index 534ffc269e..a2dfdc16ab 100644 --- a/src/cmd/compile/internal/ssa/decompose.go +++ b/src/cmd/compile/internal/ssa/decompose.go @@ -14,6 +14,8 @@ func decompose(f *Func) { continue } switch { + case v.Type.IsComplex(): + decomposeComplexPhi(v) case v.Type.IsString(): decomposeStringPhi(v) case v.Type.IsSlice(): @@ -72,6 +74,31 @@ func decomposeSlicePhi(v *Value) { v.AddArg(cap) } +func decomposeComplexPhi(v *Value) { + fe := v.Block.Func.Config.fe + var partType Type + if v.Type.Size() == 8 { + partType = fe.TypeFloat32() + } else if v.Type.Size() == 16 { + partType = fe.TypeFloat64() + } else { + panic("Whoops, are sizes in bytes or bits?") + } + + real := v.Block.NewValue0(v.Line, OpPhi, partType) + imag := v.Block.NewValue0(v.Line, OpPhi, partType) + for _, a := range v.Args { + real.AddArg(a.Block.NewValue1(v.Line, OpComplexReal, partType, a)) + imag.AddArg(a.Block.NewValue1(v.Line, OpComplexImag, partType, a)) + } + v.Op = OpComplexMake + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(real) + v.AddArg(imag) +} + func decomposeInterfacePhi(v *Value) { ptrType := v.Block.Func.Config.fe.TypeBytePtr() diff --git a/src/cmd/compile/internal/ssa/export_test.go b/src/cmd/compile/internal/ssa/export_test.go index d2e8216b5d..5b56aa5184 100644 --- a/src/cmd/compile/internal/ssa/export_test.go +++ b/src/cmd/compile/internal/ssa/export_test.go @@ -38,6 +38,8 @@ func (d DummyFrontend) TypeUInt8() Type { return TypeUInt8 } func (d DummyFrontend) TypeUInt16() Type { return TypeUInt16 } func (d DummyFrontend) TypeUInt32() Type { return TypeUInt32 } func (d DummyFrontend) TypeUInt64() Type { return TypeUInt64 } +func (d DummyFrontend) TypeFloat32() Type { return TypeFloat32 } +func (d DummyFrontend) TypeFloat64() Type { return TypeFloat64 } func (d DummyFrontend) TypeInt() Type { return TypeInt64 } func (d DummyFrontend) TypeUintptr() Type { return TypeUInt64 } func (d DummyFrontend) TypeString() Type { panic("unimplemented") } diff --git a/src/cmd/compile/internal/ssa/gen/generic.rules b/src/cmd/compile/internal/ssa/gen/generic.rules index 7be00569ea..f77b31501d 100644 --- a/src/cmd/compile/internal/ssa/gen/generic.rules +++ b/src/cmd/compile/internal/ssa/gen/generic.rules @@ -74,6 +74,36 @@ (PtrIndex ptr idx) -> (AddPtr ptr (MulPtr idx (ConstPtr [t.Elem().Size()]))) (StructSelect [idx] (Load ptr mem)) -> (Load (OffPtr [idx] ptr) mem) +// complex ops +(ComplexReal (ComplexMake real _ )) -> real +(ComplexImag (ComplexMake _ imag )) -> imag + +(Load ptr mem) && t.IsComplex() && t.Size() == 8 -> + (ComplexMake + (Load ptr mem) + (Load + (OffPtr [4] ptr) + mem) + ) +(Store [8] dst (ComplexMake real imag) mem) -> + (Store [4] + (OffPtr [4] dst) + imag + (Store [4] dst real mem)) + +(Load ptr mem) && t.IsComplex() && t.Size() == 16 -> + (ComplexMake + (Load ptr mem) + (Load + (OffPtr [8] ptr) + mem) + ) +(Store [16] dst (ComplexMake real imag) mem) -> + (Store [8] + (OffPtr [8] dst) + imag + (Store [8] dst real mem)) + // string ops (StringPtr (StringMake ptr _)) -> ptr (StringLen (StringMake _ len)) -> len diff --git a/src/cmd/compile/internal/ssa/gen/genericOps.go b/src/cmd/compile/internal/ssa/gen/genericOps.go index 726a62e6be..62d34e74bb 100644 --- a/src/cmd/compile/internal/ssa/gen/genericOps.go +++ b/src/cmd/compile/internal/ssa/gen/genericOps.go @@ -334,6 +334,11 @@ var genericOps = []opData{ {name: "SliceLen"}, // len(arg0) {name: "SliceCap"}, // cap(arg0) + // Complex (part/whole) + {name: "ComplexMake"}, // arg0=real, arg1=imag + {name: "ComplexReal"}, // real_part(arg0) + {name: "ComplexImag"}, // imaginary_part(arg0) + // Strings {name: "StringMake"}, // arg0=ptr, arg1=len {name: "StringPtr"}, // ptr(arg0) diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index 8d99d57df7..15689b2a85 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -505,6 +505,9 @@ const ( OpSlicePtr OpSliceLen OpSliceCap + OpComplexMake + OpComplexReal + OpComplexImag OpStringMake OpStringPtr OpStringLen @@ -2350,7 +2353,6 @@ var opcodeTable = [...]opInfo{ inputs: []inputInfo{ {0, 8589934592}, // .FLAGS }, - clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -2363,7 +2365,6 @@ var opcodeTable = [...]opInfo{ inputs: []inputInfo{ {0, 8589934592}, // .FLAGS }, - clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -2496,7 +2497,7 @@ var opcodeTable = [...]opInfo{ inputs: []inputInfo{ {0, 8589934592}, // .FLAGS }, - clobbers: 8589934593, // .AX .FLAGS + clobbers: 1, // .AX outputs: []regMask{ 65518, // .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -2509,7 +2510,7 @@ var opcodeTable = [...]opInfo{ inputs: []inputInfo{ {0, 8589934592}, // .FLAGS }, - clobbers: 8589934593, // .AX .FLAGS + clobbers: 1, // .AX outputs: []regMask{ 65518, // .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -2522,7 +2523,6 @@ var opcodeTable = [...]opInfo{ inputs: []inputInfo{ {0, 8589934592}, // .FLAGS }, - clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -2535,7 +2535,6 @@ var opcodeTable = [...]opInfo{ inputs: []inputInfo{ {0, 8589934592}, // .FLAGS }, - clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -2548,7 +2547,6 @@ var opcodeTable = [...]opInfo{ inputs: []inputInfo{ {0, 8589934592}, // .FLAGS }, - clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -2561,7 +2559,6 @@ var opcodeTable = [...]opInfo{ inputs: []inputInfo{ {0, 8589934592}, // .FLAGS }, - clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -4032,6 +4029,18 @@ var opcodeTable = [...]opInfo{ name: "SliceCap", generic: true, }, + { + name: "ComplexMake", + generic: true, + }, + { + name: "ComplexReal", + generic: true, + }, + { + name: "ComplexImag", + generic: true, + }, { name: "StringMake", generic: true, diff --git a/src/cmd/compile/internal/ssa/rewritegeneric.go b/src/cmd/compile/internal/ssa/rewritegeneric.go index bd53e05230..b14ed9c21e 100644 --- a/src/cmd/compile/internal/ssa/rewritegeneric.go +++ b/src/cmd/compile/internal/ssa/rewritegeneric.go @@ -237,6 +237,46 @@ func rewriteValuegeneric(v *Value, config *Config) bool { goto end4d92ff3ba567d9afd38fc9ca113602ad end4d92ff3ba567d9afd38fc9ca113602ad: ; + case OpComplexImag: + // match: (ComplexImag (ComplexMake _ imag )) + // cond: + // result: imag + { + if v.Args[0].Op != OpComplexMake { + goto endec3009fd8727d03002021997936e091f + } + imag := v.Args[0].Args[1] + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = imag.Type + v.AddArg(imag) + return true + } + goto endec3009fd8727d03002021997936e091f + endec3009fd8727d03002021997936e091f: + ; + case OpComplexReal: + // match: (ComplexReal (ComplexMake real _ )) + // cond: + // result: real + { + if v.Args[0].Op != OpComplexMake { + goto end8db3e16bd59af1adaa4b734c8adcc71d + } + real := v.Args[0].Args[0] + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = real.Type + v.AddArg(real) + return true + } + goto end8db3e16bd59af1adaa4b734c8adcc71d + end8db3e16bd59af1adaa4b734c8adcc71d: + ; case OpConstInterface: // match: (ConstInterface) // cond: @@ -569,6 +609,72 @@ func rewriteValuegeneric(v *Value, config *Config) bool { end84d6ae817944985f572ecaac51999d6c: ; case OpLoad: + // match: (Load ptr mem) + // cond: t.IsComplex() && t.Size() == 8 + // result: (ComplexMake (Load ptr mem) (Load (OffPtr [4] ptr) mem) ) + { + t := v.Type + ptr := v.Args[0] + mem := v.Args[1] + if !(t.IsComplex() && t.Size() == 8) { + goto end665854b31b828893d90b36bb462ff381 + } + v.Op = OpComplexMake + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpLoad, TypeInvalid) + v0.Type = config.fe.TypeFloat32() + v0.AddArg(ptr) + v0.AddArg(mem) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpLoad, TypeInvalid) + v1.Type = config.fe.TypeFloat32() + v2 := b.NewValue0(v.Line, OpOffPtr, TypeInvalid) + v2.Type = config.fe.TypeFloat32().PtrTo() + v2.AuxInt = 4 + v2.AddArg(ptr) + v1.AddArg(v2) + v1.AddArg(mem) + v.AddArg(v1) + return true + } + goto end665854b31b828893d90b36bb462ff381 + end665854b31b828893d90b36bb462ff381: + ; + // match: (Load ptr mem) + // cond: t.IsComplex() && t.Size() == 16 + // result: (ComplexMake (Load ptr mem) (Load (OffPtr [8] ptr) mem) ) + { + t := v.Type + ptr := v.Args[0] + mem := v.Args[1] + if !(t.IsComplex() && t.Size() == 16) { + goto end1b106f89e0e3e26c613b957a7c98d8ad + } + v.Op = OpComplexMake + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpLoad, TypeInvalid) + v0.Type = config.fe.TypeFloat64() + v0.AddArg(ptr) + v0.AddArg(mem) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpLoad, TypeInvalid) + v1.Type = config.fe.TypeFloat64() + v2 := b.NewValue0(v.Line, OpOffPtr, TypeInvalid) + v2.Type = config.fe.TypeFloat64().PtrTo() + v2.AuxInt = 8 + v2.AddArg(ptr) + v1.AddArg(v2) + v1.AddArg(mem) + v.AddArg(v1) + return true + } + goto end1b106f89e0e3e26c613b957a7c98d8ad + end1b106f89e0e3e26c613b957a7c98d8ad: + ; // match: (Load ptr mem) // cond: t.IsString() // result: (StringMake (Load ptr mem) (Load (OffPtr [config.PtrSize] ptr) mem)) @@ -1017,6 +1123,80 @@ func rewriteValuegeneric(v *Value, config *Config) bool { end526acc0a705137a5d25577499206720b: ; case OpStore: + // match: (Store [8] dst (ComplexMake real imag) mem) + // cond: + // result: (Store [4] (OffPtr [4] dst) imag (Store [4] dst real mem)) + { + if v.AuxInt != 8 { + goto endba187c049aa71488994c8a2eb3453045 + } + dst := v.Args[0] + if v.Args[1].Op != OpComplexMake { + goto endba187c049aa71488994c8a2eb3453045 + } + real := v.Args[1].Args[0] + imag := v.Args[1].Args[1] + mem := v.Args[2] + v.Op = OpStore + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = 4 + v0 := b.NewValue0(v.Line, OpOffPtr, TypeInvalid) + v0.Type = config.fe.TypeFloat32().PtrTo() + v0.AuxInt = 4 + v0.AddArg(dst) + v.AddArg(v0) + v.AddArg(imag) + v1 := b.NewValue0(v.Line, OpStore, TypeInvalid) + v1.Type = TypeMem + v1.AuxInt = 4 + v1.AddArg(dst) + v1.AddArg(real) + v1.AddArg(mem) + v.AddArg(v1) + return true + } + goto endba187c049aa71488994c8a2eb3453045 + endba187c049aa71488994c8a2eb3453045: + ; + // match: (Store [16] dst (ComplexMake real imag) mem) + // cond: + // result: (Store [8] (OffPtr [8] dst) imag (Store [8] dst real mem)) + { + if v.AuxInt != 16 { + goto end4df4c826201cf51af245d6b89de00589 + } + dst := v.Args[0] + if v.Args[1].Op != OpComplexMake { + goto end4df4c826201cf51af245d6b89de00589 + } + real := v.Args[1].Args[0] + imag := v.Args[1].Args[1] + mem := v.Args[2] + v.Op = OpStore + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = 8 + v0 := b.NewValue0(v.Line, OpOffPtr, TypeInvalid) + v0.Type = config.fe.TypeFloat64().PtrTo() + v0.AuxInt = 8 + v0.AddArg(dst) + v.AddArg(v0) + v.AddArg(imag) + v1 := b.NewValue0(v.Line, OpStore, TypeInvalid) + v1.Type = TypeMem + v1.AuxInt = 8 + v1.AddArg(dst) + v1.AddArg(real) + v1.AddArg(mem) + v.AddArg(v1) + return true + } + goto end4df4c826201cf51af245d6b89de00589 + end4df4c826201cf51af245d6b89de00589: + ; // match: (Store [2*config.PtrSize] dst (StringMake ptr len) mem) // cond: // result: (Store [config.PtrSize] (OffPtr [config.PtrSize] dst) len (Store [config.PtrSize] dst ptr mem)) diff --git a/src/cmd/compile/internal/ssa/type.go b/src/cmd/compile/internal/ssa/type.go index 15dbddd1fc..decde6889e 100644 --- a/src/cmd/compile/internal/ssa/type.go +++ b/src/cmd/compile/internal/ssa/type.go @@ -16,6 +16,7 @@ type Type interface { IsInteger() bool // ... ditto for the others IsSigned() bool IsFloat() bool + IsComplex() bool IsPtr() bool IsString() bool IsSlice() bool @@ -39,12 +40,13 @@ type CompilerType struct { Flags bool } -func (t *CompilerType) Size() int64 { return 0 } +func (t *CompilerType) Size() int64 { return 0 } // Size in bytes func (t *CompilerType) Alignment() int64 { return 0 } func (t *CompilerType) IsBoolean() bool { return false } func (t *CompilerType) IsInteger() bool { return false } func (t *CompilerType) IsSigned() bool { return false } func (t *CompilerType) IsFloat() bool { return false } +func (t *CompilerType) IsComplex() bool { return false } func (t *CompilerType) IsPtr() bool { return false } func (t *CompilerType) IsString() bool { return false } func (t *CompilerType) IsSlice() bool { return false } diff --git a/src/cmd/compile/internal/ssa/type_test.go b/src/cmd/compile/internal/ssa/type_test.go index 5f0413c397..b106688e84 100644 --- a/src/cmd/compile/internal/ssa/type_test.go +++ b/src/cmd/compile/internal/ssa/type_test.go @@ -12,6 +12,7 @@ type TypeImpl struct { Integer bool Signed bool Float bool + Complex bool Ptr bool string bool slice bool @@ -27,6 +28,7 @@ func (t *TypeImpl) IsBoolean() bool { return t.Boolean } func (t *TypeImpl) IsInteger() bool { return t.Integer } func (t *TypeImpl) IsSigned() bool { return t.Signed } func (t *TypeImpl) IsFloat() bool { return t.Float } +func (t *TypeImpl) IsComplex() bool { return t.Complex } func (t *TypeImpl) IsPtr() bool { return t.Ptr } func (t *TypeImpl) IsString() bool { return t.string } func (t *TypeImpl) IsSlice() bool { return t.slice } @@ -48,14 +50,18 @@ func (t *TypeImpl) Equal(u Type) bool { var ( // shortcuts for commonly used basic types - TypeInt8 = &TypeImpl{Size_: 1, Align: 1, Integer: true, Signed: true, Name: "int8"} - TypeInt16 = &TypeImpl{Size_: 2, Align: 2, Integer: true, Signed: true, Name: "int16"} - TypeInt32 = &TypeImpl{Size_: 4, Align: 4, Integer: true, Signed: true, Name: "int32"} - TypeInt64 = &TypeImpl{Size_: 8, Align: 8, Integer: true, Signed: true, Name: "int64"} - TypeUInt8 = &TypeImpl{Size_: 1, Align: 1, Integer: true, Name: "uint8"} - TypeUInt16 = &TypeImpl{Size_: 2, Align: 2, Integer: true, Name: "uint16"} - TypeUInt32 = &TypeImpl{Size_: 4, Align: 4, Integer: true, Name: "uint32"} - TypeUInt64 = &TypeImpl{Size_: 8, Align: 8, Integer: true, Name: "uint64"} - TypeBool = &TypeImpl{Size_: 1, Align: 1, Boolean: true, Name: "bool"} - TypeBytePtr = &TypeImpl{Size_: 8, Align: 8, Ptr: true, Name: "*byte"} + TypeInt8 = &TypeImpl{Size_: 1, Align: 1, Integer: true, Signed: true, Name: "int8"} + TypeInt16 = &TypeImpl{Size_: 2, Align: 2, Integer: true, Signed: true, Name: "int16"} + TypeInt32 = &TypeImpl{Size_: 4, Align: 4, Integer: true, Signed: true, Name: "int32"} + TypeInt64 = &TypeImpl{Size_: 8, Align: 8, Integer: true, Signed: true, Name: "int64"} + TypeFloat32 = &TypeImpl{Size_: 4, Align: 4, Float: true, Name: "float32"} + TypeFloat64 = &TypeImpl{Size_: 8, Align: 8, Float: true, Name: "float64"} + TypeComplex64 = &TypeImpl{Size_: 8, Align: 4, Complex: true, Name: "complex64"} + TypeComplex128 = &TypeImpl{Size_: 16, Align: 8, Complex: true, Name: "complex128"} + TypeUInt8 = &TypeImpl{Size_: 1, Align: 1, Integer: true, Name: "uint8"} + TypeUInt16 = &TypeImpl{Size_: 2, Align: 2, Integer: true, Name: "uint16"} + TypeUInt32 = &TypeImpl{Size_: 4, Align: 4, Integer: true, Name: "uint32"} + TypeUInt64 = &TypeImpl{Size_: 8, Align: 8, Integer: true, Name: "uint64"} + TypeBool = &TypeImpl{Size_: 1, Align: 1, Boolean: true, Name: "bool"} + TypeBytePtr = &TypeImpl{Size_: 8, Align: 8, Ptr: true, Name: "*byte"} ) -- cgit v1.3 From 73151067bc7b58c56825a4cc59282aef09aaaed8 Mon Sep 17 00:00:00 2001 From: David Chase Date: Wed, 26 Aug 2015 14:25:40 -0400 Subject: [dev.ssa] cmd/compile: added floating point to [u]int conversions Change-Id: I8dee400aef07165f911750de2615b8757f826000 Reviewed-on: https://go-review.googlesource.com/13945 Reviewed-by: Keith Randall --- src/cmd/compile/internal/gc/ssa.go | 140 ++++++++++++- src/cmd/compile/internal/gc/testdata/fp_ssa.go | 260 ++++++++++++++++++++++++- 2 files changed, 395 insertions(+), 5 deletions(-) (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 0194a52c2b..5614a6c3b9 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -1253,7 +1253,6 @@ func (s *state) expr(n *Node) *ssa.Value { return s.newValue1(op, n.Type, x) } - var op1, op2 ssa.Op if ft.IsInteger() && tt.IsFloat() { // signed 1, 2, 4, 8, unsigned 6, 7, 9, 13 signedSize := ft.Size() @@ -1261,6 +1260,7 @@ func (s *state) expr(n *Node) *ssa.Value { if !ft.IsSigned() { signedSize += 5 } + var op1, op2 ssa.Op switch signedSize { case 1: op1 = ssa.OpSignExt8to32 @@ -1315,6 +1315,72 @@ func (s *state) expr(n *Node) *ssa.Value { } return s.newValue1(op2, n.Type, s.newValue1(op1, Types[it], x)) } + + if tt.IsInteger() && ft.IsFloat() { + // signed 1, 2, 4, 8, unsigned 6, 7, 9, 13 + signedSize := tt.Size() + it := TINT32 // intermediate type in conversion, int32 or int64 + if !tt.IsSigned() { + signedSize += 5 + } + var op1, op2 ssa.Op + switch signedSize { + case 1: + op2 = ssa.OpTrunc32to8 + case 2: + op2 = ssa.OpTrunc32to16 + case 4: + op2 = ssa.OpCopy + case 8: + op2 = ssa.OpCopy + it = TINT64 + case 6: + op2 = ssa.OpTrunc32to8 + case 7: + op2 = ssa.OpTrunc32to16 + case 9: + // Go wide to dodge the unsignedness correction + op2 = ssa.OpTrunc64to32 + it = TINT64 + case 13: + // unsigned 64, branchy correction code is needed + // because there is only FP to signed-integer + // conversion in the (AMD64) instructions set. + // Branchy correction code *may* be amenable to + // optimization, and it can be cleanly expressed + // in generic SSA, so do it here. + if ft.Size() == 4 { + return s.float32ToUint64(n, x, ft, tt) + } + if ft.Size() == 8 { + return s.float64ToUint64(n, x, ft, tt) + } + // unrecognized size is also "weird", hence fatal. + fallthrough + + default: + s.Fatalf("weird float to integer conversion %s -> %s", ft, tt) + + } + if ft.Size() == 4 { + if it == TINT64 { + op1 = ssa.OpCvt32Fto64 + } else { + op1 = ssa.OpCvt32Fto32 + } + } else { + if it == TINT64 { + op1 = ssa.OpCvt64Fto64 + } else { + op1 = ssa.OpCvt64Fto32 + } + } + if op2 == ssa.OpCopy { + return s.newValue1(op1, n.Type, x) + } + return s.newValue1(op2, n.Type, s.newValue1(op1, Types[it], x)) + } + if ft.IsFloat() && tt.IsFloat() { var op ssa.Op if ft.Size() == tt.Size() { @@ -1328,7 +1394,7 @@ func (s *state) expr(n *Node) *ssa.Value { } return s.newValue1(op, n.Type, x) } - // TODO: Still lack float-to-int + // TODO: Still lack complex conversions. s.Unimplementedf("unhandled OCONV %s -> %s", Econv(int(n.Left.Type.Etype), 0), Econv(int(n.Type.Etype), 0)) return nil @@ -1981,8 +2047,8 @@ func (s *state) uintTofloat(cvttab *u2fcvtTab, n *Node, x *ssa.Value, ft, tt *Ty // z = uintX(x) ; z = z >> 1 // z = z >> 1 // z = z | y - // result = (floatY) z - // z = z + z + // result = floatY(z) + // result = result + result // } // // Code borrowed from old code generator. @@ -2068,6 +2134,72 @@ func (s *state) lenMap(n *Node, x *ssa.Value) *ssa.Value { return s.variable(n, lenType) } +type f2uCvtTab struct { + ltf, cvt2U, subf ssa.Op + value func(*state, ssa.Type, float64) *ssa.Value +} + +var f32_u64 f2uCvtTab = f2uCvtTab{ + ltf: ssa.OpLess32F, + cvt2U: ssa.OpCvt32Fto64, + subf: ssa.OpSub32F, + value: (*state).constFloat32, +} + +var f64_u64 f2uCvtTab = f2uCvtTab{ + ltf: ssa.OpLess64F, + cvt2U: ssa.OpCvt64Fto64, + subf: ssa.OpSub64F, + value: (*state).constFloat64, +} + +func (s *state) float32ToUint64(n *Node, x *ssa.Value, ft, tt *Type) *ssa.Value { + return s.floatToUint(&f32_u64, n, x, ft, tt) +} +func (s *state) float64ToUint64(n *Node, x *ssa.Value, ft, tt *Type) *ssa.Value { + return s.floatToUint(&f64_u64, n, x, ft, tt) +} + +func (s *state) floatToUint(cvttab *f2uCvtTab, n *Node, x *ssa.Value, ft, tt *Type) *ssa.Value { + // if x < 9223372036854775808.0 { + // result = uintY(x) + // } else { + // y = x - 9223372036854775808.0 + // z = uintY(y) + // result = z | -9223372036854775808 + // } + twoToThe63 := cvttab.value(s, ft, 9223372036854775808.0) + cmp := s.newValue2(cvttab.ltf, Types[TBOOL], x, twoToThe63) + b := s.endBlock() + b.Kind = ssa.BlockIf + b.Control = cmp + b.Likely = ssa.BranchLikely + + bThen := s.f.NewBlock(ssa.BlockPlain) + bElse := s.f.NewBlock(ssa.BlockPlain) + bAfter := s.f.NewBlock(ssa.BlockPlain) + + addEdge(b, bThen) + s.startBlock(bThen) + a0 := s.newValue1(cvttab.cvt2U, tt, x) + s.vars[n] = a0 + s.endBlock() + addEdge(bThen, bAfter) + + addEdge(b, bElse) + s.startBlock(bElse) + y := s.newValue2(cvttab.subf, ft, x, twoToThe63) + y = s.newValue1(cvttab.cvt2U, tt, y) + z := s.constInt64(tt, -9223372036854775808) + a1 := s.newValue2(ssa.OpOr64, tt, y, z) + s.vars[n] = a1 + s.endBlock() + addEdge(bElse, bAfter) + + s.startBlock(bAfter) + return s.variable(n, n.Type) +} + // checkgoto checks that a goto from from to to does not // jump into a block or jump over variable declarations. // It is a copy of checkgoto in the pre-SSA backend, diff --git a/src/cmd/compile/internal/gc/testdata/fp_ssa.go b/src/cmd/compile/internal/gc/testdata/fp_ssa.go index 5eb65035d4..c9eb23d371 100644 --- a/src/cmd/compile/internal/gc/testdata/fp_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/fp_ssa.go @@ -1052,6 +1052,222 @@ func gtbr32_ssa(x, y float32) float32 { return 42 } +func F32toU8_ssa(x float32) uint8 { + switch { + } + return uint8(x) +} + +func F32toI8_ssa(x float32) int8 { + switch { + } + return int8(x) +} + +func F32toU16_ssa(x float32) uint16 { + switch { + } + return uint16(x) +} + +func F32toI16_ssa(x float32) int16 { + switch { + } + return int16(x) +} + +func F32toU32_ssa(x float32) uint32 { + switch { + } + return uint32(x) +} + +func F32toI32_ssa(x float32) int32 { + switch { + } + return int32(x) +} + +func F32toU64_ssa(x float32) uint64 { + switch { + } + return uint64(x) +} + +func F32toI64_ssa(x float32) int64 { + switch { + } + return int64(x) +} + +func F64toU8_ssa(x float64) uint8 { + switch { + } + return uint8(x) +} + +func F64toI8_ssa(x float64) int8 { + switch { + } + return int8(x) +} + +func F64toU16_ssa(x float64) uint16 { + switch { + } + return uint16(x) +} + +func F64toI16_ssa(x float64) int16 { + switch { + } + return int16(x) +} + +func F64toU32_ssa(x float64) uint32 { + switch { + } + return uint32(x) +} + +func F64toI32_ssa(x float64) int32 { + switch { + } + return int32(x) +} + +func F64toU64_ssa(x float64) uint64 { + switch { + } + return uint64(x) +} + +func F64toI64_ssa(x float64) int64 { + switch { + } + return int64(x) +} + +func floatsToInts(x float64, expected int64) int { + y := float32(x) + fails := 0 + fails += expectInt64("F64toI8", int64(F64toI8_ssa(x)), expected) + fails += expectInt64("F64toI16", int64(F64toI16_ssa(x)), expected) + fails += expectInt64("F64toI32", int64(F64toI32_ssa(x)), expected) + fails += expectInt64("F64toI64", int64(F64toI64_ssa(x)), expected) + fails += expectInt64("F32toI8", int64(F32toI8_ssa(y)), expected) + fails += expectInt64("F32toI16", int64(F32toI16_ssa(y)), expected) + fails += expectInt64("F32toI32", int64(F32toI32_ssa(y)), expected) + fails += expectInt64("F32toI64", int64(F32toI64_ssa(y)), expected) + return fails +} + +func floatsToUints(x float64, expected uint64) int { + y := float32(x) + fails := 0 + fails += expectUint64("F64toU8", uint64(F64toU8_ssa(x)), expected) + fails += expectUint64("F64toU16", uint64(F64toU16_ssa(x)), expected) + fails += expectUint64("F64toU32", uint64(F64toU32_ssa(x)), expected) + fails += expectUint64("F64toU64", uint64(F64toU64_ssa(x)), expected) + fails += expectUint64("F32toU8", uint64(F32toU8_ssa(y)), expected) + fails += expectUint64("F32toU16", uint64(F32toU16_ssa(y)), expected) + fails += expectUint64("F32toU32", uint64(F32toU32_ssa(y)), expected) + fails += expectUint64("F32toU64", uint64(F32toU64_ssa(y)), expected) + return fails +} + +func floatingToIntegerConversionsTest() int { + fails := 0 + fails += floatsToInts(0.0, 0) + fails += floatsToInts(1.0, 1) + fails += floatsToInts(127.0, 127) + fails += floatsToInts(-1.0, -1) + fails += floatsToInts(-128.0, -128) + + fails += floatsToUints(0.0, 0) + fails += floatsToUints(1.0, 1) + fails += floatsToUints(255.0, 255) + + for j := uint(0); j < 24; j++ { + // Avoid hard cases in the construction + // of the test inputs. + v := int64(1<<62) | int64(1<<(62-j)) + w := uint64(v) + f := float32(v) + d := float64(v) + fails += expectUint64("2**62...", F32toU64_ssa(f), w) + fails += expectUint64("2**62...", F64toU64_ssa(d), w) + fails += expectInt64("2**62...", F32toI64_ssa(f), v) + fails += expectInt64("2**62...", F64toI64_ssa(d), v) + fails += expectInt64("2**62...", F32toI64_ssa(-f), -v) + fails += expectInt64("2**62...", F64toI64_ssa(-d), -v) + w += w + f += f + d += d + fails += expectUint64("2**63...", F32toU64_ssa(f), w) + fails += expectUint64("2**63...", F64toU64_ssa(d), w) + } + + for j := uint(0); j < 16; j++ { + // Avoid hard cases in the construction + // of the test inputs. + v := int32(1<<30) | int32(1<<(30-j)) + w := uint32(v) + f := float32(v) + d := float64(v) + fails += expectUint32("2**30...", F32toU32_ssa(f), w) + fails += expectUint32("2**30...", F64toU32_ssa(d), w) + fails += expectInt32("2**30...", F32toI32_ssa(f), v) + fails += expectInt32("2**30...", F64toI32_ssa(d), v) + fails += expectInt32("2**30...", F32toI32_ssa(-f), -v) + fails += expectInt32("2**30...", F64toI32_ssa(-d), -v) + w += w + f += f + d += d + fails += expectUint32("2**31...", F32toU32_ssa(f), w) + fails += expectUint32("2**31...", F64toU32_ssa(d), w) + } + + for j := uint(0); j < 15; j++ { + // Avoid hard cases in the construction + // of the test inputs. + v := int16(1<<14) | int16(1<<(14-j)) + w := uint16(v) + f := float32(v) + d := float64(v) + fails += expectUint16("2**14...", F32toU16_ssa(f), w) + fails += expectUint16("2**14...", F64toU16_ssa(d), w) + fails += expectInt16("2**14...", F32toI16_ssa(f), v) + fails += expectInt16("2**14...", F64toI16_ssa(d), v) + fails += expectInt16("2**14...", F32toI16_ssa(-f), -v) + fails += expectInt16("2**14...", F64toI16_ssa(-d), -v) + w += w + f += f + d += d + fails += expectUint16("2**15...", F32toU16_ssa(f), w) + fails += expectUint16("2**15...", F64toU16_ssa(d), w) + } + + fails += expectInt32("-2147483648", F32toI32_ssa(-2147483648), -2147483648) + + fails += expectInt32("-2147483648", F64toI32_ssa(-2147483648), -2147483648) + fails += expectInt32("-2147483647", F64toI32_ssa(-2147483647), -2147483647) + fails += expectUint32("4294967295", F64toU32_ssa(4294967295), 4294967295) + + fails += expectInt16("-32768", F64toI16_ssa(-32768), -32768) + fails += expectInt16("-32768", F32toI16_ssa(-32768), -32768) + + // NB more of a pain to do these for 32-bit because of lost bits in Float32 mantissa + fails += expectInt16("32767", F64toI16_ssa(32767), 32767) + fails += expectInt16("32767", F32toI16_ssa(32767), 32767) + fails += expectUint16("32767", F64toU16_ssa(32767), 32767) + fails += expectUint16("32767", F32toU16_ssa(32767), 32767) + fails += expectUint16("65535", F64toU16_ssa(65535), 65535) + fails += expectUint16("65535", F32toU16_ssa(65535), 65535) + + return fails +} + func fail64(s string, f func(a, b float64) float64, a, b, e float64) int { d := f(a, b) if d != e { @@ -1106,7 +1322,47 @@ func expect32(s string, x, expected float32) int { func expectUint64(s string, x, expected uint64) int { if x != expected { - fmt.Printf("Expected 0x%016x for %s, got 0x%016x\n", expected, s, x) + fmt.Printf("%s: Expected 0x%016x, got 0x%016x\n", s, expected, x) + return 1 + } + return 0 +} + +func expectInt64(s string, x, expected int64) int { + if x != expected { + fmt.Printf("%s: Expected 0x%016x, got 0x%016x\n", s, expected, x) + return 1 + } + return 0 +} + +func expectUint32(s string, x, expected uint32) int { + if x != expected { + fmt.Printf("U32 %s: Expected 0x%08x, got 0x%08x\n", s, expected, x) + return 1 + } + return 0 +} + +func expectInt32(s string, x, expected int32) int { + if x != expected { + fmt.Printf("I32 %s: Expected 0x%08x, got 0x%08x\n", s, expected, x) + return 1 + } + return 0 +} + +func expectUint16(s string, x, expected uint16) int { + if x != expected { + fmt.Printf("U16 %s: Expected 0x%04x, got 0x%04x\n", s, expected, x) + return 1 + } + return 0 +} + +func expectInt16(s string, x, expected int16) int { + if x != expected { + fmt.Printf("I16 %s: Expected 0x%04x, got 0x%04x\n", s, expected, x) return 1 } return 0 @@ -1266,6 +1522,8 @@ func main() { fails += expectUint64("gt", gt, 0x0000100011000000) } + fails += floatingToIntegerConversionsTest() + if fails > 0 { fmt.Printf("Saw %v failures\n", fails) panic("Failed.") -- cgit v1.3 From 707af252d9041a5a618e15d2f3683f7d57b4d34c Mon Sep 17 00:00:00 2001 From: Todd Neal Date: Fri, 28 Aug 2015 15:56:43 -0500 Subject: [dev.ssa] cmd/compile: implement len/cap(chan) Change-Id: I1453ba226376ccd4d79780fc0686876d6dde01ee Reviewed-on: https://go-review.googlesource.com/14027 Reviewed-by: Keith Randall --- src/cmd/compile/internal/gc/ssa.go | 34 +++++++---- src/cmd/compile/internal/gc/testdata/chan_ssa.go | 76 ++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 13 deletions(-) create mode 100644 src/cmd/compile/internal/gc/testdata/chan_ssa.go (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 5614a6c3b9..c92c82da1d 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -1528,15 +1528,8 @@ func (s *state) expr(n *Node) *ssa.Value { return s.newValue1(op, Types[TINT], s.expr(n.Left)) case n.Left.Type.IsString(): // string; not reachable for OCAP return s.newValue1(ssa.OpStringLen, Types[TINT], s.expr(n.Left)) - case n.Left.Type.IsMap(): - return s.lenMap(n, s.expr(n.Left)) - case n.Left.Type.IsChan(): - if n.Op == OCAP { - s.Unimplementedf("unhandled cap(chan)") - } else { - s.Unimplementedf("unhandled len(chan)") - } - return nil + case n.Left.Type.IsMap(), n.Left.Type.IsChan(): + return s.referenceTypeBuiltin(n, s.expr(n.Left)) default: // array return s.constInt(Types[TINT], n.Left.Type.Bound) } @@ -2098,11 +2091,18 @@ func (s *state) uintTofloat(cvttab *u2fcvtTab, n *Node, x *ssa.Value, ft, tt *Ty return s.variable(n, n.Type) } -func (s *state) lenMap(n *Node, x *ssa.Value) *ssa.Value { +// referenceTypeBuiltin generates code for the len/cap builtins for maps and channels. +func (s *state) referenceTypeBuiltin(n *Node, x *ssa.Value) *ssa.Value { + if !n.Left.Type.IsMap() && !n.Left.Type.IsChan() { + s.Fatalf("node must be a map or a channel") + } // if n == nil { // return 0 // } else { + // // len // return *((*int)n) + // // cap + // return *(((*int)n)+1) // } lenType := n.Type nilValue := s.newValue0(ssa.OpConstNil, Types[TUINTPTR]) @@ -2116,17 +2116,25 @@ func (s *state) lenMap(n *Node, x *ssa.Value) *ssa.Value { bElse := s.f.NewBlock(ssa.BlockPlain) bAfter := s.f.NewBlock(ssa.BlockPlain) - // length of a nil map is zero + // length/capacity of a nil map/chan is zero addEdge(b, bThen) s.startBlock(bThen) s.vars[n] = s.zeroVal(lenType) s.endBlock() addEdge(bThen, bAfter) - // the length is stored in the first word addEdge(b, bElse) s.startBlock(bElse) - s.vars[n] = s.newValue2(ssa.OpLoad, lenType, x, s.mem()) + if n.Op == OLEN { + // length is stored in the first word for map/chan + s.vars[n] = s.newValue2(ssa.OpLoad, lenType, x, s.mem()) + } else if n.Op == OCAP { + // capacity is stored in the second word for chan + sw := s.newValue1I(ssa.OpOffPtr, lenType.PtrTo(), lenType.Width, x) + s.vars[n] = s.newValue2(ssa.OpLoad, lenType, sw, s.mem()) + } else { + s.Fatalf("op must be OLEN or OCAP") + } s.endBlock() addEdge(bElse, bAfter) diff --git a/src/cmd/compile/internal/gc/testdata/chan_ssa.go b/src/cmd/compile/internal/gc/testdata/chan_ssa.go new file mode 100644 index 0000000000..c527ba95be --- /dev/null +++ b/src/cmd/compile/internal/gc/testdata/chan_ssa.go @@ -0,0 +1,76 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// chan_ssa.go tests chan operations. +package main + +import "fmt" + +var failed = false + +func lenChan_ssa(v chan int) int { + switch { // prevent inlining + + } + return len(v) +} +func capChan_ssa(v chan int) int { + switch { // prevent inlining + + } + return cap(v) +} + +func testLenChan() { + + v := make(chan int, 10) + v <- 1 + v <- 1 + v <- 1 + + if want, got := 3, lenChan_ssa(v); got != want { + fmt.Printf("expected len(chan) = %d, got %d", want, got) + failed = true + } +} + +func testLenNilChan() { + + var v chan int + if want, got := 0, lenChan_ssa(v); got != want { + fmt.Printf("expected len(nil) = %d, got %d", want, got) + failed = true + } +} + +func testCapChan() { + + v := make(chan int, 25) + + if want, got := 25, capChan_ssa(v); got != want { + fmt.Printf("expected cap(chan) = %d, got %d", want, got) + failed = true + } +} + +func testCapNilChan() { + + var v chan int + if want, got := 0, capChan_ssa(v); got != want { + fmt.Printf("expected cap(nil) = %d, got %d", want, got) + failed = true + } +} + +func main() { + testLenChan() + testLenNilChan() + + testCapChan() + testCapNilChan() + + if failed { + panic("failed") + } +} -- cgit v1.3 From 67e43c1e3b3e2470b870a9d5b5e6eedceeded5f1 Mon Sep 17 00:00:00 2001 From: Todd Neal Date: Fri, 28 Aug 2015 21:19:40 -0500 Subject: [dev.ssa] cmd/compile: implement OFALL Frontend has already rewriten fallthrough statements, we just need to ignore them. Change-Id: Iadf89b06a9f8f9e6e2e1e87c934f31add77a19a1 Reviewed-on: https://go-review.googlesource.com/14029 Reviewed-by: Josh Bleecher Snyder --- src/cmd/compile/internal/gc/ssa.go | 2 +- src/cmd/compile/internal/gc/testdata/ctl_ssa.go | 60 +++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index c92c82da1d..08a3ac2635 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -430,7 +430,7 @@ func (s *state) stmt(n *Node) { s.stmtList(n.List) // No-ops - case OEMPTY, ODCLCONST, ODCLTYPE: + case OEMPTY, ODCLCONST, ODCLTYPE, OFALL: // Expression statements case OCALLFUNC, OCALLMETH, OCALLINTER: diff --git a/src/cmd/compile/internal/gc/testdata/ctl_ssa.go b/src/cmd/compile/internal/gc/testdata/ctl_ssa.go index f7c3b80799..49050110e5 100644 --- a/src/cmd/compile/internal/gc/testdata/ctl_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/ctl_ssa.go @@ -57,11 +57,71 @@ func testEmptyRange() { } } +func switch_ssa(a int) int { + ret := 0 + switch a { + case 5: + ret += 5 + case 4: + ret += 4 + case 3: + ret += 3 + case 2: + ret += 2 + case 1: + ret += 1 + } + return ret + +} + +func fallthrough_ssa(a int) int { + ret := 0 + switch a { + case 5: + ret++ + fallthrough + case 4: + ret++ + fallthrough + case 3: + ret++ + fallthrough + case 2: + ret++ + fallthrough + case 1: + ret++ + } + return ret + +} + +func testFallthrough() { + for i := 0; i < 6; i++ { + if got := fallthrough_ssa(i); got != i { + println("fallthrough_ssa(i) =", got, "wanted", i) + } + } +} + +func testSwitch() { + for i := 0; i < 6; i++ { + if got := switch_ssa(i); got != i { + println("switch_ssa(i) =", got, "wanted", i) + } + } +} + var failed = false func main() { testPhiControl() testEmptyRange() + + testSwitch() + testFallthrough() + if failed { panic("failed") } -- cgit v1.3 From 451eca2293d7c84f5892b27462f3bab7840b11ce Mon Sep 17 00:00:00 2001 From: Todd Neal Date: Sun, 30 Aug 2015 21:21:44 -0500 Subject: [dev.ssa] cmd/compile: make test panic on failure Change-Id: Ia5483d23fe0b5dd0b6cfe2099e9b475184742716 Reviewed-on: https://go-review.googlesource.com/14074 Reviewed-by: Josh Bleecher Snyder --- src/cmd/compile/internal/gc/testdata/ctl_ssa.go | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/testdata/ctl_ssa.go b/src/cmd/compile/internal/gc/testdata/ctl_ssa.go index 49050110e5..cc55134b96 100644 --- a/src/cmd/compile/internal/gc/testdata/ctl_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/ctl_ssa.go @@ -101,6 +101,7 @@ func testFallthrough() { for i := 0; i < 6; i++ { if got := fallthrough_ssa(i); got != i { println("fallthrough_ssa(i) =", got, "wanted", i) + failed = true } } } @@ -109,6 +110,7 @@ func testSwitch() { for i := 0; i < 6; i++ { if got := switch_ssa(i); got != i { println("switch_ssa(i) =", got, "wanted", i) + failed = true } } } -- cgit v1.3 From 3a9d0ac3c807de9c6b91a91fa1e37f75da1941a8 Mon Sep 17 00:00:00 2001 From: David Chase Date: Fri, 28 Aug 2015 14:24:10 -0400 Subject: [dev.ssa] cmd/compile: add complex arithmetic Still to do: details, more testing corner cases. (e.g. negative zero) Includes small cleanups for previous CL. Note: complex division is currently done in the runtime, so the division code here is apparently not yet necessary and also not tested. Seems likely better to open code division and expose the widening/narrowing to optimization. Complex64 multiplication and division is done in wide format to avoid cancellation errors; for division, this also happens to be compatible with pre-SSA practice (which uses a single complex128 division function). It would-be-nice to widen for complex128 multiplication intermediates as well, but that is trickier to implement without a handy wider-precision format. Change-Id: I595a4300f68868fb7641852a54674c6b2b78855e Reviewed-on: https://go-review.googlesource.com/14028 Reviewed-by: Keith Randall --- src/cmd/compile/internal/gc/ssa.go | 153 ++++++++++++++++++++++--- src/cmd/compile/internal/gc/testdata/fp_ssa.go | 102 ++++++++++++++++- src/cmd/compile/internal/ssa/decompose.go | 9 +- src/cmd/compile/internal/ssa/gen/AMD64.rules | 2 + src/cmd/compile/internal/ssa/gen/AMD64Ops.go | 2 + src/cmd/compile/internal/ssa/gen/genericOps.go | 7 +- src/cmd/compile/internal/ssa/gen/rulegen.go | 3 + src/cmd/compile/internal/ssa/opGen.go | 24 ++++ src/cmd/compile/internal/ssa/rewriteAMD64.go | 43 +++++++ src/cmd/compile/internal/ssa/rewritegeneric.go | 3 + 10 files changed, 325 insertions(+), 23 deletions(-) (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index c0bff2a5f0..17288c3156 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -747,14 +747,16 @@ var opToSSA = map[opAndType]ssa.Op{ opAndType{ONOT, TBOOL}: ssa.OpNot, - opAndType{OMINUS, TINT8}: ssa.OpNeg8, - opAndType{OMINUS, TUINT8}: ssa.OpNeg8, - opAndType{OMINUS, TINT16}: ssa.OpNeg16, - opAndType{OMINUS, TUINT16}: ssa.OpNeg16, - opAndType{OMINUS, TINT32}: ssa.OpNeg32, - opAndType{OMINUS, TUINT32}: ssa.OpNeg32, - opAndType{OMINUS, TINT64}: ssa.OpNeg64, - opAndType{OMINUS, TUINT64}: ssa.OpNeg64, + opAndType{OMINUS, TINT8}: ssa.OpNeg8, + opAndType{OMINUS, TUINT8}: ssa.OpNeg8, + opAndType{OMINUS, TINT16}: ssa.OpNeg16, + opAndType{OMINUS, TUINT16}: ssa.OpNeg16, + opAndType{OMINUS, TINT32}: ssa.OpNeg32, + opAndType{OMINUS, TUINT32}: ssa.OpNeg32, + opAndType{OMINUS, TINT64}: ssa.OpNeg64, + opAndType{OMINUS, TUINT64}: ssa.OpNeg64, + opAndType{OMINUS, TFLOAT32}: ssa.OpNeg32F, + opAndType{OMINUS, TFLOAT64}: ssa.OpNeg64F, opAndType{OCOM, TINT8}: ssa.OpCom8, opAndType{OCOM, TUINT8}: ssa.OpCom8, @@ -953,6 +955,14 @@ func (s *state) ssaOp(op uint8, t *Type) ssa.Op { return x } +func floatForComplex(t *Type) *Type { + if t.Size() == 8 { + return Types[TFLOAT32] + } else { + return Types[TFLOAT64] + } +} + type opAndTwoTypes struct { op uint8 etype1 uint8 @@ -1394,7 +1404,24 @@ func (s *state) expr(n *Node) *ssa.Value { } return s.newValue1(op, n.Type, x) } - // TODO: Still lack complex conversions. + + if ft.IsComplex() && tt.IsComplex() { + var op ssa.Op + if ft.Size() == tt.Size() { + op = ssa.OpCopy + } else if ft.Size() == 8 && tt.Size() == 16 { + op = ssa.OpCvt32Fto64F + } else if ft.Size() == 16 && tt.Size() == 8 { + op = ssa.OpCvt64Fto32F + } else { + s.Fatalf("weird complex conversion %s -> %s", ft, tt) + } + ftp := floatForComplex(ft) + ttp := floatForComplex(tt) + return s.newValue2(ssa.OpComplexMake, tt, + s.newValue1(op, ttp, s.newValue1(ssa.OpComplexReal, ftp, x)), + s.newValue1(op, ttp, s.newValue1(ssa.OpComplexImag, ftp, x))) + } s.Unimplementedf("unhandled OCONV %s -> %s", Econv(int(n.Left.Type.Etype), 0), Econv(int(n.Type.Etype), 0)) return nil @@ -1404,7 +1431,97 @@ func (s *state) expr(n *Node) *ssa.Value { a := s.expr(n.Left) b := s.expr(n.Right) return s.newValue2(s.ssaOp(n.Op, n.Left.Type), Types[TBOOL], a, b) - case OADD, OAND, OMUL, OOR, OSUB, ODIV, OMOD, OHMUL, OXOR: + case OMUL: + a := s.expr(n.Left) + b := s.expr(n.Right) + if n.Type.IsComplex() { + mulop := ssa.OpMul64F + addop := ssa.OpAdd64F + subop := ssa.OpSub64F + pt := floatForComplex(n.Type) // Could be Float32 or Float64 + wt := Types[TFLOAT64] // Compute in Float64 to minimize cancellation error + + areal := s.newValue1(ssa.OpComplexReal, pt, a) + breal := s.newValue1(ssa.OpComplexReal, pt, b) + aimag := s.newValue1(ssa.OpComplexImag, pt, a) + bimag := s.newValue1(ssa.OpComplexImag, pt, b) + + if pt != wt { // Widen for calculation + areal = s.newValue1(ssa.OpCvt32Fto64F, wt, areal) + breal = s.newValue1(ssa.OpCvt32Fto64F, wt, breal) + aimag = s.newValue1(ssa.OpCvt32Fto64F, wt, aimag) + bimag = s.newValue1(ssa.OpCvt32Fto64F, wt, bimag) + } + + xreal := s.newValue2(subop, wt, s.newValue2(mulop, wt, areal, breal), s.newValue2(mulop, wt, aimag, bimag)) + ximag := s.newValue2(addop, wt, s.newValue2(mulop, wt, areal, bimag), s.newValue2(mulop, wt, aimag, breal)) + + if pt != wt { // Narrow to store back + xreal = s.newValue1(ssa.OpCvt64Fto32F, pt, xreal) + ximag = s.newValue1(ssa.OpCvt64Fto32F, pt, ximag) + } + + return s.newValue2(ssa.OpComplexMake, n.Type, xreal, ximag) + } + return s.newValue2(s.ssaOp(n.Op, n.Type), a.Type, a, b) + + case ODIV: + a := s.expr(n.Left) + b := s.expr(n.Right) + if n.Type.IsComplex() { + // TODO this is not executed because the front-end substitutes a runtime call. + // That probably ought to change; with modest optimization the widen/narrow + // conversions could all be elided in larger expression trees. + mulop := ssa.OpMul64F + addop := ssa.OpAdd64F + subop := ssa.OpSub64F + divop := ssa.OpDiv64F + pt := floatForComplex(n.Type) // Could be Float32 or Float64 + wt := Types[TFLOAT64] // Compute in Float64 to minimize cancellation error + + areal := s.newValue1(ssa.OpComplexReal, pt, a) + breal := s.newValue1(ssa.OpComplexReal, pt, b) + aimag := s.newValue1(ssa.OpComplexImag, pt, a) + bimag := s.newValue1(ssa.OpComplexImag, pt, b) + + if pt != wt { // Widen for calculation + areal = s.newValue1(ssa.OpCvt32Fto64F, wt, areal) + breal = s.newValue1(ssa.OpCvt32Fto64F, wt, breal) + aimag = s.newValue1(ssa.OpCvt32Fto64F, wt, aimag) + bimag = s.newValue1(ssa.OpCvt32Fto64F, wt, bimag) + } + + denom := s.newValue2(addop, wt, s.newValue2(mulop, wt, breal, breal), s.newValue2(mulop, wt, bimag, bimag)) + xreal := s.newValue2(addop, wt, s.newValue2(mulop, wt, areal, breal), s.newValue2(mulop, wt, aimag, bimag)) + ximag := s.newValue2(subop, wt, s.newValue2(mulop, wt, aimag, breal), s.newValue2(mulop, wt, areal, bimag)) + + // TODO not sure if this is best done in wide precision or narrow + // Double-rounding might be an issue. + // Note that the pre-SSA implementation does the entire calculation + // in wide format, so wide is compatible. + xreal = s.newValue2(divop, wt, xreal, denom) + ximag = s.newValue2(divop, wt, ximag, denom) + + if pt != wt { // Narrow to store back + xreal = s.newValue1(ssa.OpCvt64Fto32F, pt, xreal) + ximag = s.newValue1(ssa.OpCvt64Fto32F, pt, ximag) + } + + return s.newValue2(ssa.OpComplexMake, n.Type, xreal, ximag) + } + return s.newValue2(s.ssaOp(n.Op, n.Type), a.Type, a, b) + case OADD, OSUB: + a := s.expr(n.Left) + b := s.expr(n.Right) + if n.Type.IsComplex() { + pt := floatForComplex(n.Type) + op := s.ssaOp(n.Op, pt) + return s.newValue2(ssa.OpComplexMake, n.Type, + s.newValue2(op, pt, s.newValue1(ssa.OpComplexReal, pt, a), s.newValue1(ssa.OpComplexReal, pt, b)), + s.newValue2(op, pt, s.newValue1(ssa.OpComplexImag, pt, a), s.newValue1(ssa.OpComplexImag, pt, b))) + } + return s.newValue2(s.ssaOp(n.Op, n.Type), a.Type, a, b) + case OAND, OOR, OMOD, OHMUL, OXOR: a := s.expr(n.Left) b := s.expr(n.Right) return s.newValue2(s.ssaOp(n.Op, n.Type), a.Type, a, b) @@ -1464,8 +1581,18 @@ func (s *state) expr(n *Node) *ssa.Value { s.startBlock(bResult) return s.variable(n, Types[TBOOL]) - // unary ops - case ONOT, OMINUS, OCOM: + // unary ops + case OMINUS: + a := s.expr(n.Left) + if n.Type.IsComplex() { + tp := floatForComplex(n.Type) + negop := s.ssaOp(n.Op, tp) + return s.newValue2(ssa.OpComplexMake, n.Type, + s.newValue1(negop, tp, s.newValue1(ssa.OpComplexReal, tp, a)), + s.newValue1(negop, tp, s.newValue1(ssa.OpComplexImag, tp, a))) + } + return s.newValue1(s.ssaOp(n.Op, n.Type), a.Type, a) + case ONOT, OCOM: a := s.expr(n.Left) return s.newValue1(s.ssaOp(n.Op, n.Type), a.Type, a) @@ -2551,7 +2678,7 @@ func genValue(v *ssa.Value) { ssa.OpAMD64ORQ, ssa.OpAMD64ORL, ssa.OpAMD64ORW, ssa.OpAMD64ORB, ssa.OpAMD64XORQ, ssa.OpAMD64XORL, ssa.OpAMD64XORW, ssa.OpAMD64XORB, ssa.OpAMD64MULQ, ssa.OpAMD64MULL, ssa.OpAMD64MULW, ssa.OpAMD64MULB, - ssa.OpAMD64MULSS, ssa.OpAMD64MULSD: + ssa.OpAMD64MULSS, ssa.OpAMD64MULSD, ssa.OpAMD64PXOR: r := regnum(v) x := regnum(v.Args[0]) y := regnum(v.Args[1]) diff --git a/src/cmd/compile/internal/gc/testdata/fp_ssa.go b/src/cmd/compile/internal/gc/testdata/fp_ssa.go index c9eb23d371..2cbf00bab0 100644 --- a/src/cmd/compile/internal/gc/testdata/fp_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/fp_ssa.go @@ -1306,7 +1306,7 @@ func fail32bool(s string, f func(a, b float32) bool, a, b float32, e bool) int { func expect64(s string, x, expected float64) int { if x != expected { - println("Expected", expected, "for", s, ", got", x) + println("F64 Expected", expected, "for", s, ", got", x) return 1 } return 0 @@ -1314,7 +1314,7 @@ func expect64(s string, x, expected float64) int { func expect32(s string, x, expected float32) int { if x != expected { - println("Expected", expected, "for", s, ", got", x) + println("F32 Expected", expected, "for", s, ", got", x) return 1 } return 0 @@ -1322,7 +1322,7 @@ func expect32(s string, x, expected float32) int { func expectUint64(s string, x, expected uint64) int { if x != expected { - fmt.Printf("%s: Expected 0x%016x, got 0x%016x\n", s, expected, x) + fmt.Printf("U64 Expected 0x%016x for %s, got 0x%016x\n", expected, s, x) return 1 } return 0 @@ -1435,6 +1435,100 @@ func cmpOpTest(s string, return fails } +func expectCx128(s string, x, expected complex128) int { + if x != expected { + println("Cx 128 Expected", expected, "for", s, ", got", x) + return 1 + } + return 0 +} + +func expectCx64(s string, x, expected complex64) int { + if x != expected { + println("Cx 64 Expected", expected, "for", s, ", got", x) + return 1 + } + return 0 +} + +func cx128sum_ssa(a, b complex128) complex128 { + return a + b +} + +func cx128diff_ssa(a, b complex128) complex128 { + return a - b +} + +func cx128prod_ssa(a, b complex128) complex128 { + return a * b +} + +func cx128quot_ssa(a, b complex128) complex128 { + return a / b +} + +func cx128neg_ssa(a complex128) complex128 { + return -a +} + +func cx64sum_ssa(a, b complex64) complex64 { + return a + b +} + +func cx64diff_ssa(a, b complex64) complex64 { + return a - b +} + +func cx64prod_ssa(a, b complex64) complex64 { + return a * b +} + +func cx64quot_ssa(a, b complex64) complex64 { + return a / b +} + +func cx64neg_ssa(a complex64) complex64 { + return -a +} + +func complexTest128() int { + fails := 0 + var a complex128 = 1 + 2i + var b complex128 = 3 + 6i + sum := cx128sum_ssa(b, a) + diff := cx128diff_ssa(b, a) + prod := cx128prod_ssa(b, a) + quot := cx128quot_ssa(b, a) + neg := cx128neg_ssa(a) + + fails += expectCx128("sum", sum, 4+8i) + fails += expectCx128("diff", diff, 2+4i) + fails += expectCx128("prod", prod, -9+12i) + fails += expectCx128("quot", quot, 3+0i) + fails += expectCx128("neg", neg, -1-2i) + + return fails +} + +func complexTest64() int { + fails := 0 + var a complex64 = 1 + 2i + var b complex64 = 3 + 6i + sum := cx64sum_ssa(b, a) + diff := cx64diff_ssa(b, a) + prod := cx64prod_ssa(b, a) + quot := cx64quot_ssa(b, a) + neg := cx64neg_ssa(a) + + fails += expectCx64("sum", sum, 4+8i) + fails += expectCx64("diff", diff, 2+4i) + fails += expectCx64("prod", prod, -9+12i) + fails += expectCx64("quot", quot, 3+0i) + fails += expectCx64("neg", neg, -1-2i) + + return fails +} + func main() { a := 3.0 @@ -1523,6 +1617,8 @@ func main() { } fails += floatingToIntegerConversionsTest() + fails += complexTest128() + fails += complexTest64() if fails > 0 { fmt.Printf("Saw %v failures\n", fails) diff --git a/src/cmd/compile/internal/ssa/decompose.go b/src/cmd/compile/internal/ssa/decompose.go index a2dfdc16ab..3ef20ef34f 100644 --- a/src/cmd/compile/internal/ssa/decompose.go +++ b/src/cmd/compile/internal/ssa/decompose.go @@ -77,12 +77,13 @@ func decomposeSlicePhi(v *Value) { func decomposeComplexPhi(v *Value) { fe := v.Block.Func.Config.fe var partType Type - if v.Type.Size() == 8 { + switch z := v.Type.Size(); z { + case 8: partType = fe.TypeFloat32() - } else if v.Type.Size() == 16 { + case 16: partType = fe.TypeFloat64() - } else { - panic("Whoops, are sizes in bytes or bits?") + default: + v.Fatalf("decomposeComplexPhi: bad complex size %d", z) } real := v.Block.NewValue0(v.Line, OpPhi, partType) diff --git a/src/cmd/compile/internal/ssa/gen/AMD64.rules b/src/cmd/compile/internal/ssa/gen/AMD64.rules index 46fb76f1dd..28ae88ff24 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64.rules +++ b/src/cmd/compile/internal/ssa/gen/AMD64.rules @@ -81,6 +81,8 @@ (Neg32 x) -> (NEGL x) (Neg16 x) -> (NEGW x) (Neg8 x) -> (NEGB x) +(Neg32F x) -> (PXOR x (MOVSSconst {math.Copysign(0, -1)})) +(Neg64F x) -> (PXOR x (MOVSDconst {math.Copysign(0, -1)})) (Com64 x) -> (NOTQ x) (Com32 x) -> (NOTL x) diff --git a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go index f2c402a348..555a5149a7 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go @@ -354,6 +354,8 @@ func init() { {name: "CVTSD2SS", reg: fp11, asm: "CVTSD2SS"}, // convert float64 to float32 {name: "CVTSS2SD", reg: fp11, asm: "CVTSS2SD"}, // convert float32 to float64 + {name: "PXOR", reg: fp21, asm: "PXOR"}, // exclusive or, applied to X regs for float negation. + {name: "LEAQ", reg: gp11sb}, // arg0 + auxint + offset encoded in aux {name: "LEAQ1", reg: gp21sb}, // arg0 + arg1 + auxint {name: "LEAQ2", reg: gp21sb}, // arg0 + 2*arg1 + auxint diff --git a/src/cmd/compile/internal/ssa/gen/genericOps.go b/src/cmd/compile/internal/ssa/gen/genericOps.go index 8f6a858e43..d17f207a80 100644 --- a/src/cmd/compile/internal/ssa/gen/genericOps.go +++ b/src/cmd/compile/internal/ssa/gen/genericOps.go @@ -24,7 +24,6 @@ var genericOps = []opData{ {name: "SubPtr"}, {name: "Sub32F"}, {name: "Sub64F"}, - // TODO: Sub64C, Sub128C {name: "Mul8"}, // arg0 * arg1 {name: "Mul16"}, @@ -225,6 +224,8 @@ var genericOps = []opData{ {name: "Neg16"}, {name: "Neg32"}, {name: "Neg64"}, + {name: "Neg32F"}, + {name: "Neg64F"}, {name: "Com8"}, // ^arg0 {name: "Com16"}, @@ -336,8 +337,8 @@ var genericOps = []opData{ // Complex (part/whole) {name: "ComplexMake"}, // arg0=real, arg1=imag - {name: "ComplexReal"}, // real_part(arg0) - {name: "ComplexImag"}, // imaginary_part(arg0) + {name: "ComplexReal"}, // real(arg0) + {name: "ComplexImag"}, // imag(arg0) // Strings {name: "StringMake"}, // arg0=ptr, arg1=len diff --git a/src/cmd/compile/internal/ssa/gen/rulegen.go b/src/cmd/compile/internal/ssa/gen/rulegen.go index d98ad2587f..5dcbf1ee1c 100644 --- a/src/cmd/compile/internal/ssa/gen/rulegen.go +++ b/src/cmd/compile/internal/ssa/gen/rulegen.go @@ -142,6 +142,9 @@ func genRules(arch arch) { if *genLog { fmt.Fprintln(w, "import \"fmt\"") } + fmt.Fprintln(w, "import \"math\"") + fmt.Fprintln(w, "var _ = math.MinInt8 // in case not otherwise used") + fmt.Fprintf(w, "func rewriteValue%s(v *Value, config *Config) bool {\n", arch.name) fmt.Fprintln(w, "b := v.Block") diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index 51a998e352..a41b04b29f 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -237,6 +237,7 @@ const ( OpAMD64CVTSQ2SD OpAMD64CVTSD2SS OpAMD64CVTSS2SD + OpAMD64PXOR OpAMD64LEAQ OpAMD64LEAQ1 OpAMD64LEAQ2 @@ -435,6 +436,8 @@ const ( OpNeg16 OpNeg32 OpNeg64 + OpNeg32F + OpNeg64F OpCom8 OpCom16 OpCom32 @@ -2794,6 +2797,19 @@ var opcodeTable = [...]opInfo{ }, }, }, + { + name: "PXOR", + asm: x86.APXOR, + reg: regInfo{ + inputs: []inputInfo{ + {0, 4294901760}, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + {1, 4294901760}, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + }, + outputs: []regMask{ + 4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + }, + }, + }, { name: "LEAQ", reg: regInfo{ @@ -3743,6 +3759,14 @@ var opcodeTable = [...]opInfo{ name: "Neg64", generic: true, }, + { + name: "Neg32F", + generic: true, + }, + { + name: "Neg64F", + generic: true, + }, { name: "Com8", generic: true, diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go index e089028258..67ec747e20 100644 --- a/src/cmd/compile/internal/ssa/rewriteAMD64.go +++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go @@ -2,6 +2,9 @@ // generated with: cd gen; go run *.go package ssa +import "math" + +var _ = math.MinInt8 // in case not otherwise used func rewriteValueAMD64(v *Value, config *Config) bool { b := v.Block switch v.Op { @@ -6059,6 +6062,26 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto endce1f7e17fc193f6c076e47d5e401e126 endce1f7e17fc193f6c076e47d5e401e126: ; + case OpNeg32F: + // match: (Neg32F x) + // cond: + // result: (PXOR x (MOVSSconst {math.Copysign(0, -1)})) + { + x := v.Args[0] + v.Op = OpAMD64PXOR + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpAMD64MOVSSconst, TypeInvalid) + v0.Type = config.Frontend().TypeFloat32() + v0.Aux = math.Copysign(0, -1) + v.AddArg(v0) + return true + } + goto end47074133a76e069317ceca46372cafc3 + end47074133a76e069317ceca46372cafc3: + ; case OpNeg64: // match: (Neg64 x) // cond: @@ -6075,6 +6098,26 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto enda06c5b1718f2b96aba10bf5a5c437c6c enda06c5b1718f2b96aba10bf5a5c437c6c: ; + case OpNeg64F: + // match: (Neg64F x) + // cond: + // result: (PXOR x (MOVSDconst {math.Copysign(0, -1)})) + { + x := v.Args[0] + v.Op = OpAMD64PXOR + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpAMD64MOVSDconst, TypeInvalid) + v0.Type = config.Frontend().TypeFloat64() + v0.Aux = math.Copysign(0, -1) + v.AddArg(v0) + return true + } + goto end9240202f5753ebd23f11f982ece3e06e + end9240202f5753ebd23f11f982ece3e06e: + ; case OpNeg8: // match: (Neg8 x) // cond: diff --git a/src/cmd/compile/internal/ssa/rewritegeneric.go b/src/cmd/compile/internal/ssa/rewritegeneric.go index 09f03f985f..ca771d75ae 100644 --- a/src/cmd/compile/internal/ssa/rewritegeneric.go +++ b/src/cmd/compile/internal/ssa/rewritegeneric.go @@ -2,6 +2,9 @@ // generated with: cd gen; go run *.go package ssa +import "math" + +var _ = math.MinInt8 // in case not otherwise used func rewriteValuegeneric(v *Value, config *Config) bool { b := v.Block switch v.Op { -- cgit v1.3 From 6411533ebf98d898a888b0195e8c4d4039864896 Mon Sep 17 00:00:00 2001 From: Todd Neal Date: Sat, 29 Aug 2015 15:41:57 -0500 Subject: [dev.ssa] cmd/compile: fix rare issue caused by liblink rewrite liblink rewrites MOV $0, reg into XOR reg, reg. Make MOVxconst clobber flags so we don't generate invalid code in the unlikely case that it matters. In testing, this change leads to no additional regenerated flags due to a scheduling fix in CL14042. Change-Id: I7bc1cfee94ef83beb2f97c31ec6a97e19872fb89 Reviewed-on: https://go-review.googlesource.com/14043 Reviewed-by: Keith Randall --- src/cmd/compile/internal/gc/testdata/ctl_ssa.go | 31 +++++++++++++++++++++++++ src/cmd/compile/internal/ssa/gen/AMD64Ops.go | 11 +++++---- src/cmd/compile/internal/ssa/opGen.go | 4 ++++ 3 files changed, 42 insertions(+), 4 deletions(-) (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/testdata/ctl_ssa.go b/src/cmd/compile/internal/gc/testdata/ctl_ssa.go index cc55134b96..09880ef94f 100644 --- a/src/cmd/compile/internal/gc/testdata/ctl_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/ctl_ssa.go @@ -115,6 +115,35 @@ func testSwitch() { } } +type junk struct { + step int +} + +// flagOverwrite_ssa is intended to reproduce an issue seen where a XOR +// was scheduled between a compare and branch, clearing flags. +func flagOverwrite_ssa(s *junk, c int) int { + switch { + } + if '0' <= c && c <= '9' { + s.step = 0 + return 1 + } + if c == 'e' || c == 'E' { + s.step = 0 + return 2 + } + s.step = 0 + return 3 +} + +func testFlagOverwrite() { + j := junk{} + if got := flagOverwrite_ssa(&j, ' '); got != 3 { + println("flagOverwrite_ssa =", got, "wanted 3") + failed = true + } +} + var failed = false func main() { @@ -124,6 +153,8 @@ func main() { testSwitch() testFallthrough() + testFlagOverwrite() + if failed { panic("failed") } diff --git a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go index 555a5149a7..09ffd4526f 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go @@ -93,6 +93,7 @@ func init() { // Common regInfo var ( gp01 = regInfo{inputs: []regMask{}, outputs: gponly} + gp01flags = regInfo{inputs: []regMask{}, outputs: gponly, clobbers: flags} gp11 = regInfo{inputs: []regMask{gpsp}, outputs: gponly, clobbers: flags} gp11nf = regInfo{inputs: []regMask{gpsp}, outputs: gponly} // nf: no flags clobbered gp11sb = regInfo{inputs: []regMask{gpspsb}, outputs: gponly} @@ -338,10 +339,12 @@ func init() { {name: "MOVLQSX", reg: gp11nf, asm: "MOVLQSX"}, // sign extend arg0 from int32 to int64 {name: "MOVLQZX", reg: gp11nf, asm: "MOVLQZX"}, // zero extend arg0 from int32 to int64 - {name: "MOVBconst", reg: gp01, asm: "MOVB"}, // 8 low bits of auxint - {name: "MOVWconst", reg: gp01, asm: "MOVW"}, // 16 low bits of auxint - {name: "MOVLconst", reg: gp01, asm: "MOVL"}, // 32 low bits of auxint - {name: "MOVQconst", reg: gp01, asm: "MOVQ"}, // auxint + // clobbers flags as liblink will rewrite these to XOR reg, reg if the constant is zero + // TODO: revisit when issue 12405 is fixed + {name: "MOVBconst", reg: gp01flags, asm: "MOVB"}, // 8 low bits of auxint + {name: "MOVWconst", reg: gp01flags, asm: "MOVW"}, // 16 low bits of auxint + {name: "MOVLconst", reg: gp01flags, asm: "MOVL"}, // 32 low bits of auxint + {name: "MOVQconst", reg: gp01flags, asm: "MOVQ"}, // auxint {name: "CVTSD2SL", reg: fpgp, asm: "CVTSD2SL"}, // convert float64 to int32 {name: "CVTSD2SQ", reg: fpgp, asm: "CVTSD2SQ"}, // convert float64 to int64 diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index a41b04b29f..8263268019 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -2645,6 +2645,7 @@ var opcodeTable = [...]opInfo{ name: "MOVBconst", asm: x86.AMOVB, reg: regInfo{ + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -2654,6 +2655,7 @@ var opcodeTable = [...]opInfo{ name: "MOVWconst", asm: x86.AMOVW, reg: regInfo{ + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -2663,6 +2665,7 @@ var opcodeTable = [...]opInfo{ name: "MOVLconst", asm: x86.AMOVL, reg: regInfo{ + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, @@ -2672,6 +2675,7 @@ var opcodeTable = [...]opInfo{ name: "MOVQconst", asm: x86.AMOVQ, reg: regInfo{ + clobbers: 8589934592, // .FLAGS outputs: []regMask{ 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 }, -- cgit v1.3 From 634b50c6e138669d5518c0c02d3bfba79e1278ab Mon Sep 17 00:00:00 2001 From: Todd Neal Date: Tue, 1 Sep 2015 19:05:44 -0500 Subject: [dev.ssa] cmd/compile: truncate when converting floats to ints Modified to use the truncating conversion. Fixes reflect. Change-Id: I47bf3200abc2d2c662939a2a2351e2ff84168f4a Reviewed-on: https://go-review.googlesource.com/14167 Reviewed-by: David Chase --- src/cmd/compile/internal/gc/ssa.go | 2 +- src/cmd/compile/internal/gc/testdata/fp_ssa.go | 3 +++ src/cmd/compile/internal/ssa/gen/AMD64.rules | 8 +++---- src/cmd/compile/internal/ssa/gen/AMD64Ops.go | 20 ++++++++-------- src/cmd/compile/internal/ssa/opGen.go | 24 +++++++++---------- src/cmd/compile/internal/ssa/rewriteAMD64.go | 32 +++++++++++++------------- 6 files changed, 46 insertions(+), 43 deletions(-) (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 17288c3156..61e17ee68b 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -3045,7 +3045,7 @@ func genValue(v *ssa.Value) { addAux(&p.To, v) case ssa.OpAMD64MOVLQSX, ssa.OpAMD64MOVWQSX, ssa.OpAMD64MOVBQSX, ssa.OpAMD64MOVLQZX, ssa.OpAMD64MOVWQZX, ssa.OpAMD64MOVBQZX, ssa.OpAMD64CVTSL2SS, ssa.OpAMD64CVTSL2SD, ssa.OpAMD64CVTSQ2SS, ssa.OpAMD64CVTSQ2SD, - ssa.OpAMD64CVTSS2SL, ssa.OpAMD64CVTSD2SL, ssa.OpAMD64CVTSS2SQ, ssa.OpAMD64CVTSD2SQ, + ssa.OpAMD64CVTTSS2SL, ssa.OpAMD64CVTTSD2SL, ssa.OpAMD64CVTTSS2SQ, ssa.OpAMD64CVTTSD2SQ, ssa.OpAMD64CVTSS2SD, ssa.OpAMD64CVTSD2SS: opregreg(v.Op.Asm(), regnum(v), regnum(v.Args[0])) case ssa.OpAMD64MOVXzero: diff --git a/src/cmd/compile/internal/gc/testdata/fp_ssa.go b/src/cmd/compile/internal/gc/testdata/fp_ssa.go index 2cbf00bab0..6193983e4c 100644 --- a/src/cmd/compile/internal/gc/testdata/fp_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/fp_ssa.go @@ -1179,7 +1179,10 @@ func floatsToUints(x float64, expected uint64) int { func floatingToIntegerConversionsTest() int { fails := 0 fails += floatsToInts(0.0, 0) + fails += floatsToInts(0.5, 0) + fails += floatsToInts(0.9, 0) fails += floatsToInts(1.0, 1) + fails += floatsToInts(1.5, 1) fails += floatsToInts(127.0, 127) fails += floatsToInts(-1.0, -1) fails += floatsToInts(-128.0, -128) diff --git a/src/cmd/compile/internal/ssa/gen/AMD64.rules b/src/cmd/compile/internal/ssa/gen/AMD64.rules index 28ae88ff24..e8dc5cee72 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64.rules +++ b/src/cmd/compile/internal/ssa/gen/AMD64.rules @@ -109,10 +109,10 @@ (Cvt64to32F x) -> (CVTSQ2SS x) (Cvt64to64F x) -> (CVTSQ2SD x) -(Cvt32Fto32 x) -> (CVTSS2SL x) -(Cvt32Fto64 x) -> (CVTSS2SQ x) -(Cvt64Fto32 x) -> (CVTSD2SL x) -(Cvt64Fto64 x) -> (CVTSD2SQ x) +(Cvt32Fto32 x) -> (CVTTSS2SL x) +(Cvt32Fto64 x) -> (CVTTSS2SQ x) +(Cvt64Fto32 x) -> (CVTTSD2SL x) +(Cvt64Fto64 x) -> (CVTTSD2SQ x) (Cvt32Fto64F x) -> (CVTSS2SD x) (Cvt64Fto32F x) -> (CVTSD2SS x) diff --git a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go index d8d7703594..37cd096d63 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go @@ -346,16 +346,16 @@ func init() { {name: "MOVLconst", reg: gp01flags, asm: "MOVL"}, // 32 low bits of auxint {name: "MOVQconst", reg: gp01flags, asm: "MOVQ"}, // auxint - {name: "CVTSD2SL", reg: fpgp, asm: "CVTSD2SL"}, // convert float64 to int32 - {name: "CVTSD2SQ", reg: fpgp, asm: "CVTSD2SQ"}, // convert float64 to int64 - {name: "CVTSS2SL", reg: fpgp, asm: "CVTSS2SL"}, // convert float32 to int32 - {name: "CVTSS2SQ", reg: fpgp, asm: "CVTSS2SQ"}, // convert float32 to int64 - {name: "CVTSL2SS", reg: gpfp, asm: "CVTSL2SS"}, // convert int32 to float32 - {name: "CVTSL2SD", reg: gpfp, asm: "CVTSL2SD"}, // convert int32 to float64 - {name: "CVTSQ2SS", reg: gpfp, asm: "CVTSQ2SS"}, // convert int64 to float32 - {name: "CVTSQ2SD", reg: gpfp, asm: "CVTSQ2SD"}, // convert int64 to float64 - {name: "CVTSD2SS", reg: fp11, asm: "CVTSD2SS"}, // convert float64 to float32 - {name: "CVTSS2SD", reg: fp11, asm: "CVTSS2SD"}, // convert float32 to float64 + {name: "CVTTSD2SL", reg: fpgp, asm: "CVTTSD2SL"}, // convert float64 to int32 + {name: "CVTTSD2SQ", reg: fpgp, asm: "CVTTSD2SQ"}, // convert float64 to int64 + {name: "CVTTSS2SL", reg: fpgp, asm: "CVTTSS2SL"}, // convert float32 to int32 + {name: "CVTTSS2SQ", reg: fpgp, asm: "CVTTSS2SQ"}, // convert float32 to int64 + {name: "CVTSL2SS", reg: gpfp, asm: "CVTSL2SS"}, // convert int32 to float32 + {name: "CVTSL2SD", reg: gpfp, asm: "CVTSL2SD"}, // convert int32 to float64 + {name: "CVTSQ2SS", reg: gpfp, asm: "CVTSQ2SS"}, // convert int64 to float32 + {name: "CVTSQ2SD", reg: gpfp, asm: "CVTSQ2SD"}, // convert int64 to float64 + {name: "CVTSD2SS", reg: fp11, asm: "CVTSD2SS"}, // convert float64 to float32 + {name: "CVTSS2SD", reg: fp11, asm: "CVTSS2SD"}, // convert float32 to float64 {name: "PXOR", reg: fp21, asm: "PXOR"}, // exclusive or, applied to X regs for float negation. diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index d663535940..f4c74fe340 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -227,10 +227,10 @@ const ( OpAMD64MOVWconst OpAMD64MOVLconst OpAMD64MOVQconst - OpAMD64CVTSD2SL - OpAMD64CVTSD2SQ - OpAMD64CVTSS2SL - OpAMD64CVTSS2SQ + OpAMD64CVTTSD2SL + OpAMD64CVTTSD2SQ + OpAMD64CVTTSS2SL + OpAMD64CVTTSS2SQ OpAMD64CVTSL2SS OpAMD64CVTSL2SD OpAMD64CVTSQ2SS @@ -2682,8 +2682,8 @@ var opcodeTable = [...]opInfo{ }, }, { - name: "CVTSD2SL", - asm: x86.ACVTSD2SL, + name: "CVTTSD2SL", + asm: x86.ACVTTSD2SL, reg: regInfo{ inputs: []inputInfo{ {0, 4294901760}, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 @@ -2694,8 +2694,8 @@ var opcodeTable = [...]opInfo{ }, }, { - name: "CVTSD2SQ", - asm: x86.ACVTSD2SQ, + name: "CVTTSD2SQ", + asm: x86.ACVTTSD2SQ, reg: regInfo{ inputs: []inputInfo{ {0, 4294901760}, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 @@ -2706,8 +2706,8 @@ var opcodeTable = [...]opInfo{ }, }, { - name: "CVTSS2SL", - asm: x86.ACVTSS2SL, + name: "CVTTSS2SL", + asm: x86.ACVTTSS2SL, reg: regInfo{ inputs: []inputInfo{ {0, 4294901760}, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 @@ -2718,8 +2718,8 @@ var opcodeTable = [...]opInfo{ }, }, { - name: "CVTSS2SQ", - asm: x86.ACVTSS2SQ, + name: "CVTTSS2SQ", + asm: x86.ACVTTSS2SQ, reg: regInfo{ inputs: []inputInfo{ {0, 4294901760}, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go index 67ec747e20..366a195a3d 100644 --- a/src/cmd/compile/internal/ssa/rewriteAMD64.go +++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go @@ -1694,34 +1694,34 @@ func rewriteValueAMD64(v *Value, config *Config) bool { case OpCvt32Fto32: // match: (Cvt32Fto32 x) // cond: - // result: (CVTSS2SL x) + // result: (CVTTSS2SL x) { x := v.Args[0] - v.Op = OpAMD64CVTSS2SL + v.Op = OpAMD64CVTTSS2SL v.AuxInt = 0 v.Aux = nil v.resetArgs() v.AddArg(x) return true } - goto endad55e2986dea26975574ee27f4976d5e - endad55e2986dea26975574ee27f4976d5e: + goto enda410209d31804e1bce7bdc235fc62342 + enda410209d31804e1bce7bdc235fc62342: ; case OpCvt32Fto64: // match: (Cvt32Fto64 x) // cond: - // result: (CVTSS2SQ x) + // result: (CVTTSS2SQ x) { x := v.Args[0] - v.Op = OpAMD64CVTSS2SQ + v.Op = OpAMD64CVTTSS2SQ v.AuxInt = 0 v.Aux = nil v.resetArgs() v.AddArg(x) return true } - goto end227800dc831e0b4ef80fa315133c0991 - end227800dc831e0b4ef80fa315133c0991: + goto enddb02fa4f3230a14d557d6c90cdadd523 + enddb02fa4f3230a14d557d6c90cdadd523: ; case OpCvt32Fto64F: // match: (Cvt32Fto64F x) @@ -1774,18 +1774,18 @@ func rewriteValueAMD64(v *Value, config *Config) bool { case OpCvt64Fto32: // match: (Cvt64Fto32 x) // cond: - // result: (CVTSD2SL x) + // result: (CVTTSD2SL x) { x := v.Args[0] - v.Op = OpAMD64CVTSD2SL + v.Op = OpAMD64CVTTSD2SL v.AuxInt = 0 v.Aux = nil v.resetArgs() v.AddArg(x) return true } - goto end1ce5fd52f29d5a42d1aa08d7ac53e49e - end1ce5fd52f29d5a42d1aa08d7ac53e49e: + goto endc213dd690dfe568607dec717b2c385b7 + endc213dd690dfe568607dec717b2c385b7: ; case OpCvt64Fto32F: // match: (Cvt64Fto32F x) @@ -1806,18 +1806,18 @@ func rewriteValueAMD64(v *Value, config *Config) bool { case OpCvt64Fto64: // match: (Cvt64Fto64 x) // cond: - // result: (CVTSD2SQ x) + // result: (CVTTSD2SQ x) { x := v.Args[0] - v.Op = OpAMD64CVTSD2SQ + v.Op = OpAMD64CVTTSD2SQ v.AuxInt = 0 v.Aux = nil v.resetArgs() v.AddArg(x) return true } - goto end8239c11ce860dc3b5417d4d2ae59386a - end8239c11ce860dc3b5417d4d2ae59386a: + goto end0bf3e4468047fd20714266ff05797454 + end0bf3e4468047fd20714266ff05797454: ; case OpCvt64to32F: // match: (Cvt64to32F x) -- cgit v1.3 From 5cb352edeba36e862995dd82fe7312368e6e8571 Mon Sep 17 00:00:00 2001 From: Todd Neal Date: Tue, 1 Sep 2015 21:25:24 -0500 Subject: [dev.ssa] cmd/compile: fix liblink rewrite of -0.0 liblink was rewriting xor by a negative zero (used by SSA for negation) as XORPS reg,reg. Fixes strconv. Change-Id: I627a0a7366618e6b07ba8f0ad0db0e102340c5e3 Reviewed-on: https://go-review.googlesource.com/14200 Reviewed-by: Josh Bleecher Snyder Reviewed-by: Keith Randall --- src/cmd/compile/internal/gc/testdata/fp_ssa.go | 14 ++++++++++++++ src/cmd/internal/obj/x86/obj6.go | 6 ++++-- 2 files changed, 18 insertions(+), 2 deletions(-) (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/testdata/fp_ssa.go b/src/cmd/compile/internal/gc/testdata/fp_ssa.go index 6193983e4c..ee3163abb3 100644 --- a/src/cmd/compile/internal/gc/testdata/fp_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/fp_ssa.go @@ -105,6 +105,12 @@ func div64_ssa(a, b float64) float64 { return a / b } +func neg64_ssa(a, b float64) float64 { + switch { + } + return -a + -1*b +} + func add32_ssa(a, b float32) float32 { switch { } @@ -128,6 +134,12 @@ func div32_ssa(a, b float32) float32 { return a / b } +func neg32_ssa(a, b float32) float32 { + switch { + } + return -a + -1*b +} + func conv2Float64_ssa(a int8, b uint8, c int16, d uint16, e int32, f uint32, g int64, h uint64, i float32) (aa, bb, cc, dd, ee, ff, gg, hh, ii float64) { switch { @@ -1548,11 +1560,13 @@ func main() { fails += fail64("*", mul64_ssa, a, b, 12.0) fails += fail64("-", sub64_ssa, a, b, -1.0) fails += fail64("/", div64_ssa, a, b, 0.75) + fails += fail64("neg", neg64_ssa, a, b, -7) fails += fail32("+", add32_ssa, c, d, 7.0) fails += fail32("*", mul32_ssa, c, d, 12.0) fails += fail32("-", sub32_ssa, c, d, -1.0) fails += fail32("/", div32_ssa, c, d, 0.75) + fails += fail32("neg", neg32_ssa, c, d, -7) // denorm-squared should underflow to zero. fails += fail32("*", mul32_ssa, tiny, tiny, 0) diff --git a/src/cmd/internal/obj/x86/obj6.go b/src/cmd/internal/obj/x86/obj6.go index d0efffbc0a..d55dcc7cac 100644 --- a/src/cmd/internal/obj/x86/obj6.go +++ b/src/cmd/internal/obj/x86/obj6.go @@ -221,7 +221,8 @@ func progedit(ctxt *obj.Link, p *obj.Prog) { // Convert AMOVSS $(0), Xx to AXORPS Xx, Xx case AMOVSS: if p.From.Type == obj.TYPE_FCONST { - if p.From.Val.(float64) == 0 { + // f == 0 can't be used here due to -0, so use Float64bits + if f := p.From.Val.(float64); math.Float64bits(f) == 0 { if p.To.Type == obj.TYPE_REG && REG_X0 <= p.To.Reg && p.To.Reg <= REG_X15 { p.As = AXORPS p.From = p.To @@ -261,7 +262,8 @@ func progedit(ctxt *obj.Link, p *obj.Prog) { case AMOVSD: // Convert AMOVSD $(0), Xx to AXORPS Xx, Xx if p.From.Type == obj.TYPE_FCONST { - if p.From.Val.(float64) == 0 { + // f == 0 can't be used here due to -0, so use Float64bits + if f := p.From.Val.(float64); math.Float64bits(f) == 0 { if p.To.Type == obj.TYPE_REG && REG_X0 <= p.To.Reg && p.To.Reg <= REG_X15 { p.As = AXORPS p.From = p.To -- cgit v1.3 From 19285efaed7b08535e1b3ba921f584ed8bde6e49 Mon Sep 17 00:00:00 2001 From: Todd Neal Date: Wed, 2 Sep 2015 21:11:32 -0500 Subject: [dev.ssa] cmd/compile: fix complex128 complex128 was being treated as a complex64 Fixes math/cmplx. Change-Id: I2996915b4cb6b94198d41cf08a30bd8531b9fec5 Reviewed-on: https://go-review.googlesource.com/14206 Reviewed-by: Keith Randall --- src/cmd/compile/internal/gc/ssa.go | 4 ++-- src/cmd/compile/internal/gc/testdata/fp_ssa.go | 29 ++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 61e17ee68b..77c822787d 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -1139,8 +1139,8 @@ func (s *state) expr(n *Node) *ssa.Value { { pt := Types[TFLOAT64] return s.newValue2(ssa.OpComplexMake, n.Type, - s.constFloat32(pt, mpgetflt(r)), - s.constFloat32(pt, mpgetflt(i))) + s.constFloat64(pt, mpgetflt(r)), + s.constFloat64(pt, mpgetflt(i))) } default: s.Fatalf("bad float size %d", n.Type.Size()) diff --git a/src/cmd/compile/internal/gc/testdata/fp_ssa.go b/src/cmd/compile/internal/gc/testdata/fp_ssa.go index ee3163abb3..9bd545f878 100644 --- a/src/cmd/compile/internal/gc/testdata/fp_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/fp_ssa.go @@ -1467,42 +1467,69 @@ func expectCx64(s string, x, expected complex64) int { } func cx128sum_ssa(a, b complex128) complex128 { + switch { // prevent inlining + } return a + b } func cx128diff_ssa(a, b complex128) complex128 { + switch { // prevent inlining + } return a - b } func cx128prod_ssa(a, b complex128) complex128 { + switch { // prevent inlining + } return a * b } func cx128quot_ssa(a, b complex128) complex128 { + switch { // prevent inlining + } return a / b } func cx128neg_ssa(a complex128) complex128 { + switch { // prevent inlining + } return -a } +func cx128cnst_ssa(a complex128) complex128 { + switch { // prevent inlining + } + b := 2 + 3i + return a * b +} + func cx64sum_ssa(a, b complex64) complex64 { + switch { // prevent inlining + } return a + b } func cx64diff_ssa(a, b complex64) complex64 { + switch { // prevent inlining + } return a - b } func cx64prod_ssa(a, b complex64) complex64 { + switch { // prevent inlining + } return a * b } func cx64quot_ssa(a, b complex64) complex64 { + switch { // prevent inlining + } return a / b } func cx64neg_ssa(a complex64) complex64 { + switch { // prevent inlining + } return -a } @@ -1515,12 +1542,14 @@ func complexTest128() int { prod := cx128prod_ssa(b, a) quot := cx128quot_ssa(b, a) neg := cx128neg_ssa(a) + cnst := cx128cnst_ssa(a) fails += expectCx128("sum", sum, 4+8i) fails += expectCx128("diff", diff, 2+4i) fails += expectCx128("prod", prod, -9+12i) fails += expectCx128("quot", quot, 3+0i) fails += expectCx128("neg", neg, -1-2i) + fails += expectCx128("cnst", cnst, -4+7i) return fails } -- cgit v1.3 From ca9e450bed8e0884e88731526adfb2b4080b548e Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Tue, 8 Sep 2015 08:59:57 -0700 Subject: [dev.ssa] cmd/compile/internal/ssa: fix defer in functions with no return The after-defer test jumps to a deferreturn site. Some functions (those with infinite loops) have no deferreturn site. Add one so we have one to jump to. Change-Id: I505e7f3f888f5e7d03ca49a3477b41cf1f78eb8a Reviewed-on: https://go-review.googlesource.com/14349 Reviewed-by: Josh Bleecher Snyder --- src/cmd/compile/internal/gc/ssa.go | 38 ++++++++++++++-------- src/cmd/compile/internal/gc/ssa_test.go | 10 +++++- .../internal/gc/testdata/deferNoReturn_ssa.go | 21 ++++++++++++ 3 files changed, 54 insertions(+), 15 deletions(-) create mode 100644 src/cmd/compile/internal/gc/testdata/deferNoReturn_ssa.go (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 098a1e15f6..70990bbd18 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -2621,6 +2621,12 @@ func genssa(f *ssa.Func, ptxt *obj.Prog, gcargs, gclocals *Sym) { for _, br := range s.branches { br.p.To.Val = s.bstart[br.b.ID] } + if s.deferBranches != nil && s.deferTarget == nil { + // This can happen when the function has a defer but + // no return (because it has an infinite loop). + s.deferReturn() + Prog(obj.ARET) + } for _, p := range s.deferBranches { p.To.Val = s.deferTarget } @@ -3463,20 +3469,7 @@ func (s *genState) genBlock(b, next *ssa.Block) { case ssa.BlockExit: case ssa.BlockRet: if Hasdefer != 0 { - // Deferred calls will appear to be returning to - // the CALL deferreturn(SB) that we are about to emit. - // However, the stack trace code will show the line - // of the instruction byte before the return PC. - // To avoid that being an unrelated instruction, - // insert an actual hardware NOP that will have the right line number. - // This is different from obj.ANOP, which is a virtual no-op - // that doesn't make it into the instruction stream. - s.deferTarget = Pc - Thearch.Ginsnop() - p := Prog(obj.ACALL) - p.To.Type = obj.TYPE_MEM - p.To.Name = obj.NAME_EXTERN - p.To.Sym = Linksym(Deferreturn.Sym) + s.deferReturn() } Prog(obj.ARET) case ssa.BlockCall: @@ -3537,6 +3530,23 @@ func (s *genState) genBlock(b, next *ssa.Block) { } } +func (s *genState) deferReturn() { + // Deferred calls will appear to be returning to + // the CALL deferreturn(SB) that we are about to emit. + // However, the stack trace code will show the line + // of the instruction byte before the return PC. + // To avoid that being an unrelated instruction, + // insert an actual hardware NOP that will have the right line number. + // This is different from obj.ANOP, which is a virtual no-op + // that doesn't make it into the instruction stream. + s.deferTarget = Pc + Thearch.Ginsnop() + p := Prog(obj.ACALL) + p.To.Type = obj.TYPE_MEM + p.To.Name = obj.NAME_EXTERN + p.To.Sym = Linksym(Deferreturn.Sym) +} + // addAux adds the offset in the aux fields (AuxInt and Aux) of v to a. func addAux(a *obj.Addr, v *ssa.Value) { if a.Type != obj.TYPE_MEM { diff --git a/src/cmd/compile/internal/gc/ssa_test.go b/src/cmd/compile/internal/gc/ssa_test.go index e4f5bcd1fd..0bce902982 100644 --- a/src/cmd/compile/internal/gc/ssa_test.go +++ b/src/cmd/compile/internal/gc/ssa_test.go @@ -17,12 +17,18 @@ import ( // TODO: move all these tests elsewhere? // Perhaps teach test/run.go how to run them with a new action verb. func runTest(t *testing.T, filename string) { + doTest(t, filename, "run") +} +func buildTest(t *testing.T, filename string) { + doTest(t, filename, "build") +} +func doTest(t *testing.T, filename string, kind string) { if runtime.GOARCH != "amd64" { t.Skipf("skipping SSA tests on %s for now", runtime.GOARCH) } testenv.MustHaveGoBuild(t) var stdout, stderr bytes.Buffer - cmd := exec.Command("go", "run", filepath.Join("testdata", filename)) + cmd := exec.Command("go", kind, filepath.Join("testdata", filename)) cmd.Stdout = &stdout cmd.Stderr = &stderr // TODO: set GOGC=off until we have stackmaps @@ -70,3 +76,5 @@ func TestMap(t *testing.T) { runTest(t, "map_ssa.go") } func TestRegalloc(t *testing.T) { runTest(t, "regalloc_ssa.go") } func TestString(t *testing.T) { runTest(t, "string_ssa.go") } + +func TestDeferNoReturn(t *testing.T) { buildTest(t, "deferNoReturn_ssa.go") } diff --git a/src/cmd/compile/internal/gc/testdata/deferNoReturn_ssa.go b/src/cmd/compile/internal/gc/testdata/deferNoReturn_ssa.go new file mode 100644 index 0000000000..171f5837bc --- /dev/null +++ b/src/cmd/compile/internal/gc/testdata/deferNoReturn_ssa.go @@ -0,0 +1,21 @@ +// compile + +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Test that a defer in a function with no return +// statement will compile correctly. + +package main + +func deferNoReturn_ssa() { + defer func() { println("returned") }() + for { + println("loop") + } +} + +func main() { + deferNoReturn_ssa() +} -- cgit v1.3 From c684d4d26c3197039ac2c2f53a862f25dc7d1112 Mon Sep 17 00:00:00 2001 From: Alexandru Moșoi Date: Tue, 8 Sep 2015 18:18:59 +0200 Subject: [dev.ssa] cmd/compile/internal/ssa: fix string slice types. Change-Id: I28bc6373bb42d9abf4f179664dbaab8d514a6ab9 Reviewed-on: https://go-review.googlesource.com/14376 Reviewed-by: Keith Randall --- src/cmd/compile/internal/gc/ssa.go | 4 +-- src/cmd/compile/internal/gc/testdata/string_ssa.go | 30 ++++++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 70990bbd18..a554a1dfd9 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -1722,12 +1722,12 @@ func (s *state) expr(n *Node) *ssa.Value { if n.Right.Left == nil { low = zero } else { - low = s.expr(n.Right.Left) + low = s.extendIndex(s.expr(n.Right.Left)) } if n.Right.Right == nil { high = len } else { - high = s.expr(n.Right.Right) + high = s.extendIndex(s.expr(n.Right.Right)) } // Panic if slice indices are not in bounds. diff --git a/src/cmd/compile/internal/gc/testdata/string_ssa.go b/src/cmd/compile/internal/gc/testdata/string_ssa.go index efc734e1a2..448433acd3 100644 --- a/src/cmd/compile/internal/gc/testdata/string_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/string_ssa.go @@ -86,9 +86,39 @@ func testStringSlicePanic() { failed = true } +const _Accuracy_name = "BelowExactAbove" + +var _Accuracy_index = [...]uint8{0, 5, 10, 15} + +func testSmallIndexType_ssa(i int) string { + switch { // prevent inlining + } + return _Accuracy_name[_Accuracy_index[i]:_Accuracy_index[i+1]] +} + +func testSmallIndexType() { + tests := []struct { + i int + want string + }{ + {0, "Below"}, + {1, "Exact"}, + {2, "Above"}, + } + + for i, t := range tests { + if got := testSmallIndexType_ssa(t.i); got != t.want { + println("#", i, "got ", got, ", wanted", t.want) + failed = true + } + } +} + func main() { testStringSlice() testStringSlicePanic() + testStructSlice() + testSmallIndexType() if failed { panic("failed") -- cgit v1.3 From 1c2975c305b2b2c32f2673c93ab51204c5a5bff5 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Tue, 8 Sep 2015 16:23:50 -0700 Subject: [dev.ssa] cmd/compile/internal/gc: avoid generating test binary file Using the main package causes a binary to be generated. That binary clutters up git listings. Use a non-main package instead, so the results of a successful compilation are thrown away. Change-Id: I3ac91fd69ad297a5c0fe035c22fdef290b7dfbc4 Reviewed-on: https://go-review.googlesource.com/14399 Reviewed-by: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Gobot Gobot --- src/cmd/compile/internal/gc/testdata/deferNoReturn_ssa.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/testdata/deferNoReturn_ssa.go b/src/cmd/compile/internal/gc/testdata/deferNoReturn_ssa.go index 171f5837bc..7578dd56f2 100644 --- a/src/cmd/compile/internal/gc/testdata/deferNoReturn_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/deferNoReturn_ssa.go @@ -7,7 +7,7 @@ // Test that a defer in a function with no return // statement will compile correctly. -package main +package foo func deferNoReturn_ssa() { defer func() { println("returned") }() @@ -15,7 +15,3 @@ func deferNoReturn_ssa() { println("loop") } } - -func main() { - deferNoReturn_ssa() -} -- cgit v1.3 From def7c65b7062f5c087c4e348768ee4c464b79b91 Mon Sep 17 00:00:00 2001 From: Todd Neal Date: Mon, 7 Sep 2015 19:07:02 -0500 Subject: [dev.ssa] cmd/compile/internal/ssa: implement OCFUNC Change-Id: Ieb9cddf8876bf8cd5ee1705d9210d22c3959e8cc Reviewed-on: https://go-review.googlesource.com/14329 Reviewed-by: Keith Randall Run-TryBot: Todd Neal --- src/cmd/compile/internal/gc/ssa.go | 12 ++++--- src/cmd/compile/internal/gc/ssa_test.go | 3 ++ .../compile/internal/gc/testdata/closure_ssa.go | 39 ++++++++++++++++++++++ 3 files changed, 50 insertions(+), 4 deletions(-) create mode 100644 src/cmd/compile/internal/gc/testdata/closure_ssa.go (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 386420f26b..4fe8ba8836 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -1203,6 +1203,9 @@ func (s *state) expr(n *Node) *ssa.Value { s.stmtList(n.Ninit) switch n.Op { + case OCFUNC: + aux := &ssa.ExternSymbol{n.Type, n.Left.Sym} + return s.entryNewValue1A(ssa.OpAddr, n.Type, aux, s.sb) case ONAME: if n.Class == PFUNC { // "value" of a function is the address of the function's closure @@ -1296,16 +1299,17 @@ func (s *state) expr(n *Node) *ssa.Value { case OCONVNOP: to := n.Type from := n.Left.Type - if to.Etype == TFUNC { - s.Unimplementedf("CONVNOP closure") - return nil - } // Assume everything will work out, so set up our return value. // Anything interesting that happens from here is a fatal. x := s.expr(n.Left) v := s.newValue1(ssa.OpCopy, to, x) // ensure that v has the right type + // CONVNOP closure + if to.Etype == TFUNC && from.IsPtr() { + return v + } + // named <--> unnamed type or typed <--> untyped const if from.Etype == to.Etype { return v diff --git a/src/cmd/compile/internal/gc/ssa_test.go b/src/cmd/compile/internal/gc/ssa_test.go index 0bce902982..feaea8b463 100644 --- a/src/cmd/compile/internal/gc/ssa_test.go +++ b/src/cmd/compile/internal/gc/ssa_test.go @@ -78,3 +78,6 @@ func TestRegalloc(t *testing.T) { runTest(t, "regalloc_ssa.go") } func TestString(t *testing.T) { runTest(t, "string_ssa.go") } func TestDeferNoReturn(t *testing.T) { buildTest(t, "deferNoReturn_ssa.go") } + +// TestClosure tests closure related behavior. +func TestClosure(t *testing.T) { runTest(t, "closure_ssa.go") } diff --git a/src/cmd/compile/internal/gc/testdata/closure_ssa.go b/src/cmd/compile/internal/gc/testdata/closure_ssa.go new file mode 100644 index 0000000000..ac1e51a23e --- /dev/null +++ b/src/cmd/compile/internal/gc/testdata/closure_ssa.go @@ -0,0 +1,39 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// map_ssa.go tests map operations. +package main + +import "fmt" + +var failed = false + +func testCFunc_ssa() int { + switch { // prevent inlining + } + a := 0 + b := func() { + switch { + } + a++ + } + b() + b() + return a +} + +func testCFunc() { + if want, got := 2, testCFunc_ssa(); got != want { + fmt.Printf("expected %d, got %d", want, got) + failed = true + } +} + +func main() { + testCFunc() + + if failed { + panic("failed") + } +} -- cgit v1.3 From 2f518071577d177c5ec5b4c0c9e9dcd14e9cd32a Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Thu, 10 Sep 2015 11:37:09 -0700 Subject: [dev.ssa] cmd/compile/internal/ssa: fix real/imag ops They were using the result type to look up the op, not the arg type. Change-Id: I0641cba363fa6e7a66ad0860aa340106c10c2cea Reviewed-on: https://go-review.googlesource.com/14469 Reviewed-by: Brad Fitzpatrick Reviewed-by: Josh Bleecher Snyder --- src/cmd/compile/internal/gc/ssa.go | 5 +++- src/cmd/compile/internal/gc/testdata/fp_ssa.go | 32 ++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 4fe8ba8836..5132c53000 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -1638,9 +1638,12 @@ func (s *state) expr(n *Node) *ssa.Value { s.newValue1(negop, tp, s.newValue1(ssa.OpComplexImag, tp, a))) } return s.newValue1(s.ssaOp(n.Op, n.Type), a.Type, a) - case ONOT, OCOM, OIMAG, OREAL: + case ONOT, OCOM: a := s.expr(n.Left) return s.newValue1(s.ssaOp(n.Op, n.Type), a.Type, a) + case OIMAG, OREAL: + a := s.expr(n.Left) + return s.newValue1(s.ssaOp(n.Op, n.Left.Type), n.Type, a) case OPLUS: return s.expr(n.Left) diff --git a/src/cmd/compile/internal/gc/testdata/fp_ssa.go b/src/cmd/compile/internal/gc/testdata/fp_ssa.go index 9bd545f878..6985cd0641 100644 --- a/src/cmd/compile/internal/gc/testdata/fp_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/fp_ssa.go @@ -1496,6 +1496,18 @@ func cx128neg_ssa(a complex128) complex128 { return -a } +func cx128real_ssa(a complex128) float64 { + switch { // prevent inlining + } + return real(a) +} + +func cx128imag_ssa(a complex128) float64 { + switch { // prevent inlining + } + return imag(a) +} + func cx128cnst_ssa(a complex128) complex128 { switch { // prevent inlining } @@ -1533,6 +1545,18 @@ func cx64neg_ssa(a complex64) complex64 { return -a } +func cx64real_ssa(a complex64) float32 { + switch { // prevent inlining + } + return real(a) +} + +func cx64imag_ssa(a complex64) float32 { + switch { // prevent inlining + } + return imag(a) +} + func complexTest128() int { fails := 0 var a complex128 = 1 + 2i @@ -1542,6 +1566,8 @@ func complexTest128() int { prod := cx128prod_ssa(b, a) quot := cx128quot_ssa(b, a) neg := cx128neg_ssa(a) + r := cx128real_ssa(a) + i := cx128imag_ssa(a) cnst := cx128cnst_ssa(a) fails += expectCx128("sum", sum, 4+8i) @@ -1549,6 +1575,8 @@ func complexTest128() int { fails += expectCx128("prod", prod, -9+12i) fails += expectCx128("quot", quot, 3+0i) fails += expectCx128("neg", neg, -1-2i) + fails += expect64("real", r, 1) + fails += expect64("imag", i, 2) fails += expectCx128("cnst", cnst, -4+7i) return fails @@ -1563,12 +1591,16 @@ func complexTest64() int { prod := cx64prod_ssa(b, a) quot := cx64quot_ssa(b, a) neg := cx64neg_ssa(a) + r := cx64real_ssa(a) + i := cx64imag_ssa(a) fails += expectCx64("sum", sum, 4+8i) fails += expectCx64("diff", diff, 2+4i) fails += expectCx64("prod", prod, -9+12i) fails += expectCx64("quot", quot, 3+0i) fails += expectCx64("neg", neg, -1-2i) + fails += expect32("real", r, 1) + fails += expect32("imag", i, 2) return fails } -- cgit v1.3 From db380bf44bcd8bcfdcbb68d18855111090282a63 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Thu, 10 Sep 2015 11:05:42 -0700 Subject: [dev.ssa] cmd/compile/internal/ssa: add == and != for complex Change-Id: Iefabce4eb0dbc313dd1863513b45307cc76c545a Reviewed-on: https://go-review.googlesource.com/14468 Reviewed-by: Brad Fitzpatrick --- src/cmd/compile/internal/gc/ssa.go | 16 ++++++++ src/cmd/compile/internal/gc/testdata/fp_ssa.go | 55 ++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 5132c53000..b69631338e 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -1476,6 +1476,22 @@ func (s *state) expr(n *Node) *ssa.Value { case OLT, OEQ, ONE, OLE, OGE, OGT: a := s.expr(n.Left) b := s.expr(n.Right) + if n.Left.Type.IsComplex() { + pt := floatForComplex(n.Type) + op := s.ssaOp(OEQ, pt) + r := s.newValue2(op, Types[TBOOL], s.newValue1(ssa.OpComplexReal, pt, a), s.newValue1(ssa.OpComplexReal, pt, b)) + i := s.newValue2(op, Types[TBOOL], s.newValue1(ssa.OpComplexImag, pt, a), s.newValue1(ssa.OpComplexImag, pt, b)) + c := s.newValue2(ssa.OpAnd8, Types[TBOOL], r, i) + switch n.Op { + case OEQ: + return c + case ONE: + return s.newValue1(ssa.OpNot, Types[TBOOL], c) + default: + s.Fatalf("ordered complex compare %s", opnames[n.Op]) + } + + } return s.newValue2(s.ssaOp(n.Op, n.Left.Type), Types[TBOOL], a, b) case OMUL: a := s.expr(n.Left) diff --git a/src/cmd/compile/internal/gc/testdata/fp_ssa.go b/src/cmd/compile/internal/gc/testdata/fp_ssa.go index 6985cd0641..e7480a1138 100644 --- a/src/cmd/compile/internal/gc/testdata/fp_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/fp_ssa.go @@ -1557,6 +1557,45 @@ func cx64imag_ssa(a complex64) float32 { return imag(a) } +func cx128eq_ssa(a, b complex128) bool { + switch { // prevent inlining + } + return a == b +} + +func cx128ne_ssa(a, b complex128) bool { + switch { // prevent inlining + } + return a != b +} + +func cx64eq_ssa(a, b complex64) bool { + switch { // prevent inlining + } + return a == b +} + +func cx64ne_ssa(a, b complex64) bool { + switch { // prevent inlining + } + return a != b +} + +func expectTrue(s string, b bool) int { + if !b { + println("expected true for", s, ", got false") + return 1 + } + return 0 +} +func expectFalse(s string, b bool) int { + if b { + println("expected false for", s, ", got true") + return 1 + } + return 0 +} + func complexTest128() int { fails := 0 var a complex128 = 1 + 2i @@ -1569,6 +1608,10 @@ func complexTest128() int { r := cx128real_ssa(a) i := cx128imag_ssa(a) cnst := cx128cnst_ssa(a) + c1 := cx128eq_ssa(a, a) + c2 := cx128eq_ssa(a, b) + c3 := cx128ne_ssa(a, a) + c4 := cx128ne_ssa(a, b) fails += expectCx128("sum", sum, 4+8i) fails += expectCx128("diff", diff, 2+4i) @@ -1578,6 +1621,10 @@ func complexTest128() int { fails += expect64("real", r, 1) fails += expect64("imag", i, 2) fails += expectCx128("cnst", cnst, -4+7i) + fails += expectTrue(fmt.Sprintf("%v==%v", a, a), c1) + fails += expectFalse(fmt.Sprintf("%v==%v", a, b), c2) + fails += expectFalse(fmt.Sprintf("%v!=%v", a, a), c3) + fails += expectTrue(fmt.Sprintf("%v!=%v", a, b), c4) return fails } @@ -1593,6 +1640,10 @@ func complexTest64() int { neg := cx64neg_ssa(a) r := cx64real_ssa(a) i := cx64imag_ssa(a) + c1 := cx64eq_ssa(a, a) + c2 := cx64eq_ssa(a, b) + c3 := cx64ne_ssa(a, a) + c4 := cx64ne_ssa(a, b) fails += expectCx64("sum", sum, 4+8i) fails += expectCx64("diff", diff, 2+4i) @@ -1601,6 +1652,10 @@ func complexTest64() int { fails += expectCx64("neg", neg, -1-2i) fails += expect32("real", r, 1) fails += expect32("imag", i, 2) + fails += expectTrue(fmt.Sprintf("%v==%v", a, a), c1) + fails += expectFalse(fmt.Sprintf("%v==%v", a, b), c2) + fails += expectFalse(fmt.Sprintf("%v!=%v", a, a), c3) + fails += expectTrue(fmt.Sprintf("%v!=%v", a, b), c4) return fails } -- cgit v1.3 From c7081409bb58edc0fcbccbba230b1667845e94a6 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Thu, 10 Sep 2015 10:01:15 -0700 Subject: [dev.ssa] cmd/compile/internal/ssa: fix string index MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I984d3e0410ac38c4e42ae8e3670ea47e2140de76 Reviewed-on: https://go-review.googlesource.com/14466 Reviewed-by: Alexandru Moșoi Reviewed-by: Todd Neal --- src/cmd/compile/internal/gc/ssa.go | 23 ++++++------ src/cmd/compile/internal/gc/testdata/string_ssa.go | 41 ++++++++++++++++++++++ 2 files changed, 54 insertions(+), 10 deletions(-) (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 70350e0e2c..0551ddbf08 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -1693,19 +1693,22 @@ func (s *state) expr(n *Node) *ssa.Value { a := s.expr(n.Left) i := s.expr(n.Right) i = s.extendIndex(i) - var elemtype *Type - var len *ssa.Value if n.Left.Type.IsString() { - len = s.newValue1(ssa.OpStringLen, Types[TINT], a) - elemtype = Types[TUINT8] + if !n.Bounded { + len := s.newValue1(ssa.OpStringLen, Types[TINT], a) + s.boundsCheck(i, len) + } + ptrtyp := Ptrto(Types[TUINT8]) + ptr := s.newValue1(ssa.OpStringPtr, ptrtyp, a) + ptr = s.newValue2(ssa.OpAddPtr, ptrtyp, ptr, i) + return s.newValue2(ssa.OpLoad, Types[TUINT8], ptr, s.mem()) } else { - len = s.constInt(Types[TINT], n.Left.Type.Bound) - elemtype = n.Left.Type.Type - } - if !n.Bounded { - s.boundsCheck(i, len) + if !n.Bounded { + len := s.constInt(Types[TINT], n.Left.Type.Bound) + s.boundsCheck(i, len) + } + return s.newValue2(ssa.OpArrayIndex, n.Left.Type.Type, a, i) } - return s.newValue2(ssa.OpArrayIndex, elemtype, a, i) } else { // slice p := s.addr(n) return s.newValue2(ssa.OpLoad, n.Left.Type.Type, p, s.mem()) diff --git a/src/cmd/compile/internal/gc/testdata/string_ssa.go b/src/cmd/compile/internal/gc/testdata/string_ssa.go index 448433acd3..0ff6ce1a12 100644 --- a/src/cmd/compile/internal/gc/testdata/string_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/string_ssa.go @@ -70,6 +70,7 @@ func testStructSlice() { p.slice_ssa() if "pre" != p.prefix { println("wrong field slice: wanted %s got %s", "pre", p.prefix) + failed = true } } @@ -114,11 +115,51 @@ func testSmallIndexType() { } } +func testStringElem_ssa(s string, i int) byte { + switch { // prevent inlining + } + return s[i] +} + +func testStringElem() { + tests := []struct { + s string + i int + n byte + }{ + {"foobar", 3, 98}, + {"foobar", 0, 102}, + {"foobar", 5, 114}, + } + for _, t := range tests { + if got := testStringElem_ssa(t.s, t.i); got != t.n { + print("testStringElem \"", t.s, "\"[", t.i, "]=", got, ", wanted ", t.n, "\n") + failed = true + } + } +} + +func testStringElemConst_ssa(i int) byte { + switch { // prevent inlining + } + s := "foobar" + return s[i] +} + +func testStringElemConst() { + if got := testStringElemConst_ssa(3); got != 98 { + println("testStringElemConst=", got, ", wanted 98") + failed = true + } +} + func main() { testStringSlice() testStringSlicePanic() testStructSlice() testSmallIndexType() + testStringElem() + testStringElemConst() if failed { panic("failed") -- cgit v1.3 From 5505e8ccc74e8e4cbacace0143730a309b1a7655 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Sat, 12 Sep 2015 23:27:26 -0700 Subject: [dev.ssa] cmd/compile/internal/ssa: implement slice opcodes Implement OSLICE, OSLICEARR, OSLICESTR, OSLICE3, OSLICE3ARR. reviewer: Ignore the code in OINDEX, that's from CL 14466. Change-Id: I00cc8aecd4c6f40ea5517cd660bb0ce759d91171 Reviewed-on: https://go-review.googlesource.com/14538 Reviewed-by: Todd Neal --- src/cmd/compile/internal/gc/ssa.go | 210 +++++++++++++++------- src/cmd/compile/internal/gc/ssa_test.go | 2 + src/cmd/compile/internal/gc/testdata/array_ssa.go | 147 +++++++++++++++ src/cmd/compile/internal/gc/type.go | 4 + src/cmd/compile/internal/ssa/type.go | 2 + src/cmd/compile/internal/ssa/type_test.go | 2 + 6 files changed, 307 insertions(+), 60 deletions(-) create mode 100644 src/cmd/compile/internal/gc/testdata/array_ssa.go (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 0551ddbf08..738685b044 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -240,6 +240,9 @@ func (s *state) Unimplementedf(msg string, args ...interface{}) { s.config.Unimp // dummy node for the memory variable var memvar = Node{Op: ONAME, Sym: &Sym{Name: "mem"}} +// dummy nodes for temporary variables +var ptrvar = Node{Op: ONAME, Sym: &Sym{Name: "ptr"}} + // startBlock sets the current block we're generating code in to b. func (s *state) startBlock(b *ssa.Block) { if s.curBlock != nil { @@ -1747,70 +1750,38 @@ func (s *state) expr(n *Node) *ssa.Value { data := s.expr(n.Right) return s.newValue2(ssa.OpIMake, n.Type, tab, data) + case OSLICE, OSLICEARR: + v := s.expr(n.Left) + var i, j *ssa.Value + if n.Right.Left != nil { + i = s.extendIndex(s.expr(n.Right.Left)) + } + if n.Right.Right != nil { + j = s.extendIndex(s.expr(n.Right.Right)) + } + p, l, c := s.slice(n.Left.Type, v, i, j, nil) + return s.newValue3(ssa.OpSliceMake, n.Type, p, l, c) case OSLICESTR: - // Evaluate the string once. - str := s.expr(n.Left) - ptr := s.newValue1(ssa.OpStringPtr, Ptrto(Types[TUINT8]), str) - len := s.newValue1(ssa.OpStringLen, Types[TINT], str) - zero := s.constInt(Types[TINT], 0) - - // Evaluate the slice indexes. - var low, high *ssa.Value - if n.Right.Left == nil { - low = zero - } else { - low = s.extendIndex(s.expr(n.Right.Left)) + v := s.expr(n.Left) + var i, j *ssa.Value + if n.Right.Left != nil { + i = s.extendIndex(s.expr(n.Right.Left)) } - if n.Right.Right == nil { - high = len - } else { - high = s.extendIndex(s.expr(n.Right.Right)) + if n.Right.Right != nil { + j = s.extendIndex(s.expr(n.Right.Right)) } - - // Panic if slice indices are not in bounds. - s.sliceBoundsCheck(low, high) - s.sliceBoundsCheck(high, len) - - // Generate the following code assuming that indexes are in bounds. - // The conditional is to make sure that we don't generate a string - // that points to the next object in memory. - // rlen = (SubPtr high low) - // p = ptr - // if rlen != 0 { - // p = (AddPtr ptr low) - // } - // result = (StringMake p size) - rlen := s.newValue2(ssa.OpSubPtr, Types[TINT], high, low) - - // Use n as the "variable" for p. - s.vars[n] = ptr - - // Generate code to test the resulting slice length. - var cmp *ssa.Value - if s.config.IntSize == 8 { - cmp = s.newValue2(ssa.OpNeq64, Types[TBOOL], rlen, zero) - } else { - cmp = s.newValue2(ssa.OpNeq32, Types[TBOOL], rlen, zero) + p, l, _ := s.slice(n.Left.Type, v, i, j, nil) + return s.newValue2(ssa.OpStringMake, n.Type, p, l) + case OSLICE3, OSLICE3ARR: + v := s.expr(n.Left) + var i *ssa.Value + if n.Right.Left != nil { + i = s.extendIndex(s.expr(n.Right.Left)) } - - b := s.endBlock() - b.Kind = ssa.BlockIf - b.Likely = ssa.BranchLikely - b.Control = cmp - - // Generate code for non-zero length slice case. - nz := s.f.NewBlock(ssa.BlockPlain) - b.AddEdgeTo(nz) - s.startBlock(nz) - s.vars[n] = s.newValue2(ssa.OpAddPtr, Ptrto(Types[TUINT8]), ptr, low) - s.endBlock() - - // All done. - merge := s.f.NewBlock(ssa.BlockPlain) - b.AddEdgeTo(merge) - nz.AddEdgeTo(merge) - s.startBlock(merge) - return s.newValue2(ssa.OpStringMake, Types[TSTRING], s.variable(n, Ptrto(Types[TUINT8])), rlen) + j := s.extendIndex(s.expr(n.Right.Right.Left)) + k := s.extendIndex(s.expr(n.Right.Right.Right)) + p, l, c := s.slice(n.Left.Type, v, i, j, k) + return s.newValue3(ssa.OpSliceMake, n.Type, p, l, c) case OCALLFUNC, OCALLMETH: left := n.Left @@ -2201,6 +2172,125 @@ func (s *state) check(cmp *ssa.Value, panicOp ssa.Op) { s.startBlock(bNext) } +// slice computes the slice v[i:j:k] and returns ptr, len, and cap of result. +// i,j,k may be nil, in which case they are set to their default value. +// t is a slice, ptr to array, or string type. +func (s *state) slice(t *Type, v, i, j, k *ssa.Value) (p, l, c *ssa.Value) { + var elemtype *Type + var ptrtype *Type + var ptr *ssa.Value + var len *ssa.Value + var cap *ssa.Value + zero := s.constInt(Types[TINT], 0) + switch { + case t.IsSlice(): + elemtype = t.Type + ptrtype = Ptrto(elemtype) + ptr = s.newValue1(ssa.OpSlicePtr, ptrtype, v) + len = s.newValue1(ssa.OpSliceLen, Types[TINT], v) + cap = s.newValue1(ssa.OpSliceCap, Types[TINT], v) + case t.IsString(): + elemtype = Types[TUINT8] + ptrtype = Ptrto(elemtype) + ptr = s.newValue1(ssa.OpStringPtr, ptrtype, v) + len = s.newValue1(ssa.OpStringLen, Types[TINT], v) + cap = len + case t.IsPtr(): + if !t.Type.IsArray() { + s.Fatalf("bad ptr to array in slice %v\n", t) + } + elemtype = t.Type.Type + ptrtype = Ptrto(elemtype) + s.nilCheck(v) + ptr = v + len = s.constInt(Types[TINT], t.Type.Bound) + cap = len + default: + s.Fatalf("bad type in slice %v\n", t) + } + + // Set default values + if i == nil { + i = zero + } + if j == nil { + j = len + } + if k == nil { + k = cap + } + + // Panic if slice indices are not in bounds. + s.sliceBoundsCheck(i, j) + if j != k { + s.sliceBoundsCheck(j, k) + } + if k != cap { + s.sliceBoundsCheck(k, cap) + } + + // Generate the following code assuming that indexes are in bounds. + // The conditional is to make sure that we don't generate a slice + // that points to the next object in memory. + // rlen = (SubPtr j i) + // rcap = (SubPtr k i) + // p = ptr + // if rcap != 0 { + // p = (AddPtr ptr (MulPtr low (ConstPtr size))) + // } + // result = (SliceMake p size) + rlen := s.newValue2(ssa.OpSubPtr, Types[TINT], j, i) + var rcap *ssa.Value + switch { + case t.IsString(): + // Capacity of the result is unimportant. However, we use + // rcap to test if we've generated a zero-length slice. + // Use length of strings for that. + rcap = rlen + case j == k: + rcap = rlen + default: + rcap = s.newValue2(ssa.OpSubPtr, Types[TINT], k, i) + } + + s.vars[&ptrvar] = ptr + + // Generate code to test the resulting slice length. + var cmp *ssa.Value + if s.config.IntSize == 8 { + cmp = s.newValue2(ssa.OpNeq64, Types[TBOOL], rcap, s.constInt(Types[TINT], 0)) + } else { + cmp = s.newValue2(ssa.OpNeq32, Types[TBOOL], rcap, s.constInt(Types[TINT], 0)) + } + + b := s.endBlock() + b.Kind = ssa.BlockIf + b.Likely = ssa.BranchLikely + b.Control = cmp + + // Generate code for non-zero length slice case. + nz := s.f.NewBlock(ssa.BlockPlain) + b.AddEdgeTo(nz) + s.startBlock(nz) + var inc *ssa.Value + if elemtype.Width == 1 { + inc = i + } else { + inc = s.newValue2(ssa.OpMulPtr, Types[TUINTPTR], i, s.constInt(Types[TINT], elemtype.Width)) + } + s.vars[&ptrvar] = s.newValue2(ssa.OpAddPtr, ptrtype, ptr, inc) + s.endBlock() + + // All done. + merge := s.f.NewBlock(ssa.BlockPlain) + b.AddEdgeTo(merge) + nz.AddEdgeTo(merge) + s.startBlock(merge) + rptr := s.variable(&ptrvar, ptrtype) + delete(s.vars, &ptrvar) + return rptr, rlen, rcap +} + type u2fcvtTab struct { geq, cvt2F, and, rsh, or, add ssa.Op one func(*state, ssa.Type, int64) *ssa.Value diff --git a/src/cmd/compile/internal/gc/ssa_test.go b/src/cmd/compile/internal/gc/ssa_test.go index feaea8b463..74415fd560 100644 --- a/src/cmd/compile/internal/gc/ssa_test.go +++ b/src/cmd/compile/internal/gc/ssa_test.go @@ -81,3 +81,5 @@ func TestDeferNoReturn(t *testing.T) { buildTest(t, "deferNoReturn_ssa.go") } // TestClosure tests closure related behavior. func TestClosure(t *testing.T) { runTest(t, "closure_ssa.go") } + +func TestArray(t *testing.T) { runTest(t, "array_ssa.go") } diff --git a/src/cmd/compile/internal/gc/testdata/array_ssa.go b/src/cmd/compile/internal/gc/testdata/array_ssa.go new file mode 100644 index 0000000000..d7004ff26a --- /dev/null +++ b/src/cmd/compile/internal/gc/testdata/array_ssa.go @@ -0,0 +1,147 @@ +package main + +var failed = false + +func testSliceLenCap12_ssa(a [10]int, i, j int) (int, int) { + switch { // prevent inlining + } + b := a[i:j] + return len(b), cap(b) +} + +func testSliceLenCap1_ssa(a [10]int, i, j int) (int, int) { + switch { // prevent inlining + } + b := a[i:] + return len(b), cap(b) +} + +func testSliceLenCap2_ssa(a [10]int, i, j int) (int, int) { + switch { // prevent inlining + } + b := a[:j] + return len(b), cap(b) +} + +func testSliceLenCap() { + a := [10]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9} + tests := [...]struct { + fn func(a [10]int, i, j int) (int, int) + i, j int // slice range + l, c int // len, cap + }{ + // -1 means the value is not used. + {testSliceLenCap12_ssa, 0, 0, 0, 10}, + {testSliceLenCap12_ssa, 0, 1, 1, 10}, + {testSliceLenCap12_ssa, 0, 10, 10, 10}, + {testSliceLenCap12_ssa, 10, 10, 0, 0}, + {testSliceLenCap12_ssa, 0, 5, 5, 10}, + {testSliceLenCap12_ssa, 5, 5, 0, 5}, + {testSliceLenCap12_ssa, 5, 10, 5, 5}, + {testSliceLenCap1_ssa, 0, -1, 0, 10}, + {testSliceLenCap1_ssa, 5, -1, 5, 5}, + {testSliceLenCap1_ssa, 10, -1, 0, 0}, + {testSliceLenCap2_ssa, -1, 0, 0, 10}, + {testSliceLenCap2_ssa, -1, 5, 5, 10}, + {testSliceLenCap2_ssa, -1, 10, 10, 10}, + } + + for i, t := range tests { + if l, c := t.fn(a, t.i, t.j); l != t.l && c != t.c { + println("#", i, " len(a[", t.i, ":", t.j, "]), cap(a[", t.i, ":", t.j, "]) =", l, c, + ", want", t.l, t.c) + failed = true + } + } +} + +func testSliceGetElement_ssa(a [10]int, i, j, p int) int { + switch { // prevent inlining + } + return a[i:j][p] +} + +func testSliceGetElement() { + a := [10]int{0, 10, 20, 30, 40, 50, 60, 70, 80, 90} + tests := [...]struct { + i, j, p int + want int // a[i:j][p] + }{ + {0, 10, 2, 20}, + {0, 5, 4, 40}, + {5, 10, 3, 80}, + {1, 9, 7, 80}, + } + + for i, t := range tests { + if got := testSliceGetElement_ssa(a, t.i, t.j, t.p); got != t.want { + println("#", i, " a[", t.i, ":", t.j, "][", t.p, "] = ", got, " wanted ", t.want) + failed = true + } + } +} + +func testSliceSetElement_ssa(a *[10]int, i, j, p, x int) { + switch { // prevent inlining + } + (*a)[i:j][p] = x +} + +func testSliceSetElement() { + a := [10]int{0, 10, 20, 30, 40, 50, 60, 70, 80, 90} + tests := [...]struct { + i, j, p int + want int // a[i:j][p] + }{ + {0, 10, 2, 17}, + {0, 5, 4, 11}, + {5, 10, 3, 28}, + {1, 9, 7, 99}, + } + + for i, t := range tests { + testSliceSetElement_ssa(&a, t.i, t.j, t.p, t.want) + if got := a[t.i+t.p]; got != t.want { + println("#", i, " a[", t.i, ":", t.j, "][", t.p, "] = ", got, " wanted ", t.want) + failed = true + } + } +} + +func testSlicePanic1() { + defer func() { + if r := recover(); r != nil { + println("paniced as expected") + } + }() + + a := [10]int{0, 10, 20, 30, 40, 50, 60, 70, 80, 90} + testSliceLenCap12_ssa(a, 3, 12) + println("expected to panic, but didn't") + failed = true +} + +func testSlicePanic2() { + defer func() { + if r := recover(); r != nil { + println("paniced as expected") + } + }() + + a := [10]int{0, 10, 20, 30, 40, 50, 60, 70, 80, 90} + testSliceGetElement_ssa(a, 3, 7, 4) + println("expected to panic, but didn't") + failed = true +} + +func main() { + testSliceLenCap() + testSliceGetElement() + testSliceSetElement() + testSlicePanic1() + testSlicePanic2() + + if failed { + panic("failed") + } +} diff --git a/src/cmd/compile/internal/gc/type.go b/src/cmd/compile/internal/gc/type.go index cdd9b3f14a..3e07df367d 100644 --- a/src/cmd/compile/internal/gc/type.go +++ b/src/cmd/compile/internal/gc/type.go @@ -84,6 +84,10 @@ func (t *Type) IsSlice() bool { return t.Etype == TARRAY && t.Bound < 0 } +func (t *Type) IsArray() bool { + return t.Etype == TARRAY && t.Bound >= 0 +} + func (t *Type) IsInterface() bool { return t.Etype == TINTER } diff --git a/src/cmd/compile/internal/ssa/type.go b/src/cmd/compile/internal/ssa/type.go index decde6889e..6800731de6 100644 --- a/src/cmd/compile/internal/ssa/type.go +++ b/src/cmd/compile/internal/ssa/type.go @@ -20,6 +20,7 @@ type Type interface { IsPtr() bool IsString() bool IsSlice() bool + IsArray() bool IsInterface() bool IsMemory() bool // special ssa-package-only types @@ -50,6 +51,7 @@ func (t *CompilerType) IsComplex() bool { return false } func (t *CompilerType) IsPtr() bool { return false } func (t *CompilerType) IsString() bool { return false } func (t *CompilerType) IsSlice() bool { return false } +func (t *CompilerType) IsArray() bool { return false } func (t *CompilerType) IsInterface() bool { return false } func (t *CompilerType) IsMemory() bool { return t.Memory } func (t *CompilerType) IsFlags() bool { return t.Flags } diff --git a/src/cmd/compile/internal/ssa/type_test.go b/src/cmd/compile/internal/ssa/type_test.go index b106688e84..f3ac0aec2c 100644 --- a/src/cmd/compile/internal/ssa/type_test.go +++ b/src/cmd/compile/internal/ssa/type_test.go @@ -16,6 +16,7 @@ type TypeImpl struct { Ptr bool string bool slice bool + array bool inter bool Elem_ Type @@ -32,6 +33,7 @@ func (t *TypeImpl) IsComplex() bool { return t.Complex } func (t *TypeImpl) IsPtr() bool { return t.Ptr } func (t *TypeImpl) IsString() bool { return t.string } func (t *TypeImpl) IsSlice() bool { return t.slice } +func (t *TypeImpl) IsArray() bool { return t.array } func (t *TypeImpl) IsInterface() bool { return t.inter } func (t *TypeImpl) IsMemory() bool { return false } func (t *TypeImpl) IsFlags() bool { return false } -- cgit v1.3 From cde977c23cbf5fb29f12bcbca5164530d0256019 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Tue, 15 Sep 2015 09:02:07 -0700 Subject: [dev.ssa] cmd/compile/internal/ssa: fix sign extension + load combo Load-and-sign-extend opcodes were being generated in the wrong block, leading to having more than one memory variable live at once. Fix the rules + add a test. Change-Id: Iadf80e55ea901549c15c628ae295c2d0f1f64525 Reviewed-on: https://go-review.googlesource.com/14591 Reviewed-by: Todd Neal Run-TryBot: Todd Neal --- .../compile/internal/gc/testdata/loadstore_ssa.go | 21 ++++++++++++++++ src/cmd/compile/internal/ssa/gen/AMD64.rules | 10 ++++++-- src/cmd/compile/internal/ssa/regalloc.go | 28 ++++++++++++++++++++++ src/cmd/compile/internal/ssa/rewriteAMD64.go | 22 ++++++++++------- 4 files changed, 71 insertions(+), 10 deletions(-) (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/testdata/loadstore_ssa.go b/src/cmd/compile/internal/gc/testdata/loadstore_ssa.go index cf37095742..e986f53bc6 100644 --- a/src/cmd/compile/internal/gc/testdata/loadstore_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/loadstore_ssa.go @@ -57,10 +57,31 @@ func testStoreSize_ssa(p *uint16, q *uint16, v uint32) { var failed = false +func testExtStore_ssa(p *byte, b bool) int { + switch { + } + x := *p + *p = 7 + if b { + return int(x) + } + return 0 +} + +func testExtStore() { + const start = 8 + var b byte = start + if got := testExtStore_ssa(&b, true); got != start { + fmt.Println("testExtStore failed. want =", start, ", got =", got) + failed = true + } +} + func main() { testLoadStoreOrder() testStoreSize() + testExtStore() if failed { panic("failed") diff --git a/src/cmd/compile/internal/ssa/gen/AMD64.rules b/src/cmd/compile/internal/ssa/gen/AMD64.rules index 0591e8f8ef..5f34f76eda 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64.rules +++ b/src/cmd/compile/internal/ssa/gen/AMD64.rules @@ -474,8 +474,14 @@ (SETNE (InvertFlags x)) -> (SETNE x) // sign extended loads -(MOVBQSX (MOVBload [off] {sym} ptr mem)) -> (MOVBQSXload [off] {sym} ptr mem) -(MOVBQZX (MOVBload [off] {sym} ptr mem)) -> (MOVBQZXload [off] {sym} ptr mem) +// Note: The combined instruction must end up in the same block +// as the original load. If not, we end up making a value with +// memory type live in two different blocks, which can lead to +// multiple memory values alive simultaneously. +// TODO: somehow have this rewrite rule put the new MOVBQSXload in +// v.Args[0].Block instead of in v.Block? +(MOVBQSX (MOVBload [off] {sym} ptr mem)) && b == v.Args[0].Block -> (MOVBQSXload [off] {sym} ptr mem) +(MOVBQZX (MOVBload [off] {sym} ptr mem)) && b == v.Args[0].Block -> (MOVBQZXload [off] {sym} ptr mem) // TODO: more // Don't extend before storing diff --git a/src/cmd/compile/internal/ssa/regalloc.go b/src/cmd/compile/internal/ssa/regalloc.go index 3122c7a130..f529b42fe0 100644 --- a/src/cmd/compile/internal/ssa/regalloc.go +++ b/src/cmd/compile/internal/ssa/regalloc.go @@ -1046,5 +1046,33 @@ func (f *Func) live() [][][]ID { break } } + + // Make sure that there is only one live memory variable in each set. + // Ideally we should check this at every instructiom, but at every + // edge seems good enough for now. + isMem := make([]bool, f.NumValues()) + for _, b := range f.Blocks { + for _, v := range b.Values { + isMem[v.ID] = v.Type.IsMemory() + } + } + for _, b := range f.Blocks { + for i, c := range b.Succs { + nmem := 0 + for _, id := range live[b.ID][i] { + if isMem[id] { + nmem++ + } + } + if nmem > 1 { + f.Fatalf("more than one mem live on edge %v->%v: %v", b, c, live[b.ID][i]) + } + // TODO: figure out why we get nmem==0 occasionally. + //if nmem == 0 { + // f.Fatalf("no mem live on edge %v->%v: %v", b, c, live[b.ID][i]) + //} + } + } + return live } diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go index cb6405d44d..d2f5ca8f32 100644 --- a/src/cmd/compile/internal/ssa/rewriteAMD64.go +++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go @@ -3939,16 +3939,19 @@ func rewriteValueAMD64(v *Value, config *Config) bool { ; case OpAMD64MOVBQSX: // match: (MOVBQSX (MOVBload [off] {sym} ptr mem)) - // cond: + // cond: b == v.Args[0].Block // result: (MOVBQSXload [off] {sym} ptr mem) { if v.Args[0].Op != OpAMD64MOVBload { - goto end9de452216bde3b2e2a2d01f43da1f78e + goto end4fcdab76af223d4a6b942b532ebf860b } off := v.Args[0].AuxInt sym := v.Args[0].Aux ptr := v.Args[0].Args[0] mem := v.Args[0].Args[1] + if !(b == v.Args[0].Block) { + goto end4fcdab76af223d4a6b942b532ebf860b + } v.Op = OpAMD64MOVBQSXload v.AuxInt = 0 v.Aux = nil @@ -3959,21 +3962,24 @@ func rewriteValueAMD64(v *Value, config *Config) bool { v.AddArg(mem) return true } - goto end9de452216bde3b2e2a2d01f43da1f78e - end9de452216bde3b2e2a2d01f43da1f78e: + goto end4fcdab76af223d4a6b942b532ebf860b + end4fcdab76af223d4a6b942b532ebf860b: ; case OpAMD64MOVBQZX: // match: (MOVBQZX (MOVBload [off] {sym} ptr mem)) - // cond: + // cond: b == v.Args[0].Block // result: (MOVBQZXload [off] {sym} ptr mem) { if v.Args[0].Op != OpAMD64MOVBload { - goto end573f4e6a6fe8032338b85fddd4d1bab4 + goto endce35c966b0a38aa124a610e5616a220c } off := v.Args[0].AuxInt sym := v.Args[0].Aux ptr := v.Args[0].Args[0] mem := v.Args[0].Args[1] + if !(b == v.Args[0].Block) { + goto endce35c966b0a38aa124a610e5616a220c + } v.Op = OpAMD64MOVBQZXload v.AuxInt = 0 v.Aux = nil @@ -3984,8 +3990,8 @@ func rewriteValueAMD64(v *Value, config *Config) bool { v.AddArg(mem) return true } - goto end573f4e6a6fe8032338b85fddd4d1bab4 - end573f4e6a6fe8032338b85fddd4d1bab4: + goto endce35c966b0a38aa124a610e5616a220c + endce35c966b0a38aa124a610e5616a220c: ; case OpAMD64MOVBload: // match: (MOVBload [off1] {sym} (ADDQconst [off2] ptr) mem) -- cgit v1.3 From 9d22c101f58dd8f65410fb352562b91de5fbcb7a Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Fri, 11 Sep 2015 11:02:57 -0700 Subject: [dev.ssa] cmd/compile/internal/gc: implement OAPPEND Change-Id: I1fbce8c421c48074a964b4d9481c92fbc3524f80 Reviewed-on: https://go-review.googlesource.com/14525 Reviewed-by: Todd Neal --- src/cmd/compile/internal/gc/ssa.go | 182 +++++++++++++++++---- src/cmd/compile/internal/gc/ssa_test.go | 2 + src/cmd/compile/internal/gc/testdata/append_ssa.go | 71 ++++++++ 3 files changed, 221 insertions(+), 34 deletions(-) create mode 100644 src/cmd/compile/internal/gc/testdata/append_ssa.go (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index e6a5627abf..5cd074b0c6 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -181,7 +181,7 @@ func buildssa(fn *Node) (ssafn *ssa.Func, usessa bool) { hstr += fmt.Sprintf("%08b", b) } if strings.HasSuffix(hstr, os.Getenv("GOSSAHASH")) { - fmt.Println("GOSSAHASH triggered %s\n", name) + fmt.Printf("GOSSAHASH triggered %s\n", name) return s.f, true } return s.f, false @@ -264,6 +264,7 @@ var memvar = Node{Op: ONAME, Sym: &Sym{Name: "mem"}} // dummy nodes for temporary variables var ptrvar = Node{Op: ONAME, Sym: &Sym{Name: "ptr"}} +var capvar = Node{Op: ONAME, Sym: &Sym{Name: "cap"}} // startBlock sets the current block we're generating code in to b. func (s *state) startBlock(b *ssa.Block) { @@ -560,6 +561,16 @@ func (s *state) stmt(n *Node) { if n.Right != nil { r = s.expr(n.Right) } + if n.Right != nil && n.Right.Op == OAPPEND { + // Yuck! The frontend gets rid of the write barrier, but we need it! + // At least, we need it in the case where growslice is called. + // TODO: Do the write barrier on just the growslice branch. + // TODO: just add a ptr graying to the end of growslice? + // TODO: check whether we need to do this for ODOTTYPE and ORECV also. + // They get similar wb-removal treatment in walk.go:OAS. + s.assign(n.Left, r, true) + return + } s.assign(n.Left, r, n.Op == OASWB) case OIF: @@ -1865,6 +1876,103 @@ func (s *state) expr(n *Node) *ssa.Value { case OGETG: return s.newValue0(ssa.OpGetG, n.Type) + case OAPPEND: + // append(s, e1, e2, e3). Compile like: + // ptr,len,cap := s + // newlen := len + 3 + // if newlen > s.cap { + // ptr,_,cap = growslice(s, newlen) + // } + // *(ptr+len) = e1 + // *(ptr+len+1) = e2 + // *(ptr+len+2) = e3 + // makeslice(ptr,newlen,cap) + + et := n.Type.Type + pt := Ptrto(et) + + // Evaluate slice + slice := s.expr(n.List.N) + + // Evaluate args + nargs := int64(count(n.List) - 1) + args := make([]*ssa.Value, 0, nargs) + for l := n.List.Next; l != nil; l = l.Next { + args = append(args, s.expr(l.N)) + } + + // Allocate new blocks + grow := s.f.NewBlock(ssa.BlockPlain) + growresult := s.f.NewBlock(ssa.BlockPlain) + assign := s.f.NewBlock(ssa.BlockPlain) + + // Decide if we need to grow + p := s.newValue1(ssa.OpSlicePtr, pt, slice) + l := s.newValue1(ssa.OpSliceLen, Types[TINT], slice) + c := s.newValue1(ssa.OpSliceCap, Types[TINT], slice) + nl := s.newValue2(s.ssaOp(OADD, Types[TINT]), Types[TINT], l, s.constInt(Types[TINT], nargs)) + cmp := s.newValue2(s.ssaOp(OGT, Types[TINT]), Types[TBOOL], nl, c) + s.vars[&ptrvar] = p + s.vars[&capvar] = c + b := s.endBlock() + b.Kind = ssa.BlockIf + b.Likely = ssa.BranchUnlikely + b.Control = cmp + b.AddEdgeTo(grow) + b.AddEdgeTo(assign) + + // Call growslice + s.startBlock(grow) + taddr := s.newValue1A(ssa.OpAddr, Types[TUINTPTR], &ssa.ExternSymbol{Types[TUINTPTR], typenamesym(n.Type)}, s.sb) + + spplus1 := s.newValue1I(ssa.OpOffPtr, Types[TUINTPTR], int64(Widthptr), s.sp) + spplus2 := s.newValue1I(ssa.OpOffPtr, Types[TUINTPTR], int64(2*Widthptr), s.sp) + spplus3 := s.newValue1I(ssa.OpOffPtr, Types[TUINTPTR], int64(3*Widthptr), s.sp) + spplus4 := s.newValue1I(ssa.OpOffPtr, Types[TUINTPTR], int64(4*Widthptr), s.sp) + s.vars[&memvar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, int64(Widthptr), s.sp, taddr, s.mem()) + s.vars[&memvar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, int64(Widthptr), spplus1, p, s.mem()) + s.vars[&memvar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, int64(Widthptr), spplus2, l, s.mem()) + s.vars[&memvar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, int64(Widthptr), spplus3, c, s.mem()) + s.vars[&memvar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, int64(Widthptr), spplus4, nl, s.mem()) + call := s.newValue1A(ssa.OpStaticCall, ssa.TypeMem, syslook("growslice", 0).Sym, s.mem()) + call.AuxInt = int64(8 * Widthptr) + s.vars[&memvar] = call + b = s.endBlock() + b.Kind = ssa.BlockCall + b.Control = call + b.AddEdgeTo(growresult) + + // Read result of growslice + s.startBlock(growresult) + spplus5 := s.newValue1I(ssa.OpOffPtr, Types[TUINTPTR], int64(5*Widthptr), s.sp) + // Note: we don't need to read the result's length. + spplus7 := s.newValue1I(ssa.OpOffPtr, Types[TUINTPTR], int64(7*Widthptr), s.sp) + s.vars[&ptrvar] = s.newValue2(ssa.OpLoad, pt, spplus5, s.mem()) + s.vars[&capvar] = s.newValue2(ssa.OpLoad, Types[TINT], spplus7, s.mem()) + b = s.endBlock() + b.AddEdgeTo(assign) + + // assign new elements to slots + s.startBlock(assign) + p = s.variable(&ptrvar, pt) // generates phi for ptr + c = s.variable(&capvar, Types[TINT]) // generates phi for cap + p2 := s.newValue2(ssa.OpPtrIndex, pt, p, l) + for i, arg := range args { + addr := s.newValue2(ssa.OpPtrIndex, pt, p2, s.constInt(Types[TUINTPTR], int64(i))) + s.vars[&memvar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, et.Size(), addr, arg, s.mem()) + if haspointers(et) { + // TODO: just one write barrier call for all of these writes? + // TODO: maybe just one writeBarrierEnabled check? + s.insertWB(et, addr) + } + } + + // make result + r := s.newValue3(ssa.OpSliceMake, n.Type, p, nl, c) + delete(s.vars, &ptrvar) + delete(s.vars, &capvar) + return r + default: s.Unimplementedf("unhandled expr %s", opnames[n.Op]) return nil @@ -1902,39 +2010,7 @@ func (s *state) assign(left *Node, right *ssa.Value, wb bool) { } s.vars[&memvar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, t.Size(), addr, right, s.mem()) if wb { - // if writeBarrierEnabled { - // typedmemmove_nostore(t, &l) - // } - bThen := s.f.NewBlock(ssa.BlockPlain) - bNext := s.f.NewBlock(ssa.BlockPlain) - - aux := &ssa.ExternSymbol{Types[TBOOL], syslook("writeBarrierEnabled", 0).Sym} - flagaddr := s.newValue1A(ssa.OpAddr, Ptrto(Types[TBOOL]), aux, s.sb) - flag := s.newValue2(ssa.OpLoad, Types[TBOOL], flagaddr, s.mem()) - b := s.endBlock() - b.Kind = ssa.BlockIf - b.Likely = ssa.BranchUnlikely - b.Control = flag - b.AddEdgeTo(bThen) - b.AddEdgeTo(bNext) - - s.startBlock(bThen) - // NOTE: there must be no GC suspension points between the write above - // (the OpStore) and this call to typedmemmove_nostore. - // TODO: writebarrierptr_nostore if just one pointer word (or a few?) - taddr := s.newValue1A(ssa.OpAddr, Types[TUINTPTR], &ssa.ExternSymbol{Types[TUINTPTR], typenamesym(left.Type)}, s.sb) - s.vars[&memvar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, int64(Widthptr), s.sp, taddr, s.mem()) - spplus8 := s.newValue1I(ssa.OpOffPtr, Types[TUINTPTR], int64(Widthptr), s.sp) - s.vars[&memvar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, int64(Widthptr), spplus8, addr, s.mem()) - call := s.newValue1A(ssa.OpStaticCall, ssa.TypeMem, syslook("typedmemmove_nostore", 0).Sym, s.mem()) - call.AuxInt = int64(2 * Widthptr) - s.vars[&memvar] = call - c := s.endBlock() - c.Kind = ssa.BlockCall - c.Control = call - c.AddEdgeTo(bNext) - - s.startBlock(bNext) + s.insertWB(left.Type, addr) } } @@ -2228,6 +2304,44 @@ func (s *state) check(cmp *ssa.Value, panicOp ssa.Op) { s.startBlock(bNext) } +// insertWB inserts a write barrier. A value of type t has already +// been stored at location p. Tell the runtime about this write. +// Note: there must be no GC suspension points between the write and +// the call that this function inserts. +func (s *state) insertWB(t *Type, p *ssa.Value) { + // if writeBarrierEnabled { + // typedmemmove_nostore(&t, p) + // } + bThen := s.f.NewBlock(ssa.BlockPlain) + bNext := s.f.NewBlock(ssa.BlockPlain) + + aux := &ssa.ExternSymbol{Types[TBOOL], syslook("writeBarrierEnabled", 0).Sym} + flagaddr := s.newValue1A(ssa.OpAddr, Ptrto(Types[TBOOL]), aux, s.sb) + flag := s.newValue2(ssa.OpLoad, Types[TBOOL], flagaddr, s.mem()) + b := s.endBlock() + b.Kind = ssa.BlockIf + b.Likely = ssa.BranchUnlikely + b.Control = flag + b.AddEdgeTo(bThen) + b.AddEdgeTo(bNext) + + s.startBlock(bThen) + // TODO: writebarrierptr_nostore if just one pointer word (or a few?) + taddr := s.newValue1A(ssa.OpAddr, Types[TUINTPTR], &ssa.ExternSymbol{Types[TUINTPTR], typenamesym(t)}, s.sb) + s.vars[&memvar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, int64(Widthptr), s.sp, taddr, s.mem()) + spplus8 := s.newValue1I(ssa.OpOffPtr, Types[TUINTPTR], int64(Widthptr), s.sp) + s.vars[&memvar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, int64(Widthptr), spplus8, p, s.mem()) + call := s.newValue1A(ssa.OpStaticCall, ssa.TypeMem, syslook("typedmemmove_nostore", 0).Sym, s.mem()) + call.AuxInt = int64(2 * Widthptr) + s.vars[&memvar] = call + c := s.endBlock() + c.Kind = ssa.BlockCall + c.Control = call + c.AddEdgeTo(bNext) + + s.startBlock(bNext) +} + // slice computes the slice v[i:j:k] and returns ptr, len, and cap of result. // i,j,k may be nil, in which case they are set to their default value. // t is a slice, ptr to array, or string type. diff --git a/src/cmd/compile/internal/gc/ssa_test.go b/src/cmd/compile/internal/gc/ssa_test.go index b3ab09d914..bbd06748b1 100644 --- a/src/cmd/compile/internal/gc/ssa_test.go +++ b/src/cmd/compile/internal/gc/ssa_test.go @@ -82,3 +82,5 @@ func TestDeferNoReturn(t *testing.T) { buildTest(t, "deferNoReturn_ssa.go") } func TestClosure(t *testing.T) { runTest(t, "closure_ssa.go") } func TestArray(t *testing.T) { runTest(t, "array_ssa.go") } + +func TestAppend(t *testing.T) { runTest(t, "append_ssa.go") } diff --git a/src/cmd/compile/internal/gc/testdata/append_ssa.go b/src/cmd/compile/internal/gc/testdata/append_ssa.go new file mode 100644 index 0000000000..dba81736c8 --- /dev/null +++ b/src/cmd/compile/internal/gc/testdata/append_ssa.go @@ -0,0 +1,71 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// append_ssa.go tests append operations. +package main + +import "fmt" + +var failed = false + +func appendOne_ssa(a []int, x int) []int { + switch { // prevent inlining + } + return append(a, x) +} +func appendThree_ssa(a []int, x, y, z int) []int { + switch { // prevent inlining + } + return append(a, x, y, z) +} + +func eq(a, b []int) bool { + if len(a) != len(b) { + return false + } + for i := range a { + if a[i] != b[i] { + return false + } + } + return true +} + +func expect(got, want []int) { + if eq(got, want) { + return + } + fmt.Printf("expected %v, got %v\n", want, got) + failed = true +} + +func testAppend() { + var store [7]int + a := store[:0] + + a = appendOne_ssa(a, 1) + expect(a, []int{1}) + a = appendThree_ssa(a, 2, 3, 4) + expect(a, []int{1, 2, 3, 4}) + a = appendThree_ssa(a, 5, 6, 7) + expect(a, []int{1, 2, 3, 4, 5, 6, 7}) + if &a[0] != &store[0] { + fmt.Println("unnecessary grow") + failed = true + } + a = appendOne_ssa(a, 8) + expect(a, []int{1, 2, 3, 4, 5, 6, 7, 8}) + if &a[0] == &store[0] { + fmt.Println("didn't grow") + failed = true + } +} + +func main() { + testAppend() + + if failed { + panic("failed") + } +} -- cgit v1.3 From 269baa981e327caea3adb4722f17b4b02d5c834c Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Thu, 17 Sep 2015 10:31:16 -0700 Subject: [dev.ssa] cmd/compile: implement ODOTTYPE and OAS2DOTTYPE Taken over and completed from Josh's change https://go-review.googlesource.com/#/c/14524/ Change-Id: If5d4f732843cc3e99bd5edda54458f0a8be73e91 Reviewed-on: https://go-review.googlesource.com/14690 Reviewed-by: Josh Bleecher Snyder --- src/cmd/compile/internal/gc/ssa.go | 143 +++++++++++++++++++- src/cmd/compile/internal/gc/ssa_test.go | 3 + src/cmd/compile/internal/gc/testdata/assert_ssa.go | 147 +++++++++++++++++++++ 3 files changed, 287 insertions(+), 6 deletions(-) create mode 100644 src/cmd/compile/internal/gc/testdata/assert_ssa.go (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index c053eabcba..7268a34a12 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -259,12 +259,17 @@ func (s *state) Logf(msg string, args ...interface{}) { s.config.Logf( func (s *state) Fatalf(msg string, args ...interface{}) { s.config.Fatalf(msg, args...) } func (s *state) Unimplementedf(msg string, args ...interface{}) { s.config.Unimplementedf(msg, args...) } -// dummy node for the memory variable -var memvar = Node{Op: ONAME, Sym: &Sym{Name: "mem"}} - -// dummy nodes for temporary variables -var ptrvar = Node{Op: ONAME, Sym: &Sym{Name: "ptr"}} -var capvar = Node{Op: ONAME, Sym: &Sym{Name: "cap"}} +var ( + // dummy node for the memory variable + memvar = Node{Op: ONAME, Sym: &Sym{Name: "mem"}} + + // dummy nodes for temporary variables + ptrvar = Node{Op: ONAME, Sym: &Sym{Name: "ptr"}} + capvar = Node{Op: ONAME, Sym: &Sym{Name: "cap"}} + typVar = Node{Op: ONAME, Sym: &Sym{Name: "typ"}} + idataVar = Node{Op: ONAME, Sym: &Sym{Name: "idata"}} + okVar = Node{Op: ONAME, Sym: &Sym{Name: "ok"}} +) // startBlock sets the current block we're generating code in to b. func (s *state) startBlock(b *ssa.Block) { @@ -474,6 +479,12 @@ func (s *state) stmt(n *Node) { case OPROC: s.call(n.Left, callGo) + case OAS2DOTTYPE: + res, resok := s.dottype(n.Rlist.N, true) + s.assign(n.List.N, res, false) + s.assign(n.List.Next.N, resok, false) + return + case ODCL: if n.Left.Class&PHEAP == 0 { return @@ -1471,6 +1482,10 @@ func (s *state) expr(n *Node) *ssa.Value { s.Unimplementedf("unhandled OCONV %s -> %s", Econv(int(n.Left.Type.Etype), 0), Econv(int(n.Type.Etype), 0)) return nil + case ODOTTYPE: + res, _ := s.dottype(n, false) + return res + // binary ops case OLT, OEQ, ONE, OLE, OGE, OGT: a := s.expr(n.Left) @@ -2723,6 +2738,122 @@ func (s *state) floatToUint(cvttab *f2uCvtTab, n *Node, x *ssa.Value, ft, tt *Ty return s.variable(n, n.Type) } +// ifaceType returns the value for the word containing the type. +// n is the node for the interface expression. +// v is the corresponding value. +func (s *state) ifaceType(n *Node, v *ssa.Value) *ssa.Value { + byteptr := Ptrto(Types[TUINT8]) // type used in runtime prototypes for runtime type (*byte) + + if isnilinter(n.Type) { + // Have *eface. The type is the first word in the struct. + return s.newValue1(ssa.OpITab, byteptr, v) + } + + // Have *iface. + // The first word in the struct is the *itab. + // If the *itab is nil, return 0. + // Otherwise, the second word in the *itab is the type. + + tab := s.newValue1(ssa.OpITab, byteptr, v) + s.vars[&typVar] = tab + isnonnil := s.newValue2(ssa.OpNeqPtr, Types[TBOOL], tab, s.entryNewValue0(ssa.OpConstNil, byteptr)) + b := s.endBlock() + b.Kind = ssa.BlockIf + b.Control = isnonnil + b.Likely = ssa.BranchLikely + + bLoad := s.f.NewBlock(ssa.BlockPlain) + bEnd := s.f.NewBlock(ssa.BlockPlain) + + b.AddEdgeTo(bLoad) + b.AddEdgeTo(bEnd) + bLoad.AddEdgeTo(bEnd) + + s.startBlock(bLoad) + off := s.newValue1I(ssa.OpOffPtr, byteptr, int64(Widthptr), tab) + s.vars[&typVar] = s.newValue2(ssa.OpLoad, byteptr, off, s.mem()) + s.endBlock() + + s.startBlock(bEnd) + typ := s.variable(&typVar, byteptr) + delete(s.vars, &typVar) + return typ +} + +// dottype generates SSA for a type assertion node. +// commaok indicates whether to panic or return a bool. +// If commaok is false, resok will be nil. +func (s *state) dottype(n *Node, commaok bool) (res, resok *ssa.Value) { + iface := s.expr(n.Left) + typ := s.ifaceType(n.Left, iface) // actual concrete type + target := s.expr(typename(n.Type)) // target type + if !isdirectiface(n.Type) { + // walk rewrites ODOTTYPE/OAS2DOTTYPE into runtime calls except for this case. + Fatalf("dottype needs a direct iface type %s", n.Type) + } + + // TODO: If we have a nonempty interface and its itab field is nil, + // then this test is redundant and ifaceType should just branch directly to bFail. + cond := s.newValue2(ssa.OpEqPtr, Types[TBOOL], typ, target) + b := s.endBlock() + b.Kind = ssa.BlockIf + b.Control = cond + b.Likely = ssa.BranchLikely + + byteptr := Ptrto(Types[TUINT8]) + + bOk := s.f.NewBlock(ssa.BlockPlain) + bFail := s.f.NewBlock(ssa.BlockPlain) + b.AddEdgeTo(bOk) + b.AddEdgeTo(bFail) + + if !commaok { + // on failure, panic by calling panicdottype + s.startBlock(bFail) + + spplus1 := s.newValue1I(ssa.OpOffPtr, Types[TUINTPTR], int64(Widthptr), s.sp) + spplus2 := s.newValue1I(ssa.OpOffPtr, Types[TUINTPTR], int64(2*Widthptr), s.sp) + taddr := s.newValue1A(ssa.OpAddr, byteptr, &ssa.ExternSymbol{byteptr, typenamesym(n.Left.Type)}, s.sb) + s.vars[&memvar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, int64(Widthptr), s.sp, typ, s.mem()) // actual dynamic type + s.vars[&memvar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, int64(Widthptr), spplus1, target, s.mem()) // type we're casting to + s.vars[&memvar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, int64(Widthptr), spplus2, taddr, s.mem()) // static source type + call := s.newValue1A(ssa.OpStaticCall, ssa.TypeMem, syslook("panicdottype", 0).Sym, s.mem()) + s.endBlock() + bFail.Kind = ssa.BlockExit + bFail.Control = call + + // on success, return idata field + s.startBlock(bOk) + return s.newValue1(ssa.OpIData, n.Type, iface), nil + } + + // commaok is the more complicated case because we have + // a control flow merge point. + bEnd := s.f.NewBlock(ssa.BlockPlain) + + // type assertion succeeded + s.startBlock(bOk) + s.vars[&idataVar] = s.newValue1(ssa.OpIData, n.Type, iface) + s.vars[&okVar] = s.constBool(true) + s.endBlock() + bOk.AddEdgeTo(bEnd) + + // type assertion failed + s.startBlock(bFail) + s.vars[&idataVar] = s.entryNewValue0(ssa.OpConstNil, byteptr) + s.vars[&okVar] = s.constBool(false) + s.endBlock() + bFail.AddEdgeTo(bEnd) + + // merge point + s.startBlock(bEnd) + res = s.variable(&idataVar, byteptr) + resok = s.variable(&okVar, Types[TBOOL]) + delete(s.vars, &idataVar) + delete(s.vars, &okVar) + return res, resok +} + // checkgoto checks that a goto from from to to does not // jump into a block or jump over variable declarations. // It is a copy of checkgoto in the pre-SSA backend, diff --git a/src/cmd/compile/internal/gc/ssa_test.go b/src/cmd/compile/internal/gc/ssa_test.go index bbd06748b1..b63749fcc6 100644 --- a/src/cmd/compile/internal/gc/ssa_test.go +++ b/src/cmd/compile/internal/gc/ssa_test.go @@ -48,6 +48,9 @@ func TestShortCircuit(t *testing.T) { runTest(t, "short_ssa.go") } // TestBreakContinue tests that continue and break statements do what they say. func TestBreakContinue(t *testing.T) { runTest(t, "break_ssa.go") } +// TestTypeAssertion tests type assertions. +func TestTypeAssertion(t *testing.T) { runTest(t, "assert_ssa.go") } + // TestArithmetic tests that both backends have the same result for arithmetic expressions. func TestArithmetic(t *testing.T) { runTest(t, "arith_ssa.go") } diff --git a/src/cmd/compile/internal/gc/testdata/assert_ssa.go b/src/cmd/compile/internal/gc/testdata/assert_ssa.go new file mode 100644 index 0000000000..d64d4fc35a --- /dev/null +++ b/src/cmd/compile/internal/gc/testdata/assert_ssa.go @@ -0,0 +1,147 @@ +// run + +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Tests type assertion expressions and statements + +package main + +import ( + "fmt" + "runtime" +) + +type ( + S struct{} + T struct{} + + I interface { + F() + } +) + +var ( + s *S + t *T +) + +func (s *S) F() {} +func (t *T) F() {} + +func e2t_ssa(e interface{}) *T { + return e.(*T) +} + +func i2t_ssa(i I) *T { + return i.(*T) +} + +func testAssertE2TOk() { + if got := e2t_ssa(t); got != t { + fmt.Printf("e2t_ssa(t)=%v want %v", got, t) + failed = true + } +} + +func testAssertE2TPanic() { + var got *T + defer func() { + if got != nil { + fmt.Printf("e2t_ssa(s)=%v want nil", got) + failed = true + } + e := recover() + err, ok := e.(*runtime.TypeAssertionError) + if !ok { + fmt.Printf("e2t_ssa(s) panic type %T", e) + failed = true + } + want := "interface conversion: interface {} is *main.S, not *main.T" + if err.Error() != want { + fmt.Printf("e2t_ssa(s) wrong error, want '%s', got '%s'\n", want, err.Error()) + failed = true + } + }() + got = e2t_ssa(s) + fmt.Printf("e2t_ssa(s) should panic") + failed = true +} + +func testAssertI2TOk() { + if got := i2t_ssa(t); got != t { + fmt.Printf("i2t_ssa(t)=%v want %v", got, t) + failed = true + } +} + +func testAssertI2TPanic() { + var got *T + defer func() { + if got != nil { + fmt.Printf("i2t_ssa(s)=%v want nil", got) + failed = true + } + e := recover() + err, ok := e.(*runtime.TypeAssertionError) + if !ok { + fmt.Printf("i2t_ssa(s) panic type %T", e) + failed = true + } + want := "interface conversion: main.I is *main.S, not *main.T" + if err.Error() != want { + fmt.Printf("i2t_ssa(s) wrong error, want '%s', got '%s'\n", want, err.Error()) + failed = true + } + }() + got = i2t_ssa(s) + fmt.Printf("i2t_ssa(s) should panic") + failed = true +} + +func e2t2_ssa(e interface{}) (*T, bool) { + t, ok := e.(*T) + return t, ok +} + +func i2t2_ssa(i I) (*T, bool) { + t, ok := i.(*T) + return t, ok +} + +func testAssertE2T2() { + if got, ok := e2t2_ssa(t); !ok || got != t { + fmt.Printf("e2t2_ssa(t)=(%v, %v) want (%v, %v)", got, ok, t, true) + failed = true + } + if got, ok := e2t2_ssa(s); ok || got != nil { + fmt.Printf("e2t2_ssa(s)=(%v, %v) want (%v, %v)", got, ok, nil, false) + failed = true + } +} + +func testAssertI2T2() { + if got, ok := i2t2_ssa(t); !ok || got != t { + fmt.Printf("i2t2_ssa(t)=(%v, %v) want (%v, %v)", got, ok, t, true) + failed = true + } + if got, ok := i2t2_ssa(s); ok || got != nil { + fmt.Printf("i2t2_ssa(s)=(%v, %v) want (%v, %v)", got, ok, nil, false) + failed = true + } +} + +var failed = false + +func main() { + testAssertE2TOk() + testAssertE2TPanic() + testAssertI2TOk() + testAssertI2TPanic() + testAssertE2T2() + testAssertI2T2() + if failed { + panic("failed") + } +} -- cgit v1.3 From 04d6edc36debf5e3ec5420f2522f7ef4341bb65e Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Fri, 18 Sep 2015 18:23:34 -0700 Subject: [dev.ssa] cmd/compile: clean up zeroing. Use duffzero when appropriate. Change-Id: I4deb03340e87f43179d5e22bf81843c17b5581fc Reviewed-on: https://go-review.googlesource.com/14756 Reviewed-by: David Chase --- src/cmd/compile/internal/gc/ssa.go | 27 +- src/cmd/compile/internal/gc/ssa_test.go | 2 + .../compile/internal/gc/testdata/gen/zeroGen.go | 88 ++++ src/cmd/compile/internal/gc/testdata/zero_ssa.go | 563 +++++++++++++++++++++ src/cmd/compile/internal/ssa/gen/AMD64.rules | 53 +- src/cmd/compile/internal/ssa/gen/AMD64Ops.go | 86 ++-- src/cmd/compile/internal/ssa/opGen.go | 11 +- src/cmd/compile/internal/ssa/rewrite.go | 49 ++ src/cmd/compile/internal/ssa/rewriteAMD64.go | 417 +++++++++++++-- 9 files changed, 1183 insertions(+), 113 deletions(-) create mode 100644 src/cmd/compile/internal/gc/testdata/gen/zeroGen.go create mode 100644 src/cmd/compile/internal/gc/testdata/zero_ssa.go (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index b9da5eda7c..51cf01a9ed 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -3613,22 +3613,12 @@ func (s *genState) genValue(v *ssa.Value) { ssa.OpAMD64CVTTSS2SL, ssa.OpAMD64CVTTSD2SL, ssa.OpAMD64CVTTSS2SQ, ssa.OpAMD64CVTTSD2SQ, ssa.OpAMD64CVTSS2SD, ssa.OpAMD64CVTSD2SS: opregreg(v.Op.Asm(), regnum(v), regnum(v.Args[0])) - case ssa.OpAMD64MOVXzero: - nb := v.AuxInt - offset := int64(0) - reg := regnum(v.Args[0]) - for nb >= 8 { - nb, offset = movZero(x86.AMOVQ, 8, nb, offset, reg) - } - for nb >= 4 { - nb, offset = movZero(x86.AMOVL, 4, nb, offset, reg) - } - for nb >= 2 { - nb, offset = movZero(x86.AMOVW, 2, nb, offset, reg) - } - for nb >= 1 { - nb, offset = movZero(x86.AMOVB, 1, nb, offset, reg) - } + case ssa.OpAMD64DUFFZERO: + p := Prog(obj.ADUFFZERO) + p.To.Type = obj.TYPE_ADDR + p.To.Sym = Linksym(Pkglookup("duffzero", Runtimepkg)) + p.To.Offset = v.AuxInt + case ssa.OpCopy: // TODO: lower to MOVQ earlier? if v.Type.IsMemory() { return @@ -3830,11 +3820,6 @@ func (s *genState) genValue(v *ssa.Value) { case ssa.OpAMD64InvertFlags: v.Fatalf("InvertFlags should never make it to codegen %v", v) case ssa.OpAMD64REPSTOSQ: - p := Prog(x86.AXORL) // TODO: lift out zeroing into its own instruction? - p.From.Type = obj.TYPE_REG - p.From.Reg = x86.REG_AX - p.To.Type = obj.TYPE_REG - p.To.Reg = x86.REG_AX Prog(x86.AREP) Prog(x86.ASTOSQ) case ssa.OpAMD64REPMOVSB: diff --git a/src/cmd/compile/internal/gc/ssa_test.go b/src/cmd/compile/internal/gc/ssa_test.go index b63749fcc6..dafbcf2166 100644 --- a/src/cmd/compile/internal/gc/ssa_test.go +++ b/src/cmd/compile/internal/gc/ssa_test.go @@ -87,3 +87,5 @@ func TestClosure(t *testing.T) { runTest(t, "closure_ssa.go") } func TestArray(t *testing.T) { runTest(t, "array_ssa.go") } func TestAppend(t *testing.T) { runTest(t, "append_ssa.go") } + +func TestZero(t *testing.T) { runTest(t, "zero_ssa.go") } diff --git a/src/cmd/compile/internal/gc/testdata/gen/zeroGen.go b/src/cmd/compile/internal/gc/testdata/gen/zeroGen.go new file mode 100644 index 0000000000..90e8029f3f --- /dev/null +++ b/src/cmd/compile/internal/gc/testdata/gen/zeroGen.go @@ -0,0 +1,88 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "bytes" + "fmt" + "go/format" + "io/ioutil" + "log" +) + +// This program generates tests to verify that zeroing operations +// zero the data they are supposed to and clobber no adjacent values. + +// run as `go run zeroGen.go`. A file called zero_ssa.go +// will be written into the parent directory containing the tests. + +var sizes = [...]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 16, 17, 23, 24, 25, 31, 32, 33, 63, 64, 65, 1023, 1024, 1025} + +func main() { + w := new(bytes.Buffer) + fmt.Fprintf(w, "// run\n") + fmt.Fprintf(w, "// autogenerated from gen/zeroGen.go - do not edit!\n") + fmt.Fprintf(w, "package main\n") + fmt.Fprintf(w, "import \"fmt\"\n") + + for _, s := range sizes { + // type for test + fmt.Fprintf(w, "type T%d struct {\n", s) + fmt.Fprintf(w, " pre [8]byte\n") + fmt.Fprintf(w, " mid [%d]byte\n", s) + fmt.Fprintf(w, " post [8]byte\n") + fmt.Fprintf(w, "}\n") + + // function being tested + fmt.Fprintf(w, "func zero%d_ssa(x *[%d]byte) {\n", s, s) + fmt.Fprintf(w, " switch{}\n") + fmt.Fprintf(w, " *x = [%d]byte{}\n", s) + fmt.Fprintf(w, "}\n") + + // testing harness + fmt.Fprintf(w, "func testZero%d() {\n", s) + fmt.Fprintf(w, " a := T%d{[8]byte{255,255,255,255,255,255,255,255},[%d]byte{", s, s) + for i := 0; i < s; i++ { + fmt.Fprintf(w, "255,") + } + fmt.Fprintf(w, "},[8]byte{255,255,255,255,255,255,255,255}}\n") + fmt.Fprintf(w, " zero%d_ssa(&a.mid)\n", s) + fmt.Fprintf(w, " want := T%d{[8]byte{255,255,255,255,255,255,255,255},[%d]byte{", s, s) + for i := 0; i < s; i++ { + fmt.Fprintf(w, "0,") + } + fmt.Fprintf(w, "},[8]byte{255,255,255,255,255,255,255,255}}\n") + fmt.Fprintf(w, " if a != want {\n") + fmt.Fprintf(w, " fmt.Printf(\"zero%d got=%%v, want %%v\\n\", a, want)\n", s) + fmt.Fprintf(w, " failed=true\n") + fmt.Fprintf(w, " }\n") + fmt.Fprintf(w, "}\n") + } + + // boilerplate at end + fmt.Fprintf(w, "var failed bool\n") + fmt.Fprintf(w, "func main() {\n") + for _, s := range sizes { + fmt.Fprintf(w, " testZero%d()\n", s) + } + fmt.Fprintf(w, " if failed {\n") + fmt.Fprintf(w, " panic(\"failed\")\n") + fmt.Fprintf(w, " }\n") + fmt.Fprintf(w, "}\n") + + // gofmt result + b := w.Bytes() + src, err := format.Source(b) + if err != nil { + fmt.Printf("%s\n", b) + panic(err) + } + + // write to file + err = ioutil.WriteFile("../zero_ssa.go", src, 0666) + if err != nil { + log.Fatalf("can't write output: %v\n", err) + } +} diff --git a/src/cmd/compile/internal/gc/testdata/zero_ssa.go b/src/cmd/compile/internal/gc/testdata/zero_ssa.go new file mode 100644 index 0000000000..0ec883b7f4 --- /dev/null +++ b/src/cmd/compile/internal/gc/testdata/zero_ssa.go @@ -0,0 +1,563 @@ +// run +// autogenerated from gen/zeroGen.go - do not edit! +package main + +import "fmt" + +type T1 struct { + pre [8]byte + mid [1]byte + post [8]byte +} + +func zero1_ssa(x *[1]byte) { + switch { + } + *x = [1]byte{} +} +func testZero1() { + a := T1{[8]byte{255, 255, 255, 255, 255, 255, 255, 255}, [1]byte{255}, [8]byte{255, 255, 255, 255, 255, 255, 255, 255}} + zero1_ssa(&a.mid) + want := T1{[8]byte{255, 255, 255, 255, 255, 255, 255, 255}, [1]byte{0}, [8]byte{255, 255, 255, 255, 255, 255, 255, 255}} + if a != want { + fmt.Printf("zero1 got=%v, want %v\n", a, want) + failed = true + } +} + +type T2 struct { + pre [8]byte + mid [2]byte + post [8]byte +} + +func zero2_ssa(x *[2]byte) { + switch { + } + *x = [2]byte{} +} +func testZero2() { + a := T2{[8]byte{255, 255, 255, 255, 255, 255, 255, 255}, [2]byte{255, 255}, [8]byte{255, 255, 255, 255, 255, 255, 255, 255}} + zero2_ssa(&a.mid) + want := T2{[8]byte{255, 255, 255, 255, 255, 255, 255, 255}, [2]byte{0, 0}, [8]byte{255, 255, 255, 255, 255, 255, 255, 255}} + if a != want { + fmt.Printf("zero2 got=%v, want %v\n", a, want) + failed = true + } +} + +type T3 struct { + pre [8]byte + mid [3]byte + post [8]byte +} + +func zero3_ssa(x *[3]byte) { + switch { + } + *x = [3]byte{} +} +func testZero3() { + a := T3{[8]byte{255, 255, 255, 255, 255, 255, 255, 255}, [3]byte{255, 255, 255}, [8]byte{255, 255, 255, 255, 255, 255, 255, 255}} + zero3_ssa(&a.mid) + want := T3{[8]byte{255, 255, 255, 255, 255, 255, 255, 255}, [3]byte{0, 0, 0}, [8]byte{255, 255, 255, 255, 255, 255, 255, 255}} + if a != want { + fmt.Printf("zero3 got=%v, want %v\n", a, want) + failed = true + } +} + +type T4 struct { + pre [8]byte + mid [4]byte + post [8]byte +} + +func zero4_ssa(x *[4]byte) { + switch { + } + *x = [4]byte{} +} +func testZero4() { + a := T4{[8]byte{255, 255, 255, 255, 255, 255, 255, 255}, [4]byte{255, 255, 255, 255}, [8]byte{255, 255, 255, 255, 255, 255, 255, 255}} + zero4_ssa(&a.mid) + want := T4{[8]byte{255, 255, 255, 255, 255, 255, 255, 255}, [4]byte{0, 0, 0, 0}, [8]byte{255, 255, 255, 255, 255, 255, 255, 255}} + if a != want { + fmt.Printf("zero4 got=%v, want %v\n", a, want) + failed = true + } +} + +type T5 struct { + pre [8]byte + mid [5]byte + post [8]byte +} + +func zero5_ssa(x *[5]byte) { + switch { + } + *x = [5]byte{} +} +func testZero5() { + a := T5{[8]byte{255, 255, 255, 255, 255, 255, 255, 255}, [5]byte{255, 255, 255, 255, 255}, [8]byte{255, 255, 255, 255, 255, 255, 255, 255}} + zero5_ssa(&a.mid) + want := T5{[8]byte{255, 255, 255, 255, 255, 255, 255, 255}, [5]byte{0, 0, 0, 0, 0}, [8]byte{255, 255, 255, 255, 255, 255, 255, 255}} + if a != want { + fmt.Printf("zero5 got=%v, want %v\n", a, want) + failed = true + } +} + +type T6 struct { + pre [8]byte + mid [6]byte + post [8]byte +} + +func zero6_ssa(x *[6]byte) { + switch { + } + *x = [6]byte{} +} +func testZero6() { + a := T6{[8]byte{255, 255, 255, 255, 255, 255, 255, 255}, [6]byte{255, 255, 255, 255, 255, 255}, [8]byte{255, 255, 255, 255, 255, 255, 255, 255}} + zero6_ssa(&a.mid) + want := T6{[8]byte{255, 255, 255, 255, 255, 255, 255, 255}, [6]byte{0, 0, 0, 0, 0, 0}, [8]byte{255, 255, 255, 255, 255, 255, 255, 255}} + if a != want { + fmt.Printf("zero6 got=%v, want %v\n", a, want) + failed = true + } +} + +type T7 struct { + pre [8]byte + mid [7]byte + post [8]byte +} + +func zero7_ssa(x *[7]byte) { + switch { + } + *x = [7]byte{} +} +func testZero7() { + a := T7{[8]byte{255, 255, 255, 255, 255, 255, 255, 255}, [7]byte{255, 255, 255, 255, 255, 255, 255}, [8]byte{255, 255, 255, 255, 255, 255, 255, 255}} + zero7_ssa(&a.mid) + want := T7{[8]byte{255, 255, 255, 255, 255, 255, 255, 255}, [7]byte{0, 0, 0, 0, 0, 0, 0}, [8]byte{255, 255, 255, 255, 255, 255, 255, 255}} + if a != want { + fmt.Printf("zero7 got=%v, want %v\n", a, want) + failed = true + } +} + +type T8 struct { + pre [8]byte + mid [8]byte + post [8]byte +} + +func zero8_ssa(x *[8]byte) { + switch { + } + *x = [8]byte{} +} +func testZero8() { + a := T8{[8]byte{255, 255, 255, 255, 255, 255, 255, 255}, [8]byte{255, 255, 255, 255, 255, 255, 255, 255}, [8]byte{255, 255, 255, 255, 255, 255, 255, 255}} + zero8_ssa(&a.mid) + want := T8{[8]byte{255, 255, 255, 255, 255, 255, 255, 255}, [8]byte{0, 0, 0, 0, 0, 0, 0, 0}, [8]byte{255, 255, 255, 255, 255, 255, 255, 255}} + if a != want { + fmt.Printf("zero8 got=%v, want %v\n", a, want) + failed = true + } +} + +type T9 struct { + pre [8]byte + mid [9]byte + post [8]byte +} + +func zero9_ssa(x *[9]byte) { + switch { + } + *x = [9]byte{} +} +func testZero9() { + a := T9{[8]byte{255, 255, 255, 255, 255, 255, 255, 255}, [9]byte{255, 255, 255, 255, 255, 255, 255, 255, 255}, [8]byte{255, 255, 255, 255, 255, 255, 255, 255}} + zero9_ssa(&a.mid) + want := T9{[8]byte{255, 255, 255, 255, 255, 255, 255, 255}, [9]byte{0, 0, 0, 0, 0, 0, 0, 0, 0}, [8]byte{255, 255, 255, 255, 255, 255, 255, 255}} + if a != want { + fmt.Printf("zero9 got=%v, want %v\n", a, want) + failed = true + } +} + +type T10 struct { + pre [8]byte + mid [10]byte + post [8]byte +} + +func zero10_ssa(x *[10]byte) { + switch { + } + *x = [10]byte{} +} +func testZero10() { + a := T10{[8]byte{255, 255, 255, 255, 255, 255, 255, 255}, [10]byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, [8]byte{255, 255, 255, 255, 255, 255, 255, 255}} + zero10_ssa(&a.mid) + want := T10{[8]byte{255, 255, 255, 255, 255, 255, 255, 255}, [10]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, [8]byte{255, 255, 255, 255, 255, 255, 255, 255}} + if a != want { + fmt.Printf("zero10 got=%v, want %v\n", a, want) + failed = true + } +} + +type T15 struct { + pre [8]byte + mid [15]byte + post [8]byte +} + +func zero15_ssa(x *[15]byte) { + switch { + } + *x = [15]byte{} +} +func testZero15() { + a := T15{[8]byte{255, 255, 255, 255, 255, 255, 255, 255}, [15]byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, [8]byte{255, 255, 255, 255, 255, 255, 255, 255}} + zero15_ssa(&a.mid) + want := T15{[8]byte{255, 255, 255, 255, 255, 255, 255, 255}, [15]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, [8]byte{255, 255, 255, 255, 255, 255, 255, 255}} + if a != want { + fmt.Printf("zero15 got=%v, want %v\n", a, want) + failed = true + } +} + +type T16 struct { + pre [8]byte + mid [16]byte + post [8]byte +} + +func zero16_ssa(x *[16]byte) { + switch { + } + *x = [16]byte{} +} +func testZero16() { + a := T16{[8]byte{255, 255, 255, 255, 255, 255, 255, 255}, [16]byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, [8]byte{255, 255, 255, 255, 255, 255, 255, 255}} + zero16_ssa(&a.mid) + want := T16{[8]byte{255, 255, 255, 255, 255, 255, 255, 255}, [16]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, [8]byte{255, 255, 255, 255, 255, 255, 255, 255}} + if a != want { + fmt.Printf("zero16 got=%v, want %v\n", a, want) + failed = true + } +} + +type T17 struct { + pre [8]byte + mid [17]byte + post [8]byte +} + +func zero17_ssa(x *[17]byte) { + switch { + } + *x = [17]byte{} +} +func testZero17() { + a := T17{[8]byte{255, 255, 255, 255, 255, 255, 255, 255}, [17]byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, [8]byte{255, 255, 255, 255, 255, 255, 255, 255}} + zero17_ssa(&a.mid) + want := T17{[8]byte{255, 255, 255, 255, 255, 255, 255, 255}, [17]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, [8]byte{255, 255, 255, 255, 255, 255, 255, 255}} + if a != want { + fmt.Printf("zero17 got=%v, want %v\n", a, want) + failed = true + } +} + +type T23 struct { + pre [8]byte + mid [23]byte + post [8]byte +} + +func zero23_ssa(x *[23]byte) { + switch { + } + *x = [23]byte{} +} +func testZero23() { + a := T23{[8]byte{255, 255, 255, 255, 255, 255, 255, 255}, [23]byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, [8]byte{255, 255, 255, 255, 255, 255, 255, 255}} + zero23_ssa(&a.mid) + want := T23{[8]byte{255, 255, 255, 255, 255, 255, 255, 255}, [23]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, [8]byte{255, 255, 255, 255, 255, 255, 255, 255}} + if a != want { + fmt.Printf("zero23 got=%v, want %v\n", a, want) + failed = true + } +} + +type T24 struct { + pre [8]byte + mid [24]byte + post [8]byte +} + +func zero24_ssa(x *[24]byte) { + switch { + } + *x = [24]byte{} +} +func testZero24() { + a := T24{[8]byte{255, 255, 255, 255, 255, 255, 255, 255}, [24]byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, [8]byte{255, 255, 255, 255, 255, 255, 255, 255}} + zero24_ssa(&a.mid) + want := T24{[8]byte{255, 255, 255, 255, 255, 255, 255, 255}, [24]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, [8]byte{255, 255, 255, 255, 255, 255, 255, 255}} + if a != want { + fmt.Printf("zero24 got=%v, want %v\n", a, want) + failed = true + } +} + +type T25 struct { + pre [8]byte + mid [25]byte + post [8]byte +} + +func zero25_ssa(x *[25]byte) { + switch { + } + *x = [25]byte{} +} +func testZero25() { + a := T25{[8]byte{255, 255, 255, 255, 255, 255, 255, 255}, [25]byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, [8]byte{255, 255, 255, 255, 255, 255, 255, 255}} + zero25_ssa(&a.mid) + want := T25{[8]byte{255, 255, 255, 255, 255, 255, 255, 255}, [25]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, [8]byte{255, 255, 255, 255, 255, 255, 255, 255}} + if a != want { + fmt.Printf("zero25 got=%v, want %v\n", a, want) + failed = true + } +} + +type T31 struct { + pre [8]byte + mid [31]byte + post [8]byte +} + +func zero31_ssa(x *[31]byte) { + switch { + } + *x = [31]byte{} +} +func testZero31() { + a := T31{[8]byte{255, 255, 255, 255, 255, 255, 255, 255}, [31]byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, [8]byte{255, 255, 255, 255, 255, 255, 255, 255}} + zero31_ssa(&a.mid) + want := T31{[8]byte{255, 255, 255, 255, 255, 255, 255, 255}, [31]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, [8]byte{255, 255, 255, 255, 255, 255, 255, 255}} + if a != want { + fmt.Printf("zero31 got=%v, want %v\n", a, want) + failed = true + } +} + +type T32 struct { + pre [8]byte + mid [32]byte + post [8]byte +} + +func zero32_ssa(x *[32]byte) { + switch { + } + *x = [32]byte{} +} +func testZero32() { + a := T32{[8]byte{255, 255, 255, 255, 255, 255, 255, 255}, [32]byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, [8]byte{255, 255, 255, 255, 255, 255, 255, 255}} + zero32_ssa(&a.mid) + want := T32{[8]byte{255, 255, 255, 255, 255, 255, 255, 255}, [32]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, [8]byte{255, 255, 255, 255, 255, 255, 255, 255}} + if a != want { + fmt.Printf("zero32 got=%v, want %v\n", a, want) + failed = true + } +} + +type T33 struct { + pre [8]byte + mid [33]byte + post [8]byte +} + +func zero33_ssa(x *[33]byte) { + switch { + } + *x = [33]byte{} +} +func testZero33() { + a := T33{[8]byte{255, 255, 255, 255, 255, 255, 255, 255}, [33]byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, [8]byte{255, 255, 255, 255, 255, 255, 255, 255}} + zero33_ssa(&a.mid) + want := T33{[8]byte{255, 255, 255, 255, 255, 255, 255, 255}, [33]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, [8]byte{255, 255, 255, 255, 255, 255, 255, 255}} + if a != want { + fmt.Printf("zero33 got=%v, want %v\n", a, want) + failed = true + } +} + +type T63 struct { + pre [8]byte + mid [63]byte + post [8]byte +} + +func zero63_ssa(x *[63]byte) { + switch { + } + *x = [63]byte{} +} +func testZero63() { + a := T63{[8]byte{255, 255, 255, 255, 255, 255, 255, 255}, [63]byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, [8]byte{255, 255, 255, 255, 255, 255, 255, 255}} + zero63_ssa(&a.mid) + want := T63{[8]byte{255, 255, 255, 255, 255, 255, 255, 255}, [63]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, [8]byte{255, 255, 255, 255, 255, 255, 255, 255}} + if a != want { + fmt.Printf("zero63 got=%v, want %v\n", a, want) + failed = true + } +} + +type T64 struct { + pre [8]byte + mid [64]byte + post [8]byte +} + +func zero64_ssa(x *[64]byte) { + switch { + } + *x = [64]byte{} +} +func testZero64() { + a := T64{[8]byte{255, 255, 255, 255, 255, 255, 255, 255}, [64]byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, [8]byte{255, 255, 255, 255, 255, 255, 255, 255}} + zero64_ssa(&a.mid) + want := T64{[8]byte{255, 255, 255, 255, 255, 255, 255, 255}, [64]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, [8]byte{255, 255, 255, 255, 255, 255, 255, 255}} + if a != want { + fmt.Printf("zero64 got=%v, want %v\n", a, want) + failed = true + } +} + +type T65 struct { + pre [8]byte + mid [65]byte + post [8]byte +} + +func zero65_ssa(x *[65]byte) { + switch { + } + *x = [65]byte{} +} +func testZero65() { + a := T65{[8]byte{255, 255, 255, 255, 255, 255, 255, 255}, [65]byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, [8]byte{255, 255, 255, 255, 255, 255, 255, 255}} + zero65_ssa(&a.mid) + want := T65{[8]byte{255, 255, 255, 255, 255, 255, 255, 255}, [65]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, [8]byte{255, 255, 255, 255, 255, 255, 255, 255}} + if a != want { + fmt.Printf("zero65 got=%v, want %v\n", a, want) + failed = true + } +} + +type T1023 struct { + pre [8]byte + mid [1023]byte + post [8]byte +} + +func zero1023_ssa(x *[1023]byte) { + switch { + } + *x = [1023]byte{} +} +func testZero1023() { + a := T1023{[8]byte{255, 255, 255, 255, 255, 255, 255, 255}, [1023]byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, [8]byte{255, 255, 255, 255, 255, 255, 255, 255}} + zero1023_ssa(&a.mid) + want := T1023{[8]byte{255, 255, 255, 255, 255, 255, 255, 255}, [1023]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, [8]byte{255, 255, 255, 255, 255, 255, 255, 255}} + if a != want { + fmt.Printf("zero1023 got=%v, want %v\n", a, want) + failed = true + } +} + +type T1024 struct { + pre [8]byte + mid [1024]byte + post [8]byte +} + +func zero1024_ssa(x *[1024]byte) { + switch { + } + *x = [1024]byte{} +} +func testZero1024() { + a := T1024{[8]byte{255, 255, 255, 255, 255, 255, 255, 255}, [1024]byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, [8]byte{255, 255, 255, 255, 255, 255, 255, 255}} + zero1024_ssa(&a.mid) + want := T1024{[8]byte{255, 255, 255, 255, 255, 255, 255, 255}, [1024]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, [8]byte{255, 255, 255, 255, 255, 255, 255, 255}} + if a != want { + fmt.Printf("zero1024 got=%v, want %v\n", a, want) + failed = true + } +} + +type T1025 struct { + pre [8]byte + mid [1025]byte + post [8]byte +} + +func zero1025_ssa(x *[1025]byte) { + switch { + } + *x = [1025]byte{} +} +func testZero1025() { + a := T1025{[8]byte{255, 255, 255, 255, 255, 255, 255, 255}, [1025]byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, [8]byte{255, 255, 255, 255, 255, 255, 255, 255}} + zero1025_ssa(&a.mid) + want := T1025{[8]byte{255, 255, 255, 255, 255, 255, 255, 255}, [1025]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, [8]byte{255, 255, 255, 255, 255, 255, 255, 255}} + if a != want { + fmt.Printf("zero1025 got=%v, want %v\n", a, want) + failed = true + } +} + +var failed bool + +func main() { + testZero1() + testZero2() + testZero3() + testZero4() + testZero5() + testZero6() + testZero7() + testZero8() + testZero9() + testZero10() + testZero15() + testZero16() + testZero17() + testZero23() + testZero24() + testZero25() + testZero31() + testZero32() + testZero33() + testZero63() + testZero64() + testZero65() + testZero1023() + testZero1024() + testZero1025() + if failed { + panic("failed") + } +} diff --git a/src/cmd/compile/internal/ssa/gen/AMD64.rules b/src/cmd/compile/internal/ssa/gen/AMD64.rules index 5b83c9781f..3d308d7ef8 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64.rules +++ b/src/cmd/compile/internal/ssa/gen/AMD64.rules @@ -565,15 +565,50 @@ // lower Zero instructions with word sizes (Zero [0] _ mem) -> mem -(Zero [1] destptr mem) -> (MOVBstore destptr (MOVBconst [0]) mem) -(Zero [2] destptr mem) -> (MOVWstore destptr (MOVWconst [0]) mem) -(Zero [4] destptr mem) -> (MOVLstore destptr (MOVLconst [0]) mem) -(Zero [8] destptr mem) -> (MOVQstore destptr (MOVQconst [0]) mem) - -// rewrite anything less than 4 words into a series of MOV[BWLQ] $0, ptr(off) instructions -(Zero [size] destptr mem) && size < 4*8 -> (MOVXzero [size] destptr mem) -// Use STOSQ to zero memory. Rewrite this into storing the words with REPSTOSQ and then filling in the remainder with linear moves -(Zero [size] destptr mem) && size >= 4*8 -> (Zero [size%8] (OffPtr [size-(size%8)] destptr) (REPSTOSQ destptr (MOVQconst [size/8]) mem)) +(Zero [1] destptr mem) -> (MOVBstore destptr (MOVBconst [0]) mem) +(Zero [2] destptr mem) -> (MOVWstore destptr (MOVWconst [0]) mem) +(Zero [4] destptr mem) -> (MOVLstore destptr (MOVLconst [0]) mem) +(Zero [8] destptr mem) -> (MOVQstore destptr (MOVQconst [0]) mem) + +(Zero [3] destptr mem) -> + (MOVBstore (ADDQconst [2] destptr) (MOVBconst [0]) + (MOVWstore destptr (MOVWconst [0]) mem)) +(Zero [5] destptr mem) -> + (MOVBstore (ADDQconst [4] destptr) (MOVBconst [0]) + (MOVLstore destptr (MOVLconst [0]) mem)) +(Zero [6] destptr mem) -> + (MOVWstore (ADDQconst [4] destptr) (MOVWconst [0]) + (MOVLstore destptr (MOVLconst [0]) mem)) +(Zero [7] destptr mem) -> + (MOVLstore (ADDQconst [3] destptr) (MOVLconst [0]) + (MOVLstore destptr (MOVLconst [0]) mem)) + +// Strip off any fractional word zeroing. +(Zero [size] destptr mem) && size%8 != 0 && size > 8 -> + (Zero [size-size%8] (ADDQconst destptr [size%8]) + (MOVQstore destptr (MOVQconst [0]) mem)) + +// Zero small numbers of words directly. +(Zero [16] destptr mem) -> + (MOVQstore (ADDQconst [8] destptr) (MOVQconst [0]) + (MOVQstore destptr (MOVQconst [0]) mem)) +(Zero [24] destptr mem) -> + (MOVQstore (ADDQconst [16] destptr) (MOVQconst [0]) + (MOVQstore (ADDQconst [8] destptr) (MOVQconst [0]) + (MOVQstore destptr (MOVQconst [0]) mem))) +(Zero [32] destptr mem) -> + (MOVQstore (ADDQconst [24] destptr) (MOVQconst [0]) + (MOVQstore (ADDQconst [16] destptr) (MOVQconst [0]) + (MOVQstore (ADDQconst [8] destptr) (MOVQconst [0]) + (MOVQstore destptr (MOVQconst [0]) mem)))) + +// Medium zeroing uses a duff device. +(Zero [size] destptr mem) && size <= 1024 && size%8 == 0 -> + (DUFFZERO [duffStart(size)] (ADDQconst [duffAdj(size)] destptr) (MOVQconst [0]) mem) + +// Large zeroing uses REP STOSQ. +(Zero [size] destptr mem) && size > 1024 && size%8 == 0 -> + (REPSTOSQ destptr (MOVQconst [size/8]) (MOVQconst [0]) mem) // Absorb InvertFlags into branches. (LT (InvertFlags cmp) yes no) -> (GT cmp yes no) diff --git a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go index 79d45e990a..6f318d3589 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go @@ -117,9 +117,8 @@ func init() { gpload = regInfo{inputs: []regMask{gpspsb, 0}, outputs: gponly} gploadidx = regInfo{inputs: []regMask{gpspsb, gpsp, 0}, outputs: gponly} - gpstore = regInfo{inputs: []regMask{gpspsb, gpsp, 0}} - gpstoreconst = regInfo{inputs: []regMask{gpspsb, 0}} - gpstoreidx = regInfo{inputs: []regMask{gpspsb, gpsp, gpsp, 0}} + gpstore = regInfo{inputs: []regMask{gpspsb, gpsp, 0}} + gpstoreidx = regInfo{inputs: []regMask{gpspsb, gpsp, gpsp, 0}} fp01 = regInfo{inputs: []regMask{}, outputs: fponly} fp21 = regInfo{inputs: []regMask{fp, fp}, outputs: fponly} @@ -167,14 +166,14 @@ func init() { {name: "MOVSDstoreidx8", reg: fpstoreidx, asm: "MOVSD"}, // fp64 indexed by 8i store // binary ops - {name: "ADDQ", reg: gp21, asm: "ADDQ"}, // arg0 + arg1 - {name: "ADDL", reg: gp21, asm: "ADDL"}, // arg0 + arg1 - {name: "ADDW", reg: gp21, asm: "ADDW"}, // arg0 + arg1 - {name: "ADDB", reg: gp21, asm: "ADDB"}, // arg0 + arg1 - {name: "ADDQconst", reg: gp11, asm: "ADDQ"}, // arg0 + auxint - {name: "ADDLconst", reg: gp11, asm: "ADDL"}, // arg0 + auxint - {name: "ADDWconst", reg: gp11, asm: "ADDW"}, // arg0 + auxint - {name: "ADDBconst", reg: gp11, asm: "ADDB"}, // arg0 + auxint + {name: "ADDQ", reg: gp21, asm: "ADDQ"}, // arg0 + arg1 + {name: "ADDL", reg: gp21, asm: "ADDL"}, // arg0 + arg1 + {name: "ADDW", reg: gp21, asm: "ADDW"}, // arg0 + arg1 + {name: "ADDB", reg: gp21, asm: "ADDB"}, // arg0 + arg1 + {name: "ADDQconst", reg: gp11, asm: "ADDQ", typ: "UInt64"}, // arg0 + auxint + {name: "ADDLconst", reg: gp11, asm: "ADDL"}, // arg0 + auxint + {name: "ADDWconst", reg: gp11, asm: "ADDW"}, // arg0 + auxint + {name: "ADDBconst", reg: gp11, asm: "ADDB"}, // arg0 + auxint {name: "SUBQ", reg: gp21, asm: "SUBQ"}, // arg0 - arg1 {name: "SUBL", reg: gp21, asm: "SUBL"}, // arg0 - arg1 @@ -343,10 +342,10 @@ func init() { // clobbers flags as liblink will rewrite these to XOR reg, reg if the constant is zero // TODO: revisit when issue 12405 is fixed - {name: "MOVBconst", reg: gp01flags, asm: "MOVB"}, // 8 low bits of auxint - {name: "MOVWconst", reg: gp01flags, asm: "MOVW"}, // 16 low bits of auxint - {name: "MOVLconst", reg: gp01flags, asm: "MOVL"}, // 32 low bits of auxint - {name: "MOVQconst", reg: gp01flags, asm: "MOVQ"}, // auxint + {name: "MOVBconst", reg: gp01flags, asm: "MOVB", typ: "UInt8"}, // 8 low bits of auxint + {name: "MOVWconst", reg: gp01flags, asm: "MOVW", typ: "UInt16"}, // 16 low bits of auxint + {name: "MOVLconst", reg: gp01flags, asm: "MOVL", typ: "UInt32"}, // 32 low bits of auxint + {name: "MOVQconst", reg: gp01flags, asm: "MOVQ", typ: "UInt64"}, // auxint {name: "CVTTSD2SL", reg: fpgp, asm: "CVTTSD2SL"}, // convert float64 to int32 {name: "CVTTSD2SQ", reg: fpgp, asm: "CVTTSD2SQ"}, // convert float64 to int64 @@ -368,24 +367,45 @@ func init() { {name: "LEAQ8", reg: gp21sb}, // arg0 + 8*arg1 + auxint // auxint+aux == add auxint and the offset of the symbol in aux (if any) to the effective address - {name: "MOVBload", reg: gpload, asm: "MOVB"}, // load byte from arg0+auxint+aux. arg1=mem - {name: "MOVBQSXload", reg: gpload, asm: "MOVBQSX"}, // ditto, extend to int64 - {name: "MOVBQZXload", reg: gpload, asm: "MOVBQZX"}, // ditto, extend to uint64 - {name: "MOVWload", reg: gpload, asm: "MOVW"}, // load 2 bytes from arg0+auxint+aux. arg1=mem - {name: "MOVLload", reg: gpload, asm: "MOVL"}, // load 4 bytes from arg0+auxint+aux. arg1=mem - {name: "MOVQload", reg: gpload, asm: "MOVQ"}, // load 8 bytes from arg0+auxint+aux. arg1=mem - {name: "MOVQloadidx8", reg: gploadidx, asm: "MOVQ"}, // load 8 bytes from arg0+8*arg1+auxint+aux. arg2=mem - {name: "MOVBstore", reg: gpstore, asm: "MOVB"}, // store byte in arg1 to arg0+auxint+aux. arg2=mem - {name: "MOVWstore", reg: gpstore, asm: "MOVW"}, // store 2 bytes in arg1 to arg0+auxint+aux. arg2=mem - {name: "MOVLstore", reg: gpstore, asm: "MOVL"}, // store 4 bytes in arg1 to arg0+auxint+aux. arg2=mem - {name: "MOVQstore", reg: gpstore, asm: "MOVQ"}, // store 8 bytes in arg1 to arg0+auxint+aux. arg2=mem - {name: "MOVQstoreidx8", reg: gpstoreidx, asm: "MOVQ"}, // store 8 bytes in arg2 to arg0+8*arg1+auxint+aux. arg3=mem - - {name: "MOVXzero", reg: gpstoreconst}, // store auxint 0 bytes into arg0 using a series of MOV instructions. arg1=mem. - - {name: "REPSTOSQ", reg: regInfo{[]regMask{buildReg("DI"), buildReg("CX")}, buildReg("DI AX CX FLAGS"), nil}}, // store arg1 8-byte words containing zero into arg0 using STOSQ. arg2=mem. - - //TODO: set register clobber to everything? + {name: "MOVBload", reg: gpload, asm: "MOVB"}, // load byte from arg0+auxint+aux. arg1=mem + {name: "MOVBQSXload", reg: gpload, asm: "MOVBQSX"}, // ditto, extend to int64 + {name: "MOVBQZXload", reg: gpload, asm: "MOVBQZX"}, // ditto, extend to uint64 + {name: "MOVWload", reg: gpload, asm: "MOVW"}, // load 2 bytes from arg0+auxint+aux. arg1=mem + {name: "MOVLload", reg: gpload, asm: "MOVL"}, // load 4 bytes from arg0+auxint+aux. arg1=mem + {name: "MOVQload", reg: gpload, asm: "MOVQ"}, // load 8 bytes from arg0+auxint+aux. arg1=mem + {name: "MOVQloadidx8", reg: gploadidx, asm: "MOVQ"}, // load 8 bytes from arg0+8*arg1+auxint+aux. arg2=mem + {name: "MOVBstore", reg: gpstore, asm: "MOVB", typ: "Mem"}, // store byte in arg1 to arg0+auxint+aux. arg2=mem + {name: "MOVWstore", reg: gpstore, asm: "MOVW", typ: "Mem"}, // store 2 bytes in arg1 to arg0+auxint+aux. arg2=mem + {name: "MOVLstore", reg: gpstore, asm: "MOVL", typ: "Mem"}, // store 4 bytes in arg1 to arg0+auxint+aux. arg2=mem + {name: "MOVQstore", reg: gpstore, asm: "MOVQ", typ: "Mem"}, // store 8 bytes in arg1 to arg0+auxint+aux. arg2=mem + {name: "MOVQstoreidx8", reg: gpstoreidx, asm: "MOVQ"}, // store 8 bytes in arg2 to arg0+8*arg1+auxint+aux. arg3=mem + + // arg0 = (duff-adjusted) pointer to start of memory to zero + // arg1 = value to store (will always be zero) + // arg2 = mem + // auxint = offset into duffzero code to start executing + // returns mem + { + name: "DUFFZERO", + reg: regInfo{ + inputs: []regMask{buildReg("DI"), buildReg("AX")}, + clobbers: buildReg("DI FLAGS"), + }, + }, + + // arg0 = address of memory to zero + // arg1 = # of 8-byte words to zero + // arg2 = value to store (will always be zero) + // arg3 = mem + // returns mem + { + name: "REPSTOSQ", + reg: regInfo{ + inputs: []regMask{buildReg("DI"), buildReg("CX"), buildReg("AX")}, + clobbers: buildReg("DI CX FLAGS"), + }, + }, + {name: "CALLstatic", reg: regInfo{clobbers: callerSave}}, // call static function aux.(*gc.Sym). arg0=mem, auxint=argsize, returns mem {name: "CALLclosure", reg: regInfo{[]regMask{gpsp, buildReg("DX"), 0}, callerSave, nil}}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem {name: "CALLdefer", reg: regInfo{clobbers: callerSave}}, // call deferproc. arg0=mem, auxint=argsize, returns mem diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index 8617cf3e62..0da7946365 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -260,7 +260,7 @@ const ( OpAMD64MOVLstore OpAMD64MOVQstore OpAMD64MOVQstoreidx8 - OpAMD64MOVXzero + OpAMD64DUFFZERO OpAMD64REPSTOSQ OpAMD64CALLstatic OpAMD64CALLclosure @@ -3034,11 +3034,13 @@ var opcodeTable = [...]opInfo{ }, }, { - name: "MOVXzero", + name: "DUFFZERO", reg: regInfo{ inputs: []inputInfo{ - {0, 4295032831}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB + {0, 128}, // .DI + {1, 1}, // .AX }, + clobbers: 8589934720, // .DI .FLAGS }, }, { @@ -3047,8 +3049,9 @@ var opcodeTable = [...]opInfo{ inputs: []inputInfo{ {0, 128}, // .DI {1, 2}, // .CX + {2, 1}, // .AX }, - clobbers: 8589934723, // .AX .CX .DI .FLAGS + clobbers: 8589934722, // .CX .DI .FLAGS }, }, { diff --git a/src/cmd/compile/internal/ssa/rewrite.go b/src/cmd/compile/internal/ssa/rewrite.go index 5c47ec6660..4e783062ec 100644 --- a/src/cmd/compile/internal/ssa/rewrite.go +++ b/src/cmd/compile/internal/ssa/rewrite.go @@ -178,3 +178,52 @@ func b2i(b bool) int64 { func f2i(f float64) int64 { return int64(math.Float64bits(f)) } + +// DUFFZERO consists of repeated blocks of 4 MOVs + ADD, +// with 4 STOSQs at the very end. +// The trailing STOSQs prevent the need for a DI preadjustment +// for small numbers of words to clear. +// See runtime/mkduff.go. +const ( + dzBlocks = 31 // number of MOV/ADD blocks + dzBlockLen = 4 // number of clears per block + dzBlockSize = 19 // size of instructions in a single block + dzMovSize = 4 // size of single MOV instruction w/ offset + dzAddSize = 4 // size of single ADD instruction + dzDIStep = 8 // number of bytes cleared by each MOV instruction + + dzTailLen = 4 // number of final STOSQ instructions + dzTailSize = 2 // size of single STOSQ instruction + + dzSize = dzBlocks*dzBlockSize + dzTailLen*dzTailSize // total size of DUFFZERO routine +) + +func duffStart(size int64) int64 { + x, _ := duff(size) + return x +} +func duffAdj(size int64) int64 { + _, x := duff(size) + return x +} + +// duff returns the offset (from duffzero, in bytes) and pointer adjust (in bytes) +// required to use the duffzero mechanism for a block of the given size. +func duff(size int64) (int64, int64) { + if size < 32 || size > 1024 || size%8 != 0 { + panic("bad duffzero size") + } + // TODO: arch-dependent + off := int64(dzSize) + off -= dzTailLen * dzTailSize + size -= dzTailLen * dzDIStep + q := size / dzDIStep + blocks, singles := q/dzBlockLen, q%dzBlockLen + off -= dzBlockSize * blocks + var adj int64 + if singles > 0 { + off -= dzAddSize + dzMovSize*singles + adj -= dzDIStep * (dzBlockLen - singles) + } + return off, adj +} diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go index 50510d2351..590efdb2eb 100644 --- a/src/cmd/compile/internal/ssa/rewriteAMD64.go +++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go @@ -10204,10 +10204,10 @@ func rewriteValueAMD64(v *Value, config *Config) bool { ; // match: (Zero [1] destptr mem) // cond: - // result: (MOVBstore destptr (MOVBconst [0]) mem) + // result: (MOVBstore destptr (MOVBconst [0]) mem) { if v.AuxInt != 1 { - goto end56bcaef03cce4d15c03efff669bb5585 + goto endf7c8ca6a444f19e1142977e2ac42ab24 } destptr := v.Args[0] mem := v.Args[1] @@ -10217,21 +10217,21 @@ func rewriteValueAMD64(v *Value, config *Config) bool { v.resetArgs() v.AddArg(destptr) v0 := b.NewValue0(v.Line, OpAMD64MOVBconst, TypeInvalid) - v0.Type = config.Frontend().TypeInt8() v0.AuxInt = 0 + v0.Type = config.fe.TypeUInt8() v.AddArg(v0) v.AddArg(mem) return true } - goto end56bcaef03cce4d15c03efff669bb5585 - end56bcaef03cce4d15c03efff669bb5585: + goto endf7c8ca6a444f19e1142977e2ac42ab24 + endf7c8ca6a444f19e1142977e2ac42ab24: ; // match: (Zero [2] destptr mem) // cond: - // result: (MOVWstore destptr (MOVWconst [0]) mem) + // result: (MOVWstore destptr (MOVWconst [0]) mem) { if v.AuxInt != 2 { - goto endf52f08f1f7b0ae220c4cfca6586a8586 + goto end7609a67450ab21eba86f456886fc8496 } destptr := v.Args[0] mem := v.Args[1] @@ -10241,21 +10241,21 @@ func rewriteValueAMD64(v *Value, config *Config) bool { v.resetArgs() v.AddArg(destptr) v0 := b.NewValue0(v.Line, OpAMD64MOVWconst, TypeInvalid) - v0.Type = config.Frontend().TypeInt16() v0.AuxInt = 0 + v0.Type = config.fe.TypeUInt16() v.AddArg(v0) v.AddArg(mem) return true } - goto endf52f08f1f7b0ae220c4cfca6586a8586 - endf52f08f1f7b0ae220c4cfca6586a8586: + goto end7609a67450ab21eba86f456886fc8496 + end7609a67450ab21eba86f456886fc8496: ; // match: (Zero [4] destptr mem) // cond: - // result: (MOVLstore destptr (MOVLconst [0]) mem) + // result: (MOVLstore destptr (MOVLconst [0]) mem) { if v.AuxInt != 4 { - goto end41c91e0c7a23e233de77812b5264fd10 + goto enda8e1cf1298794cc3cb79cab108e33007 } destptr := v.Args[0] mem := v.Args[1] @@ -10265,21 +10265,21 @@ func rewriteValueAMD64(v *Value, config *Config) bool { v.resetArgs() v.AddArg(destptr) v0 := b.NewValue0(v.Line, OpAMD64MOVLconst, TypeInvalid) - v0.Type = config.Frontend().TypeInt32() v0.AuxInt = 0 + v0.Type = config.fe.TypeUInt32() v.AddArg(v0) v.AddArg(mem) return true } - goto end41c91e0c7a23e233de77812b5264fd10 - end41c91e0c7a23e233de77812b5264fd10: + goto enda8e1cf1298794cc3cb79cab108e33007 + enda8e1cf1298794cc3cb79cab108e33007: ; // match: (Zero [8] destptr mem) // cond: - // result: (MOVQstore destptr (MOVQconst [0]) mem) + // result: (MOVQstore destptr (MOVQconst [0]) mem) { if v.AuxInt != 8 { - goto end157ad586af643d8dac6cc84a776000ca + goto end1791556f0b03ea065d38a3267fbe01c6 } destptr := v.Args[0] mem := v.Args[1] @@ -10289,70 +10289,395 @@ func rewriteValueAMD64(v *Value, config *Config) bool { v.resetArgs() v.AddArg(destptr) v0 := b.NewValue0(v.Line, OpAMD64MOVQconst, TypeInvalid) - v0.Type = config.Frontend().TypeInt64() v0.AuxInt = 0 + v0.Type = config.fe.TypeUInt64() v.AddArg(v0) v.AddArg(mem) return true } - goto end157ad586af643d8dac6cc84a776000ca - end157ad586af643d8dac6cc84a776000ca: + goto end1791556f0b03ea065d38a3267fbe01c6 + end1791556f0b03ea065d38a3267fbe01c6: ; - // match: (Zero [size] destptr mem) - // cond: size < 4*8 - // result: (MOVXzero [size] destptr mem) + // match: (Zero [3] destptr mem) + // cond: + // result: (MOVBstore (ADDQconst [2] destptr) (MOVBconst [0]) (MOVWstore destptr (MOVWconst [0]) mem)) { - size := v.AuxInt + if v.AuxInt != 3 { + goto end7f8f5c8214f8b81a73fdde78b03ce53c + } destptr := v.Args[0] mem := v.Args[1] - if !(size < 4*8) { - goto endf0a22f1506977610ac0a310eee152075 + v.Op = OpAMD64MOVBstore + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64ADDQconst, TypeInvalid) + v0.AuxInt = 2 + v0.AddArg(destptr) + v0.Type = config.fe.TypeUInt64() + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpAMD64MOVBconst, TypeInvalid) + v1.AuxInt = 0 + v1.Type = config.fe.TypeUInt8() + v.AddArg(v1) + v2 := b.NewValue0(v.Line, OpAMD64MOVWstore, TypeInvalid) + v2.AddArg(destptr) + v3 := b.NewValue0(v.Line, OpAMD64MOVWconst, TypeInvalid) + v3.AuxInt = 0 + v3.Type = config.fe.TypeUInt16() + v2.AddArg(v3) + v2.AddArg(mem) + v2.Type = TypeMem + v.AddArg(v2) + return true + } + goto end7f8f5c8214f8b81a73fdde78b03ce53c + end7f8f5c8214f8b81a73fdde78b03ce53c: + ; + // match: (Zero [5] destptr mem) + // cond: + // result: (MOVBstore (ADDQconst [4] destptr) (MOVBconst [0]) (MOVLstore destptr (MOVLconst [0]) mem)) + { + if v.AuxInt != 5 { + goto end54466baa4eac09020bee720efbb82d0f } - v.Op = OpAMD64MOVXzero + destptr := v.Args[0] + mem := v.Args[1] + v.Op = OpAMD64MOVBstore v.AuxInt = 0 v.Aux = nil v.resetArgs() - v.AuxInt = size - v.AddArg(destptr) - v.AddArg(mem) + v0 := b.NewValue0(v.Line, OpAMD64ADDQconst, TypeInvalid) + v0.AuxInt = 4 + v0.AddArg(destptr) + v0.Type = config.fe.TypeUInt64() + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpAMD64MOVBconst, TypeInvalid) + v1.AuxInt = 0 + v1.Type = config.fe.TypeUInt8() + v.AddArg(v1) + v2 := b.NewValue0(v.Line, OpAMD64MOVLstore, TypeInvalid) + v2.AddArg(destptr) + v3 := b.NewValue0(v.Line, OpAMD64MOVLconst, TypeInvalid) + v3.AuxInt = 0 + v3.Type = config.fe.TypeUInt32() + v2.AddArg(v3) + v2.AddArg(mem) + v2.Type = TypeMem + v.AddArg(v2) return true } - goto endf0a22f1506977610ac0a310eee152075 - endf0a22f1506977610ac0a310eee152075: + goto end54466baa4eac09020bee720efbb82d0f + end54466baa4eac09020bee720efbb82d0f: + ; + // match: (Zero [6] destptr mem) + // cond: + // result: (MOVWstore (ADDQconst [4] destptr) (MOVWconst [0]) (MOVLstore destptr (MOVLconst [0]) mem)) + { + if v.AuxInt != 6 { + goto end3a37ae6095ddc37646d6ad6eeda986e2 + } + destptr := v.Args[0] + mem := v.Args[1] + v.Op = OpAMD64MOVWstore + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64ADDQconst, TypeInvalid) + v0.AuxInt = 4 + v0.AddArg(destptr) + v0.Type = config.fe.TypeUInt64() + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpAMD64MOVWconst, TypeInvalid) + v1.AuxInt = 0 + v1.Type = config.fe.TypeUInt16() + v.AddArg(v1) + v2 := b.NewValue0(v.Line, OpAMD64MOVLstore, TypeInvalid) + v2.AddArg(destptr) + v3 := b.NewValue0(v.Line, OpAMD64MOVLconst, TypeInvalid) + v3.AuxInt = 0 + v3.Type = config.fe.TypeUInt32() + v2.AddArg(v3) + v2.AddArg(mem) + v2.Type = TypeMem + v.AddArg(v2) + return true + } + goto end3a37ae6095ddc37646d6ad6eeda986e2 + end3a37ae6095ddc37646d6ad6eeda986e2: + ; + // match: (Zero [7] destptr mem) + // cond: + // result: (MOVLstore (ADDQconst [3] destptr) (MOVLconst [0]) (MOVLstore destptr (MOVLconst [0]) mem)) + { + if v.AuxInt != 7 { + goto endd53a750fa01c5a5a238ba8fcabb416b2 + } + destptr := v.Args[0] + mem := v.Args[1] + v.Op = OpAMD64MOVLstore + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64ADDQconst, TypeInvalid) + v0.AuxInt = 3 + v0.AddArg(destptr) + v0.Type = config.fe.TypeUInt64() + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpAMD64MOVLconst, TypeInvalid) + v1.AuxInt = 0 + v1.Type = config.fe.TypeUInt32() + v.AddArg(v1) + v2 := b.NewValue0(v.Line, OpAMD64MOVLstore, TypeInvalid) + v2.AddArg(destptr) + v3 := b.NewValue0(v.Line, OpAMD64MOVLconst, TypeInvalid) + v3.AuxInt = 0 + v3.Type = config.fe.TypeUInt32() + v2.AddArg(v3) + v2.AddArg(mem) + v2.Type = TypeMem + v.AddArg(v2) + return true + } + goto endd53a750fa01c5a5a238ba8fcabb416b2 + endd53a750fa01c5a5a238ba8fcabb416b2: ; // match: (Zero [size] destptr mem) - // cond: size >= 4*8 - // result: (Zero [size%8] (OffPtr [size-(size%8)] destptr) (REPSTOSQ destptr (MOVQconst [size/8]) mem)) + // cond: size%8 != 0 && size > 8 + // result: (Zero [size-size%8] (ADDQconst destptr [size%8]) (MOVQstore destptr (MOVQconst [0]) mem)) { size := v.AuxInt destptr := v.Args[0] mem := v.Args[1] - if !(size >= 4*8) { - goto end84c39fe2e8d40e0042a10741a0ef16bd + if !(size%8 != 0 && size > 8) { + goto end5efefe1d9cca07e7ad6f4832f774b938 } v.Op = OpZero v.AuxInt = 0 v.Aux = nil v.resetArgs() - v.AuxInt = size % 8 - v0 := b.NewValue0(v.Line, OpOffPtr, TypeInvalid) - v0.Type = config.Frontend().TypeUInt64() - v0.AuxInt = size - (size % 8) + v.AuxInt = size - size%8 + v0 := b.NewValue0(v.Line, OpAMD64ADDQconst, TypeInvalid) v0.AddArg(destptr) + v0.AuxInt = size % 8 + v0.Type = config.fe.TypeUInt64() v.AddArg(v0) - v1 := b.NewValue0(v.Line, OpAMD64REPSTOSQ, TypeInvalid) - v1.Type = TypeMem + v1 := b.NewValue0(v.Line, OpAMD64MOVQstore, TypeInvalid) v1.AddArg(destptr) v2 := b.NewValue0(v.Line, OpAMD64MOVQconst, TypeInvalid) - v2.Type = config.Frontend().TypeUInt64() - v2.AuxInt = size / 8 + v2.AuxInt = 0 + v2.Type = config.fe.TypeUInt64() v1.AddArg(v2) v1.AddArg(mem) + v1.Type = TypeMem + v.AddArg(v1) + return true + } + goto end5efefe1d9cca07e7ad6f4832f774b938 + end5efefe1d9cca07e7ad6f4832f774b938: + ; + // match: (Zero [16] destptr mem) + // cond: + // result: (MOVQstore (ADDQconst [8] destptr) (MOVQconst [0]) (MOVQstore destptr (MOVQconst [0]) mem)) + { + if v.AuxInt != 16 { + goto endad489c16378959a764292e8b1cb72ba2 + } + destptr := v.Args[0] + mem := v.Args[1] + v.Op = OpAMD64MOVQstore + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64ADDQconst, TypeInvalid) + v0.AuxInt = 8 + v0.AddArg(destptr) + v0.Type = config.fe.TypeUInt64() + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpAMD64MOVQconst, TypeInvalid) + v1.AuxInt = 0 + v1.Type = config.fe.TypeUInt64() v.AddArg(v1) + v2 := b.NewValue0(v.Line, OpAMD64MOVQstore, TypeInvalid) + v2.AddArg(destptr) + v3 := b.NewValue0(v.Line, OpAMD64MOVQconst, TypeInvalid) + v3.AuxInt = 0 + v3.Type = config.fe.TypeUInt64() + v2.AddArg(v3) + v2.AddArg(mem) + v2.Type = TypeMem + v.AddArg(v2) + return true + } + goto endad489c16378959a764292e8b1cb72ba2 + endad489c16378959a764292e8b1cb72ba2: + ; + // match: (Zero [24] destptr mem) + // cond: + // result: (MOVQstore (ADDQconst [16] destptr) (MOVQconst [0]) (MOVQstore (ADDQconst [8] destptr) (MOVQconst [0]) (MOVQstore destptr (MOVQconst [0]) mem))) + { + if v.AuxInt != 24 { + goto enddc443320a1be0b3c2e213bd6778197dd + } + destptr := v.Args[0] + mem := v.Args[1] + v.Op = OpAMD64MOVQstore + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64ADDQconst, TypeInvalid) + v0.AuxInt = 16 + v0.AddArg(destptr) + v0.Type = config.fe.TypeUInt64() + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpAMD64MOVQconst, TypeInvalid) + v1.AuxInt = 0 + v1.Type = config.fe.TypeUInt64() + v.AddArg(v1) + v2 := b.NewValue0(v.Line, OpAMD64MOVQstore, TypeInvalid) + v3 := b.NewValue0(v.Line, OpAMD64ADDQconst, TypeInvalid) + v3.AuxInt = 8 + v3.AddArg(destptr) + v3.Type = config.fe.TypeUInt64() + v2.AddArg(v3) + v4 := b.NewValue0(v.Line, OpAMD64MOVQconst, TypeInvalid) + v4.AuxInt = 0 + v4.Type = config.fe.TypeUInt64() + v2.AddArg(v4) + v5 := b.NewValue0(v.Line, OpAMD64MOVQstore, TypeInvalid) + v5.AddArg(destptr) + v6 := b.NewValue0(v.Line, OpAMD64MOVQconst, TypeInvalid) + v6.AuxInt = 0 + v6.Type = config.fe.TypeUInt64() + v5.AddArg(v6) + v5.AddArg(mem) + v5.Type = TypeMem + v2.AddArg(v5) + v2.Type = TypeMem + v.AddArg(v2) + return true + } + goto enddc443320a1be0b3c2e213bd6778197dd + enddc443320a1be0b3c2e213bd6778197dd: + ; + // match: (Zero [32] destptr mem) + // cond: + // result: (MOVQstore (ADDQconst [24] destptr) (MOVQconst [0]) (MOVQstore (ADDQconst [16] destptr) (MOVQconst [0]) (MOVQstore (ADDQconst [8] destptr) (MOVQconst [0]) (MOVQstore destptr (MOVQconst [0]) mem)))) + { + if v.AuxInt != 32 { + goto end282b5e36693f06e2cd1ac563e0d419b5 + } + destptr := v.Args[0] + mem := v.Args[1] + v.Op = OpAMD64MOVQstore + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64ADDQconst, TypeInvalid) + v0.AuxInt = 24 + v0.AddArg(destptr) + v0.Type = config.fe.TypeUInt64() + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpAMD64MOVQconst, TypeInvalid) + v1.AuxInt = 0 + v1.Type = config.fe.TypeUInt64() + v.AddArg(v1) + v2 := b.NewValue0(v.Line, OpAMD64MOVQstore, TypeInvalid) + v3 := b.NewValue0(v.Line, OpAMD64ADDQconst, TypeInvalid) + v3.AuxInt = 16 + v3.AddArg(destptr) + v3.Type = config.fe.TypeUInt64() + v2.AddArg(v3) + v4 := b.NewValue0(v.Line, OpAMD64MOVQconst, TypeInvalid) + v4.AuxInt = 0 + v4.Type = config.fe.TypeUInt64() + v2.AddArg(v4) + v5 := b.NewValue0(v.Line, OpAMD64MOVQstore, TypeInvalid) + v6 := b.NewValue0(v.Line, OpAMD64ADDQconst, TypeInvalid) + v6.AuxInt = 8 + v6.AddArg(destptr) + v6.Type = config.fe.TypeUInt64() + v5.AddArg(v6) + v7 := b.NewValue0(v.Line, OpAMD64MOVQconst, TypeInvalid) + v7.AuxInt = 0 + v7.Type = config.fe.TypeUInt64() + v5.AddArg(v7) + v8 := b.NewValue0(v.Line, OpAMD64MOVQstore, TypeInvalid) + v8.AddArg(destptr) + v9 := b.NewValue0(v.Line, OpAMD64MOVQconst, TypeInvalid) + v9.AuxInt = 0 + v9.Type = config.fe.TypeUInt64() + v8.AddArg(v9) + v8.AddArg(mem) + v8.Type = TypeMem + v5.AddArg(v8) + v5.Type = TypeMem + v2.AddArg(v5) + v2.Type = TypeMem + v.AddArg(v2) + return true + } + goto end282b5e36693f06e2cd1ac563e0d419b5 + end282b5e36693f06e2cd1ac563e0d419b5: + ; + // match: (Zero [size] destptr mem) + // cond: size <= 1024 && size%8 == 0 + // result: (DUFFZERO [duffStart(size)] (ADDQconst [duffAdj(size)] destptr) (MOVQconst [0]) mem) + { + size := v.AuxInt + destptr := v.Args[0] + mem := v.Args[1] + if !(size <= 1024 && size%8 == 0) { + goto endfae59ebc96f670276efea844c3b302ac + } + v.Op = OpAMD64DUFFZERO + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = duffStart(size) + v0 := b.NewValue0(v.Line, OpAMD64ADDQconst, TypeInvalid) + v0.AuxInt = duffAdj(size) + v0.AddArg(destptr) + v0.Type = config.fe.TypeUInt64() + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpAMD64MOVQconst, TypeInvalid) + v1.AuxInt = 0 + v1.Type = config.fe.TypeUInt64() + v.AddArg(v1) + v.AddArg(mem) + return true + } + goto endfae59ebc96f670276efea844c3b302ac + endfae59ebc96f670276efea844c3b302ac: + ; + // match: (Zero [size] destptr mem) + // cond: size > 1024 && size%8 == 0 + // result: (REPSTOSQ destptr (MOVQconst [size/8]) (MOVQconst [0]) mem) + { + size := v.AuxInt + destptr := v.Args[0] + mem := v.Args[1] + if !(size > 1024 && size%8 == 0) { + goto endb9d55d4ba0e70ed918e3ac757727441b + } + v.Op = OpAMD64REPSTOSQ + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(destptr) + v0 := b.NewValue0(v.Line, OpAMD64MOVQconst, TypeInvalid) + v0.AuxInt = size / 8 + v0.Type = config.fe.TypeUInt64() + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpAMD64MOVQconst, TypeInvalid) + v1.AuxInt = 0 + v1.Type = config.fe.TypeUInt64() + v.AddArg(v1) + v.AddArg(mem) return true } - goto end84c39fe2e8d40e0042a10741a0ef16bd - end84c39fe2e8d40e0042a10741a0ef16bd: + goto endb9d55d4ba0e70ed918e3ac757727441b + endb9d55d4ba0e70ed918e3ac757727441b: ; case OpZeroExt16to32: // match: (ZeroExt16to32 x) -- cgit v1.3 From 956f3199a397ef05a4a34b2059d15c033556517a Mon Sep 17 00:00:00 2001 From: David Chase Date: Fri, 11 Sep 2015 16:40:05 -0400 Subject: [dev.ssa] cmd/compile: addressed vars and closures Cleaned up first-block-in-function code. Added cases for |PHEAP for PPARAM and PAUTO. Made PPARAMOUT act more like PAUTO for purposes of address generation and vardef placement. Added cases for OCLOSUREVAR and Ops for getting closure pointer. Closure ops are scheduled at top of entry block to capture DX. Wrote test that seems to show proper behavior for addressed parameters, locals, and returns. Change-Id: Iee93ebf9e3d9f74cfb4d1c1da8038eb278d8a857 Reviewed-on: https://go-review.googlesource.com/14650 Reviewed-by: Keith Randall Run-TryBot: David Chase --- src/cmd/compile/internal/gc/plive.go | 2 +- src/cmd/compile/internal/gc/ssa.go | 56 +++++- src/cmd/compile/internal/gc/ssa_test.go | 2 + src/cmd/compile/internal/gc/syntax.go | 2 +- .../compile/internal/gc/testdata/addressed_ssa.go | 216 +++++++++++++++++++++ src/cmd/compile/internal/ssa/check.go | 2 +- src/cmd/compile/internal/ssa/gen/AMD64.rules | 1 + src/cmd/compile/internal/ssa/gen/AMD64Ops.go | 4 + src/cmd/compile/internal/ssa/gen/genericOps.go | 1 + src/cmd/compile/internal/ssa/opGen.go | 14 ++ src/cmd/compile/internal/ssa/regalloc.go | 10 +- src/cmd/compile/internal/ssa/rewriteAMD64.go | 14 ++ src/cmd/compile/internal/ssa/schedule.go | 37 +++- 13 files changed, 339 insertions(+), 22 deletions(-) create mode 100644 src/cmd/compile/internal/gc/testdata/addressed_ssa.go (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/plive.go b/src/cmd/compile/internal/gc/plive.go index 2ac639629c..c7414d0c9b 100644 --- a/src/cmd/compile/internal/gc/plive.go +++ b/src/cmd/compile/internal/gc/plive.go @@ -1383,7 +1383,7 @@ func livenessepilogue(lv *Liveness) { } n = lv.vars[j] if n.Class != PPARAM { - yyerrorl(int(p.Lineno), "internal error: %v %v recorded as live on entry", Curfn.Func.Nname, Nconv(n, obj.FmtLong)) + yyerrorl(int(p.Lineno), "internal error: %v %v recorded as live on entry, p.Pc=%v", Curfn.Func.Nname, Nconv(n, obj.FmtLong), p.Pc) } } } diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 51cf01a9ed..f4d5946c03 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -24,7 +24,7 @@ import ( // it will never return nil, and the bool can be removed. func buildssa(fn *Node) (ssafn *ssa.Func, usessa bool) { name := fn.Func.Nname.Sym.Name - usessa = strings.HasSuffix(name, "_ssa") || name == os.Getenv("GOSSAFUNC") + usessa = strings.HasSuffix(name, "_ssa") || strings.Contains(name, "_ssa.") || name == os.Getenv("GOSSAFUNC") if usessa { fmt.Println("generating SSA for", name) @@ -76,22 +76,30 @@ func buildssa(fn *Node) (ssafn *ssa.Func, usessa bool) { s.f.Entry = s.f.NewBlock(ssa.BlockPlain) // Allocate starting values - s.vars = map[*Node]*ssa.Value{} s.labels = map[string]*ssaLabel{} s.labeledNodes = map[*Node]*ssaLabel{} s.startmem = s.entryNewValue0(ssa.OpArg, ssa.TypeMem) s.sp = s.entryNewValue0(ssa.OpSP, Types[TUINTPTR]) // TODO: use generic pointer type (unsafe.Pointer?) instead s.sb = s.entryNewValue0(ssa.OpSB, Types[TUINTPTR]) + s.startBlock(s.f.Entry) + s.vars[&memVar] = s.startmem + // Generate addresses of local declarations s.decladdrs = map[*Node]*ssa.Value{} for d := fn.Func.Dcl; d != nil; d = d.Next { n := d.N switch n.Class { - case PPARAM, PPARAMOUT: + case PPARAM: aux := &ssa.ArgSymbol{Typ: n.Type, Node: n} s.decladdrs[n] = s.entryNewValue1A(ssa.OpAddr, Ptrto(n.Type), aux, s.sp) - case PAUTO: + case PAUTO | PHEAP: + // TODO this looks wrong for PAUTO|PHEAP, no vardef, but also no definition + aux := &ssa.AutoSymbol{Typ: n.Type, Node: n} + s.decladdrs[n] = s.entryNewValue1A(ssa.OpAddr, Ptrto(n.Type), aux, s.sp) + case PPARAM | PHEAP: // PPARAMOUT | PHEAP seems to not occur + // This ends up wrong, have to do it at the PARAM node instead. + case PAUTO, PPARAMOUT: // processed at each use, to prevent Addr coming // before the decl. case PFUNC: @@ -109,7 +117,6 @@ func buildssa(fn *Node) (ssafn *ssa.Func, usessa bool) { s.decladdrs[nodfp] = s.entryNewValue1A(ssa.OpAddr, Types[TUINTPTR], aux, s.sp) // Convert the AST-based IR to the SSA-based IR - s.startBlock(s.f.Entry) s.stmtList(fn.Func.Enter) s.stmtList(fn.Nbody) @@ -1231,6 +1238,23 @@ func (s *state) expr(n *Node) *ssa.Value { case OCFUNC: aux := &ssa.ExternSymbol{n.Type, n.Left.Sym} return s.entryNewValue1A(ssa.OpAddr, n.Type, aux, s.sb) + case OPARAM: + // Reach through param to expected ONAME w/ PHEAP|PARAM class + // to reference the incoming parameter. Used in initialization + // of heap storage allocated for escaping params, where it appears + // as the RHS of an OAS node. No point doing SSA for this variable, + // this is the only use. + p := n.Left + if p.Op != ONAME || !(p.Class == PPARAM|PHEAP || p.Class == PPARAMOUT|PHEAP) { + s.Fatalf("OPARAM not of ONAME,{PPARAM,PPARAMOUT}|PHEAP, instead %s", nodedump(p, 0)) + } + + // Recover original offset to address passed-in param value. + original_p := *p + original_p.Xoffset = n.Xoffset + aux := &ssa.ArgSymbol{Typ: n.Type, Node: &original_p} + addr := s.entryNewValue1A(ssa.OpAddr, Ptrto(n.Type), aux, s.sp) + return s.newValue2(ssa.OpLoad, p.Type, addr, s.mem()) case ONAME: if n.Class == PFUNC { // "value" of a function is the address of the function's closure @@ -1243,6 +1267,9 @@ func (s *state) expr(n *Node) *ssa.Value { } addr := s.addr(n) return s.newValue2(ssa.OpLoad, n.Type, addr, s.mem()) + case OCLOSUREVAR: + addr := s.addr(n) + return s.newValue2(ssa.OpLoad, n.Type, addr, s.mem()) case OLITERAL: switch n.Val().Ctype() { case CTINT: @@ -2138,8 +2165,8 @@ func (s *state) addr(n *Node) *ssa.Value { v = s.entryNewValue1I(ssa.OpOffPtr, v.Type, n.Xoffset, v) } return v - case PPARAM, PPARAMOUT: - // parameter/result slot or local variable + case PPARAM: + // parameter slot v := s.decladdrs[n] if v == nil { if flag_race != 0 && n.String() == ".fp" { @@ -2159,7 +2186,10 @@ func (s *state) addr(n *Node) *ssa.Value { // between vardef and addr ops. aux := &ssa.AutoSymbol{Typ: n.Type, Node: n} return s.newValue1A(ssa.OpAddr, Ptrto(n.Type), aux, s.sp) - case PAUTO | PHEAP, PPARAMREF: + case PPARAMOUT: // Same as PAUTO -- cannot generate LEA early. + aux := &ssa.ArgSymbol{Typ: n.Type, Node: n} + return s.newValue1A(ssa.OpAddr, Ptrto(n.Type), aux, s.sp) + case PAUTO | PHEAP, PPARAM | PHEAP, PPARAMOUT | PHEAP, PPARAMREF: return s.expr(n.Name.Heapaddr) default: s.Unimplementedf("variable address class %v not implemented", n.Class) @@ -2205,6 +2235,10 @@ func (s *state) addr(n *Node) *ssa.Value { p := s.expr(n.Left) s.nilCheck(p) return s.newValue2(ssa.OpAddPtr, p.Type, p, s.constIntPtr(Types[TUINTPTR], n.Xoffset)) + case OCLOSUREVAR: + return s.newValue2(ssa.OpAddPtr, Ptrto(n.Type), + s.entryNewValue0(ssa.OpGetClosurePtr, Types[TUINTPTR]), + s.constIntPtr(Types[TUINTPTR], n.Xoffset)) default: s.Unimplementedf("unhandled addr %v", Oconv(int(n.Op), 0)) return nil @@ -3688,6 +3722,12 @@ func (s *genState) genValue(v *ssa.Value) { q.From.Reg = x86.REG_AX q.To.Type = obj.TYPE_MEM q.To.Reg = r + case ssa.OpAMD64LoweredGetClosurePtr: + // Output is hardwired to DX only, + // and DX contains the closure pointer on + // closure entry, and this "instruction" + // is scheduled to the very beginning + // of the entry block. case ssa.OpAMD64LoweredGetG: r := regnum(v) // See the comments in cmd/internal/obj/x86/obj6.go diff --git a/src/cmd/compile/internal/gc/ssa_test.go b/src/cmd/compile/internal/gc/ssa_test.go index dafbcf2166..1e06fd0d3d 100644 --- a/src/cmd/compile/internal/gc/ssa_test.go +++ b/src/cmd/compile/internal/gc/ssa_test.go @@ -89,3 +89,5 @@ func TestArray(t *testing.T) { runTest(t, "array_ssa.go") } func TestAppend(t *testing.T) { runTest(t, "append_ssa.go") } func TestZero(t *testing.T) { runTest(t, "zero_ssa.go") } + +func TestAddressed(t *testing.T) { runTest(t, "addressed_ssa.go") } diff --git a/src/cmd/compile/internal/gc/syntax.go b/src/cmd/compile/internal/gc/syntax.go index 5081ea0cb9..b71a1e7b0d 100644 --- a/src/cmd/compile/internal/gc/syntax.go +++ b/src/cmd/compile/internal/gc/syntax.go @@ -148,7 +148,7 @@ type Param struct { // Func holds Node fields used only with function-like nodes. type Func struct { Shortname *Node - Enter *NodeList + Enter *NodeList // for example, allocate and initialize memory for escaping parameters Exit *NodeList Cvars *NodeList // closure params Dcl *NodeList // autodcl for this func/closure diff --git a/src/cmd/compile/internal/gc/testdata/addressed_ssa.go b/src/cmd/compile/internal/gc/testdata/addressed_ssa.go new file mode 100644 index 0000000000..f9f459360b --- /dev/null +++ b/src/cmd/compile/internal/gc/testdata/addressed_ssa.go @@ -0,0 +1,216 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import "fmt" + +var output string + +func mypanic(s string) { + fmt.Printf(output) + panic(s) +} + +func assertEqual(x, y int) { + if x != y { + mypanic("assertEqual failed") + } +} + +func main() { + x := f1_ssa(2, 3) + output += fmt.Sprintln("*x is", *x) + output += fmt.Sprintln("Gratuitously use some stack") + output += fmt.Sprintln("*x is", *x) + assertEqual(*x, 9) + + w := f3a_ssa(6) + output += fmt.Sprintln("*w is", *w) + output += fmt.Sprintln("Gratuitously use some stack") + output += fmt.Sprintln("*w is", *w) + assertEqual(*w, 6) + + y := f3b_ssa(12) + output += fmt.Sprintln("*y.(*int) is", *y.(*int)) + output += fmt.Sprintln("Gratuitously use some stack") + output += fmt.Sprintln("*y.(*int) is", *y.(*int)) + assertEqual(*y.(*int), 12) + + z := f3c_ssa(8) + output += fmt.Sprintln("*z.(*int) is", *z.(*int)) + output += fmt.Sprintln("Gratuitously use some stack") + output += fmt.Sprintln("*z.(*int) is", *z.(*int)) + assertEqual(*z.(*int), 8) + + args() + test_autos() +} + +func f1_ssa(x, y int) *int { + switch { + } //go:noinline + x = x*y + y + return &x +} + +func f3a_ssa(x int) *int { + switch { + } //go:noinline + return &x +} + +func f3b_ssa(x int) interface{} { // ./foo.go:15: internal error: f3b_ssa ~r1 (type interface {}) recorded as live on entry + switch { + } //go:noinline + return &x +} + +func f3c_ssa(y int) interface{} { + switch { + } //go:noinline + x := y + return &x +} + +type V struct { + p *V + w, x int64 +} + +func args() { + v := V{p: nil, w: 1, x: 1} + a := V{p: &v, w: 2, x: 2} + b := V{p: &v, w: 0, x: 0} + i := v.args_ssa(a, b) + output += fmt.Sprintln("i=", i) + assertEqual(int(i), 2) +} + +func (v V) args_ssa(a, b V) int64 { + switch { + } //go:noinline + if v.w == 0 { + return v.x + } + if v.w == 1 { + return a.x + } + if v.w == 2 { + return b.x + } + b.p.p = &a // v.p in caller = &a + + return -1 +} + +func test_autos() { + test(11) + test(12) + test(13) + test(21) + test(22) + test(23) + test(31) + test(32) +} + +func test(which int64) { + output += fmt.Sprintln("test", which) + v1 := V{w: 30, x: 3, p: nil} + v2, v3 := v1.autos_ssa(which, 10, 1, 20, 2) + if which != v2.val() { + output += fmt.Sprintln("Expected which=", which, "got v2.val()=", v2.val()) + mypanic("Failure of expected V value") + } + if v2.p.val() != v3.val() { + output += fmt.Sprintln("Expected v2.p.val()=", v2.p.val(), "got v3.val()=", v3.val()) + mypanic("Failure of expected V.p value") + } + if which != v3.p.p.p.p.p.p.p.val() { + output += fmt.Sprintln("Expected which=", which, "got v3.p.p.p.p.p.p.p.val()=", v3.p.p.p.p.p.p.p.val()) + mypanic("Failure of expected V.p value") + } +} + +func (v V) val() int64 { + return v.w + v.x +} + +// autos_ssa uses contents of v and parameters w1, w2, x1, x2 +// to initialize a bunch of locals, all of which have their +// address taken to force heap allocation, and then based on +// the value of which a pair of those locals are copied in +// various ways to the two results y, and z, which are also +// addressed. Which is expected to be one of 11-13, 21-23, 31, 32, +// and y.val() should be equal to which and y.p.val() should +// be equal to z.val(). Also, x(.p)**8 == x; that is, the +// autos are all linked into a ring. +func (v V) autos_ssa(which, w1, x1, w2, x2 int64) (y, z V) { + switch { + } //go:noinline + fill_ssa(v.w, v.x, &v, v.p) // gratuitous no-op to force addressing + var a, b, c, d, e, f, g, h V + fill_ssa(w1, x1, &a, &b) + fill_ssa(w1, x2, &b, &c) + fill_ssa(w1, v.x, &c, &d) + fill_ssa(w2, x1, &d, &e) + fill_ssa(w2, x2, &e, &f) + fill_ssa(w2, v.x, &f, &g) + fill_ssa(v.w, x1, &g, &h) + fill_ssa(v.w, x2, &h, &a) + switch which { + case 11: + y = a + z.getsI(&b) + case 12: + y.gets(&b) + z = c + case 13: + y.gets(&c) + z = d + case 21: + y.getsI(&d) + z.gets(&e) + case 22: + y = e + z = f + case 23: + y.gets(&f) + z.getsI(&g) + case 31: + y = g + z.gets(&h) + case 32: + y.getsI(&h) + z = a + default: + + panic("") + } + return +} + +// gets is an address-mentioning way of implementing +// structure assignment. +func (to *V) gets(from *V) { + switch { + } //go:noinline + *to = *from +} + +// gets is an address-and-interface-mentioning way of +// implementing structure assignment. +func (to *V) getsI(from interface{}) { + switch { + } //go:noinline + *to = *from.(*V) +} + +// fill_ssa initializes r with V{w:w, x:x, p:p} +func fill_ssa(w, x int64, r, p *V) { + switch { + } //go:noinline + *r = V{w: w, x: x, p: p} +} diff --git a/src/cmd/compile/internal/ssa/check.go b/src/cmd/compile/internal/ssa/check.go index 44ce4a3c71..6c45957fdc 100644 --- a/src/cmd/compile/internal/ssa/check.go +++ b/src/cmd/compile/internal/ssa/check.go @@ -231,7 +231,7 @@ func checkFunc(f *Func) { y = b.Preds[i] } if !domCheck(f, idom, x, y) { - f.Fatalf("arg %d of value %s does not dominate", i, v.LongString()) + f.Fatalf("arg %d of value %s does not dominate, arg=%s", i, v.LongString(), arg.LongString()) } } } diff --git a/src/cmd/compile/internal/ssa/gen/AMD64.rules b/src/cmd/compile/internal/ssa/gen/AMD64.rules index 3d308d7ef8..b02af9413e 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64.rules +++ b/src/cmd/compile/internal/ssa/gen/AMD64.rules @@ -288,6 +288,7 @@ (PanicNilCheck ptr mem) -> (LoweredPanicNilCheck ptr mem) (GetG) -> (LoweredGetG) +(GetClosurePtr) -> (LoweredGetClosurePtr) (Move [size] dst src mem) -> (REPMOVSB dst src (MOVQconst [size]) mem) diff --git a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go index 6f318d3589..5d171dc87a 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go @@ -424,6 +424,10 @@ func init() { // Pseudo-ops {name: "LoweredPanicNilCheck", reg: gp10}, {name: "LoweredGetG", reg: gp01}, + // Scheduler ensures LoweredGetClosurePtr occurs only in entry block, + // and sorts it to the very beginning of the block to prevent other + // use of DX (the closure pointer) + {name: "LoweredGetClosurePtr", reg: regInfo{outputs: []regMask{buildReg("DX")}}}, } var AMD64blocks = []blockData{ diff --git a/src/cmd/compile/internal/ssa/gen/genericOps.go b/src/cmd/compile/internal/ssa/gen/genericOps.go index ff63fa880c..1ee38103ac 100644 --- a/src/cmd/compile/internal/ssa/gen/genericOps.go +++ b/src/cmd/compile/internal/ssa/gen/genericOps.go @@ -327,6 +327,7 @@ var genericOps = []opData{ // Pseudo-ops {name: "PanicNilCheck"}, // trigger a dereference fault; arg0=nil ptr, arg1=mem, returns mem {name: "GetG"}, // runtime.getg() (read g pointer) + {name: "GetClosurePtr"}, // get closure pointer from dedicated register // Indexing operations {name: "ArrayIndex"}, // arg0=array, arg1=index. Returns a[i] diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index 0da7946365..c52ef2d352 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -271,6 +271,7 @@ const ( OpAMD64InvertFlags OpAMD64LoweredPanicNilCheck OpAMD64LoweredGetG + OpAMD64LoweredGetClosurePtr OpAdd8 OpAdd16 @@ -512,6 +513,7 @@ const ( OpIsSliceInBounds OpPanicNilCheck OpGetG + OpGetClosurePtr OpArrayIndex OpPtrIndex OpOffPtr @@ -3122,6 +3124,14 @@ var opcodeTable = [...]opInfo{ }, }, }, + { + name: "LoweredGetClosurePtr", + reg: regInfo{ + outputs: []regMask{ + 4, // .DX + }, + }, + }, { name: "Add8", @@ -4083,6 +4093,10 @@ var opcodeTable = [...]opInfo{ name: "GetG", generic: true, }, + { + name: "GetClosurePtr", + generic: true, + }, { name: "ArrayIndex", generic: true, diff --git a/src/cmd/compile/internal/ssa/regalloc.go b/src/cmd/compile/internal/ssa/regalloc.go index f529b42fe0..9d0aab64cc 100644 --- a/src/cmd/compile/internal/ssa/regalloc.go +++ b/src/cmd/compile/internal/ssa/regalloc.go @@ -333,7 +333,11 @@ func (s *regAllocState) allocReg(mask regMask) register { // farthest-in-the-future use. // TODO: Prefer registers with already spilled Values? // TODO: Modify preference using affinity graph. - mask &^= 1<<4 | 1<<32 // don't spill SP or SB + + // SP and SB are allocated specially. No regular value should + // be allocated to them. + mask &^= 1<<4 | 1<<32 + maxuse := int32(-1) for t := register(0); t < numRegs; t++ { if mask>>t&1 == 0 { @@ -381,9 +385,7 @@ func (s *regAllocState) allocValToReg(v *Value, mask regMask, nospill bool) *Val return s.regs[r].c } - // SP and SB are allocated specially. No regular value should - // be allocated to them. - mask &^= 1<<4 | 1<<32 + mask &^= 1<<4 | 1<<32 // don't spill SP or SB // Allocate a register. r := s.allocReg(mask) diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go index 590efdb2eb..71cbb8171b 100644 --- a/src/cmd/compile/internal/ssa/rewriteAMD64.go +++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go @@ -2397,6 +2397,20 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto enda617119faaccc0f0c2d23548116cf331 enda617119faaccc0f0c2d23548116cf331: ; + case OpGetClosurePtr: + // match: (GetClosurePtr) + // cond: + // result: (LoweredGetClosurePtr) + { + v.Op = OpAMD64LoweredGetClosurePtr + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + return true + } + goto end6fd0b53f0acb4d35e7d7fa78d2ca1392 + end6fd0b53f0acb4d35e7d7fa78d2ca1392: + ; case OpGetG: // match: (GetG) // cond: diff --git a/src/cmd/compile/internal/ssa/schedule.go b/src/cmd/compile/internal/ssa/schedule.go index e551a6375c..949de31afc 100644 --- a/src/cmd/compile/internal/ssa/schedule.go +++ b/src/cmd/compile/internal/ssa/schedule.go @@ -4,6 +4,17 @@ package ssa +const ( + ScorePhi = iota // towards top of block + ScoreVarDef + ScoreMemory + ScoreDefault + ScoreFlags + ScoreControl // towards bottom of block + + ScoreCount // not a real score +) + // Schedule the Values in each Block. After this phase returns, the // order of b.Values matters and is the order in which those values // will appear in the assembly output. For now it generates a @@ -21,7 +32,7 @@ func schedule(f *Func) { var order []*Value // priority queue of legally schedulable (0 unscheduled uses) values - var priq [5][]*Value + var priq [ScoreCount][]*Value // maps mem values to the next live memory value nextMem := make([]*Value, f.NumValues()) @@ -69,27 +80,39 @@ func schedule(f *Func) { // Compute score. Larger numbers are scheduled closer to the end of the block. for _, v := range b.Values { switch { + case v.Op == OpAMD64LoweredGetClosurePtr: + // We also score GetLoweredClosurePtr as early as possible to ensure that the + // context register is not stomped. GetLoweredClosurePtr should only appear + // in the entry block where there are no phi functions, so there is no + // conflict or ambiguity here. + if b != f.Entry { + f.Fatalf("LoweredGetClosurePtr appeared outside of entry block.") + } + score[v.ID] = ScorePhi case v.Op == OpPhi: // We want all the phis first. - score[v.ID] = 0 + score[v.ID] = ScorePhi + case v.Op == OpVarDef: + // We want all the vardefs next. + score[v.ID] = ScoreVarDef case v.Type.IsMemory(): // Schedule stores as early as possible. This tends to // reduce register pressure. It also helps make sure // VARDEF ops are scheduled before the corresponding LEA. - score[v.ID] = 1 + score[v.ID] = ScoreMemory case v.Type.IsFlags(): // Schedule flag register generation as late as possible. // This makes sure that we only have one live flags // value at a time. - score[v.ID] = 3 + score[v.ID] = ScoreFlags default: - score[v.ID] = 2 + score[v.ID] = ScoreDefault } } if b.Control != nil && b.Control.Op != OpPhi { // Force the control value to be scheduled at the end, // unless it is a phi value (which must be first). - score[b.Control.ID] = 4 + score[b.Control.ID] = ScoreControl // Schedule values dependent on the control value at the end. // This reduces the number of register spills. We don't find @@ -100,7 +123,7 @@ func schedule(f *Func) { if v.Op != OpPhi { for _, a := range v.Args { if a == b.Control { - score[v.ID] = 4 + score[v.ID] = ScoreControl } } } -- cgit v1.3 From 10462eb30f60c140bd3ab524272488f9e349335d Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Wed, 21 Oct 2015 17:18:07 -0700 Subject: [dev.ssa] cmd/compile: better copying Replace REP MOVSB with all the copying techniques used by the old compiler. Copy in chunks, DUFFCOPY, etc. Introduces MOVO opcodes and an Int128 type to move around 16 bytes at a time. Change-Id: I1e73e68ca1d8b3dd58bb4af2f4c9e5d9bf13a502 Reviewed-on: https://go-review.googlesource.com/16174 Reviewed-by: Todd Neal Run-TryBot: Keith Randall --- src/cmd/compile/internal/gc/ssa.go | 13 +- src/cmd/compile/internal/gc/ssa_test.go | 2 + src/cmd/compile/internal/gc/testdata/copy_ssa.go | 726 +++++++++++++++++++++ .../compile/internal/gc/testdata/gen/copyGen.go | 93 +++ src/cmd/compile/internal/ssa/gen/AMD64.rules | 51 +- src/cmd/compile/internal/ssa/gen/AMD64Ops.go | 55 +- src/cmd/compile/internal/ssa/gen/rulegen.go | 2 +- src/cmd/compile/internal/ssa/opGen.go | 39 +- src/cmd/compile/internal/ssa/rewriteAMD64.go | 574 +++++++++++++++- src/cmd/compile/internal/ssa/type.go | 2 + 10 files changed, 1527 insertions(+), 30 deletions(-) create mode 100644 src/cmd/compile/internal/gc/testdata/copy_ssa.go create mode 100644 src/cmd/compile/internal/gc/testdata/gen/copyGen.go (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 50fc935dec..96c9a5fc9c 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -3697,7 +3697,7 @@ func (s *genState) genValue(v *ssa.Value) { p.From.Val = math.Float64frombits(uint64(v.AuxInt)) p.To.Type = obj.TYPE_REG p.To.Reg = x - case ssa.OpAMD64MOVQload, ssa.OpAMD64MOVSSload, ssa.OpAMD64MOVSDload, ssa.OpAMD64MOVLload, ssa.OpAMD64MOVWload, ssa.OpAMD64MOVBload, ssa.OpAMD64MOVBQSXload, ssa.OpAMD64MOVBQZXload: + case ssa.OpAMD64MOVQload, ssa.OpAMD64MOVSSload, ssa.OpAMD64MOVSDload, ssa.OpAMD64MOVLload, ssa.OpAMD64MOVWload, ssa.OpAMD64MOVBload, ssa.OpAMD64MOVBQSXload, ssa.OpAMD64MOVBQZXload, ssa.OpAMD64MOVOload: p := Prog(v.Op.Asm()) p.From.Type = obj.TYPE_MEM p.From.Reg = regnum(v.Args[0]) @@ -3722,7 +3722,7 @@ func (s *genState) genValue(v *ssa.Value) { p.From.Index = regnum(v.Args[1]) p.To.Type = obj.TYPE_REG p.To.Reg = regnum(v) - case ssa.OpAMD64MOVQstore, ssa.OpAMD64MOVSSstore, ssa.OpAMD64MOVSDstore, ssa.OpAMD64MOVLstore, ssa.OpAMD64MOVWstore, ssa.OpAMD64MOVBstore: + case ssa.OpAMD64MOVQstore, ssa.OpAMD64MOVSSstore, ssa.OpAMD64MOVSDstore, ssa.OpAMD64MOVLstore, ssa.OpAMD64MOVWstore, ssa.OpAMD64MOVBstore, ssa.OpAMD64MOVOstore: p := Prog(v.Op.Asm()) p.From.Type = obj.TYPE_REG p.From.Reg = regnum(v.Args[1]) @@ -3763,6 +3763,11 @@ func (s *genState) genValue(v *ssa.Value) { } r := regnum(v) opregreg(x86.AXORPS, r, r) + case ssa.OpAMD64DUFFCOPY: + p := Prog(obj.ADUFFCOPY) + p.To.Type = obj.TYPE_ADDR + p.To.Sym = Linksym(Pkglookup("duffcopy", Runtimepkg)) + p.To.Offset = v.AuxInt case ssa.OpCopy: // TODO: lower to MOVQ earlier? if v.Type.IsMemory() { @@ -3961,9 +3966,9 @@ func (s *genState) genValue(v *ssa.Value) { case ssa.OpAMD64REPSTOSQ: Prog(x86.AREP) Prog(x86.ASTOSQ) - case ssa.OpAMD64REPMOVSB: + case ssa.OpAMD64REPMOVSQ: Prog(x86.AREP) - Prog(x86.AMOVSB) + Prog(x86.AMOVSQ) case ssa.OpVarDef: Gvardef(v.Aux.(*Node)) case ssa.OpVarKill: diff --git a/src/cmd/compile/internal/gc/ssa_test.go b/src/cmd/compile/internal/gc/ssa_test.go index 1e06fd0d3d..5a881ed819 100644 --- a/src/cmd/compile/internal/gc/ssa_test.go +++ b/src/cmd/compile/internal/gc/ssa_test.go @@ -91,3 +91,5 @@ func TestAppend(t *testing.T) { runTest(t, "append_ssa.go") } func TestZero(t *testing.T) { runTest(t, "zero_ssa.go") } func TestAddressed(t *testing.T) { runTest(t, "addressed_ssa.go") } + +func TestCopy(t *testing.T) { runTest(t, "copy_ssa.go") } diff --git a/src/cmd/compile/internal/gc/testdata/copy_ssa.go b/src/cmd/compile/internal/gc/testdata/copy_ssa.go new file mode 100644 index 0000000000..44f0223a43 --- /dev/null +++ b/src/cmd/compile/internal/gc/testdata/copy_ssa.go @@ -0,0 +1,726 @@ +// run +// autogenerated from gen/copyGen.go - do not edit! +package main + +import "fmt" + +type T1 struct { + pre [8]byte + mid [1]byte + post [8]byte +} + +func t1copy_ssa(y, x *[1]byte) { + switch { + } + *y = *x +} +func testCopy1() { + a := T1{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [1]byte{0}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + x := [1]byte{100} + t1copy_ssa(&a.mid, &x) + want := T1{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [1]byte{100}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + if a != want { + fmt.Printf("t1copy got=%v, want %v\n", a, want) + failed = true + } +} + +type T2 struct { + pre [8]byte + mid [2]byte + post [8]byte +} + +func t2copy_ssa(y, x *[2]byte) { + switch { + } + *y = *x +} +func testCopy2() { + a := T2{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [2]byte{0, 1}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + x := [2]byte{100, 101} + t2copy_ssa(&a.mid, &x) + want := T2{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [2]byte{100, 101}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + if a != want { + fmt.Printf("t2copy got=%v, want %v\n", a, want) + failed = true + } +} + +type T3 struct { + pre [8]byte + mid [3]byte + post [8]byte +} + +func t3copy_ssa(y, x *[3]byte) { + switch { + } + *y = *x +} +func testCopy3() { + a := T3{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [3]byte{0, 1, 2}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + x := [3]byte{100, 101, 102} + t3copy_ssa(&a.mid, &x) + want := T3{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [3]byte{100, 101, 102}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + if a != want { + fmt.Printf("t3copy got=%v, want %v\n", a, want) + failed = true + } +} + +type T4 struct { + pre [8]byte + mid [4]byte + post [8]byte +} + +func t4copy_ssa(y, x *[4]byte) { + switch { + } + *y = *x +} +func testCopy4() { + a := T4{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [4]byte{0, 1, 2, 3}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + x := [4]byte{100, 101, 102, 103} + t4copy_ssa(&a.mid, &x) + want := T4{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [4]byte{100, 101, 102, 103}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + if a != want { + fmt.Printf("t4copy got=%v, want %v\n", a, want) + failed = true + } +} + +type T5 struct { + pre [8]byte + mid [5]byte + post [8]byte +} + +func t5copy_ssa(y, x *[5]byte) { + switch { + } + *y = *x +} +func testCopy5() { + a := T5{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [5]byte{0, 1, 2, 3, 4}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + x := [5]byte{100, 101, 102, 103, 104} + t5copy_ssa(&a.mid, &x) + want := T5{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [5]byte{100, 101, 102, 103, 104}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + if a != want { + fmt.Printf("t5copy got=%v, want %v\n", a, want) + failed = true + } +} + +type T6 struct { + pre [8]byte + mid [6]byte + post [8]byte +} + +func t6copy_ssa(y, x *[6]byte) { + switch { + } + *y = *x +} +func testCopy6() { + a := T6{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [6]byte{0, 1, 2, 3, 4, 5}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + x := [6]byte{100, 101, 102, 103, 104, 105} + t6copy_ssa(&a.mid, &x) + want := T6{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [6]byte{100, 101, 102, 103, 104, 105}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + if a != want { + fmt.Printf("t6copy got=%v, want %v\n", a, want) + failed = true + } +} + +type T7 struct { + pre [8]byte + mid [7]byte + post [8]byte +} + +func t7copy_ssa(y, x *[7]byte) { + switch { + } + *y = *x +} +func testCopy7() { + a := T7{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [7]byte{0, 1, 2, 3, 4, 5, 6}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + x := [7]byte{100, 101, 102, 103, 104, 105, 106} + t7copy_ssa(&a.mid, &x) + want := T7{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [7]byte{100, 101, 102, 103, 104, 105, 106}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + if a != want { + fmt.Printf("t7copy got=%v, want %v\n", a, want) + failed = true + } +} + +type T8 struct { + pre [8]byte + mid [8]byte + post [8]byte +} + +func t8copy_ssa(y, x *[8]byte) { + switch { + } + *y = *x +} +func testCopy8() { + a := T8{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [8]byte{0, 1, 2, 3, 4, 5, 6, 7}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + x := [8]byte{100, 101, 102, 103, 104, 105, 106, 107} + t8copy_ssa(&a.mid, &x) + want := T8{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [8]byte{100, 101, 102, 103, 104, 105, 106, 107}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + if a != want { + fmt.Printf("t8copy got=%v, want %v\n", a, want) + failed = true + } +} + +type T9 struct { + pre [8]byte + mid [9]byte + post [8]byte +} + +func t9copy_ssa(y, x *[9]byte) { + switch { + } + *y = *x +} +func testCopy9() { + a := T9{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [9]byte{0, 1, 2, 3, 4, 5, 6, 7, 8}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + x := [9]byte{100, 101, 102, 103, 104, 105, 106, 107, 108} + t9copy_ssa(&a.mid, &x) + want := T9{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [9]byte{100, 101, 102, 103, 104, 105, 106, 107, 108}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + if a != want { + fmt.Printf("t9copy got=%v, want %v\n", a, want) + failed = true + } +} + +type T10 struct { + pre [8]byte + mid [10]byte + post [8]byte +} + +func t10copy_ssa(y, x *[10]byte) { + switch { + } + *y = *x +} +func testCopy10() { + a := T10{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [10]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + x := [10]byte{100, 101, 102, 103, 104, 105, 106, 107, 108, 109} + t10copy_ssa(&a.mid, &x) + want := T10{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [10]byte{100, 101, 102, 103, 104, 105, 106, 107, 108, 109}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + if a != want { + fmt.Printf("t10copy got=%v, want %v\n", a, want) + failed = true + } +} + +type T15 struct { + pre [8]byte + mid [15]byte + post [8]byte +} + +func t15copy_ssa(y, x *[15]byte) { + switch { + } + *y = *x +} +func testCopy15() { + a := T15{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [15]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + x := [15]byte{100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114} + t15copy_ssa(&a.mid, &x) + want := T15{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [15]byte{100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + if a != want { + fmt.Printf("t15copy got=%v, want %v\n", a, want) + failed = true + } +} + +type T16 struct { + pre [8]byte + mid [16]byte + post [8]byte +} + +func t16copy_ssa(y, x *[16]byte) { + switch { + } + *y = *x +} +func testCopy16() { + a := T16{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [16]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + x := [16]byte{100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115} + t16copy_ssa(&a.mid, &x) + want := T16{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [16]byte{100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + if a != want { + fmt.Printf("t16copy got=%v, want %v\n", a, want) + failed = true + } +} + +type T17 struct { + pre [8]byte + mid [17]byte + post [8]byte +} + +func t17copy_ssa(y, x *[17]byte) { + switch { + } + *y = *x +} +func testCopy17() { + a := T17{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [17]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + x := [17]byte{100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116} + t17copy_ssa(&a.mid, &x) + want := T17{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [17]byte{100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + if a != want { + fmt.Printf("t17copy got=%v, want %v\n", a, want) + failed = true + } +} + +type T23 struct { + pre [8]byte + mid [23]byte + post [8]byte +} + +func t23copy_ssa(y, x *[23]byte) { + switch { + } + *y = *x +} +func testCopy23() { + a := T23{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [23]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + x := [23]byte{100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122} + t23copy_ssa(&a.mid, &x) + want := T23{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [23]byte{100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + if a != want { + fmt.Printf("t23copy got=%v, want %v\n", a, want) + failed = true + } +} + +type T24 struct { + pre [8]byte + mid [24]byte + post [8]byte +} + +func t24copy_ssa(y, x *[24]byte) { + switch { + } + *y = *x +} +func testCopy24() { + a := T24{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [24]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + x := [24]byte{100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123} + t24copy_ssa(&a.mid, &x) + want := T24{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [24]byte{100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + if a != want { + fmt.Printf("t24copy got=%v, want %v\n", a, want) + failed = true + } +} + +type T25 struct { + pre [8]byte + mid [25]byte + post [8]byte +} + +func t25copy_ssa(y, x *[25]byte) { + switch { + } + *y = *x +} +func testCopy25() { + a := T25{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [25]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + x := [25]byte{100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124} + t25copy_ssa(&a.mid, &x) + want := T25{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [25]byte{100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + if a != want { + fmt.Printf("t25copy got=%v, want %v\n", a, want) + failed = true + } +} + +type T31 struct { + pre [8]byte + mid [31]byte + post [8]byte +} + +func t31copy_ssa(y, x *[31]byte) { + switch { + } + *y = *x +} +func testCopy31() { + a := T31{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [31]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + x := [31]byte{100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130} + t31copy_ssa(&a.mid, &x) + want := T31{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [31]byte{100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + if a != want { + fmt.Printf("t31copy got=%v, want %v\n", a, want) + failed = true + } +} + +type T32 struct { + pre [8]byte + mid [32]byte + post [8]byte +} + +func t32copy_ssa(y, x *[32]byte) { + switch { + } + *y = *x +} +func testCopy32() { + a := T32{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [32]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + x := [32]byte{100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131} + t32copy_ssa(&a.mid, &x) + want := T32{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [32]byte{100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + if a != want { + fmt.Printf("t32copy got=%v, want %v\n", a, want) + failed = true + } +} + +type T33 struct { + pre [8]byte + mid [33]byte + post [8]byte +} + +func t33copy_ssa(y, x *[33]byte) { + switch { + } + *y = *x +} +func testCopy33() { + a := T33{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [33]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + x := [33]byte{100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132} + t33copy_ssa(&a.mid, &x) + want := T33{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [33]byte{100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + if a != want { + fmt.Printf("t33copy got=%v, want %v\n", a, want) + failed = true + } +} + +type T63 struct { + pre [8]byte + mid [63]byte + post [8]byte +} + +func t63copy_ssa(y, x *[63]byte) { + switch { + } + *y = *x +} +func testCopy63() { + a := T63{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [63]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + x := [63]byte{100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162} + t63copy_ssa(&a.mid, &x) + want := T63{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [63]byte{100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + if a != want { + fmt.Printf("t63copy got=%v, want %v\n", a, want) + failed = true + } +} + +type T64 struct { + pre [8]byte + mid [64]byte + post [8]byte +} + +func t64copy_ssa(y, x *[64]byte) { + switch { + } + *y = *x +} +func testCopy64() { + a := T64{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [64]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + x := [64]byte{100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163} + t64copy_ssa(&a.mid, &x) + want := T64{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [64]byte{100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + if a != want { + fmt.Printf("t64copy got=%v, want %v\n", a, want) + failed = true + } +} + +type T65 struct { + pre [8]byte + mid [65]byte + post [8]byte +} + +func t65copy_ssa(y, x *[65]byte) { + switch { + } + *y = *x +} +func testCopy65() { + a := T65{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [65]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + x := [65]byte{100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164} + t65copy_ssa(&a.mid, &x) + want := T65{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [65]byte{100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + if a != want { + fmt.Printf("t65copy got=%v, want %v\n", a, want) + failed = true + } +} + +type T1023 struct { + pre [8]byte + mid [1023]byte + post [8]byte +} + +func t1023copy_ssa(y, x *[1023]byte) { + switch { + } + *y = *x +} +func testCopy1023() { + a := T1023{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [1023]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + x := [1023]byte{100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122} + t1023copy_ssa(&a.mid, &x) + want := T1023{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [1023]byte{100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + if a != want { + fmt.Printf("t1023copy got=%v, want %v\n", a, want) + failed = true + } +} + +type T1024 struct { + pre [8]byte + mid [1024]byte + post [8]byte +} + +func t1024copy_ssa(y, x *[1024]byte) { + switch { + } + *y = *x +} +func testCopy1024() { + a := T1024{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [1024]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + x := [1024]byte{100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123} + t1024copy_ssa(&a.mid, &x) + want := T1024{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [1024]byte{100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + if a != want { + fmt.Printf("t1024copy got=%v, want %v\n", a, want) + failed = true + } +} + +type T1025 struct { + pre [8]byte + mid [1025]byte + post [8]byte +} + +func t1025copy_ssa(y, x *[1025]byte) { + switch { + } + *y = *x +} +func testCopy1025() { + a := T1025{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [1025]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + x := [1025]byte{100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124} + t1025copy_ssa(&a.mid, &x) + want := T1025{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [1025]byte{100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + if a != want { + fmt.Printf("t1025copy got=%v, want %v\n", a, want) + failed = true + } +} + +type T1031 struct { + pre [8]byte + mid [1031]byte + post [8]byte +} + +func t1031copy_ssa(y, x *[1031]byte) { + switch { + } + *y = *x +} +func testCopy1031() { + a := T1031{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [1031]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + x := [1031]byte{100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130} + t1031copy_ssa(&a.mid, &x) + want := T1031{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [1031]byte{100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + if a != want { + fmt.Printf("t1031copy got=%v, want %v\n", a, want) + failed = true + } +} + +type T1032 struct { + pre [8]byte + mid [1032]byte + post [8]byte +} + +func t1032copy_ssa(y, x *[1032]byte) { + switch { + } + *y = *x +} +func testCopy1032() { + a := T1032{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [1032]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + x := [1032]byte{100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131} + t1032copy_ssa(&a.mid, &x) + want := T1032{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [1032]byte{100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + if a != want { + fmt.Printf("t1032copy got=%v, want %v\n", a, want) + failed = true + } +} + +type T1033 struct { + pre [8]byte + mid [1033]byte + post [8]byte +} + +func t1033copy_ssa(y, x *[1033]byte) { + switch { + } + *y = *x +} +func testCopy1033() { + a := T1033{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [1033]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + x := [1033]byte{100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132} + t1033copy_ssa(&a.mid, &x) + want := T1033{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [1033]byte{100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + if a != want { + fmt.Printf("t1033copy got=%v, want %v\n", a, want) + failed = true + } +} + +type T1039 struct { + pre [8]byte + mid [1039]byte + post [8]byte +} + +func t1039copy_ssa(y, x *[1039]byte) { + switch { + } + *y = *x +} +func testCopy1039() { + a := T1039{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [1039]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + x := [1039]byte{100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138} + t1039copy_ssa(&a.mid, &x) + want := T1039{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [1039]byte{100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + if a != want { + fmt.Printf("t1039copy got=%v, want %v\n", a, want) + failed = true + } +} + +type T1040 struct { + pre [8]byte + mid [1040]byte + post [8]byte +} + +func t1040copy_ssa(y, x *[1040]byte) { + switch { + } + *y = *x +} +func testCopy1040() { + a := T1040{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [1040]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + x := [1040]byte{100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139} + t1040copy_ssa(&a.mid, &x) + want := T1040{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [1040]byte{100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + if a != want { + fmt.Printf("t1040copy got=%v, want %v\n", a, want) + failed = true + } +} + +type T1041 struct { + pre [8]byte + mid [1041]byte + post [8]byte +} + +func t1041copy_ssa(y, x *[1041]byte) { + switch { + } + *y = *x +} +func testCopy1041() { + a := T1041{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [1041]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + x := [1041]byte{100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140} + t1041copy_ssa(&a.mid, &x) + want := T1041{[8]byte{201, 202, 203, 204, 205, 206, 207, 208}, [1041]byte{100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140}, [8]byte{211, 212, 213, 214, 215, 216, 217, 218}} + if a != want { + fmt.Printf("t1041copy got=%v, want %v\n", a, want) + failed = true + } +} + +var failed bool + +func main() { + testCopy1() + testCopy2() + testCopy3() + testCopy4() + testCopy5() + testCopy6() + testCopy7() + testCopy8() + testCopy9() + testCopy10() + testCopy15() + testCopy16() + testCopy17() + testCopy23() + testCopy24() + testCopy25() + testCopy31() + testCopy32() + testCopy33() + testCopy63() + testCopy64() + testCopy65() + testCopy1023() + testCopy1024() + testCopy1025() + testCopy1031() + testCopy1032() + testCopy1033() + testCopy1039() + testCopy1040() + testCopy1041() + if failed { + panic("failed") + } +} diff --git a/src/cmd/compile/internal/gc/testdata/gen/copyGen.go b/src/cmd/compile/internal/gc/testdata/gen/copyGen.go new file mode 100644 index 0000000000..a699fac6c0 --- /dev/null +++ b/src/cmd/compile/internal/gc/testdata/gen/copyGen.go @@ -0,0 +1,93 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "bytes" + "fmt" + "go/format" + "io/ioutil" + "log" +) + +// This program generates tests to verify that copying operations +// copy the data they are supposed to and clobber no adjacent values. + +// run as `go run copyGen.go`. A file called copy_ssa.go +// will be written into the parent directory containing the tests. + +var sizes = [...]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 16, 17, 23, 24, 25, 31, 32, 33, 63, 64, 65, 1023, 1024, 1025, 1024 + 7, 1024 + 8, 1024 + 9, 1024 + 15, 1024 + 16, 1024 + 17} + +func main() { + w := new(bytes.Buffer) + fmt.Fprintf(w, "// run\n") + fmt.Fprintf(w, "// autogenerated from gen/copyGen.go - do not edit!\n") + fmt.Fprintf(w, "package main\n") + fmt.Fprintf(w, "import \"fmt\"\n") + + for _, s := range sizes { + // type for test + fmt.Fprintf(w, "type T%d struct {\n", s) + fmt.Fprintf(w, " pre [8]byte\n") + fmt.Fprintf(w, " mid [%d]byte\n", s) + fmt.Fprintf(w, " post [8]byte\n") + fmt.Fprintf(w, "}\n") + + // function being tested + fmt.Fprintf(w, "func t%dcopy_ssa(y, x *[%d]byte) {\n", s, s) + fmt.Fprintf(w, " switch{}\n") + fmt.Fprintf(w, " *y = *x\n") + fmt.Fprintf(w, "}\n") + + // testing harness + fmt.Fprintf(w, "func testCopy%d() {\n", s) + fmt.Fprintf(w, " a := T%d{[8]byte{201, 202, 203, 204, 205, 206, 207, 208},[%d]byte{", s, s) + for i := 0; i < s; i++ { + fmt.Fprintf(w, "%d,", i%100) + } + fmt.Fprintf(w, "},[8]byte{211, 212, 213, 214, 215, 216, 217, 218}}\n") + fmt.Fprintf(w, " x := [%d]byte{", s) + for i := 0; i < s; i++ { + fmt.Fprintf(w, "%d,", 100+i%100) + } + fmt.Fprintf(w, "}\n") + fmt.Fprintf(w, " t%dcopy_ssa(&a.mid, &x)\n", s) + fmt.Fprintf(w, " want := T%d{[8]byte{201, 202, 203, 204, 205, 206, 207, 208},[%d]byte{", s, s) + for i := 0; i < s; i++ { + fmt.Fprintf(w, "%d,", 100+i%100) + } + fmt.Fprintf(w, "},[8]byte{211, 212, 213, 214, 215, 216, 217, 218}}\n") + fmt.Fprintf(w, " if a != want {\n") + fmt.Fprintf(w, " fmt.Printf(\"t%dcopy got=%%v, want %%v\\n\", a, want)\n", s) + fmt.Fprintf(w, " failed=true\n") + fmt.Fprintf(w, " }\n") + fmt.Fprintf(w, "}\n") + } + + // boilerplate at end + fmt.Fprintf(w, "var failed bool\n") + fmt.Fprintf(w, "func main() {\n") + for _, s := range sizes { + fmt.Fprintf(w, " testCopy%d()\n", s) + } + fmt.Fprintf(w, " if failed {\n") + fmt.Fprintf(w, " panic(\"failed\")\n") + fmt.Fprintf(w, " }\n") + fmt.Fprintf(w, "}\n") + + // gofmt result + b := w.Bytes() + src, err := format.Source(b) + if err != nil { + fmt.Printf("%s\n", b) + panic(err) + } + + // write to file + err = ioutil.WriteFile("../copy_ssa.go", src, 0666) + if err != nil { + log.Fatalf("can't write output: %v\n", err) + } +} diff --git a/src/cmd/compile/internal/ssa/gen/AMD64.rules b/src/cmd/compile/internal/ssa/gen/AMD64.rules index 4eef40c478..a6ea970fdb 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64.rules +++ b/src/cmd/compile/internal/ssa/gen/AMD64.rules @@ -293,7 +293,50 @@ (GetG mem) -> (LoweredGetG mem) (GetClosurePtr) -> (LoweredGetClosurePtr) -(Move [size] dst src mem) -> (REPMOVSB dst src (MOVQconst [size]) mem) +// Small moves +(Move [0] _ _ mem) -> mem +(Move [1] dst src mem) -> (MOVBstore dst (MOVBload src mem) mem) +(Move [2] dst src mem) -> (MOVWstore dst (MOVWload src mem) mem) +(Move [4] dst src mem) -> (MOVLstore dst (MOVLload src mem) mem) +(Move [8] dst src mem) -> (MOVQstore dst (MOVQload src mem) mem) +(Move [16] dst src mem) -> (MOVOstore dst (MOVOload src mem) mem) +(Move [3] dst src mem) -> + (MOVBstore [2] dst (MOVBload [2] src mem) + (MOVWstore dst (MOVWload src mem) mem)) +(Move [5] dst src mem) -> + (MOVBstore [4] dst (MOVBload [4] src mem) + (MOVLstore dst (MOVLload src mem) mem)) +(Move [6] dst src mem) -> + (MOVWstore [4] dst (MOVWload [4] src mem) + (MOVLstore dst (MOVLload src mem) mem)) +(Move [7] dst src mem) -> + (MOVLstore [3] dst (MOVLload [3] src mem) + (MOVLstore dst (MOVLload src mem) mem)) +(Move [size] dst src mem) && size > 8 && size < 16 -> + (MOVQstore [size-8] dst (MOVQload [size-8] src mem) + (MOVQstore dst (MOVQload src mem) mem)) + +// Adjust moves to be a multiple of 16 bytes. +(Move [size] dst src mem) && size > 16 && size%16 != 0 && size%16 <= 8 -> + (Move [size-size%16] (ADDQconst dst [size%16]) (ADDQconst src [size%16]) + (MOVQstore dst (MOVQload src mem) mem)) +(Move [size] dst src mem) && size > 16 && size%16 != 0 && size%16 > 8 -> + (Move [size-size%16] (ADDQconst dst [size%16]) (ADDQconst src [size%16]) + (MOVOstore dst (MOVOload src mem) mem)) + +// Medium copying uses a duff device. +(Move [size] dst src mem) && size >= 32 && size <= 16*64 && size%16 == 0 -> + (DUFFCOPY [14*(64-size/16)] dst src mem) +// 14 and 64 are magic constants. 14 is the number of bytes to encode: +// MOVUPS (SI), X0 +// ADDQ $16, SI +// MOVUPS X0, (DI) +// ADDQ $16, DI +// and 64 is the number of such blocks. See src/runtime/duff_amd64.s:duffcopy. + +// Large copying uses REP MOVSQ. +(Move [size] dst src mem) && size > 16*64 && size%8 == 0 -> + (REPMOVSQ dst src (MOVQconst [size/8]) mem) (Not x) -> (XORBconst [1] x) @@ -504,6 +547,7 @@ (MOVBload [off1] {sym} (ADDQconst [off2] ptr) mem) -> (MOVBload [addOff(off1, off2)] {sym} ptr mem) (MOVSSload [off1] {sym} (ADDQconst [off2] ptr) mem) -> (MOVSSload [addOff(off1, off2)] {sym} ptr mem) (MOVSDload [off1] {sym} (ADDQconst [off2] ptr) mem) -> (MOVSDload [addOff(off1, off2)] {sym} ptr mem) +(MOVOload [off1] {sym} (ADDQconst [off2] ptr) mem) -> (MOVOload [addOff(off1, off2)] {sym} ptr mem) (MOVQstore [off1] {sym} (ADDQconst [off2] ptr) val mem) -> (MOVQstore [addOff(off1, off2)] {sym} ptr val mem) (MOVLstore [off1] {sym} (ADDQconst [off2] ptr) val mem) -> (MOVLstore [addOff(off1, off2)] {sym} ptr val mem) @@ -511,6 +555,7 @@ (MOVBstore [off1] {sym} (ADDQconst [off2] ptr) val mem) -> (MOVBstore [addOff(off1, off2)] {sym} ptr val mem) (MOVSSstore [off1] {sym} (ADDQconst [off2] ptr) val mem) -> (MOVSSstore [addOff(off1, off2)] {sym} ptr val mem) (MOVSDstore [off1] {sym} (ADDQconst [off2] ptr) val mem) -> (MOVSDstore [addOff(off1, off2)] {sym} ptr val mem) +(MOVOstore [off1] {sym} (ADDQconst [off2] ptr) val mem) -> (MOVOstore [addOff(off1, off2)] {sym} ptr val mem) // We need to fold LEAQ into the MOVx ops so that the live variable analysis knows // what variables are being read/written by the ops. @@ -526,6 +571,8 @@ (MOVSSload [addOff(off1,off2)] {mergeSym(sym1,sym2)} base mem) (MOVSDload [off1] {sym1} (LEAQ [off2] {sym2} base) mem) && canMergeSym(sym1, sym2) -> (MOVSDload [addOff(off1,off2)] {mergeSym(sym1,sym2)} base mem) +(MOVOload [off1] {sym1} (LEAQ [off2] {sym2} base) mem) && canMergeSym(sym1, sym2) -> + (MOVOload [addOff(off1,off2)] {mergeSym(sym1,sym2)} base mem) (MOVQstore [off1] {sym1} (LEAQ [off2] {sym2} base) val mem) && canMergeSym(sym1, sym2) -> (MOVQstore [addOff(off1,off2)] {mergeSym(sym1,sym2)} base val mem) @@ -539,6 +586,8 @@ (MOVSSstore [addOff(off1,off2)] {mergeSym(sym1,sym2)} base val mem) (MOVSDstore [off1] {sym1} (LEAQ [off2] {sym2} base) val mem) && canMergeSym(sym1, sym2) -> (MOVSDstore [addOff(off1,off2)] {mergeSym(sym1,sym2)} base val mem) +(MOVOstore [off1] {sym1} (LEAQ [off2] {sym2} base) val mem) && canMergeSym(sym1, sym2) -> + (MOVOstore [addOff(off1,off2)] {mergeSym(sym1,sym2)} base val mem) // indexed loads and stores (MOVQloadidx8 [off1] {sym} (ADDQconst [off2] ptr) idx mem) -> (MOVQloadidx8 [addOff(off1, off2)] {sym} ptr idx mem) diff --git a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go index 2af50d3584..80f7096f80 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go @@ -366,18 +366,21 @@ func init() { {name: "LEAQ8", reg: gp21sb}, // arg0 + 8*arg1 + auxint // auxint+aux == add auxint and the offset of the symbol in aux (if any) to the effective address - {name: "MOVBload", reg: gpload, asm: "MOVB"}, // load byte from arg0+auxint+aux. arg1=mem - {name: "MOVBQSXload", reg: gpload, asm: "MOVBQSX"}, // ditto, extend to int64 - {name: "MOVBQZXload", reg: gpload, asm: "MOVBQZX"}, // ditto, extend to uint64 - {name: "MOVWload", reg: gpload, asm: "MOVW"}, // load 2 bytes from arg0+auxint+aux. arg1=mem - {name: "MOVLload", reg: gpload, asm: "MOVL"}, // load 4 bytes from arg0+auxint+aux. arg1=mem - {name: "MOVQload", reg: gpload, asm: "MOVQ"}, // load 8 bytes from arg0+auxint+aux. arg1=mem - {name: "MOVQloadidx8", reg: gploadidx, asm: "MOVQ"}, // load 8 bytes from arg0+8*arg1+auxint+aux. arg2=mem - {name: "MOVBstore", reg: gpstore, asm: "MOVB", typ: "Mem"}, // store byte in arg1 to arg0+auxint+aux. arg2=mem - {name: "MOVWstore", reg: gpstore, asm: "MOVW", typ: "Mem"}, // store 2 bytes in arg1 to arg0+auxint+aux. arg2=mem - {name: "MOVLstore", reg: gpstore, asm: "MOVL", typ: "Mem"}, // store 4 bytes in arg1 to arg0+auxint+aux. arg2=mem - {name: "MOVQstore", reg: gpstore, asm: "MOVQ", typ: "Mem"}, // store 8 bytes in arg1 to arg0+auxint+aux. arg2=mem - {name: "MOVQstoreidx8", reg: gpstoreidx, asm: "MOVQ"}, // store 8 bytes in arg2 to arg0+8*arg1+auxint+aux. arg3=mem + {name: "MOVBload", reg: gpload, asm: "MOVB", typ: "UInt8"}, // load byte from arg0+auxint+aux. arg1=mem + {name: "MOVBQSXload", reg: gpload, asm: "MOVBQSX"}, // ditto, extend to int64 + {name: "MOVBQZXload", reg: gpload, asm: "MOVBQZX"}, // ditto, extend to uint64 + {name: "MOVWload", reg: gpload, asm: "MOVW", typ: "UInt16"}, // load 2 bytes from arg0+auxint+aux. arg1=mem + {name: "MOVLload", reg: gpload, asm: "MOVL", typ: "UInt32"}, // load 4 bytes from arg0+auxint+aux. arg1=mem + {name: "MOVQload", reg: gpload, asm: "MOVQ", typ: "UInt64"}, // load 8 bytes from arg0+auxint+aux. arg1=mem + {name: "MOVQloadidx8", reg: gploadidx, asm: "MOVQ"}, // load 8 bytes from arg0+8*arg1+auxint+aux. arg2=mem + {name: "MOVBstore", reg: gpstore, asm: "MOVB", typ: "Mem"}, // store byte in arg1 to arg0+auxint+aux. arg2=mem + {name: "MOVWstore", reg: gpstore, asm: "MOVW", typ: "Mem"}, // store 2 bytes in arg1 to arg0+auxint+aux. arg2=mem + {name: "MOVLstore", reg: gpstore, asm: "MOVL", typ: "Mem"}, // store 4 bytes in arg1 to arg0+auxint+aux. arg2=mem + {name: "MOVQstore", reg: gpstore, asm: "MOVQ", typ: "Mem"}, // store 8 bytes in arg1 to arg0+auxint+aux. arg2=mem + {name: "MOVQstoreidx8", reg: gpstoreidx, asm: "MOVQ"}, // store 8 bytes in arg2 to arg0+8*arg1+auxint+aux. arg3=mem + + {name: "MOVOload", reg: fpload, asm: "MOVUPS", typ: "Int128"}, // load 16 bytes from arg0+auxint+aux. arg1=mem + {name: "MOVOstore", reg: fpstore, asm: "MOVUPS", typ: "Mem"}, // store 16 bytes in arg1 to arg0+auxint+aux. arg2=mem // arg0 = (duff-adjusted) pointer to start of memory to zero // arg1 = value to store (will always be zero) @@ -391,7 +394,7 @@ func init() { clobbers: buildReg("DI FLAGS"), }, }, - {name: "MOVOconst", reg: regInfo{nil, 0, []regMask{fp}}, typ: "Float64"}, + {name: "MOVOconst", reg: regInfo{nil, 0, []regMask{fp}}, typ: "Int128"}, // arg0 = address of memory to zero // arg1 = # of 8-byte words to zero @@ -412,7 +415,31 @@ func init() { {name: "CALLgo", reg: regInfo{clobbers: callerSave}}, // call newproc. arg0=mem, auxint=argsize, returns mem {name: "CALLinter", reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem - {name: "REPMOVSB", reg: regInfo{[]regMask{buildReg("DI"), buildReg("SI"), buildReg("CX")}, buildReg("DI SI CX"), nil}}, // move arg2 bytes from arg1 to arg0. arg3=mem, returns memory + // arg0 = destination pointer + // arg1 = source pointer + // arg2 = mem + // auxint = offset from duffcopy symbol to call + // returns memory + { + name: "DUFFCOPY", + reg: regInfo{ + inputs: []regMask{buildReg("DI"), buildReg("SI")}, + clobbers: buildReg("DI SI X0"), // uses X0 as a temporary + }, + }, + + // arg0 = destination pointer + // arg1 = source pointer + // arg2 = # of 8-byte words to copy + // arg3 = mem + // returns memory + { + name: "REPMOVSQ", + reg: regInfo{ + inputs: []regMask{buildReg("DI"), buildReg("SI"), buildReg("CX")}, + clobbers: buildReg("DI SI CX"), + }, + }, // (InvertFlags (CMPQ a b)) == (CMPQ b a) // So if we want (SETL (CMPQ a b)) but we can't do that because a is a constant, diff --git a/src/cmd/compile/internal/ssa/gen/rulegen.go b/src/cmd/compile/internal/ssa/gen/rulegen.go index 71c9ca7ec2..1aef1dab8f 100644 --- a/src/cmd/compile/internal/ssa/gen/rulegen.go +++ b/src/cmd/compile/internal/ssa/gen/rulegen.go @@ -585,7 +585,7 @@ func blockName(name string, arch arch) string { // typeName returns the string to use to generate a type. func typeName(typ string) string { switch typ { - case "Flags", "Mem", "Void": + case "Flags", "Mem", "Void", "Int128": return "Type" + typ default: return "config.fe.Type" + typ + "()" diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index bddb1176ad..a1a2ce9e49 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -262,6 +262,8 @@ const ( OpAMD64MOVLstore OpAMD64MOVQstore OpAMD64MOVQstoreidx8 + OpAMD64MOVOload + OpAMD64MOVOstore OpAMD64DUFFZERO OpAMD64MOVOconst OpAMD64REPSTOSQ @@ -270,7 +272,8 @@ const ( OpAMD64CALLdefer OpAMD64CALLgo OpAMD64CALLinter - OpAMD64REPMOVSB + OpAMD64DUFFCOPY + OpAMD64REPMOVSQ OpAMD64InvertFlags OpAMD64LoweredGetG OpAMD64LoweredGetClosurePtr @@ -3039,6 +3042,28 @@ var opcodeTable = [...]opInfo{ }, }, }, + { + name: "MOVOload", + asm: x86.AMOVUPS, + reg: regInfo{ + inputs: []inputInfo{ + {0, 4295032831}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB + }, + outputs: []regMask{ + 4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + }, + }, + }, + { + name: "MOVOstore", + asm: x86.AMOVUPS, + reg: regInfo{ + inputs: []inputInfo{ + {1, 4294901760}, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 + {0, 4295032831}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .SB + }, + }, + }, { name: "DUFFZERO", reg: regInfo{ @@ -3106,7 +3131,17 @@ var opcodeTable = [...]opInfo{ }, }, { - name: "REPMOVSB", + name: "DUFFCOPY", + reg: regInfo{ + inputs: []inputInfo{ + {0, 128}, // .DI + {1, 64}, // .SI + }, + clobbers: 65728, // .SI .DI .X0 + }, + }, + { + name: "REPMOVSQ", reg: regInfo{ inputs: []inputInfo{ {0, 128}, // .DI diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go index f32b524689..1d7695fa4b 100644 --- a/src/cmd/compile/internal/ssa/rewriteAMD64.go +++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go @@ -4379,6 +4379,120 @@ func rewriteValueAMD64(v *Value, config *Config) bool { goto endd57b1e4313fc7a3331340a9af00ba116 endd57b1e4313fc7a3331340a9af00ba116: ; + case OpAMD64MOVOload: + // match: (MOVOload [off1] {sym} (ADDQconst [off2] ptr) mem) + // cond: + // result: (MOVOload [addOff(off1, off2)] {sym} ptr mem) + { + off1 := v.AuxInt + sym := v.Aux + if v.Args[0].Op != OpAMD64ADDQconst { + goto endf1e8fcf569ddd8b3f7a2f61696971913 + } + off2 := v.Args[0].AuxInt + ptr := v.Args[0].Args[0] + mem := v.Args[1] + v.Op = OpAMD64MOVOload + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = addOff(off1, off2) + v.Aux = sym + v.AddArg(ptr) + v.AddArg(mem) + return true + } + goto endf1e8fcf569ddd8b3f7a2f61696971913 + endf1e8fcf569ddd8b3f7a2f61696971913: + ; + // match: (MOVOload [off1] {sym1} (LEAQ [off2] {sym2} base) mem) + // cond: canMergeSym(sym1, sym2) + // result: (MOVOload [addOff(off1,off2)] {mergeSym(sym1,sym2)} base mem) + { + off1 := v.AuxInt + sym1 := v.Aux + if v.Args[0].Op != OpAMD64LEAQ { + goto endd36cf9b00af7a8f44fb8c60067a8efb2 + } + off2 := v.Args[0].AuxInt + sym2 := v.Args[0].Aux + base := v.Args[0].Args[0] + mem := v.Args[1] + if !(canMergeSym(sym1, sym2)) { + goto endd36cf9b00af7a8f44fb8c60067a8efb2 + } + v.Op = OpAMD64MOVOload + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = addOff(off1, off2) + v.Aux = mergeSym(sym1, sym2) + v.AddArg(base) + v.AddArg(mem) + return true + } + goto endd36cf9b00af7a8f44fb8c60067a8efb2 + endd36cf9b00af7a8f44fb8c60067a8efb2: + ; + case OpAMD64MOVOstore: + // match: (MOVOstore [off1] {sym} (ADDQconst [off2] ptr) val mem) + // cond: + // result: (MOVOstore [addOff(off1, off2)] {sym} ptr val mem) + { + off1 := v.AuxInt + sym := v.Aux + if v.Args[0].Op != OpAMD64ADDQconst { + goto end2be573aa1bd919e567e6156a4ee36517 + } + off2 := v.Args[0].AuxInt + ptr := v.Args[0].Args[0] + val := v.Args[1] + mem := v.Args[2] + v.Op = OpAMD64MOVOstore + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = addOff(off1, off2) + v.Aux = sym + v.AddArg(ptr) + v.AddArg(val) + v.AddArg(mem) + return true + } + goto end2be573aa1bd919e567e6156a4ee36517 + end2be573aa1bd919e567e6156a4ee36517: + ; + // match: (MOVOstore [off1] {sym1} (LEAQ [off2] {sym2} base) val mem) + // cond: canMergeSym(sym1, sym2) + // result: (MOVOstore [addOff(off1,off2)] {mergeSym(sym1,sym2)} base val mem) + { + off1 := v.AuxInt + sym1 := v.Aux + if v.Args[0].Op != OpAMD64LEAQ { + goto endc28b9b3efe9eb235e1586c4555280c20 + } + off2 := v.Args[0].AuxInt + sym2 := v.Args[0].Aux + base := v.Args[0].Args[0] + val := v.Args[1] + mem := v.Args[2] + if !(canMergeSym(sym1, sym2)) { + goto endc28b9b3efe9eb235e1586c4555280c20 + } + v.Op = OpAMD64MOVOstore + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = addOff(off1, off2) + v.Aux = mergeSym(sym1, sym2) + v.AddArg(base) + v.AddArg(val) + v.AddArg(mem) + return true + } + goto endc28b9b3efe9eb235e1586c4555280c20 + endc28b9b3efe9eb235e1586c4555280c20: + ; case OpAMD64MOVQload: // match: (MOVQload [off1] {sym} (ADDQconst [off2] ptr) mem) // cond: @@ -5803,29 +5917,473 @@ func rewriteValueAMD64(v *Value, config *Config) bool { end9b3274d9dd7f1e91c75ce5e7b548fe97: ; case OpMove: - // match: (Move [size] dst src mem) + // match: (Move [0] _ _ mem) + // cond: + // result: mem + { + if v.AuxInt != 0 { + goto end0961cbfe144a616cba75190d07d65e41 + } + mem := v.Args[2] + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = mem.Type + v.AddArg(mem) + return true + } + goto end0961cbfe144a616cba75190d07d65e41 + end0961cbfe144a616cba75190d07d65e41: + ; + // match: (Move [1] dst src mem) + // cond: + // result: (MOVBstore dst (MOVBload src mem) mem) + { + if v.AuxInt != 1 { + goto end72e5dd27e999493b67ea3af4ecc60d48 + } + dst := v.Args[0] + src := v.Args[1] + mem := v.Args[2] + v.Op = OpAMD64MOVBstore + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(dst) + v0 := b.NewValue0(v.Line, OpAMD64MOVBload, TypeInvalid) + v0.AddArg(src) + v0.AddArg(mem) + v0.Type = config.fe.TypeUInt8() + v.AddArg(v0) + v.AddArg(mem) + return true + } + goto end72e5dd27e999493b67ea3af4ecc60d48 + end72e5dd27e999493b67ea3af4ecc60d48: + ; + // match: (Move [2] dst src mem) + // cond: + // result: (MOVWstore dst (MOVWload src mem) mem) + { + if v.AuxInt != 2 { + goto end017f774e406d4578b4bcefcd8db8ec1e + } + dst := v.Args[0] + src := v.Args[1] + mem := v.Args[2] + v.Op = OpAMD64MOVWstore + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(dst) + v0 := b.NewValue0(v.Line, OpAMD64MOVWload, TypeInvalid) + v0.AddArg(src) + v0.AddArg(mem) + v0.Type = config.fe.TypeUInt16() + v.AddArg(v0) + v.AddArg(mem) + return true + } + goto end017f774e406d4578b4bcefcd8db8ec1e + end017f774e406d4578b4bcefcd8db8ec1e: + ; + // match: (Move [4] dst src mem) + // cond: + // result: (MOVLstore dst (MOVLload src mem) mem) + { + if v.AuxInt != 4 { + goto end938ec47a2ddf8e9b4bf71ffade6e5b3f + } + dst := v.Args[0] + src := v.Args[1] + mem := v.Args[2] + v.Op = OpAMD64MOVLstore + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(dst) + v0 := b.NewValue0(v.Line, OpAMD64MOVLload, TypeInvalid) + v0.AddArg(src) + v0.AddArg(mem) + v0.Type = config.fe.TypeUInt32() + v.AddArg(v0) + v.AddArg(mem) + return true + } + goto end938ec47a2ddf8e9b4bf71ffade6e5b3f + end938ec47a2ddf8e9b4bf71ffade6e5b3f: + ; + // match: (Move [8] dst src mem) + // cond: + // result: (MOVQstore dst (MOVQload src mem) mem) + { + if v.AuxInt != 8 { + goto end696b3498f5fee17f49ae0f708d3dfe4b + } + dst := v.Args[0] + src := v.Args[1] + mem := v.Args[2] + v.Op = OpAMD64MOVQstore + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(dst) + v0 := b.NewValue0(v.Line, OpAMD64MOVQload, TypeInvalid) + v0.AddArg(src) + v0.AddArg(mem) + v0.Type = config.fe.TypeUInt64() + v.AddArg(v0) + v.AddArg(mem) + return true + } + goto end696b3498f5fee17f49ae0f708d3dfe4b + end696b3498f5fee17f49ae0f708d3dfe4b: + ; + // match: (Move [16] dst src mem) + // cond: + // result: (MOVOstore dst (MOVOload src mem) mem) + { + if v.AuxInt != 16 { + goto end4894ace925d468c10a5b0c5b91fc4c1c + } + dst := v.Args[0] + src := v.Args[1] + mem := v.Args[2] + v.Op = OpAMD64MOVOstore + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(dst) + v0 := b.NewValue0(v.Line, OpAMD64MOVOload, TypeInvalid) + v0.AddArg(src) + v0.AddArg(mem) + v0.Type = TypeInt128 + v.AddArg(v0) + v.AddArg(mem) + return true + } + goto end4894ace925d468c10a5b0c5b91fc4c1c + end4894ace925d468c10a5b0c5b91fc4c1c: + ; + // match: (Move [3] dst src mem) + // cond: + // result: (MOVBstore [2] dst (MOVBload [2] src mem) (MOVWstore dst (MOVWload src mem) mem)) + { + if v.AuxInt != 3 { + goto end76ce0004999139fe4608c3c5356eb364 + } + dst := v.Args[0] + src := v.Args[1] + mem := v.Args[2] + v.Op = OpAMD64MOVBstore + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = 2 + v.AddArg(dst) + v0 := b.NewValue0(v.Line, OpAMD64MOVBload, TypeInvalid) + v0.AuxInt = 2 + v0.AddArg(src) + v0.AddArg(mem) + v0.Type = config.fe.TypeUInt8() + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpAMD64MOVWstore, TypeInvalid) + v1.AddArg(dst) + v2 := b.NewValue0(v.Line, OpAMD64MOVWload, TypeInvalid) + v2.AddArg(src) + v2.AddArg(mem) + v2.Type = config.fe.TypeUInt16() + v1.AddArg(v2) + v1.AddArg(mem) + v1.Type = TypeMem + v.AddArg(v1) + return true + } + goto end76ce0004999139fe4608c3c5356eb364 + end76ce0004999139fe4608c3c5356eb364: + ; + // match: (Move [5] dst src mem) + // cond: + // result: (MOVBstore [4] dst (MOVBload [4] src mem) (MOVLstore dst (MOVLload src mem) mem)) + { + if v.AuxInt != 5 { + goto end21378690c0f39bdd6b46566d57da34e3 + } + dst := v.Args[0] + src := v.Args[1] + mem := v.Args[2] + v.Op = OpAMD64MOVBstore + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = 4 + v.AddArg(dst) + v0 := b.NewValue0(v.Line, OpAMD64MOVBload, TypeInvalid) + v0.AuxInt = 4 + v0.AddArg(src) + v0.AddArg(mem) + v0.Type = config.fe.TypeUInt8() + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpAMD64MOVLstore, TypeInvalid) + v1.AddArg(dst) + v2 := b.NewValue0(v.Line, OpAMD64MOVLload, TypeInvalid) + v2.AddArg(src) + v2.AddArg(mem) + v2.Type = config.fe.TypeUInt32() + v1.AddArg(v2) + v1.AddArg(mem) + v1.Type = TypeMem + v.AddArg(v1) + return true + } + goto end21378690c0f39bdd6b46566d57da34e3 + end21378690c0f39bdd6b46566d57da34e3: + ; + // match: (Move [6] dst src mem) // cond: - // result: (REPMOVSB dst src (MOVQconst [size]) mem) + // result: (MOVWstore [4] dst (MOVWload [4] src mem) (MOVLstore dst (MOVLload src mem) mem)) + { + if v.AuxInt != 6 { + goto endcb6e509881d8638d8cae3af4f2b19a8e + } + dst := v.Args[0] + src := v.Args[1] + mem := v.Args[2] + v.Op = OpAMD64MOVWstore + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = 4 + v.AddArg(dst) + v0 := b.NewValue0(v.Line, OpAMD64MOVWload, TypeInvalid) + v0.AuxInt = 4 + v0.AddArg(src) + v0.AddArg(mem) + v0.Type = config.fe.TypeUInt16() + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpAMD64MOVLstore, TypeInvalid) + v1.AddArg(dst) + v2 := b.NewValue0(v.Line, OpAMD64MOVLload, TypeInvalid) + v2.AddArg(src) + v2.AddArg(mem) + v2.Type = config.fe.TypeUInt32() + v1.AddArg(v2) + v1.AddArg(mem) + v1.Type = TypeMem + v.AddArg(v1) + return true + } + goto endcb6e509881d8638d8cae3af4f2b19a8e + endcb6e509881d8638d8cae3af4f2b19a8e: + ; + // match: (Move [7] dst src mem) + // cond: + // result: (MOVLstore [3] dst (MOVLload [3] src mem) (MOVLstore dst (MOVLload src mem) mem)) + { + if v.AuxInt != 7 { + goto end3429ae54bc071c0856ad366c79b7ab97 + } + dst := v.Args[0] + src := v.Args[1] + mem := v.Args[2] + v.Op = OpAMD64MOVLstore + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = 3 + v.AddArg(dst) + v0 := b.NewValue0(v.Line, OpAMD64MOVLload, TypeInvalid) + v0.AuxInt = 3 + v0.AddArg(src) + v0.AddArg(mem) + v0.Type = config.fe.TypeUInt32() + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpAMD64MOVLstore, TypeInvalid) + v1.AddArg(dst) + v2 := b.NewValue0(v.Line, OpAMD64MOVLload, TypeInvalid) + v2.AddArg(src) + v2.AddArg(mem) + v2.Type = config.fe.TypeUInt32() + v1.AddArg(v2) + v1.AddArg(mem) + v1.Type = TypeMem + v.AddArg(v1) + return true + } + goto end3429ae54bc071c0856ad366c79b7ab97 + end3429ae54bc071c0856ad366c79b7ab97: + ; + // match: (Move [size] dst src mem) + // cond: size > 8 && size < 16 + // result: (MOVQstore [size-8] dst (MOVQload [size-8] src mem) (MOVQstore dst (MOVQload src mem) mem)) + { + size := v.AuxInt + dst := v.Args[0] + src := v.Args[1] + mem := v.Args[2] + if !(size > 8 && size < 16) { + goto endc90f121709d5411d389649dea89a2251 + } + v.Op = OpAMD64MOVQstore + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = size - 8 + v.AddArg(dst) + v0 := b.NewValue0(v.Line, OpAMD64MOVQload, TypeInvalid) + v0.AuxInt = size - 8 + v0.AddArg(src) + v0.AddArg(mem) + v0.Type = config.fe.TypeUInt64() + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpAMD64MOVQstore, TypeInvalid) + v1.AddArg(dst) + v2 := b.NewValue0(v.Line, OpAMD64MOVQload, TypeInvalid) + v2.AddArg(src) + v2.AddArg(mem) + v2.Type = config.fe.TypeUInt64() + v1.AddArg(v2) + v1.AddArg(mem) + v1.Type = TypeMem + v.AddArg(v1) + return true + } + goto endc90f121709d5411d389649dea89a2251 + endc90f121709d5411d389649dea89a2251: + ; + // match: (Move [size] dst src mem) + // cond: size > 16 && size%16 != 0 && size%16 <= 8 + // result: (Move [size-size%16] (ADDQconst dst [size%16]) (ADDQconst src [size%16]) (MOVQstore dst (MOVQload src mem) mem)) + { + size := v.AuxInt + dst := v.Args[0] + src := v.Args[1] + mem := v.Args[2] + if !(size > 16 && size%16 != 0 && size%16 <= 8) { + goto end376c57db23b866866f23677c6cde43ba + } + v.Op = OpMove + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = size - size%16 + v0 := b.NewValue0(v.Line, OpAMD64ADDQconst, TypeInvalid) + v0.Type = dst.Type + v0.AddArg(dst) + v0.AuxInt = size % 16 + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpAMD64ADDQconst, TypeInvalid) + v1.Type = src.Type + v1.AddArg(src) + v1.AuxInt = size % 16 + v.AddArg(v1) + v2 := b.NewValue0(v.Line, OpAMD64MOVQstore, TypeInvalid) + v2.AddArg(dst) + v3 := b.NewValue0(v.Line, OpAMD64MOVQload, TypeInvalid) + v3.AddArg(src) + v3.AddArg(mem) + v3.Type = config.fe.TypeUInt64() + v2.AddArg(v3) + v2.AddArg(mem) + v2.Type = TypeMem + v.AddArg(v2) + return true + } + goto end376c57db23b866866f23677c6cde43ba + end376c57db23b866866f23677c6cde43ba: + ; + // match: (Move [size] dst src mem) + // cond: size > 16 && size%16 != 0 && size%16 > 8 + // result: (Move [size-size%16] (ADDQconst dst [size%16]) (ADDQconst src [size%16]) (MOVOstore dst (MOVOload src mem) mem)) { size := v.AuxInt dst := v.Args[0] src := v.Args[1] mem := v.Args[2] - v.Op = OpAMD64REPMOVSB + if !(size > 16 && size%16 != 0 && size%16 > 8) { + goto end2f82f76766a21f8802768380cf10a497 + } + v.Op = OpMove + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = size - size%16 + v0 := b.NewValue0(v.Line, OpAMD64ADDQconst, TypeInvalid) + v0.Type = dst.Type + v0.AddArg(dst) + v0.AuxInt = size % 16 + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpAMD64ADDQconst, TypeInvalid) + v1.Type = src.Type + v1.AddArg(src) + v1.AuxInt = size % 16 + v.AddArg(v1) + v2 := b.NewValue0(v.Line, OpAMD64MOVOstore, TypeInvalid) + v2.AddArg(dst) + v3 := b.NewValue0(v.Line, OpAMD64MOVOload, TypeInvalid) + v3.AddArg(src) + v3.AddArg(mem) + v3.Type = TypeInt128 + v2.AddArg(v3) + v2.AddArg(mem) + v2.Type = TypeMem + v.AddArg(v2) + return true + } + goto end2f82f76766a21f8802768380cf10a497 + end2f82f76766a21f8802768380cf10a497: + ; + // match: (Move [size] dst src mem) + // cond: size >= 32 && size <= 16*64 && size%16 == 0 + // result: (DUFFCOPY [14*(64-size/16)] dst src mem) + { + size := v.AuxInt + dst := v.Args[0] + src := v.Args[1] + mem := v.Args[2] + if !(size >= 32 && size <= 16*64 && size%16 == 0) { + goto endcb66da6685f0079ee1f84d10fa561f22 + } + v.Op = OpAMD64DUFFCOPY + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = 14 * (64 - size/16) + v.AddArg(dst) + v.AddArg(src) + v.AddArg(mem) + return true + } + goto endcb66da6685f0079ee1f84d10fa561f22 + endcb66da6685f0079ee1f84d10fa561f22: + ; + // match: (Move [size] dst src mem) + // cond: size > 16*64 && size%8 == 0 + // result: (REPMOVSQ dst src (MOVQconst [size/8]) mem) + { + size := v.AuxInt + dst := v.Args[0] + src := v.Args[1] + mem := v.Args[2] + if !(size > 16*64 && size%8 == 0) { + goto end7ae25ff1bbdcf34efef09613745e9d6e + } + v.Op = OpAMD64REPMOVSQ v.AuxInt = 0 v.Aux = nil v.resetArgs() v.AddArg(dst) v.AddArg(src) v0 := b.NewValue0(v.Line, OpAMD64MOVQconst, TypeInvalid) - v0.Type = config.Frontend().TypeUInt64() - v0.AuxInt = size + v0.AuxInt = size / 8 + v0.Type = config.fe.TypeUInt64() v.AddArg(v0) v.AddArg(mem) return true } - goto end4dd156b33beb9981378c91e46f055a56 - end4dd156b33beb9981378c91e46f055a56: + goto end7ae25ff1bbdcf34efef09613745e9d6e + end7ae25ff1bbdcf34efef09613745e9d6e: ; case OpMul16: // match: (Mul16 x y) @@ -10710,7 +11268,7 @@ func rewriteValueAMD64(v *Value, config *Config) bool { v.AddArg(v0) v1 := b.NewValue0(v.Line, OpAMD64MOVOconst, TypeInvalid) v1.AuxInt = 0 - v1.Type = config.fe.TypeFloat64() + v1.Type = TypeInt128 v.AddArg(v1) v.AddArg(mem) return true diff --git a/src/cmd/compile/internal/ssa/type.go b/src/cmd/compile/internal/ssa/type.go index 8b6098f65f..9a692dcfb0 100644 --- a/src/cmd/compile/internal/ssa/type.go +++ b/src/cmd/compile/internal/ssa/type.go @@ -48,6 +48,7 @@ type CompilerType struct { Memory bool Flags bool Void bool + Int128 bool } func (t *CompilerType) Size() int64 { return 0 } // Size in bytes @@ -88,4 +89,5 @@ var ( TypeMem = &CompilerType{Name: "mem", Memory: true} TypeFlags = &CompilerType{Name: "flags", Flags: true} TypeVoid = &CompilerType{Name: "void", Void: true} + TypeInt128 = &CompilerType{Name: "int128", Int128: true} ) -- cgit v1.3 From 74180dd7dad42b800f2408340ad17cb62c6c11fb Mon Sep 17 00:00:00 2001 From: Todd Neal Date: Tue, 27 Oct 2015 21:35:48 -0500 Subject: [dev.ssa] cmd/compile/internal/ssa: reuse Aux values for PEXTERN This improves cse and works correctly now that divide by zero is checked explicitly. Change-Id: If54fbe403ed5230b897afc5def644ba9f0056dfd Reviewed-on: https://go-review.googlesource.com/16454 Run-TryBot: Todd Neal Reviewed-by: Keith Randall TryBot-Result: Gobot Gobot --- src/cmd/compile/internal/gc/ssa.go | 2 +- .../compile/internal/gc/testdata/loadstore_ssa.go | 28 ++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 4b4dc09f11..b96661d15e 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -2265,7 +2265,7 @@ func (s *state) addr(n *Node, bounded bool) *ssa.Value { switch n.Class { case PEXTERN: // global variable - aux := &ssa.ExternSymbol{n.Type, n.Sym} + aux := s.lookupSymbol(n, &ssa.ExternSymbol{n.Type, n.Sym}) v := s.entryNewValue1A(ssa.OpAddr, t, aux, s.sb) // TODO: Make OpAddr use AuxInt as well as Aux. if n.Xoffset != 0 { diff --git a/src/cmd/compile/internal/gc/testdata/loadstore_ssa.go b/src/cmd/compile/internal/gc/testdata/loadstore_ssa.go index e986f53bc6..e0b0b4dfab 100644 --- a/src/cmd/compile/internal/gc/testdata/loadstore_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/loadstore_ssa.go @@ -77,11 +77,39 @@ func testExtStore() { } } +var b int + +// testDeadStorePanic_ssa ensures that we don't optimize away stores +// that could be read by after recover(). Modeled after fixedbugs/issue1304. +func testDeadStorePanic_ssa(a int) (r int) { + switch { + } + defer func() { + recover() + r = a + }() + a = 2 // store + b := a - a // optimized to zero + c := 4 + a = c / b // store, but panics + a = 3 // store + r = a + return +} + +func testDeadStorePanic() { + if want, got := 2, testDeadStorePanic_ssa(1); want != got { + fmt.Println("testDeadStorePanic failed. want =", want, ", got =", got) + failed = true + } +} + func main() { testLoadStoreOrder() testStoreSize() testExtStore() + testDeadStorePanic() if failed { panic("failed") -- cgit v1.3 From 7807bda91d4038241b857a8bd341e6b9baf3a264 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Tue, 10 Nov 2015 15:35:36 -0800 Subject: [dev.ssa] cmd/compile: be safer about uintptr/unsafe.Pointer conversions Make sure that when a pointer value is live across a function call, we save it as a pointer. (And similarly a uintptr live across a function call should not be saved as a pointer.) Add a nasty test case. This is probably what is preventing the merge from master to dev.ssa. Signs point to something like this bug happening in mallocgc. Change-Id: Ib23fa1251b8d1c50d82c6a448cb4a4fc28219029 Reviewed-on: https://go-review.googlesource.com/16830 Run-TryBot: Keith Randall TryBot-Result: Gobot Gobot Reviewed-by: David Chase --- src/cmd/compile/internal/gc/ssa.go | 4 +- src/cmd/compile/internal/gc/ssa_test.go | 2 + src/cmd/compile/internal/gc/testdata/unsafe_ssa.go | 129 +++++++++++++++++++++ src/cmd/compile/internal/ssa/gen/AMD64.rules | 2 +- src/cmd/compile/internal/ssa/gen/AMD64Ops.go | 7 ++ src/cmd/compile/internal/ssa/gen/generic.rules | 3 +- src/cmd/compile/internal/ssa/gen/genericOps.go | 11 +- src/cmd/compile/internal/ssa/opGen.go | 13 +++ src/cmd/compile/internal/ssa/rewriteAMD64.go | 12 +- src/cmd/compile/internal/ssa/rewritegeneric.go | 37 +++++- 10 files changed, 203 insertions(+), 17 deletions(-) create mode 100644 src/cmd/compile/internal/gc/testdata/unsafe_ssa.go (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 0b674806fe..4cdfa5c265 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -1375,7 +1375,7 @@ func (s *state) expr(n *Node) *ssa.Value { // as not-pointers or vice-versa because of copy // elision. if to.IsPtr() != from.IsPtr() { - return s.newValue1(ssa.OpConvert, to, x) + return s.newValue2(ssa.OpConvert, to, x, s.mem()) } v := s.newValue1(ssa.OpCopy, to, x) // ensure that v has the right type @@ -3886,7 +3886,7 @@ func (s *genState) genValue(v *ssa.Value) { p.To.Sym = Linksym(Pkglookup("duffcopy", Runtimepkg)) p.To.Offset = v.AuxInt - case ssa.OpCopy: // TODO: lower to MOVQ earlier? + case ssa.OpCopy, ssa.OpAMD64MOVQconvert: // TODO: lower Copy to MOVQ earlier? if v.Type.IsMemory() { return } diff --git a/src/cmd/compile/internal/gc/ssa_test.go b/src/cmd/compile/internal/gc/ssa_test.go index 5a881ed819..74fa847c92 100644 --- a/src/cmd/compile/internal/gc/ssa_test.go +++ b/src/cmd/compile/internal/gc/ssa_test.go @@ -93,3 +93,5 @@ func TestZero(t *testing.T) { runTest(t, "zero_ssa.go") } func TestAddressed(t *testing.T) { runTest(t, "addressed_ssa.go") } func TestCopy(t *testing.T) { runTest(t, "copy_ssa.go") } + +func TestUnsafe(t *testing.T) { runTest(t, "unsafe_ssa.go") } diff --git a/src/cmd/compile/internal/gc/testdata/unsafe_ssa.go b/src/cmd/compile/internal/gc/testdata/unsafe_ssa.go new file mode 100644 index 0000000000..bc292828d5 --- /dev/null +++ b/src/cmd/compile/internal/gc/testdata/unsafe_ssa.go @@ -0,0 +1,129 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "fmt" + "runtime" + "unsafe" +) + +// global pointer slot +var a *[8]uint + +// unfoldable true +var b = true + +// Test to make sure that a pointer value which is alive +// across a call is retained, even when there are matching +// conversions to/from uintptr around the call. +// We arrange things very carefully to have to/from +// conversions on either side of the call which cannot be +// combined with any other conversions. +func f_ssa() *[8]uint { + // Make x a uintptr pointing to where a points. + var x uintptr + if b { + x = uintptr(unsafe.Pointer(a)) + } else { + x = 0 + } + // Clobber the global pointer. The only live ref + // to the allocated object is now x. + a = nil + + // Convert to pointer so it should hold + // the object live across GC call. + p := unsafe.Pointer(x) + + // Call gc. + runtime.GC() + + // Convert back to uintptr. + y := uintptr(p) + + // Mess with y so that the subsequent cast + // to unsafe.Pointer can't be combined with the + // uintptr cast above. + var z uintptr + if b { + z = y + } else { + z = 0 + } + return (*[8]uint)(unsafe.Pointer(z)) +} + +// g_ssa is the same as f_ssa, but with a bit of pointer +// arithmetic for added insanity. +func g_ssa() *[7]uint { + // Make x a uintptr pointing to where a points. + var x uintptr + if b { + x = uintptr(unsafe.Pointer(a)) + } else { + x = 0 + } + // Clobber the global pointer. The only live ref + // to the allocated object is now x. + a = nil + + // Offset x by one int. + x += unsafe.Sizeof(int(0)) + + // Convert to pointer so it should hold + // the object live across GC call. + p := unsafe.Pointer(x) + + // Call gc. + runtime.GC() + + // Convert back to uintptr. + y := uintptr(p) + + // Mess with y so that the subsequent cast + // to unsafe.Pointer can't be combined with the + // uintptr cast above. + var z uintptr + if b { + z = y + } else { + z = 0 + } + return (*[7]uint)(unsafe.Pointer(z)) +} + +func testf() { + a = new([8]uint) + for i := 0; i < 8; i++ { + a[i] = 0xabcd + } + c := f_ssa() + for i := 0; i < 8; i++ { + if c[i] != 0xabcd { + fmt.Printf("%d:%x\n", i, c[i]) + panic("bad c") + } + } +} + +func testg() { + a = new([8]uint) + for i := 0; i < 8; i++ { + a[i] = 0xabcd + } + c := g_ssa() + for i := 0; i < 7; i++ { + if c[i] != 0xabcd { + fmt.Printf("%d:%x\n", i, c[i]) + panic("bad c") + } + } +} + +func main() { + testf() + testg() +} diff --git a/src/cmd/compile/internal/ssa/gen/AMD64.rules b/src/cmd/compile/internal/ssa/gen/AMD64.rules index 4364022f41..7d0aa4b2d3 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64.rules +++ b/src/cmd/compile/internal/ssa/gen/AMD64.rules @@ -281,7 +281,7 @@ (Store [1] ptr val mem) -> (MOVBstore ptr val mem) // We want this to stick out so the to/from ptr conversion is obvious -(Convert x) -> (LEAQ x) +(Convert x mem) -> (MOVQconvert x mem) // checks (IsNonNil p) -> (SETNE (TESTQ p p)) diff --git a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go index fa5072f7c5..ba53e81ddd 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go @@ -465,6 +465,13 @@ func init() { {name: "LoweredGetClosurePtr", reg: regInfo{outputs: []regMask{buildReg("DX")}}}, //arg0=ptr,arg1=mem, returns void. Faults if ptr is nil. {name: "LoweredNilCheck", reg: regInfo{inputs: []regMask{gpsp}, clobbers: flags}}, + + // MOVQconvert converts between pointers and integers. + // We have a special op for this so as to not confuse GC + // (particularly stack maps). It takes a memory arg so it + // gets correctly ordered with respect to GC safepoints. + // arg0=ptr/int arg1=mem, output=int/ptr + {name: "MOVQconvert", reg: gp11nf, asm: "MOVQ"}, } var AMD64blocks = []blockData{ diff --git a/src/cmd/compile/internal/ssa/gen/generic.rules b/src/cmd/compile/internal/ssa/gen/generic.rules index d3de24d956..5de877d31a 100644 --- a/src/cmd/compile/internal/ssa/gen/generic.rules +++ b/src/cmd/compile/internal/ssa/gen/generic.rules @@ -274,7 +274,8 @@ (If (ConstBool [c]) yes no) && c == 0 -> (First nil no yes) // Get rid of Convert ops for pointer arithmetic on unsafe.Pointer. -(Convert (Add64 (Convert ptr) off)) -> (Add64 ptr off) +(Convert (Add64 (Convert ptr mem) off) mem) -> (Add64 ptr off) +(Convert (Convert ptr mem) mem) -> ptr // Decompose compound argument values (Arg {n} [off]) && v.Type.IsString() -> diff --git a/src/cmd/compile/internal/ssa/gen/genericOps.go b/src/cmd/compile/internal/ssa/gen/genericOps.go index ead0cfd17a..e57dd932d8 100644 --- a/src/cmd/compile/internal/ssa/gen/genericOps.go +++ b/src/cmd/compile/internal/ssa/gen/genericOps.go @@ -236,9 +236,14 @@ var genericOps = []opData{ {name: "Sqrt"}, // sqrt(arg0), float64 only // Data movement - {name: "Phi"}, // select an argument based on which predecessor block we came from - {name: "Copy"}, // output = arg0 - {name: "Convert"}, // output = arg0 -- a copy that converts to/from a pointer + {name: "Phi"}, // select an argument based on which predecessor block we came from + {name: "Copy"}, // output = arg0 + // Convert converts between pointers and integers. + // We have a special op for this so as to not confuse GC + // (particularly stack maps). It takes a memory arg so it + // gets correctly ordered with respect to GC safepoints. + // arg0=ptr/int arg1=mem, output=int/ptr + {name: "Convert"}, // constants. Constant values are stored in the aux field. // booleans have a bool aux field, strings have a string aux diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index d043e076ea..132ca83f95 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -282,6 +282,7 @@ const ( OpAMD64LoweredGetG OpAMD64LoweredGetClosurePtr OpAMD64LoweredNilCheck + OpAMD64MOVQconvert OpAdd8 OpAdd16 @@ -3219,6 +3220,18 @@ var opcodeTable = [...]opInfo{ clobbers: 8589934592, // .FLAGS }, }, + { + name: "MOVQconvert", + asm: x86.AMOVQ, + reg: regInfo{ + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + outputs: []regMask{ + 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + }, + }, { name: "Add8", diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go index cfdd5a2851..3be94e37e7 100644 --- a/src/cmd/compile/internal/ssa/rewriteAMD64.go +++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go @@ -2585,22 +2585,24 @@ endea557d921056c25b945a49649e4b9b91: func rewriteValueAMD64_OpConvert(v *Value, config *Config) bool { b := v.Block _ = b - // match: (Convert x) + // match: (Convert x mem) // cond: - // result: (LEAQ x) + // result: (MOVQconvert x mem) { t := v.Type x := v.Args[0] - v.Op = OpAMD64LEAQ + mem := v.Args[1] + v.Op = OpAMD64MOVQconvert v.AuxInt = 0 v.Aux = nil v.resetArgs() v.Type = t v.AddArg(x) + v.AddArg(mem) return true } - goto end1cac40a6074914d6ae3d4aa039a625ed -end1cac40a6074914d6ae3d4aa039a625ed: + goto end0aa5cd28888761ffab21bce45db361c8 +end0aa5cd28888761ffab21bce45db361c8: ; return false } diff --git a/src/cmd/compile/internal/ssa/rewritegeneric.go b/src/cmd/compile/internal/ssa/rewritegeneric.go index 174967a194..9563e878e8 100644 --- a/src/cmd/compile/internal/ssa/rewritegeneric.go +++ b/src/cmd/compile/internal/ssa/rewritegeneric.go @@ -926,18 +926,22 @@ end7ce9db29d17866f26d21e6e12f442e54: func rewriteValuegeneric_OpConvert(v *Value, config *Config) bool { b := v.Block _ = b - // match: (Convert (Add64 (Convert ptr) off)) + // match: (Convert (Add64 (Convert ptr mem) off) mem) // cond: // result: (Add64 ptr off) { if v.Args[0].Op != OpAdd64 { - goto end913a7ecf456c00ffbee36c2dbbf0e1af + goto endbbc9f1666b4d39a130e1b86f109e7c1b } if v.Args[0].Args[0].Op != OpConvert { - goto end913a7ecf456c00ffbee36c2dbbf0e1af + goto endbbc9f1666b4d39a130e1b86f109e7c1b } ptr := v.Args[0].Args[0].Args[0] + mem := v.Args[0].Args[0].Args[1] off := v.Args[0].Args[1] + if v.Args[1] != mem { + goto endbbc9f1666b4d39a130e1b86f109e7c1b + } v.Op = OpAdd64 v.AuxInt = 0 v.Aux = nil @@ -946,8 +950,31 @@ func rewriteValuegeneric_OpConvert(v *Value, config *Config) bool { v.AddArg(off) return true } - goto end913a7ecf456c00ffbee36c2dbbf0e1af -end913a7ecf456c00ffbee36c2dbbf0e1af: + goto endbbc9f1666b4d39a130e1b86f109e7c1b +endbbc9f1666b4d39a130e1b86f109e7c1b: + ; + // match: (Convert (Convert ptr mem) mem) + // cond: + // result: ptr + { + if v.Args[0].Op != OpConvert { + goto end98c5e0ca257eb216989171786f91b42d + } + ptr := v.Args[0].Args[0] + mem := v.Args[0].Args[1] + if v.Args[1] != mem { + goto end98c5e0ca257eb216989171786f91b42d + } + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = ptr.Type + v.AddArg(ptr) + return true + } + goto end98c5e0ca257eb216989171786f91b42d +end98c5e0ca257eb216989171786f91b42d: ; return false } -- cgit v1.3 From 09ffa0c4c772ff119d42820a8d90aba8b481397c Mon Sep 17 00:00:00 2001 From: Todd Neal Date: Sun, 6 Dec 2015 21:25:24 -0600 Subject: [dev.ssa] test: use new go:noinline feature Replace old mechanisms for preventing inlining with go:noinline. Change-Id: I021a6450e6d644ec1042594730a9c64d695949a1 Reviewed-on: https://go-review.googlesource.com/17500 Reviewed-by: Brad Fitzpatrick --- src/cmd/compile/internal/gc/testdata/append_ssa.go | 7 +- .../internal/gc/testdata/arithBoundary_ssa.go | 159 ++++++++++----------- src/cmd/compile/internal/gc/testdata/arith_ssa.go | 48 +++---- src/cmd/compile/internal/gc/testdata/array_ssa.go | 15 +- src/cmd/compile/internal/gc/testdata/chan_ssa.go | 9 +- .../compile/internal/gc/testdata/closure_ssa.go | 3 +- src/cmd/compile/internal/gc/testdata/fp_ssa.go | 57 +++----- .../internal/gc/testdata/gen/arithBoundaryGen.go | 4 +- src/cmd/compile/internal/gc/testdata/map_ssa.go | 4 +- src/cmd/compile/internal/gc/testdata/short_ssa.go | 2 +- src/cmd/compile/internal/gc/testdata/string_ssa.go | 18 +-- 11 files changed, 138 insertions(+), 188 deletions(-) (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/testdata/append_ssa.go b/src/cmd/compile/internal/gc/testdata/append_ssa.go index dba81736c8..03cd219c32 100644 --- a/src/cmd/compile/internal/gc/testdata/append_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/append_ssa.go @@ -9,14 +9,13 @@ import "fmt" var failed = false +//go:noinline func appendOne_ssa(a []int, x int) []int { - switch { // prevent inlining - } return append(a, x) } + +//go:noinline func appendThree_ssa(a []int, x, y, z int) []int { - switch { // prevent inlining - } return append(a, x, y, z) } diff --git a/src/cmd/compile/internal/gc/testdata/arithBoundary_ssa.go b/src/cmd/compile/internal/gc/testdata/arithBoundary_ssa.go index 9f1b9a4a60..929e4e1f0b 100644 --- a/src/cmd/compile/internal/gc/testdata/arithBoundary_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/arithBoundary_ssa.go @@ -35,204 +35,203 @@ type itd8 struct { add, sub, mul, div, mod int8 } +//go:noinline func add_uint64_ssa(a, b uint64) uint64 { - switch { - } // prevent inlining return a + b } + +//go:noinline func sub_uint64_ssa(a, b uint64) uint64 { - switch { - } // prevent inlining return a - b } + +//go:noinline func div_uint64_ssa(a, b uint64) uint64 { - switch { - } // prevent inlining return a / b } + +//go:noinline func mod_uint64_ssa(a, b uint64) uint64 { - switch { - } // prevent inlining return a % b } + +//go:noinline func mul_uint64_ssa(a, b uint64) uint64 { - switch { - } // prevent inlining return a * b } + +//go:noinline func add_int64_ssa(a, b int64) int64 { - switch { - } // prevent inlining return a + b } + +//go:noinline func sub_int64_ssa(a, b int64) int64 { - switch { - } // prevent inlining return a - b } + +//go:noinline func div_int64_ssa(a, b int64) int64 { - switch { - } // prevent inlining return a / b } + +//go:noinline func mod_int64_ssa(a, b int64) int64 { - switch { - } // prevent inlining return a % b } + +//go:noinline func mul_int64_ssa(a, b int64) int64 { - switch { - } // prevent inlining return a * b } + +//go:noinline func add_uint32_ssa(a, b uint32) uint32 { - switch { - } // prevent inlining return a + b } + +//go:noinline func sub_uint32_ssa(a, b uint32) uint32 { - switch { - } // prevent inlining return a - b } + +//go:noinline func div_uint32_ssa(a, b uint32) uint32 { - switch { - } // prevent inlining return a / b } + +//go:noinline func mod_uint32_ssa(a, b uint32) uint32 { - switch { - } // prevent inlining return a % b } + +//go:noinline func mul_uint32_ssa(a, b uint32) uint32 { - switch { - } // prevent inlining return a * b } + +//go:noinline func add_int32_ssa(a, b int32) int32 { - switch { - } // prevent inlining return a + b } + +//go:noinline func sub_int32_ssa(a, b int32) int32 { - switch { - } // prevent inlining return a - b } + +//go:noinline func div_int32_ssa(a, b int32) int32 { - switch { - } // prevent inlining return a / b } + +//go:noinline func mod_int32_ssa(a, b int32) int32 { - switch { - } // prevent inlining return a % b } + +//go:noinline func mul_int32_ssa(a, b int32) int32 { - switch { - } // prevent inlining return a * b } + +//go:noinline func add_uint16_ssa(a, b uint16) uint16 { - switch { - } // prevent inlining return a + b } + +//go:noinline func sub_uint16_ssa(a, b uint16) uint16 { - switch { - } // prevent inlining return a - b } + +//go:noinline func div_uint16_ssa(a, b uint16) uint16 { - switch { - } // prevent inlining return a / b } + +//go:noinline func mod_uint16_ssa(a, b uint16) uint16 { - switch { - } // prevent inlining return a % b } + +//go:noinline func mul_uint16_ssa(a, b uint16) uint16 { - switch { - } // prevent inlining return a * b } + +//go:noinline func add_int16_ssa(a, b int16) int16 { - switch { - } // prevent inlining return a + b } + +//go:noinline func sub_int16_ssa(a, b int16) int16 { - switch { - } // prevent inlining return a - b } + +//go:noinline func div_int16_ssa(a, b int16) int16 { - switch { - } // prevent inlining return a / b } + +//go:noinline func mod_int16_ssa(a, b int16) int16 { - switch { - } // prevent inlining return a % b } + +//go:noinline func mul_int16_ssa(a, b int16) int16 { - switch { - } // prevent inlining return a * b } + +//go:noinline func add_uint8_ssa(a, b uint8) uint8 { - switch { - } // prevent inlining return a + b } + +//go:noinline func sub_uint8_ssa(a, b uint8) uint8 { - switch { - } // prevent inlining return a - b } + +//go:noinline func div_uint8_ssa(a, b uint8) uint8 { - switch { - } // prevent inlining return a / b } + +//go:noinline func mod_uint8_ssa(a, b uint8) uint8 { - switch { - } // prevent inlining return a % b } + +//go:noinline func mul_uint8_ssa(a, b uint8) uint8 { - switch { - } // prevent inlining return a * b } + +//go:noinline func add_int8_ssa(a, b int8) int8 { - switch { - } // prevent inlining return a + b } + +//go:noinline func sub_int8_ssa(a, b int8) int8 { - switch { - } // prevent inlining return a - b } + +//go:noinline func div_int8_ssa(a, b int8) int8 { - switch { - } // prevent inlining return a / b } + +//go:noinline func mod_int8_ssa(a, b int8) int8 { - switch { - } // prevent inlining return a % b } + +//go:noinline func mul_int8_ssa(a, b int8) int8 { - switch { - } // prevent inlining return a * b } diff --git a/src/cmd/compile/internal/gc/testdata/arith_ssa.go b/src/cmd/compile/internal/gc/testdata/arith_ssa.go index f6f123c0be..af31245505 100644 --- a/src/cmd/compile/internal/gc/testdata/arith_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/arith_ssa.go @@ -17,9 +17,9 @@ func test64BitConstMult() { failed = true } } + +//go:noinline func test64BitConstMult_ssa(a, b int64) int64 { - switch { // prevent inlining - } return 34359738369*a + b*34359738370 } @@ -32,9 +32,9 @@ func test64BitConstAdd() { failed = true } } + +//go:noinline func test64BitConstAdd_ssa(a, b int64) int64 { - switch { // prevent inlining - } return a + 575815584948629622 + b + 2991856197886747025 } @@ -47,9 +47,9 @@ func testRegallocCVSpill() { failed = true } } + +//go:noinline func testRegallocCVSpill_ssa(a, b, c, d int8) int8 { - switch { // prevent inlining - } return a + -32 + b + 63*c*-87*d } @@ -105,45 +105,38 @@ func testBitwiseLogic() { } } +//go:noinline func testBitwiseAnd_ssa(a, b uint32) uint32 { - switch { // prevent inlining - } return a & b } +//go:noinline func testBitwiseOr_ssa(a, b uint32) uint32 { - switch { // prevent inlining - } return a | b } +//go:noinline func testBitwiseXor_ssa(a, b uint32) uint32 { - switch { // prevent inlining - } return a ^ b } +//go:noinline func testBitwiseLsh_ssa(a int32, b, c uint32) int32 { - switch { // prevent inlining - } return a << b << c } +//go:noinline func testBitwiseRsh_ssa(a int32, b, c uint32) int32 { - switch { // prevent inlining - } return a >> b >> c } +//go:noinline func testBitwiseRshU_ssa(a uint32, b, c uint32) uint32 { - switch { // prevent inlining - } return a >> b >> c } +//go:noinline func testShiftCX_ssa() int { - switch { - } // prevent inlining v1 := uint8(3) v4 := (v1 * v1) ^ v1 | v1 - v1 - v1&v1 ^ uint8(3+2) + v1*1>>0 - v1 | 1 | v1<<(2*3|0-0*0^1) v5 := v4>>(3-0-uint(3)) | v1 | v1 + v1 ^ v4<<(0+1|3&1)<<(uint64(1)<<0*2*0<<0) ^ v1 @@ -172,9 +165,8 @@ func testSubqToNegq() { } } +//go:noinline func testSubqToNegq_ssa(a, b, c, d, e, f, g, h, i, j, k int64) int64 { - switch { // prevent inlining - } return a + 8207351403619448057 - b - 1779494519303207690 + c*8810076340510052032*d - 4465874067674546219 - e*4361839741470334295 - f + 8688847565426072650*g*8065564729145417479 } @@ -187,9 +179,8 @@ func testOcom() { } } +//go:noinline func testOcom_ssa(a, b int32) (int32, int32) { - switch { // prevent inlining - } return ^^^^a, ^^^^^b } @@ -201,21 +192,19 @@ func lrot1_ssa(w uint8, x uint16, y uint32, z uint64) (a uint8, b uint16, c uint return } +//go:noinline func lrot2_ssa(w, n uint32) uint32 { // Want to be sure that a "rotate by 32" which // is really 0 | (w >> 0) == w // is correctly compiled. - switch { // prevents inlining - } return (w << n) | (w >> (32 - n)) } +//go:noinline func lrot3_ssa(w uint32) uint32 { // Want to be sure that a "rotate by 32" which // is really 0 | (w >> 0) == w // is correctly compiled. - switch { // prevents inlining - } return (w << 32) | (w >> (32 - 32)) } @@ -244,9 +233,8 @@ func testLrot() { } +//go:noinline func sub1_ssa() uint64 { - switch { - } // prevent inlining v1 := uint64(3) // uint64 return v1*v1 - (v1&v1)&v1 } diff --git a/src/cmd/compile/internal/gc/testdata/array_ssa.go b/src/cmd/compile/internal/gc/testdata/array_ssa.go index d7004ff26a..0334339d43 100644 --- a/src/cmd/compile/internal/gc/testdata/array_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/array_ssa.go @@ -2,23 +2,20 @@ package main var failed = false +//go:noinline func testSliceLenCap12_ssa(a [10]int, i, j int) (int, int) { - switch { // prevent inlining - } b := a[i:j] return len(b), cap(b) } +//go:noinline func testSliceLenCap1_ssa(a [10]int, i, j int) (int, int) { - switch { // prevent inlining - } b := a[i:] return len(b), cap(b) } +//go:noinline func testSliceLenCap2_ssa(a [10]int, i, j int) (int, int) { - switch { // prevent inlining - } b := a[:j] return len(b), cap(b) } @@ -55,9 +52,8 @@ func testSliceLenCap() { } } +//go:noinline func testSliceGetElement_ssa(a [10]int, i, j, p int) int { - switch { // prevent inlining - } return a[i:j][p] } @@ -81,9 +77,8 @@ func testSliceGetElement() { } } +//go:noinline func testSliceSetElement_ssa(a *[10]int, i, j, p, x int) { - switch { // prevent inlining - } (*a)[i:j][p] = x } diff --git a/src/cmd/compile/internal/gc/testdata/chan_ssa.go b/src/cmd/compile/internal/gc/testdata/chan_ssa.go index c527ba95be..0766fcda5b 100644 --- a/src/cmd/compile/internal/gc/testdata/chan_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/chan_ssa.go @@ -9,16 +9,13 @@ import "fmt" var failed = false +//go:noinline func lenChan_ssa(v chan int) int { - switch { // prevent inlining - - } return len(v) } -func capChan_ssa(v chan int) int { - switch { // prevent inlining - } +//go:noinline +func capChan_ssa(v chan int) int { return cap(v) } diff --git a/src/cmd/compile/internal/gc/testdata/closure_ssa.go b/src/cmd/compile/internal/gc/testdata/closure_ssa.go index ac1e51a23e..70181bc24b 100644 --- a/src/cmd/compile/internal/gc/testdata/closure_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/closure_ssa.go @@ -9,9 +9,8 @@ import "fmt" var failed = false +//go:noinline func testCFunc_ssa() int { - switch { // prevent inlining - } a := 0 b := func() { switch { diff --git a/src/cmd/compile/internal/gc/testdata/fp_ssa.go b/src/cmd/compile/internal/gc/testdata/fp_ssa.go index e7480a1138..cfbdcda251 100644 --- a/src/cmd/compile/internal/gc/testdata/fp_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/fp_ssa.go @@ -1466,118 +1466,99 @@ func expectCx64(s string, x, expected complex64) int { return 0 } +//go:noinline func cx128sum_ssa(a, b complex128) complex128 { - switch { // prevent inlining - } return a + b } +//go:noinline func cx128diff_ssa(a, b complex128) complex128 { - switch { // prevent inlining - } return a - b } +//go:noinline func cx128prod_ssa(a, b complex128) complex128 { - switch { // prevent inlining - } return a * b } +//go:noinline func cx128quot_ssa(a, b complex128) complex128 { - switch { // prevent inlining - } return a / b } +//go:noinline func cx128neg_ssa(a complex128) complex128 { - switch { // prevent inlining - } return -a } +//go:noinline func cx128real_ssa(a complex128) float64 { - switch { // prevent inlining - } return real(a) } +//go:noinline func cx128imag_ssa(a complex128) float64 { - switch { // prevent inlining - } return imag(a) } +//go:noinline func cx128cnst_ssa(a complex128) complex128 { - switch { // prevent inlining - } b := 2 + 3i return a * b } +//go:noinline func cx64sum_ssa(a, b complex64) complex64 { - switch { // prevent inlining - } return a + b } +//go:noinline func cx64diff_ssa(a, b complex64) complex64 { - switch { // prevent inlining - } return a - b } +//go:noinline func cx64prod_ssa(a, b complex64) complex64 { - switch { // prevent inlining - } return a * b } +//go:noinline func cx64quot_ssa(a, b complex64) complex64 { - switch { // prevent inlining - } return a / b } +//go:noinline func cx64neg_ssa(a complex64) complex64 { - switch { // prevent inlining - } return -a } +//go:noinline func cx64real_ssa(a complex64) float32 { - switch { // prevent inlining - } return real(a) } +//go:noinline func cx64imag_ssa(a complex64) float32 { - switch { // prevent inlining - } return imag(a) } +//go:noinline func cx128eq_ssa(a, b complex128) bool { - switch { // prevent inlining - } return a == b } +//go:noinline func cx128ne_ssa(a, b complex128) bool { - switch { // prevent inlining - } return a != b } +//go:noinline func cx64eq_ssa(a, b complex64) bool { - switch { // prevent inlining - } return a == b } +//go:noinline func cx64ne_ssa(a, b complex64) bool { - switch { // prevent inlining - } return a != b } diff --git a/src/cmd/compile/internal/gc/testdata/gen/arithBoundaryGen.go b/src/cmd/compile/internal/gc/testdata/gen/arithBoundaryGen.go index 19bb04b6f1..7c7d721a23 100644 --- a/src/cmd/compile/internal/gc/testdata/gen/arithBoundaryGen.go +++ b/src/cmd/compile/internal/gc/testdata/gen/arithBoundaryGen.go @@ -109,8 +109,8 @@ func main() { // the function being tested testFunc, err := template.New("testFunc").Parse( - `func {{.Name}}_{{.Stype}}_ssa(a, b {{.Stype}}) {{.Stype}} { - switch{} // prevent inlining + `//go:noinline + func {{.Name}}_{{.Stype}}_ssa(a, b {{.Stype}}) {{.Stype}} { return a {{.SymFirst}} b } `) diff --git a/src/cmd/compile/internal/gc/testdata/map_ssa.go b/src/cmd/compile/internal/gc/testdata/map_ssa.go index 41c949a9f2..4a466003c7 100644 --- a/src/cmd/compile/internal/gc/testdata/map_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/map_ssa.go @@ -9,10 +9,8 @@ import "fmt" var failed = false +//go:noinline func lenMap_ssa(v map[int]int) int { - switch { // prevent inlining - - } return len(v) } diff --git a/src/cmd/compile/internal/gc/testdata/short_ssa.go b/src/cmd/compile/internal/gc/testdata/short_ssa.go index 1aa7d3e677..fcec1baf09 100644 --- a/src/cmd/compile/internal/gc/testdata/short_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/short_ssa.go @@ -18,10 +18,10 @@ func or_ssa(arg1, arg2 bool) bool { var rightCalled bool +//go:noinline func rightCall(v bool) bool { rightCalled = true return v - select {} // hack to prevent inlining panic("unreached") } diff --git a/src/cmd/compile/internal/gc/testdata/string_ssa.go b/src/cmd/compile/internal/gc/testdata/string_ssa.go index 0ff6ce1a12..a949fbcefb 100644 --- a/src/cmd/compile/internal/gc/testdata/string_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/string_ssa.go @@ -7,21 +7,18 @@ package main var failed = false +//go:noinline func testStringSlice1_ssa(a string, i, j int) string { - switch { // prevent inlining - } return a[i:] } +//go:noinline func testStringSlice2_ssa(a string, i, j int) string { - switch { // prevent inlining - } return a[:j] } +//go:noinline func testStringSlice12_ssa(a string, i, j int) string { - switch { // prevent inlining - } return a[i:j] } @@ -91,9 +88,8 @@ const _Accuracy_name = "BelowExactAbove" var _Accuracy_index = [...]uint8{0, 5, 10, 15} +//go:noinline func testSmallIndexType_ssa(i int) string { - switch { // prevent inlining - } return _Accuracy_name[_Accuracy_index[i]:_Accuracy_index[i+1]] } @@ -115,9 +111,8 @@ func testSmallIndexType() { } } +//go:noinline func testStringElem_ssa(s string, i int) byte { - switch { // prevent inlining - } return s[i] } @@ -139,9 +134,8 @@ func testStringElem() { } } +//go:noinline func testStringElemConst_ssa(i int) byte { - switch { // prevent inlining - } s := "foobar" return s[i] } -- cgit v1.3 From 9094e3ada2de3cc8129b70730c2c0782a4040201 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Mon, 4 Jan 2016 13:34:54 -0800 Subject: [dev.ssa] cmd/compile: fix spill sizes In code that does: var x, z int32 var y int64 z = phi(x, int32(y)) We silently drop the int32 cast because truncation is a no-op. The phi operation needs to make sure it uses the size of the phi, not the size of its arguments, when generating spills. Change-Id: I1f7baf44f019256977a46fdd3dad1972be209042 Reviewed-on: https://go-review.googlesource.com/18390 Reviewed-by: David Chase --- src/cmd/compile/internal/gc/ssa.go | 3 + src/cmd/compile/internal/gc/ssa_test.go | 2 + src/cmd/compile/internal/gc/testdata/phi_ssa.go | 103 ++++++++++++++++++++++++ src/cmd/compile/internal/ssa/regalloc.go | 9 ++- 4 files changed, 114 insertions(+), 3 deletions(-) create mode 100644 src/cmd/compile/internal/gc/testdata/phi_ssa.go (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 55ab8ce283..eee3051c39 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -4536,6 +4536,9 @@ func regnum(v *ssa.Value) int16 { // where v should be spilled. func autoVar(v *ssa.Value) (*Node, int64) { loc := v.Block.Func.RegAlloc[v.ID].(ssa.LocalSlot) + if v.Type.Size() > loc.Type.Size() { + v.Fatalf("spill/restore type %s doesn't fit in slot type %s", v.Type, loc.Type) + } return loc.N.(*Node), loc.Off } diff --git a/src/cmd/compile/internal/gc/ssa_test.go b/src/cmd/compile/internal/gc/ssa_test.go index 74fa847c92..d0c44b5dce 100644 --- a/src/cmd/compile/internal/gc/ssa_test.go +++ b/src/cmd/compile/internal/gc/ssa_test.go @@ -95,3 +95,5 @@ func TestAddressed(t *testing.T) { runTest(t, "addressed_ssa.go") } func TestCopy(t *testing.T) { runTest(t, "copy_ssa.go") } func TestUnsafe(t *testing.T) { runTest(t, "unsafe_ssa.go") } + +func TestPhi(t *testing.T) { runTest(t, "phi_ssa.go") } diff --git a/src/cmd/compile/internal/gc/testdata/phi_ssa.go b/src/cmd/compile/internal/gc/testdata/phi_ssa.go new file mode 100644 index 0000000000..e855070fc3 --- /dev/null +++ b/src/cmd/compile/internal/gc/testdata/phi_ssa.go @@ -0,0 +1,103 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +// Test to make sure spills of cast-shortened values +// don't end up spilling the pre-shortened size instead +// of the post-shortened size. + +import ( + "fmt" + "runtime" +) + +// unfoldable true +var true_ = true + +var data1 [26]int32 +var data2 [26]int64 + +func init() { + for i := 0; i < 26; i++ { + // If we spill all 8 bytes of this datum, the 1 in the high-order 4 bytes + // will overwrite some other variable in the stack frame. + data2[i] = 0x100000000 + } +} + +func foo() int32 { + var a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z int32 + if true_ { + a = data1[0] + b = data1[1] + c = data1[2] + d = data1[3] + e = data1[4] + f = data1[5] + g = data1[6] + h = data1[7] + i = data1[8] + j = data1[9] + k = data1[10] + l = data1[11] + m = data1[12] + n = data1[13] + o = data1[14] + p = data1[15] + q = data1[16] + r = data1[17] + s = data1[18] + t = data1[19] + u = data1[20] + v = data1[21] + w = data1[22] + x = data1[23] + y = data1[24] + z = data1[25] + } else { + a = int32(data2[0]) + b = int32(data2[1]) + c = int32(data2[2]) + d = int32(data2[3]) + e = int32(data2[4]) + f = int32(data2[5]) + g = int32(data2[6]) + h = int32(data2[7]) + i = int32(data2[8]) + j = int32(data2[9]) + k = int32(data2[10]) + l = int32(data2[11]) + m = int32(data2[12]) + n = int32(data2[13]) + o = int32(data2[14]) + p = int32(data2[15]) + q = int32(data2[16]) + r = int32(data2[17]) + s = int32(data2[18]) + t = int32(data2[19]) + u = int32(data2[20]) + v = int32(data2[21]) + w = int32(data2[22]) + x = int32(data2[23]) + y = int32(data2[24]) + z = int32(data2[25]) + } + // Lots of phis of the form phi(int32,int64) of type int32 happen here. + // Some will be stack phis. For those stack phis, make sure the spill + // of the second argument uses the phi's width (4 bytes), not its width + // (8 bytes). Otherwise, a random stack slot gets clobbered. + + runtime.Gosched() + return a + b + c + d + e + f + g + h + i + j + k + l + m + n + o + p + q + r + s + t + u + v + w + x + y + z +} + +func main() { + want := int32(0) + got := foo() + if got != want { + fmt.Printf("want %d, got %d\n", want, got) + panic("bad") + } +} diff --git a/src/cmd/compile/internal/ssa/regalloc.go b/src/cmd/compile/internal/ssa/regalloc.go index d7c4674cfd..27deeba718 100644 --- a/src/cmd/compile/internal/ssa/regalloc.go +++ b/src/cmd/compile/internal/ssa/regalloc.go @@ -1223,7 +1223,10 @@ func (e *edgeState) processDest(loc Location, vid ID, splice **Value) bool { r := e.findRegFor(v.Type) x = v.copyInto(e.p) e.set(r, vid, x, false) - x = e.p.NewValue1(x.Line, OpStoreReg, x.Type, x) + // Make sure we spill with the size of the slot, not the + // size of x (which might be wider due to our dropping + // of narrowing conversions). + x = e.p.NewValue1(x.Line, OpStoreReg, loc.(LocalSlot).Type, x) } } else { // Emit move from src to dst. @@ -1232,7 +1235,7 @@ func (e *edgeState) processDest(loc Location, vid ID, splice **Value) bool { if dstReg { x = e.p.NewValue1(c.Line, OpCopy, c.Type, c) } else { - x = e.p.NewValue1(c.Line, OpStoreReg, c.Type, c) + x = e.p.NewValue1(c.Line, OpStoreReg, loc.(LocalSlot).Type, c) } } else { if dstReg { @@ -1255,7 +1258,7 @@ func (e *edgeState) processDest(loc Location, vid ID, splice **Value) bool { r := e.findRegFor(c.Type) t := e.p.NewValue1(c.Line, OpLoadReg, c.Type, c) e.set(r, vid, t, false) - x = e.p.NewValue1(c.Line, OpStoreReg, c.Type, t) + x = e.p.NewValue1(c.Line, OpStoreReg, loc.(LocalSlot).Type, t) } } } -- cgit v1.3 From d4a95e78fa176e02a19cd94c9c273743f3a983c1 Mon Sep 17 00:00:00 2001 From: Alexandru Moșoi Date: Wed, 3 Feb 2016 19:43:46 +0100 Subject: [dev.ssa] cmd/compile/internal/ssa: simplify comparisons with constants * Simplify comparisons of form a + const1 == const2 or a + const1 != const2. * Canonicalize Eq, Neq, Add, Sub to have a constant as first argument. Needed for the above new rules and helps constant folding. Change-Id: I8078702a5daa706da57106073a3e9f640a67f486 Reviewed-on: https://go-review.googlesource.com/19192 Reviewed-by: Keith Randall --- src/cmd/compile/internal/gc/testdata/cmp_ssa.go | 48 ++ src/cmd/compile/internal/ssa/gen/generic.rules | 31 ++ src/cmd/compile/internal/ssa/rewritegeneric.go | 704 ++++++++++++++++++++++++ 3 files changed, 783 insertions(+) create mode 100644 src/cmd/compile/internal/gc/testdata/cmp_ssa.go (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/testdata/cmp_ssa.go b/src/cmd/compile/internal/gc/testdata/cmp_ssa.go new file mode 100644 index 0000000000..ba420f2e4e --- /dev/null +++ b/src/cmd/compile/internal/gc/testdata/cmp_ssa.go @@ -0,0 +1,48 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// cmp_ssa.go tests compare simplification operations. +package main + +import "fmt" + +var failed = false + +//go:noinline +func eq_ssa(a int64) bool { + return 4+a == 10 +} + +//go:noinline +func neq_ssa(a int64) bool { + return 10 != a+4 +} + +func testCmp() { + if wanted, got := true, eq_ssa(6); wanted != got { + fmt.Printf("eq_ssa: expected %v, got %v\n", wanted, got) + failed = true + } + if wanted, got := false, eq_ssa(7); wanted != got { + fmt.Printf("eq_ssa: expected %v, got %v\n", wanted, got) + failed = true + } + + if wanted, got := false, neq_ssa(6); wanted != got { + fmt.Printf("neq_ssa: expected %v, got %v\n", wanted, got) + failed = true + } + if wanted, got := true, neq_ssa(7); wanted != got { + fmt.Printf("neq_ssa: expected %v, got %v\n", wanted, got) + failed = true + } +} + +func main() { + testCmp() + + if failed { + panic("failed") + } +} diff --git a/src/cmd/compile/internal/ssa/gen/generic.rules b/src/cmd/compile/internal/ssa/gen/generic.rules index 3b7209a2b2..658d78ca32 100644 --- a/src/cmd/compile/internal/ssa/gen/generic.rules +++ b/src/cmd/compile/internal/ssa/gen/generic.rules @@ -48,6 +48,37 @@ (Neq16 x x) -> (ConstBool [0]) (Neq8 x x) -> (ConstBool [0]) +(Eq64 (Const64 [c]) (Add64 (Const64 [d]) x)) -> (Eq64 (Const64 [c-d]) x) +(Eq32 (Const32 [c]) (Add32 (Const32 [d]) x)) -> (Eq32 (Const32 [c-d]) x) +(Eq16 (Const16 [c]) (Add16 (Const16 [d]) x)) -> (Eq16 (Const16 [c-d]) x) +(Eq8 (Const8 [c]) (Add8 (Const8 [d]) x)) -> (Eq8 (Const8 [c-d]) x) + +(Neq64 (Const64 [c]) (Add64 (Const64 [d]) x)) -> (Neq64 (Const64 [c-d]) x) +(Neq32 (Const32 [c]) (Add32 (Const32 [d]) x)) -> (Neq32 (Const32 [c-d]) x) +(Neq16 (Const16 [c]) (Add16 (Const16 [d]) x)) -> (Neq16 (Const16 [c-d]) x) +(Neq8 (Const8 [c]) (Add8 (Const8 [d]) x)) -> (Neq8 (Const8 [c-d]) x) + +// canonicalize: swap arguments for commutative opertions when one argument is a constant. +(Eq64 x (Const64 [c])) && x.Op != OpConst64 -> (Eq64 (Const64 [c]) x) +(Eq32 x (Const32 [c])) && x.Op != OpConst32 -> (Eq32 (Const32 [c]) x) +(Eq16 x (Const16 [c])) && x.Op != OpConst16 -> (Eq16 (Const16 [c]) x) +(Eq8 x (Const8 [c])) && x.Op != OpConst8 -> (Eq8 (Const8 [c]) x) + +(Neq64 x (Const64 [c])) && x.Op != OpConst64 -> (Neq64 (Const64 [c]) x) +(Neq32 x (Const32 [c])) && x.Op != OpConst32 -> (Neq32 (Const32 [c]) x) +(Neq16 x (Const16 [c])) && x.Op != OpConst16 -> (Neq16 (Const16 [c]) x) +(Neq8 x (Const8 [c])) && x.Op != OpConst8 -> (Neq8 (Const8 [c]) x) + +(Add64 x (Const64 [c])) && x.Op != OpConst64 -> (Add64 (Const64 [c]) x) +(Add32 x (Const32 [c])) && x.Op != OpConst32 -> (Add32 (Const32 [c]) x) +(Add16 x (Const16 [c])) && x.Op != OpConst16 -> (Add16 (Const16 [c]) x) +(Add8 x (Const8 [c])) && x.Op != OpConst8 -> (Add8 (Const8 [c]) x) + +(Sub64 x (Const64 [c])) && x.Op != OpConst64 -> (Add64 (Const64 [-c]) x) +(Sub32 x (Const32 [c])) && x.Op != OpConst32 -> (Add32 (Const32 [-c]) x) +(Sub16 x (Const16 [c])) && x.Op != OpConst16 -> (Add16 (Const16 [-c]) x) +(Sub8 x (Const8 [c])) && x.Op != OpConst8 -> (Add8 (Const8 [-c]) x) + // constant comparisons (Eq64 (Const64 [c]) (Const64 [d])) -> (ConstBool [b2i(int64(c) == int64(d))]) (Eq32 (Const32 [c]) (Const32 [d])) -> (ConstBool [b2i(int32(c) == int32(d))]) diff --git a/src/cmd/compile/internal/ssa/rewritegeneric.go b/src/cmd/compile/internal/ssa/rewritegeneric.go index 149553dbc2..60d9f06ae6 100644 --- a/src/cmd/compile/internal/ssa/rewritegeneric.go +++ b/src/cmd/compile/internal/ssa/rewritegeneric.go @@ -224,6 +224,33 @@ func rewriteValuegeneric_OpAdd16(v *Value, config *Config) bool { } goto end359c546ef662b7990116329cb30d6892 end359c546ef662b7990116329cb30d6892: + ; + // match: (Add16 x (Const16 [c])) + // cond: x.Op != OpConst16 + // result: (Add16 (Const16 [c]) x) + { + x := v.Args[0] + if v.Args[1].Op != OpConst16 { + goto end89b69a89778f375b0ebbc683b0c63176 + } + t := v.Args[1].Type + c := v.Args[1].AuxInt + if !(x.Op != OpConst16) { + goto end89b69a89778f375b0ebbc683b0c63176 + } + v.Op = OpAdd16 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpConst16, TypeInvalid) + v0.Type = t + v0.AuxInt = c + v.AddArg(v0) + v.AddArg(x) + return true + } + goto end89b69a89778f375b0ebbc683b0c63176 +end89b69a89778f375b0ebbc683b0c63176: ; return false } @@ -251,6 +278,33 @@ func rewriteValuegeneric_OpAdd32(v *Value, config *Config) bool { } goto enda3edaa9a512bd1d7a95f002c890bfb88 enda3edaa9a512bd1d7a95f002c890bfb88: + ; + // match: (Add32 x (Const32 [c])) + // cond: x.Op != OpConst32 + // result: (Add32 (Const32 [c]) x) + { + x := v.Args[0] + if v.Args[1].Op != OpConst32 { + goto end28a8c474bfa6968950dce0ed73b14a0b + } + t := v.Args[1].Type + c := v.Args[1].AuxInt + if !(x.Op != OpConst32) { + goto end28a8c474bfa6968950dce0ed73b14a0b + } + v.Op = OpAdd32 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpConst32, TypeInvalid) + v0.Type = t + v0.AuxInt = c + v.AddArg(v0) + v.AddArg(x) + return true + } + goto end28a8c474bfa6968950dce0ed73b14a0b +end28a8c474bfa6968950dce0ed73b14a0b: ; return false } @@ -278,6 +332,33 @@ func rewriteValuegeneric_OpAdd64(v *Value, config *Config) bool { } goto end8c46df6f85a11cb1d594076b0e467908 end8c46df6f85a11cb1d594076b0e467908: + ; + // match: (Add64 x (Const64 [c])) + // cond: x.Op != OpConst64 + // result: (Add64 (Const64 [c]) x) + { + x := v.Args[0] + if v.Args[1].Op != OpConst64 { + goto end39caa6cf1044f5c47ddbeb062d1a13bd + } + t := v.Args[1].Type + c := v.Args[1].AuxInt + if !(x.Op != OpConst64) { + goto end39caa6cf1044f5c47ddbeb062d1a13bd + } + v.Op = OpAdd64 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpConst64, TypeInvalid) + v0.Type = t + v0.AuxInt = c + v.AddArg(v0) + v.AddArg(x) + return true + } + goto end39caa6cf1044f5c47ddbeb062d1a13bd +end39caa6cf1044f5c47ddbeb062d1a13bd: ; return false } @@ -305,6 +386,33 @@ func rewriteValuegeneric_OpAdd8(v *Value, config *Config) bool { } goto end60c66721511a442aade8e4da2fb326bd end60c66721511a442aade8e4da2fb326bd: + ; + // match: (Add8 x (Const8 [c])) + // cond: x.Op != OpConst8 + // result: (Add8 (Const8 [c]) x) + { + x := v.Args[0] + if v.Args[1].Op != OpConst8 { + goto end8c2901b8d12fa5c37f190783b4db8df5 + } + t := v.Args[1].Type + c := v.Args[1].AuxInt + if !(x.Op != OpConst8) { + goto end8c2901b8d12fa5c37f190783b4db8df5 + } + v.Op = OpAdd8 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpConst8, TypeInvalid) + v0.Type = t + v0.AuxInt = c + v.AddArg(v0) + v.AddArg(x) + return true + } + goto end8c2901b8d12fa5c37f190783b4db8df5 +end8c2901b8d12fa5c37f190783b4db8df5: ; return false } @@ -1141,6 +1249,67 @@ func rewriteValuegeneric_OpEq16(v *Value, config *Config) bool { } goto end0c0fe5fdfba3821add3448fd3f1fc6b7 end0c0fe5fdfba3821add3448fd3f1fc6b7: + ; + // match: (Eq16 (Const16 [c]) (Add16 (Const16 [d]) x)) + // cond: + // result: (Eq16 (Const16 [c-d]) x) + { + if v.Args[0].Op != OpConst16 { + goto end79c830afa265161fc0f0532c4c4e7f50 + } + t := v.Args[0].Type + c := v.Args[0].AuxInt + if v.Args[1].Op != OpAdd16 { + goto end79c830afa265161fc0f0532c4c4e7f50 + } + if v.Args[1].Args[0].Op != OpConst16 { + goto end79c830afa265161fc0f0532c4c4e7f50 + } + if v.Args[1].Args[0].Type != v.Args[0].Type { + goto end79c830afa265161fc0f0532c4c4e7f50 + } + d := v.Args[1].Args[0].AuxInt + x := v.Args[1].Args[1] + v.Op = OpEq16 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpConst16, TypeInvalid) + v0.Type = t + v0.AuxInt = c - d + v.AddArg(v0) + v.AddArg(x) + return true + } + goto end79c830afa265161fc0f0532c4c4e7f50 +end79c830afa265161fc0f0532c4c4e7f50: + ; + // match: (Eq16 x (Const16 [c])) + // cond: x.Op != OpConst16 + // result: (Eq16 (Const16 [c]) x) + { + x := v.Args[0] + if v.Args[1].Op != OpConst16 { + goto end5d89fe1eeb145f14e11578f41282c904 + } + t := v.Args[1].Type + c := v.Args[1].AuxInt + if !(x.Op != OpConst16) { + goto end5d89fe1eeb145f14e11578f41282c904 + } + v.Op = OpEq16 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpConst16, TypeInvalid) + v0.Type = t + v0.AuxInt = c + v.AddArg(v0) + v.AddArg(x) + return true + } + goto end5d89fe1eeb145f14e11578f41282c904 +end5d89fe1eeb145f14e11578f41282c904: ; // match: (Eq16 (Const16 [c]) (Const16 [d])) // cond: @@ -1186,6 +1355,67 @@ func rewriteValuegeneric_OpEq32(v *Value, config *Config) bool { } goto end6da547ec4ee93d787434f3bda873e4a0 end6da547ec4ee93d787434f3bda873e4a0: + ; + // match: (Eq32 (Const32 [c]) (Add32 (Const32 [d]) x)) + // cond: + // result: (Eq32 (Const32 [c-d]) x) + { + if v.Args[0].Op != OpConst32 { + goto end1a69730a32c6e432784dcdf643320ecd + } + t := v.Args[0].Type + c := v.Args[0].AuxInt + if v.Args[1].Op != OpAdd32 { + goto end1a69730a32c6e432784dcdf643320ecd + } + if v.Args[1].Args[0].Op != OpConst32 { + goto end1a69730a32c6e432784dcdf643320ecd + } + if v.Args[1].Args[0].Type != v.Args[0].Type { + goto end1a69730a32c6e432784dcdf643320ecd + } + d := v.Args[1].Args[0].AuxInt + x := v.Args[1].Args[1] + v.Op = OpEq32 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpConst32, TypeInvalid) + v0.Type = t + v0.AuxInt = c - d + v.AddArg(v0) + v.AddArg(x) + return true + } + goto end1a69730a32c6e432784dcdf643320ecd +end1a69730a32c6e432784dcdf643320ecd: + ; + // match: (Eq32 x (Const32 [c])) + // cond: x.Op != OpConst32 + // result: (Eq32 (Const32 [c]) x) + { + x := v.Args[0] + if v.Args[1].Op != OpConst32 { + goto end0ca4ef4cf416ec3083d38667e263cf45 + } + t := v.Args[1].Type + c := v.Args[1].AuxInt + if !(x.Op != OpConst32) { + goto end0ca4ef4cf416ec3083d38667e263cf45 + } + v.Op = OpEq32 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpConst32, TypeInvalid) + v0.Type = t + v0.AuxInt = c + v.AddArg(v0) + v.AddArg(x) + return true + } + goto end0ca4ef4cf416ec3083d38667e263cf45 +end0ca4ef4cf416ec3083d38667e263cf45: ; // match: (Eq32 (Const32 [c]) (Const32 [d])) // cond: @@ -1231,6 +1461,67 @@ func rewriteValuegeneric_OpEq64(v *Value, config *Config) bool { } goto endb1d471cc503ba8bb05440f01dbf33d81 endb1d471cc503ba8bb05440f01dbf33d81: + ; + // match: (Eq64 (Const64 [c]) (Add64 (Const64 [d]) x)) + // cond: + // result: (Eq64 (Const64 [c-d]) x) + { + if v.Args[0].Op != OpConst64 { + goto endffd67f3b83f6972cd459153d318f714d + } + t := v.Args[0].Type + c := v.Args[0].AuxInt + if v.Args[1].Op != OpAdd64 { + goto endffd67f3b83f6972cd459153d318f714d + } + if v.Args[1].Args[0].Op != OpConst64 { + goto endffd67f3b83f6972cd459153d318f714d + } + if v.Args[1].Args[0].Type != v.Args[0].Type { + goto endffd67f3b83f6972cd459153d318f714d + } + d := v.Args[1].Args[0].AuxInt + x := v.Args[1].Args[1] + v.Op = OpEq64 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpConst64, TypeInvalid) + v0.Type = t + v0.AuxInt = c - d + v.AddArg(v0) + v.AddArg(x) + return true + } + goto endffd67f3b83f6972cd459153d318f714d +endffd67f3b83f6972cd459153d318f714d: + ; + // match: (Eq64 x (Const64 [c])) + // cond: x.Op != OpConst64 + // result: (Eq64 (Const64 [c]) x) + { + x := v.Args[0] + if v.Args[1].Op != OpConst64 { + goto endc2ecf8254dc736e97c5815362d0b477d + } + t := v.Args[1].Type + c := v.Args[1].AuxInt + if !(x.Op != OpConst64) { + goto endc2ecf8254dc736e97c5815362d0b477d + } + v.Op = OpEq64 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpConst64, TypeInvalid) + v0.Type = t + v0.AuxInt = c + v.AddArg(v0) + v.AddArg(x) + return true + } + goto endc2ecf8254dc736e97c5815362d0b477d +endc2ecf8254dc736e97c5815362d0b477d: ; // match: (Eq64 (Const64 [c]) (Const64 [d])) // cond: @@ -1276,6 +1567,67 @@ func rewriteValuegeneric_OpEq8(v *Value, config *Config) bool { } goto enda66da0d3e7e51624ee46527727c48a9a enda66da0d3e7e51624ee46527727c48a9a: + ; + // match: (Eq8 (Const8 [c]) (Add8 (Const8 [d]) x)) + // cond: + // result: (Eq8 (Const8 [c-d]) x) + { + if v.Args[0].Op != OpConst8 { + goto end6912961350bb485f56ef176522aa683b + } + t := v.Args[0].Type + c := v.Args[0].AuxInt + if v.Args[1].Op != OpAdd8 { + goto end6912961350bb485f56ef176522aa683b + } + if v.Args[1].Args[0].Op != OpConst8 { + goto end6912961350bb485f56ef176522aa683b + } + if v.Args[1].Args[0].Type != v.Args[0].Type { + goto end6912961350bb485f56ef176522aa683b + } + d := v.Args[1].Args[0].AuxInt + x := v.Args[1].Args[1] + v.Op = OpEq8 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpConst8, TypeInvalid) + v0.Type = t + v0.AuxInt = c - d + v.AddArg(v0) + v.AddArg(x) + return true + } + goto end6912961350bb485f56ef176522aa683b +end6912961350bb485f56ef176522aa683b: + ; + // match: (Eq8 x (Const8 [c])) + // cond: x.Op != OpConst8 + // result: (Eq8 (Const8 [c]) x) + { + x := v.Args[0] + if v.Args[1].Op != OpConst8 { + goto end70d0b569427b24e7a912a1aa8fab3b20 + } + t := v.Args[1].Type + c := v.Args[1].AuxInt + if !(x.Op != OpConst8) { + goto end70d0b569427b24e7a912a1aa8fab3b20 + } + v.Op = OpEq8 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpConst8, TypeInvalid) + v0.Type = t + v0.AuxInt = c + v.AddArg(v0) + v.AddArg(x) + return true + } + goto end70d0b569427b24e7a912a1aa8fab3b20 +end70d0b569427b24e7a912a1aa8fab3b20: ; // match: (Eq8 (Const8 [c]) (Const8 [d])) // cond: @@ -2888,6 +3240,67 @@ func rewriteValuegeneric_OpNeq16(v *Value, config *Config) bool { } goto ende76a50b524aeb16c7aeccf5f5cc60c06 ende76a50b524aeb16c7aeccf5f5cc60c06: + ; + // match: (Neq16 (Const16 [c]) (Add16 (Const16 [d]) x)) + // cond: + // result: (Neq16 (Const16 [c-d]) x) + { + if v.Args[0].Op != OpConst16 { + goto end552011bd97e6f92ebc2672aa1843eadd + } + t := v.Args[0].Type + c := v.Args[0].AuxInt + if v.Args[1].Op != OpAdd16 { + goto end552011bd97e6f92ebc2672aa1843eadd + } + if v.Args[1].Args[0].Op != OpConst16 { + goto end552011bd97e6f92ebc2672aa1843eadd + } + if v.Args[1].Args[0].Type != v.Args[0].Type { + goto end552011bd97e6f92ebc2672aa1843eadd + } + d := v.Args[1].Args[0].AuxInt + x := v.Args[1].Args[1] + v.Op = OpNeq16 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpConst16, TypeInvalid) + v0.Type = t + v0.AuxInt = c - d + v.AddArg(v0) + v.AddArg(x) + return true + } + goto end552011bd97e6f92ebc2672aa1843eadd +end552011bd97e6f92ebc2672aa1843eadd: + ; + // match: (Neq16 x (Const16 [c])) + // cond: x.Op != OpConst16 + // result: (Neq16 (Const16 [c]) x) + { + x := v.Args[0] + if v.Args[1].Op != OpConst16 { + goto end0e45958f29e87997f632248aa9ee97e0 + } + t := v.Args[1].Type + c := v.Args[1].AuxInt + if !(x.Op != OpConst16) { + goto end0e45958f29e87997f632248aa9ee97e0 + } + v.Op = OpNeq16 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpConst16, TypeInvalid) + v0.Type = t + v0.AuxInt = c + v.AddArg(v0) + v.AddArg(x) + return true + } + goto end0e45958f29e87997f632248aa9ee97e0 +end0e45958f29e87997f632248aa9ee97e0: ; // match: (Neq16 (Const16 [c]) (Const16 [d])) // cond: @@ -2933,6 +3346,67 @@ func rewriteValuegeneric_OpNeq32(v *Value, config *Config) bool { } goto end3713a608cffd29b40ff7c3b3f2585cbb end3713a608cffd29b40ff7c3b3f2585cbb: + ; + // match: (Neq32 (Const32 [c]) (Add32 (Const32 [d]) x)) + // cond: + // result: (Neq32 (Const32 [c-d]) x) + { + if v.Args[0].Op != OpConst32 { + goto end93fc3b4a3639b965b414891111b16245 + } + t := v.Args[0].Type + c := v.Args[0].AuxInt + if v.Args[1].Op != OpAdd32 { + goto end93fc3b4a3639b965b414891111b16245 + } + if v.Args[1].Args[0].Op != OpConst32 { + goto end93fc3b4a3639b965b414891111b16245 + } + if v.Args[1].Args[0].Type != v.Args[0].Type { + goto end93fc3b4a3639b965b414891111b16245 + } + d := v.Args[1].Args[0].AuxInt + x := v.Args[1].Args[1] + v.Op = OpNeq32 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpConst32, TypeInvalid) + v0.Type = t + v0.AuxInt = c - d + v.AddArg(v0) + v.AddArg(x) + return true + } + goto end93fc3b4a3639b965b414891111b16245 +end93fc3b4a3639b965b414891111b16245: + ; + // match: (Neq32 x (Const32 [c])) + // cond: x.Op != OpConst32 + // result: (Neq32 (Const32 [c]) x) + { + x := v.Args[0] + if v.Args[1].Op != OpConst32 { + goto end5376f9ab90e282450f49011d0e0ce236 + } + t := v.Args[1].Type + c := v.Args[1].AuxInt + if !(x.Op != OpConst32) { + goto end5376f9ab90e282450f49011d0e0ce236 + } + v.Op = OpNeq32 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpConst32, TypeInvalid) + v0.Type = t + v0.AuxInt = c + v.AddArg(v0) + v.AddArg(x) + return true + } + goto end5376f9ab90e282450f49011d0e0ce236 +end5376f9ab90e282450f49011d0e0ce236: ; // match: (Neq32 (Const32 [c]) (Const32 [d])) // cond: @@ -2978,6 +3452,67 @@ func rewriteValuegeneric_OpNeq64(v *Value, config *Config) bool { } goto end3601ad382705ea12b79d2008c1e5725c end3601ad382705ea12b79d2008c1e5725c: + ; + // match: (Neq64 (Const64 [c]) (Add64 (Const64 [d]) x)) + // cond: + // result: (Neq64 (Const64 [c-d]) x) + { + if v.Args[0].Op != OpConst64 { + goto enda3d39cad13a557a2aa6d086f43596c1b + } + t := v.Args[0].Type + c := v.Args[0].AuxInt + if v.Args[1].Op != OpAdd64 { + goto enda3d39cad13a557a2aa6d086f43596c1b + } + if v.Args[1].Args[0].Op != OpConst64 { + goto enda3d39cad13a557a2aa6d086f43596c1b + } + if v.Args[1].Args[0].Type != v.Args[0].Type { + goto enda3d39cad13a557a2aa6d086f43596c1b + } + d := v.Args[1].Args[0].AuxInt + x := v.Args[1].Args[1] + v.Op = OpNeq64 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpConst64, TypeInvalid) + v0.Type = t + v0.AuxInt = c - d + v.AddArg(v0) + v.AddArg(x) + return true + } + goto enda3d39cad13a557a2aa6d086f43596c1b +enda3d39cad13a557a2aa6d086f43596c1b: + ; + // match: (Neq64 x (Const64 [c])) + // cond: x.Op != OpConst64 + // result: (Neq64 (Const64 [c]) x) + { + x := v.Args[0] + if v.Args[1].Op != OpConst64 { + goto end0936a57de20373ca6cacb9506ddde708 + } + t := v.Args[1].Type + c := v.Args[1].AuxInt + if !(x.Op != OpConst64) { + goto end0936a57de20373ca6cacb9506ddde708 + } + v.Op = OpNeq64 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpConst64, TypeInvalid) + v0.Type = t + v0.AuxInt = c + v.AddArg(v0) + v.AddArg(x) + return true + } + goto end0936a57de20373ca6cacb9506ddde708 +end0936a57de20373ca6cacb9506ddde708: ; // match: (Neq64 (Const64 [c]) (Const64 [d])) // cond: @@ -3023,6 +3558,67 @@ func rewriteValuegeneric_OpNeq8(v *Value, config *Config) bool { } goto end09a0deaf3c42627d0d2d3efa96e30745 end09a0deaf3c42627d0d2d3efa96e30745: + ; + // match: (Neq8 (Const8 [c]) (Add8 (Const8 [d]) x)) + // cond: + // result: (Neq8 (Const8 [c-d]) x) + { + if v.Args[0].Op != OpConst8 { + goto endc8f853c610c460c887cbfdca958e3691 + } + t := v.Args[0].Type + c := v.Args[0].AuxInt + if v.Args[1].Op != OpAdd8 { + goto endc8f853c610c460c887cbfdca958e3691 + } + if v.Args[1].Args[0].Op != OpConst8 { + goto endc8f853c610c460c887cbfdca958e3691 + } + if v.Args[1].Args[0].Type != v.Args[0].Type { + goto endc8f853c610c460c887cbfdca958e3691 + } + d := v.Args[1].Args[0].AuxInt + x := v.Args[1].Args[1] + v.Op = OpNeq8 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpConst8, TypeInvalid) + v0.Type = t + v0.AuxInt = c - d + v.AddArg(v0) + v.AddArg(x) + return true + } + goto endc8f853c610c460c887cbfdca958e3691 +endc8f853c610c460c887cbfdca958e3691: + ; + // match: (Neq8 x (Const8 [c])) + // cond: x.Op != OpConst8 + // result: (Neq8 (Const8 [c]) x) + { + x := v.Args[0] + if v.Args[1].Op != OpConst8 { + goto end04dc0ae2b08cf0447b50e5b8ef469252 + } + t := v.Args[1].Type + c := v.Args[1].AuxInt + if !(x.Op != OpConst8) { + goto end04dc0ae2b08cf0447b50e5b8ef469252 + } + v.Op = OpNeq8 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpConst8, TypeInvalid) + v0.Type = t + v0.AuxInt = c + v.AddArg(v0) + v.AddArg(x) + return true + } + goto end04dc0ae2b08cf0447b50e5b8ef469252 +end04dc0ae2b08cf0447b50e5b8ef469252: ; // match: (Neq8 (Const8 [c]) (Const8 [d])) // cond: @@ -4152,6 +4748,33 @@ func rewriteValuegeneric_OpSub16(v *Value, config *Config) bool { } goto end5c6fab95c9dbeff5973119096bfd4e78 end5c6fab95c9dbeff5973119096bfd4e78: + ; + // match: (Sub16 x (Const16 [c])) + // cond: x.Op != OpConst16 + // result: (Add16 (Const16 [-c]) x) + { + x := v.Args[0] + if v.Args[1].Op != OpConst16 { + goto end493545258a8e7e79d005b34c712ddd0c + } + t := v.Args[1].Type + c := v.Args[1].AuxInt + if !(x.Op != OpConst16) { + goto end493545258a8e7e79d005b34c712ddd0c + } + v.Op = OpAdd16 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpConst16, TypeInvalid) + v0.Type = t + v0.AuxInt = -c + v.AddArg(v0) + v.AddArg(x) + return true + } + goto end493545258a8e7e79d005b34c712ddd0c +end493545258a8e7e79d005b34c712ddd0c: ; // match: (Sub16 x x) // cond: @@ -4243,6 +4866,33 @@ func rewriteValuegeneric_OpSub32(v *Value, config *Config) bool { } goto end7623799db780e1bcc42c6ea0df9c49d3 end7623799db780e1bcc42c6ea0df9c49d3: + ; + // match: (Sub32 x (Const32 [c])) + // cond: x.Op != OpConst32 + // result: (Add32 (Const32 [-c]) x) + { + x := v.Args[0] + if v.Args[1].Op != OpConst32 { + goto end391e2f2ba8c7502b62c0153ec69c4fbd + } + t := v.Args[1].Type + c := v.Args[1].AuxInt + if !(x.Op != OpConst32) { + goto end391e2f2ba8c7502b62c0153ec69c4fbd + } + v.Op = OpAdd32 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpConst32, TypeInvalid) + v0.Type = t + v0.AuxInt = -c + v.AddArg(v0) + v.AddArg(x) + return true + } + goto end391e2f2ba8c7502b62c0153ec69c4fbd +end391e2f2ba8c7502b62c0153ec69c4fbd: ; // match: (Sub32 x x) // cond: @@ -4334,6 +4984,33 @@ func rewriteValuegeneric_OpSub64(v *Value, config *Config) bool { } goto end5a84a285ff0ff48b8ad3c64b15e3459f end5a84a285ff0ff48b8ad3c64b15e3459f: + ; + // match: (Sub64 x (Const64 [c])) + // cond: x.Op != OpConst64 + // result: (Add64 (Const64 [-c]) x) + { + x := v.Args[0] + if v.Args[1].Op != OpConst64 { + goto enda80d30f6794bcf02cd4442b238f68333 + } + t := v.Args[1].Type + c := v.Args[1].AuxInt + if !(x.Op != OpConst64) { + goto enda80d30f6794bcf02cd4442b238f68333 + } + v.Op = OpAdd64 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpConst64, TypeInvalid) + v0.Type = t + v0.AuxInt = -c + v.AddArg(v0) + v.AddArg(x) + return true + } + goto enda80d30f6794bcf02cd4442b238f68333 +enda80d30f6794bcf02cd4442b238f68333: ; // match: (Sub64 x x) // cond: @@ -4425,6 +5102,33 @@ func rewriteValuegeneric_OpSub8(v *Value, config *Config) bool { } goto endc00ea11c7535529e211710574f5cff24 endc00ea11c7535529e211710574f5cff24: + ; + // match: (Sub8 x (Const8 [c])) + // cond: x.Op != OpConst8 + // result: (Add8 (Const8 [-c]) x) + { + x := v.Args[0] + if v.Args[1].Op != OpConst8 { + goto end0bfab5b6f1037e55dc049b79e2636678 + } + t := v.Args[1].Type + c := v.Args[1].AuxInt + if !(x.Op != OpConst8) { + goto end0bfab5b6f1037e55dc049b79e2636678 + } + v.Op = OpAdd8 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpConst8, TypeInvalid) + v0.Type = t + v0.AuxInt = -c + v.AddArg(v0) + v.AddArg(x) + return true + } + goto end0bfab5b6f1037e55dc049b79e2636678 +end0bfab5b6f1037e55dc049b79e2636678: ; // match: (Sub8 x x) // cond: -- cgit v1.3 From 93a0b0f315a1b37e59449740dc5e5bb692b0d9f5 Mon Sep 17 00:00:00 2001 From: Todd Neal Date: Wed, 3 Feb 2016 06:21:24 -0500 Subject: [dev.ssa] cmd/compile: rewrites for constant shifts Add rewrite rules to optimize constant shifts. Fixes #10637 Change-Id: I74b724d3e81aeb7098c696d02c050f7fdfd5b523 Reviewed-on: https://go-review.googlesource.com/19106 Reviewed-by: Keith Randall Run-TryBot: Todd Neal TryBot-Result: Gobot Gobot --- .../compile/internal/gc/testdata/arithConst_ssa.go | 11758 ++++++++++++++++--- src/cmd/compile/internal/gc/testdata/arith_ssa.go | 99 + .../internal/gc/testdata/gen/arithConstGen.go | 294 + src/cmd/compile/internal/ssa/gen/generic.rules | 96 + src/cmd/compile/internal/ssa/rewrite.go | 5 + src/cmd/compile/internal/ssa/rewritegeneric.go | 3096 ++++- 6 files changed, 13383 insertions(+), 1965 deletions(-) create mode 100644 src/cmd/compile/internal/gc/testdata/gen/arithConstGen.go (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/testdata/arithConst_ssa.go b/src/cmd/compile/internal/gc/testdata/arithConst_ssa.go index 93420aee66..782d2df8c8 100644 --- a/src/cmd/compile/internal/gc/testdata/arithConst_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/arithConst_ssa.go @@ -2,1811 +2,1903 @@ package main import "fmt" +//go:noinline func add_uint64_0_ssa(a uint64) uint64 { - switch { - } return a + 0 } + +//go:noinline func add_0_uint64_ssa(a uint64) uint64 { - switch { - } return 0 + a } +//go:noinline func add_uint64_1_ssa(a uint64) uint64 { - switch { - } return a + 1 } + +//go:noinline func add_1_uint64_ssa(a uint64) uint64 { - switch { - } return 1 + a } +//go:noinline func add_uint64_4294967296_ssa(a uint64) uint64 { - switch { - } return a + 4294967296 } + +//go:noinline func add_4294967296_uint64_ssa(a uint64) uint64 { - switch { - } return 4294967296 + a } +//go:noinline func add_uint64_18446744073709551615_ssa(a uint64) uint64 { - switch { - } return a + 18446744073709551615 } + +//go:noinline func add_18446744073709551615_uint64_ssa(a uint64) uint64 { - switch { - } return 18446744073709551615 + a } +//go:noinline func sub_uint64_0_ssa(a uint64) uint64 { - switch { - } return a - 0 } + +//go:noinline func sub_0_uint64_ssa(a uint64) uint64 { - switch { - } return 0 - a } +//go:noinline func sub_uint64_1_ssa(a uint64) uint64 { - switch { - } return a - 1 } + +//go:noinline func sub_1_uint64_ssa(a uint64) uint64 { - switch { - } return 1 - a } +//go:noinline func sub_uint64_4294967296_ssa(a uint64) uint64 { - switch { - } return a - 4294967296 } + +//go:noinline func sub_4294967296_uint64_ssa(a uint64) uint64 { - switch { - } return 4294967296 - a } +//go:noinline func sub_uint64_18446744073709551615_ssa(a uint64) uint64 { - switch { - } return a - 18446744073709551615 } + +//go:noinline func sub_18446744073709551615_uint64_ssa(a uint64) uint64 { - switch { - } return 18446744073709551615 - a } +//go:noinline func div_0_uint64_ssa(a uint64) uint64 { - switch { - } return 0 / a } +//go:noinline func div_uint64_1_ssa(a uint64) uint64 { - switch { - } return a / 1 } + +//go:noinline func div_1_uint64_ssa(a uint64) uint64 { - switch { - } return 1 / a } +//go:noinline func div_uint64_4294967296_ssa(a uint64) uint64 { - switch { - } return a / 4294967296 } + +//go:noinline func div_4294967296_uint64_ssa(a uint64) uint64 { - switch { - } return 4294967296 / a } +//go:noinline func div_uint64_18446744073709551615_ssa(a uint64) uint64 { - switch { - } return a / 18446744073709551615 } + +//go:noinline func div_18446744073709551615_uint64_ssa(a uint64) uint64 { - switch { - } return 18446744073709551615 / a } +//go:noinline func mul_uint64_0_ssa(a uint64) uint64 { - switch { - } return a * 0 } + +//go:noinline func mul_0_uint64_ssa(a uint64) uint64 { - switch { - } return 0 * a } +//go:noinline func mul_uint64_1_ssa(a uint64) uint64 { - switch { - } return a * 1 } + +//go:noinline func mul_1_uint64_ssa(a uint64) uint64 { - switch { - } return 1 * a } +//go:noinline func mul_uint64_4294967296_ssa(a uint64) uint64 { - switch { - } return a * 4294967296 } + +//go:noinline func mul_4294967296_uint64_ssa(a uint64) uint64 { - switch { - } return 4294967296 * a } +//go:noinline func mul_uint64_18446744073709551615_ssa(a uint64) uint64 { - switch { - } return a * 18446744073709551615 } + +//go:noinline func mul_18446744073709551615_uint64_ssa(a uint64) uint64 { - switch { - } return 18446744073709551615 * a } +//go:noinline +func lsh_uint64_0_ssa(a uint64) uint64 { + return a << 0 +} + +//go:noinline +func lsh_0_uint64_ssa(a uint64) uint64 { + return 0 << a +} + +//go:noinline +func lsh_uint64_1_ssa(a uint64) uint64 { + return a << 1 +} + +//go:noinline +func lsh_1_uint64_ssa(a uint64) uint64 { + return 1 << a +} + +//go:noinline +func lsh_uint64_4294967296_ssa(a uint64) uint64 { + return a << 4294967296 +} + +//go:noinline +func lsh_4294967296_uint64_ssa(a uint64) uint64 { + return 4294967296 << a +} + +//go:noinline +func lsh_uint64_18446744073709551615_ssa(a uint64) uint64 { + return a << 18446744073709551615 +} + +//go:noinline +func lsh_18446744073709551615_uint64_ssa(a uint64) uint64 { + return 18446744073709551615 << a +} + +//go:noinline +func rsh_uint64_0_ssa(a uint64) uint64 { + return a >> 0 +} + +//go:noinline +func rsh_0_uint64_ssa(a uint64) uint64 { + return 0 >> a +} + +//go:noinline +func rsh_uint64_1_ssa(a uint64) uint64 { + return a >> 1 +} + +//go:noinline +func rsh_1_uint64_ssa(a uint64) uint64 { + return 1 >> a +} + +//go:noinline +func rsh_uint64_4294967296_ssa(a uint64) uint64 { + return a >> 4294967296 +} + +//go:noinline +func rsh_4294967296_uint64_ssa(a uint64) uint64 { + return 4294967296 >> a +} + +//go:noinline +func rsh_uint64_18446744073709551615_ssa(a uint64) uint64 { + return a >> 18446744073709551615 +} + +//go:noinline +func rsh_18446744073709551615_uint64_ssa(a uint64) uint64 { + return 18446744073709551615 >> a +} + +//go:noinline func add_int64_Neg9223372036854775808_ssa(a int64) int64 { - switch { - } return a + -9223372036854775808 } + +//go:noinline func add_Neg9223372036854775808_int64_ssa(a int64) int64 { - switch { - } return -9223372036854775808 + a } +//go:noinline func add_int64_Neg9223372036854775807_ssa(a int64) int64 { - switch { - } return a + -9223372036854775807 } + +//go:noinline func add_Neg9223372036854775807_int64_ssa(a int64) int64 { - switch { - } return -9223372036854775807 + a } +//go:noinline func add_int64_Neg4294967296_ssa(a int64) int64 { - switch { - } return a + -4294967296 } + +//go:noinline func add_Neg4294967296_int64_ssa(a int64) int64 { - switch { - } return -4294967296 + a } +//go:noinline func add_int64_Neg1_ssa(a int64) int64 { - switch { - } return a + -1 } + +//go:noinline func add_Neg1_int64_ssa(a int64) int64 { - switch { - } return -1 + a } +//go:noinline func add_int64_0_ssa(a int64) int64 { - switch { - } return a + 0 } + +//go:noinline func add_0_int64_ssa(a int64) int64 { - switch { - } return 0 + a } +//go:noinline func add_int64_1_ssa(a int64) int64 { - switch { - } return a + 1 } + +//go:noinline func add_1_int64_ssa(a int64) int64 { - switch { - } return 1 + a } +//go:noinline func add_int64_4294967296_ssa(a int64) int64 { - switch { - } return a + 4294967296 } + +//go:noinline func add_4294967296_int64_ssa(a int64) int64 { - switch { - } return 4294967296 + a } +//go:noinline func add_int64_9223372036854775806_ssa(a int64) int64 { - switch { - } return a + 9223372036854775806 } + +//go:noinline func add_9223372036854775806_int64_ssa(a int64) int64 { - switch { - } return 9223372036854775806 + a } +//go:noinline func add_int64_9223372036854775807_ssa(a int64) int64 { - switch { - } return a + 9223372036854775807 } + +//go:noinline func add_9223372036854775807_int64_ssa(a int64) int64 { - switch { - } return 9223372036854775807 + a } +//go:noinline func sub_int64_Neg9223372036854775808_ssa(a int64) int64 { - switch { - } return a - -9223372036854775808 } + +//go:noinline func sub_Neg9223372036854775808_int64_ssa(a int64) int64 { - switch { - } return -9223372036854775808 - a } +//go:noinline func sub_int64_Neg9223372036854775807_ssa(a int64) int64 { - switch { - } return a - -9223372036854775807 } + +//go:noinline func sub_Neg9223372036854775807_int64_ssa(a int64) int64 { - switch { - } return -9223372036854775807 - a } +//go:noinline func sub_int64_Neg4294967296_ssa(a int64) int64 { - switch { - } return a - -4294967296 } + +//go:noinline func sub_Neg4294967296_int64_ssa(a int64) int64 { - switch { - } return -4294967296 - a } +//go:noinline func sub_int64_Neg1_ssa(a int64) int64 { - switch { - } return a - -1 } + +//go:noinline func sub_Neg1_int64_ssa(a int64) int64 { - switch { - } return -1 - a } +//go:noinline func sub_int64_0_ssa(a int64) int64 { - switch { - } return a - 0 } + +//go:noinline func sub_0_int64_ssa(a int64) int64 { - switch { - } return 0 - a } +//go:noinline func sub_int64_1_ssa(a int64) int64 { - switch { - } return a - 1 } + +//go:noinline func sub_1_int64_ssa(a int64) int64 { - switch { - } return 1 - a } +//go:noinline func sub_int64_4294967296_ssa(a int64) int64 { - switch { - } return a - 4294967296 } + +//go:noinline func sub_4294967296_int64_ssa(a int64) int64 { - switch { - } return 4294967296 - a } +//go:noinline func sub_int64_9223372036854775806_ssa(a int64) int64 { - switch { - } return a - 9223372036854775806 } + +//go:noinline func sub_9223372036854775806_int64_ssa(a int64) int64 { - switch { - } return 9223372036854775806 - a } +//go:noinline func sub_int64_9223372036854775807_ssa(a int64) int64 { - switch { - } return a - 9223372036854775807 } + +//go:noinline func sub_9223372036854775807_int64_ssa(a int64) int64 { - switch { - } return 9223372036854775807 - a } +//go:noinline func div_int64_Neg9223372036854775808_ssa(a int64) int64 { - switch { - } return a / -9223372036854775808 } + +//go:noinline func div_Neg9223372036854775808_int64_ssa(a int64) int64 { - switch { - } return -9223372036854775808 / a } +//go:noinline func div_int64_Neg9223372036854775807_ssa(a int64) int64 { - switch { - } return a / -9223372036854775807 } + +//go:noinline func div_Neg9223372036854775807_int64_ssa(a int64) int64 { - switch { - } return -9223372036854775807 / a } +//go:noinline func div_int64_Neg4294967296_ssa(a int64) int64 { - switch { - } return a / -4294967296 } + +//go:noinline func div_Neg4294967296_int64_ssa(a int64) int64 { - switch { - } return -4294967296 / a } +//go:noinline func div_int64_Neg1_ssa(a int64) int64 { - switch { - } return a / -1 } + +//go:noinline func div_Neg1_int64_ssa(a int64) int64 { - switch { - } return -1 / a } +//go:noinline func div_0_int64_ssa(a int64) int64 { - switch { - } return 0 / a } +//go:noinline func div_int64_1_ssa(a int64) int64 { - switch { - } return a / 1 } + +//go:noinline func div_1_int64_ssa(a int64) int64 { - switch { - } return 1 / a } +//go:noinline func div_int64_4294967296_ssa(a int64) int64 { - switch { - } return a / 4294967296 } + +//go:noinline func div_4294967296_int64_ssa(a int64) int64 { - switch { - } return 4294967296 / a } +//go:noinline func div_int64_9223372036854775806_ssa(a int64) int64 { - switch { - } return a / 9223372036854775806 } + +//go:noinline func div_9223372036854775806_int64_ssa(a int64) int64 { - switch { - } return 9223372036854775806 / a } +//go:noinline func div_int64_9223372036854775807_ssa(a int64) int64 { - switch { - } return a / 9223372036854775807 } + +//go:noinline func div_9223372036854775807_int64_ssa(a int64) int64 { - switch { - } return 9223372036854775807 / a } +//go:noinline func mul_int64_Neg9223372036854775808_ssa(a int64) int64 { - switch { - } return a * -9223372036854775808 } + +//go:noinline func mul_Neg9223372036854775808_int64_ssa(a int64) int64 { - switch { - } return -9223372036854775808 * a } +//go:noinline func mul_int64_Neg9223372036854775807_ssa(a int64) int64 { - switch { - } return a * -9223372036854775807 } + +//go:noinline func mul_Neg9223372036854775807_int64_ssa(a int64) int64 { - switch { - } return -9223372036854775807 * a } +//go:noinline func mul_int64_Neg4294967296_ssa(a int64) int64 { - switch { - } return a * -4294967296 } + +//go:noinline func mul_Neg4294967296_int64_ssa(a int64) int64 { - switch { - } return -4294967296 * a } +//go:noinline func mul_int64_Neg1_ssa(a int64) int64 { - switch { - } return a * -1 } + +//go:noinline func mul_Neg1_int64_ssa(a int64) int64 { - switch { - } return -1 * a } +//go:noinline func mul_int64_0_ssa(a int64) int64 { - switch { - } return a * 0 } + +//go:noinline func mul_0_int64_ssa(a int64) int64 { - switch { - } return 0 * a } +//go:noinline func mul_int64_1_ssa(a int64) int64 { - switch { - } return a * 1 } + +//go:noinline func mul_1_int64_ssa(a int64) int64 { - switch { - } return 1 * a } +//go:noinline func mul_int64_4294967296_ssa(a int64) int64 { - switch { - } return a * 4294967296 } + +//go:noinline func mul_4294967296_int64_ssa(a int64) int64 { - switch { - } return 4294967296 * a } +//go:noinline func mul_int64_9223372036854775806_ssa(a int64) int64 { - switch { - } return a * 9223372036854775806 } + +//go:noinline func mul_9223372036854775806_int64_ssa(a int64) int64 { - switch { - } return 9223372036854775806 * a } +//go:noinline func mul_int64_9223372036854775807_ssa(a int64) int64 { - switch { - } return a * 9223372036854775807 } + +//go:noinline func mul_9223372036854775807_int64_ssa(a int64) int64 { - switch { - } return 9223372036854775807 * a } +//go:noinline func add_uint32_0_ssa(a uint32) uint32 { - switch { - } return a + 0 } + +//go:noinline func add_0_uint32_ssa(a uint32) uint32 { - switch { - } return 0 + a } +//go:noinline func add_uint32_1_ssa(a uint32) uint32 { - switch { - } return a + 1 } + +//go:noinline func add_1_uint32_ssa(a uint32) uint32 { - switch { - } return 1 + a } +//go:noinline func add_uint32_4294967295_ssa(a uint32) uint32 { - switch { - } return a + 4294967295 } + +//go:noinline func add_4294967295_uint32_ssa(a uint32) uint32 { - switch { - } return 4294967295 + a } +//go:noinline func sub_uint32_0_ssa(a uint32) uint32 { - switch { - } return a - 0 } + +//go:noinline func sub_0_uint32_ssa(a uint32) uint32 { - switch { - } return 0 - a } +//go:noinline func sub_uint32_1_ssa(a uint32) uint32 { - switch { - } return a - 1 } + +//go:noinline func sub_1_uint32_ssa(a uint32) uint32 { - switch { - } return 1 - a } +//go:noinline func sub_uint32_4294967295_ssa(a uint32) uint32 { - switch { - } return a - 4294967295 } + +//go:noinline func sub_4294967295_uint32_ssa(a uint32) uint32 { - switch { - } return 4294967295 - a } +//go:noinline func div_0_uint32_ssa(a uint32) uint32 { - switch { - } return 0 / a } +//go:noinline func div_uint32_1_ssa(a uint32) uint32 { - switch { - } return a / 1 } + +//go:noinline func div_1_uint32_ssa(a uint32) uint32 { - switch { - } return 1 / a } +//go:noinline func div_uint32_4294967295_ssa(a uint32) uint32 { - switch { - } return a / 4294967295 } + +//go:noinline func div_4294967295_uint32_ssa(a uint32) uint32 { - switch { - } return 4294967295 / a } +//go:noinline func mul_uint32_0_ssa(a uint32) uint32 { - switch { - } return a * 0 } + +//go:noinline func mul_0_uint32_ssa(a uint32) uint32 { - switch { - } return 0 * a } +//go:noinline func mul_uint32_1_ssa(a uint32) uint32 { - switch { - } return a * 1 } + +//go:noinline func mul_1_uint32_ssa(a uint32) uint32 { - switch { - } return 1 * a } +//go:noinline func mul_uint32_4294967295_ssa(a uint32) uint32 { - switch { - } return a * 4294967295 } + +//go:noinline func mul_4294967295_uint32_ssa(a uint32) uint32 { - switch { - } return 4294967295 * a } +//go:noinline +func lsh_uint32_0_ssa(a uint32) uint32 { + return a << 0 +} + +//go:noinline +func lsh_0_uint32_ssa(a uint32) uint32 { + return 0 << a +} + +//go:noinline +func lsh_uint32_1_ssa(a uint32) uint32 { + return a << 1 +} + +//go:noinline +func lsh_1_uint32_ssa(a uint32) uint32 { + return 1 << a +} + +//go:noinline +func lsh_uint32_4294967295_ssa(a uint32) uint32 { + return a << 4294967295 +} + +//go:noinline +func lsh_4294967295_uint32_ssa(a uint32) uint32 { + return 4294967295 << a +} + +//go:noinline +func rsh_uint32_0_ssa(a uint32) uint32 { + return a >> 0 +} + +//go:noinline +func rsh_0_uint32_ssa(a uint32) uint32 { + return 0 >> a +} + +//go:noinline +func rsh_uint32_1_ssa(a uint32) uint32 { + return a >> 1 +} + +//go:noinline +func rsh_1_uint32_ssa(a uint32) uint32 { + return 1 >> a +} + +//go:noinline +func rsh_uint32_4294967295_ssa(a uint32) uint32 { + return a >> 4294967295 +} + +//go:noinline +func rsh_4294967295_uint32_ssa(a uint32) uint32 { + return 4294967295 >> a +} + +//go:noinline func add_int32_Neg2147483648_ssa(a int32) int32 { - switch { - } return a + -2147483648 } + +//go:noinline func add_Neg2147483648_int32_ssa(a int32) int32 { - switch { - } return -2147483648 + a } +//go:noinline func add_int32_Neg2147483647_ssa(a int32) int32 { - switch { - } return a + -2147483647 } + +//go:noinline func add_Neg2147483647_int32_ssa(a int32) int32 { - switch { - } return -2147483647 + a } +//go:noinline func add_int32_Neg1_ssa(a int32) int32 { - switch { - } return a + -1 } + +//go:noinline func add_Neg1_int32_ssa(a int32) int32 { - switch { - } return -1 + a } +//go:noinline func add_int32_0_ssa(a int32) int32 { - switch { - } return a + 0 } + +//go:noinline func add_0_int32_ssa(a int32) int32 { - switch { - } return 0 + a } +//go:noinline func add_int32_1_ssa(a int32) int32 { - switch { - } return a + 1 } + +//go:noinline func add_1_int32_ssa(a int32) int32 { - switch { - } return 1 + a } +//go:noinline func add_int32_2147483647_ssa(a int32) int32 { - switch { - } return a + 2147483647 } + +//go:noinline func add_2147483647_int32_ssa(a int32) int32 { - switch { - } return 2147483647 + a } +//go:noinline func sub_int32_Neg2147483648_ssa(a int32) int32 { - switch { - } return a - -2147483648 } + +//go:noinline func sub_Neg2147483648_int32_ssa(a int32) int32 { - switch { - } return -2147483648 - a } +//go:noinline func sub_int32_Neg2147483647_ssa(a int32) int32 { - switch { - } return a - -2147483647 } + +//go:noinline func sub_Neg2147483647_int32_ssa(a int32) int32 { - switch { - } return -2147483647 - a } +//go:noinline func sub_int32_Neg1_ssa(a int32) int32 { - switch { - } return a - -1 } + +//go:noinline func sub_Neg1_int32_ssa(a int32) int32 { - switch { - } return -1 - a } +//go:noinline func sub_int32_0_ssa(a int32) int32 { - switch { - } return a - 0 } + +//go:noinline func sub_0_int32_ssa(a int32) int32 { - switch { - } return 0 - a } +//go:noinline func sub_int32_1_ssa(a int32) int32 { - switch { - } return a - 1 } + +//go:noinline func sub_1_int32_ssa(a int32) int32 { - switch { - } return 1 - a } +//go:noinline func sub_int32_2147483647_ssa(a int32) int32 { - switch { - } return a - 2147483647 } + +//go:noinline func sub_2147483647_int32_ssa(a int32) int32 { - switch { - } return 2147483647 - a } +//go:noinline func div_int32_Neg2147483648_ssa(a int32) int32 { - switch { - } return a / -2147483648 } + +//go:noinline func div_Neg2147483648_int32_ssa(a int32) int32 { - switch { - } return -2147483648 / a } +//go:noinline func div_int32_Neg2147483647_ssa(a int32) int32 { - switch { - } return a / -2147483647 } + +//go:noinline func div_Neg2147483647_int32_ssa(a int32) int32 { - switch { - } return -2147483647 / a } +//go:noinline func div_int32_Neg1_ssa(a int32) int32 { - switch { - } return a / -1 } + +//go:noinline func div_Neg1_int32_ssa(a int32) int32 { - switch { - } return -1 / a } +//go:noinline func div_0_int32_ssa(a int32) int32 { - switch { - } return 0 / a } +//go:noinline func div_int32_1_ssa(a int32) int32 { - switch { - } return a / 1 } + +//go:noinline func div_1_int32_ssa(a int32) int32 { - switch { - } return 1 / a } +//go:noinline func div_int32_2147483647_ssa(a int32) int32 { - switch { - } return a / 2147483647 } + +//go:noinline func div_2147483647_int32_ssa(a int32) int32 { - switch { - } return 2147483647 / a } +//go:noinline func mul_int32_Neg2147483648_ssa(a int32) int32 { - switch { - } return a * -2147483648 } + +//go:noinline func mul_Neg2147483648_int32_ssa(a int32) int32 { - switch { - } return -2147483648 * a } +//go:noinline func mul_int32_Neg2147483647_ssa(a int32) int32 { - switch { - } return a * -2147483647 } + +//go:noinline func mul_Neg2147483647_int32_ssa(a int32) int32 { - switch { - } return -2147483647 * a } +//go:noinline func mul_int32_Neg1_ssa(a int32) int32 { - switch { - } return a * -1 } + +//go:noinline func mul_Neg1_int32_ssa(a int32) int32 { - switch { - } return -1 * a } +//go:noinline func mul_int32_0_ssa(a int32) int32 { - switch { - } return a * 0 } + +//go:noinline func mul_0_int32_ssa(a int32) int32 { - switch { - } return 0 * a } +//go:noinline func mul_int32_1_ssa(a int32) int32 { - switch { - } return a * 1 } + +//go:noinline func mul_1_int32_ssa(a int32) int32 { - switch { - } return 1 * a } +//go:noinline func mul_int32_2147483647_ssa(a int32) int32 { - switch { - } return a * 2147483647 } + +//go:noinline func mul_2147483647_int32_ssa(a int32) int32 { - switch { - } return 2147483647 * a } +//go:noinline func add_uint16_0_ssa(a uint16) uint16 { - switch { - } return a + 0 } + +//go:noinline func add_0_uint16_ssa(a uint16) uint16 { - switch { - } return 0 + a } +//go:noinline func add_uint16_1_ssa(a uint16) uint16 { - switch { - } return a + 1 } + +//go:noinline func add_1_uint16_ssa(a uint16) uint16 { - switch { - } return 1 + a } +//go:noinline func add_uint16_65535_ssa(a uint16) uint16 { - switch { - } return a + 65535 } + +//go:noinline func add_65535_uint16_ssa(a uint16) uint16 { - switch { - } return 65535 + a } +//go:noinline func sub_uint16_0_ssa(a uint16) uint16 { - switch { - } return a - 0 } + +//go:noinline func sub_0_uint16_ssa(a uint16) uint16 { - switch { - } return 0 - a } +//go:noinline func sub_uint16_1_ssa(a uint16) uint16 { - switch { - } return a - 1 } + +//go:noinline func sub_1_uint16_ssa(a uint16) uint16 { - switch { - } return 1 - a } +//go:noinline func sub_uint16_65535_ssa(a uint16) uint16 { - switch { - } return a - 65535 } + +//go:noinline func sub_65535_uint16_ssa(a uint16) uint16 { - switch { - } return 65535 - a } +//go:noinline func div_0_uint16_ssa(a uint16) uint16 { - switch { - } return 0 / a } +//go:noinline func div_uint16_1_ssa(a uint16) uint16 { - switch { - } return a / 1 } + +//go:noinline func div_1_uint16_ssa(a uint16) uint16 { - switch { - } return 1 / a } +//go:noinline func div_uint16_65535_ssa(a uint16) uint16 { - switch { - } return a / 65535 } + +//go:noinline func div_65535_uint16_ssa(a uint16) uint16 { - switch { - } return 65535 / a } +//go:noinline func mul_uint16_0_ssa(a uint16) uint16 { - switch { - } return a * 0 } + +//go:noinline func mul_0_uint16_ssa(a uint16) uint16 { - switch { - } return 0 * a } +//go:noinline func mul_uint16_1_ssa(a uint16) uint16 { - switch { - } return a * 1 } + +//go:noinline func mul_1_uint16_ssa(a uint16) uint16 { - switch { - } return 1 * a } +//go:noinline func mul_uint16_65535_ssa(a uint16) uint16 { - switch { - } return a * 65535 } + +//go:noinline func mul_65535_uint16_ssa(a uint16) uint16 { - switch { - } return 65535 * a } +//go:noinline +func lsh_uint16_0_ssa(a uint16) uint16 { + return a << 0 +} + +//go:noinline +func lsh_0_uint16_ssa(a uint16) uint16 { + return 0 << a +} + +//go:noinline +func lsh_uint16_1_ssa(a uint16) uint16 { + return a << 1 +} + +//go:noinline +func lsh_1_uint16_ssa(a uint16) uint16 { + return 1 << a +} + +//go:noinline +func lsh_uint16_65535_ssa(a uint16) uint16 { + return a << 65535 +} + +//go:noinline +func lsh_65535_uint16_ssa(a uint16) uint16 { + return 65535 << a +} + +//go:noinline +func rsh_uint16_0_ssa(a uint16) uint16 { + return a >> 0 +} + +//go:noinline +func rsh_0_uint16_ssa(a uint16) uint16 { + return 0 >> a +} + +//go:noinline +func rsh_uint16_1_ssa(a uint16) uint16 { + return a >> 1 +} + +//go:noinline +func rsh_1_uint16_ssa(a uint16) uint16 { + return 1 >> a +} + +//go:noinline +func rsh_uint16_65535_ssa(a uint16) uint16 { + return a >> 65535 +} + +//go:noinline +func rsh_65535_uint16_ssa(a uint16) uint16 { + return 65535 >> a +} + +//go:noinline func add_int16_Neg32768_ssa(a int16) int16 { - switch { - } return a + -32768 } + +//go:noinline func add_Neg32768_int16_ssa(a int16) int16 { - switch { - } return -32768 + a } +//go:noinline func add_int16_Neg32767_ssa(a int16) int16 { - switch { - } return a + -32767 } + +//go:noinline func add_Neg32767_int16_ssa(a int16) int16 { - switch { - } return -32767 + a } +//go:noinline func add_int16_Neg1_ssa(a int16) int16 { - switch { - } return a + -1 } + +//go:noinline func add_Neg1_int16_ssa(a int16) int16 { - switch { - } return -1 + a } +//go:noinline func add_int16_0_ssa(a int16) int16 { - switch { - } return a + 0 } + +//go:noinline func add_0_int16_ssa(a int16) int16 { - switch { - } return 0 + a } +//go:noinline func add_int16_1_ssa(a int16) int16 { - switch { - } return a + 1 } + +//go:noinline func add_1_int16_ssa(a int16) int16 { - switch { - } return 1 + a } +//go:noinline func add_int16_32766_ssa(a int16) int16 { - switch { - } return a + 32766 } + +//go:noinline func add_32766_int16_ssa(a int16) int16 { - switch { - } return 32766 + a } +//go:noinline func add_int16_32767_ssa(a int16) int16 { - switch { - } return a + 32767 } + +//go:noinline func add_32767_int16_ssa(a int16) int16 { - switch { - } return 32767 + a } +//go:noinline func sub_int16_Neg32768_ssa(a int16) int16 { - switch { - } return a - -32768 } + +//go:noinline func sub_Neg32768_int16_ssa(a int16) int16 { - switch { - } return -32768 - a } +//go:noinline func sub_int16_Neg32767_ssa(a int16) int16 { - switch { - } return a - -32767 } + +//go:noinline func sub_Neg32767_int16_ssa(a int16) int16 { - switch { - } return -32767 - a } +//go:noinline func sub_int16_Neg1_ssa(a int16) int16 { - switch { - } return a - -1 } + +//go:noinline func sub_Neg1_int16_ssa(a int16) int16 { - switch { - } return -1 - a } +//go:noinline func sub_int16_0_ssa(a int16) int16 { - switch { - } return a - 0 } + +//go:noinline func sub_0_int16_ssa(a int16) int16 { - switch { - } return 0 - a } +//go:noinline func sub_int16_1_ssa(a int16) int16 { - switch { - } return a - 1 } + +//go:noinline func sub_1_int16_ssa(a int16) int16 { - switch { - } return 1 - a } +//go:noinline func sub_int16_32766_ssa(a int16) int16 { - switch { - } return a - 32766 } + +//go:noinline func sub_32766_int16_ssa(a int16) int16 { - switch { - } return 32766 - a } +//go:noinline func sub_int16_32767_ssa(a int16) int16 { - switch { - } return a - 32767 } + +//go:noinline func sub_32767_int16_ssa(a int16) int16 { - switch { - } return 32767 - a } +//go:noinline func div_int16_Neg32768_ssa(a int16) int16 { - switch { - } return a / -32768 } + +//go:noinline func div_Neg32768_int16_ssa(a int16) int16 { - switch { - } return -32768 / a } +//go:noinline func div_int16_Neg32767_ssa(a int16) int16 { - switch { - } return a / -32767 } + +//go:noinline func div_Neg32767_int16_ssa(a int16) int16 { - switch { - } return -32767 / a } +//go:noinline func div_int16_Neg1_ssa(a int16) int16 { - switch { - } return a / -1 } + +//go:noinline func div_Neg1_int16_ssa(a int16) int16 { - switch { - } return -1 / a } +//go:noinline func div_0_int16_ssa(a int16) int16 { - switch { - } return 0 / a } +//go:noinline func div_int16_1_ssa(a int16) int16 { - switch { - } return a / 1 } + +//go:noinline func div_1_int16_ssa(a int16) int16 { - switch { - } return 1 / a } +//go:noinline func div_int16_32766_ssa(a int16) int16 { - switch { - } return a / 32766 } + +//go:noinline func div_32766_int16_ssa(a int16) int16 { - switch { - } return 32766 / a } +//go:noinline func div_int16_32767_ssa(a int16) int16 { - switch { - } return a / 32767 } + +//go:noinline func div_32767_int16_ssa(a int16) int16 { - switch { - } return 32767 / a } +//go:noinline func mul_int16_Neg32768_ssa(a int16) int16 { - switch { - } return a * -32768 } + +//go:noinline func mul_Neg32768_int16_ssa(a int16) int16 { - switch { - } return -32768 * a } +//go:noinline func mul_int16_Neg32767_ssa(a int16) int16 { - switch { - } return a * -32767 } + +//go:noinline func mul_Neg32767_int16_ssa(a int16) int16 { - switch { - } return -32767 * a } +//go:noinline func mul_int16_Neg1_ssa(a int16) int16 { - switch { - } return a * -1 } + +//go:noinline func mul_Neg1_int16_ssa(a int16) int16 { - switch { - } return -1 * a } +//go:noinline func mul_int16_0_ssa(a int16) int16 { - switch { - } return a * 0 } + +//go:noinline func mul_0_int16_ssa(a int16) int16 { - switch { - } return 0 * a } +//go:noinline func mul_int16_1_ssa(a int16) int16 { - switch { - } return a * 1 } + +//go:noinline func mul_1_int16_ssa(a int16) int16 { - switch { - } return 1 * a } +//go:noinline func mul_int16_32766_ssa(a int16) int16 { - switch { - } return a * 32766 } + +//go:noinline func mul_32766_int16_ssa(a int16) int16 { - switch { - } return 32766 * a } +//go:noinline func mul_int16_32767_ssa(a int16) int16 { - switch { - } return a * 32767 } + +//go:noinline func mul_32767_int16_ssa(a int16) int16 { - switch { - } return 32767 * a } +//go:noinline func add_uint8_0_ssa(a uint8) uint8 { - switch { - } return a + 0 } + +//go:noinline func add_0_uint8_ssa(a uint8) uint8 { - switch { - } return 0 + a } +//go:noinline func add_uint8_1_ssa(a uint8) uint8 { - switch { - } return a + 1 } + +//go:noinline func add_1_uint8_ssa(a uint8) uint8 { - switch { - } return 1 + a } +//go:noinline func add_uint8_255_ssa(a uint8) uint8 { - switch { - } return a + 255 } + +//go:noinline func add_255_uint8_ssa(a uint8) uint8 { - switch { - } return 255 + a } +//go:noinline func sub_uint8_0_ssa(a uint8) uint8 { - switch { - } return a - 0 } + +//go:noinline func sub_0_uint8_ssa(a uint8) uint8 { - switch { - } return 0 - a } +//go:noinline func sub_uint8_1_ssa(a uint8) uint8 { - switch { - } return a - 1 } + +//go:noinline func sub_1_uint8_ssa(a uint8) uint8 { - switch { - } return 1 - a } +//go:noinline func sub_uint8_255_ssa(a uint8) uint8 { - switch { - } return a - 255 } + +//go:noinline func sub_255_uint8_ssa(a uint8) uint8 { - switch { - } return 255 - a } +//go:noinline func div_0_uint8_ssa(a uint8) uint8 { - switch { - } return 0 / a } +//go:noinline func div_uint8_1_ssa(a uint8) uint8 { - switch { - } return a / 1 } + +//go:noinline func div_1_uint8_ssa(a uint8) uint8 { - switch { - } return 1 / a } +//go:noinline func div_uint8_255_ssa(a uint8) uint8 { - switch { - } return a / 255 } + +//go:noinline func div_255_uint8_ssa(a uint8) uint8 { - switch { - } return 255 / a } +//go:noinline func mul_uint8_0_ssa(a uint8) uint8 { - switch { - } return a * 0 } + +//go:noinline func mul_0_uint8_ssa(a uint8) uint8 { - switch { - } return 0 * a } +//go:noinline func mul_uint8_1_ssa(a uint8) uint8 { - switch { - } return a * 1 } + +//go:noinline func mul_1_uint8_ssa(a uint8) uint8 { - switch { - } return 1 * a } +//go:noinline func mul_uint8_255_ssa(a uint8) uint8 { - switch { - } return a * 255 } + +//go:noinline func mul_255_uint8_ssa(a uint8) uint8 { - switch { - } return 255 * a } -func add_int8_Neg128_ssa(a int8) int8 { - switch { - } - return a + -128 +//go:noinline +func lsh_uint8_0_ssa(a uint8) uint8 { + return a << 0 } -func add_Neg128_int8_ssa(a int8) int8 { - switch { - } - return -128 + a + +//go:noinline +func lsh_0_uint8_ssa(a uint8) uint8 { + return 0 << a } -func add_int8_Neg127_ssa(a int8) int8 { - switch { - } - return a + -127 +//go:noinline +func lsh_uint8_1_ssa(a uint8) uint8 { + return a << 1 } -func add_Neg127_int8_ssa(a int8) int8 { - switch { - } - return -127 + a + +//go:noinline +func lsh_1_uint8_ssa(a uint8) uint8 { + return 1 << a } -func add_int8_Neg1_ssa(a int8) int8 { - switch { - } - return a + -1 +//go:noinline +func lsh_uint8_255_ssa(a uint8) uint8 { + return a << 255 } -func add_Neg1_int8_ssa(a int8) int8 { - switch { - } - return -1 + a + +//go:noinline +func lsh_255_uint8_ssa(a uint8) uint8 { + return 255 << a } -func add_int8_0_ssa(a int8) int8 { - switch { - } - return a + 0 +//go:noinline +func rsh_uint8_0_ssa(a uint8) uint8 { + return a >> 0 } -func add_0_int8_ssa(a int8) int8 { - switch { - } + +//go:noinline +func rsh_0_uint8_ssa(a uint8) uint8 { + return 0 >> a +} + +//go:noinline +func rsh_uint8_1_ssa(a uint8) uint8 { + return a >> 1 +} + +//go:noinline +func rsh_1_uint8_ssa(a uint8) uint8 { + return 1 >> a +} + +//go:noinline +func rsh_uint8_255_ssa(a uint8) uint8 { + return a >> 255 +} + +//go:noinline +func rsh_255_uint8_ssa(a uint8) uint8 { + return 255 >> a +} + +//go:noinline +func add_int8_Neg128_ssa(a int8) int8 { + return a + -128 +} + +//go:noinline +func add_Neg128_int8_ssa(a int8) int8 { + return -128 + a +} + +//go:noinline +func add_int8_Neg127_ssa(a int8) int8 { + return a + -127 +} + +//go:noinline +func add_Neg127_int8_ssa(a int8) int8 { + return -127 + a +} + +//go:noinline +func add_int8_Neg1_ssa(a int8) int8 { + return a + -1 +} + +//go:noinline +func add_Neg1_int8_ssa(a int8) int8 { + return -1 + a +} + +//go:noinline +func add_int8_0_ssa(a int8) int8 { + return a + 0 +} + +//go:noinline +func add_0_int8_ssa(a int8) int8 { return 0 + a } +//go:noinline func add_int8_1_ssa(a int8) int8 { - switch { - } return a + 1 } + +//go:noinline func add_1_int8_ssa(a int8) int8 { - switch { - } return 1 + a } +//go:noinline func add_int8_126_ssa(a int8) int8 { - switch { - } return a + 126 } + +//go:noinline func add_126_int8_ssa(a int8) int8 { - switch { - } return 126 + a } +//go:noinline func add_int8_127_ssa(a int8) int8 { - switch { - } return a + 127 } + +//go:noinline func add_127_int8_ssa(a int8) int8 { - switch { - } return 127 + a } +//go:noinline func sub_int8_Neg128_ssa(a int8) int8 { - switch { - } return a - -128 } + +//go:noinline func sub_Neg128_int8_ssa(a int8) int8 { - switch { - } return -128 - a } +//go:noinline func sub_int8_Neg127_ssa(a int8) int8 { - switch { - } return a - -127 } + +//go:noinline func sub_Neg127_int8_ssa(a int8) int8 { - switch { - } return -127 - a } +//go:noinline func sub_int8_Neg1_ssa(a int8) int8 { - switch { - } return a - -1 } + +//go:noinline func sub_Neg1_int8_ssa(a int8) int8 { - switch { - } return -1 - a } +//go:noinline func sub_int8_0_ssa(a int8) int8 { - switch { - } return a - 0 } + +//go:noinline func sub_0_int8_ssa(a int8) int8 { - switch { - } return 0 - a } +//go:noinline func sub_int8_1_ssa(a int8) int8 { - switch { - } return a - 1 } + +//go:noinline func sub_1_int8_ssa(a int8) int8 { - switch { - } return 1 - a } +//go:noinline func sub_int8_126_ssa(a int8) int8 { - switch { - } return a - 126 } + +//go:noinline func sub_126_int8_ssa(a int8) int8 { - switch { - } return 126 - a } +//go:noinline func sub_int8_127_ssa(a int8) int8 { - switch { - } return a - 127 } + +//go:noinline func sub_127_int8_ssa(a int8) int8 { - switch { - } return 127 - a } +//go:noinline func div_int8_Neg128_ssa(a int8) int8 { - switch { - } return a / -128 } + +//go:noinline func div_Neg128_int8_ssa(a int8) int8 { - switch { - } return -128 / a } +//go:noinline func div_int8_Neg127_ssa(a int8) int8 { - switch { - } return a / -127 } + +//go:noinline func div_Neg127_int8_ssa(a int8) int8 { - switch { - } return -127 / a } +//go:noinline func div_int8_Neg1_ssa(a int8) int8 { - switch { - } return a / -1 } + +//go:noinline func div_Neg1_int8_ssa(a int8) int8 { - switch { - } return -1 / a } +//go:noinline func div_0_int8_ssa(a int8) int8 { - switch { - } return 0 / a } +//go:noinline func div_int8_1_ssa(a int8) int8 { - switch { - } return a / 1 } + +//go:noinline func div_1_int8_ssa(a int8) int8 { - switch { - } return 1 / a } +//go:noinline func div_int8_126_ssa(a int8) int8 { - switch { - } return a / 126 } + +//go:noinline func div_126_int8_ssa(a int8) int8 { - switch { - } return 126 / a } +//go:noinline func div_int8_127_ssa(a int8) int8 { - switch { - } return a / 127 } + +//go:noinline func div_127_int8_ssa(a int8) int8 { - switch { - } return 127 / a } +//go:noinline func mul_int8_Neg128_ssa(a int8) int8 { - switch { - } return a * -128 } + +//go:noinline func mul_Neg128_int8_ssa(a int8) int8 { - switch { - } return -128 * a } +//go:noinline func mul_int8_Neg127_ssa(a int8) int8 { - switch { - } return a * -127 } + +//go:noinline func mul_Neg127_int8_ssa(a int8) int8 { - switch { - } return -127 * a } +//go:noinline func mul_int8_Neg1_ssa(a int8) int8 { - switch { - } return a * -1 } + +//go:noinline func mul_Neg1_int8_ssa(a int8) int8 { - switch { - } return -1 * a } +//go:noinline func mul_int8_0_ssa(a int8) int8 { - switch { - } return a * 0 } + +//go:noinline func mul_0_int8_ssa(a int8) int8 { - switch { - } return 0 * a } +//go:noinline func mul_int8_1_ssa(a int8) int8 { - switch { - } return a * 1 } + +//go:noinline func mul_1_int8_ssa(a int8) int8 { - switch { - } return 1 * a } +//go:noinline func mul_int8_126_ssa(a int8) int8 { - switch { - } return a * 126 } + +//go:noinline func mul_126_int8_ssa(a int8) int8 { - switch { - } return 126 * a } +//go:noinline func mul_int8_127_ssa(a int8) int8 { - switch { - } return a * 127 } + +//go:noinline func mul_127_int8_ssa(a int8) int8 { - switch { - } return 127 * a } @@ -1814,1528 +1906,7718 @@ var failed bool func main() { - if got := div_0_uint64_ssa(1); got != 0 { - fmt.Printf("div_uint64 0/1 = %d, wanted 0\n", got) + if got := add_0_uint64_ssa(0); got != 0 { + fmt.Printf("add_uint64 0+0 = %d, wanted 0\n", got) failed = true } - if got := div_0_uint64_ssa(4294967296); got != 0 { - fmt.Printf("div_uint64 0/4294967296 = %d, wanted 0\n", got) + if got := add_uint64_0_ssa(0); got != 0 { + fmt.Printf("add_uint64 0+0 = %d, wanted 0\n", got) failed = true } - if got := div_0_uint64_ssa(18446744073709551615); got != 0 { - fmt.Printf("div_uint64 0/18446744073709551615 = %d, wanted 0\n", got) + if got := add_0_uint64_ssa(1); got != 1 { + fmt.Printf("add_uint64 0+1 = %d, wanted 1\n", got) failed = true } - if got := div_uint64_1_ssa(0); got != 0 { - fmt.Printf("div_uint64 0/1 = %d, wanted 0\n", got) + if got := add_uint64_0_ssa(1); got != 1 { + fmt.Printf("add_uint64 1+0 = %d, wanted 1\n", got) failed = true } - if got := div_1_uint64_ssa(1); got != 1 { - fmt.Printf("div_uint64 1/1 = %d, wanted 1\n", got) + if got := add_0_uint64_ssa(4294967296); got != 4294967296 { + fmt.Printf("add_uint64 0+4294967296 = %d, wanted 4294967296\n", got) failed = true } - if got := div_uint64_1_ssa(1); got != 1 { - fmt.Printf("div_uint64 1/1 = %d, wanted 1\n", got) + if got := add_uint64_0_ssa(4294967296); got != 4294967296 { + fmt.Printf("add_uint64 4294967296+0 = %d, wanted 4294967296\n", got) failed = true } - if got := div_1_uint64_ssa(4294967296); got != 0 { - fmt.Printf("div_uint64 1/4294967296 = %d, wanted 0\n", got) + if got := add_0_uint64_ssa(18446744073709551615); got != 18446744073709551615 { + fmt.Printf("add_uint64 0+18446744073709551615 = %d, wanted 18446744073709551615\n", got) failed = true } - if got := div_uint64_1_ssa(4294967296); got != 4294967296 { - fmt.Printf("div_uint64 4294967296/1 = %d, wanted 4294967296\n", got) + if got := add_uint64_0_ssa(18446744073709551615); got != 18446744073709551615 { + fmt.Printf("add_uint64 18446744073709551615+0 = %d, wanted 18446744073709551615\n", got) failed = true } - if got := div_1_uint64_ssa(18446744073709551615); got != 0 { - fmt.Printf("div_uint64 1/18446744073709551615 = %d, wanted 0\n", got) + if got := add_1_uint64_ssa(0); got != 1 { + fmt.Printf("add_uint64 1+0 = %d, wanted 1\n", got) failed = true } - if got := div_uint64_1_ssa(18446744073709551615); got != 18446744073709551615 { - fmt.Printf("div_uint64 18446744073709551615/1 = %d, wanted 18446744073709551615\n", got) + if got := add_uint64_1_ssa(0); got != 1 { + fmt.Printf("add_uint64 0+1 = %d, wanted 1\n", got) failed = true } - if got := div_uint64_4294967296_ssa(0); got != 0 { - fmt.Printf("div_uint64 0/4294967296 = %d, wanted 0\n", got) + if got := add_1_uint64_ssa(1); got != 2 { + fmt.Printf("add_uint64 1+1 = %d, wanted 2\n", got) failed = true } - if got := div_4294967296_uint64_ssa(1); got != 4294967296 { - fmt.Printf("div_uint64 4294967296/1 = %d, wanted 4294967296\n", got) + if got := add_uint64_1_ssa(1); got != 2 { + fmt.Printf("add_uint64 1+1 = %d, wanted 2\n", got) failed = true } - if got := div_uint64_4294967296_ssa(1); got != 0 { - fmt.Printf("div_uint64 1/4294967296 = %d, wanted 0\n", got) + if got := add_1_uint64_ssa(4294967296); got != 4294967297 { + fmt.Printf("add_uint64 1+4294967296 = %d, wanted 4294967297\n", got) failed = true } - if got := div_4294967296_uint64_ssa(4294967296); got != 1 { - fmt.Printf("div_uint64 4294967296/4294967296 = %d, wanted 1\n", got) + if got := add_uint64_1_ssa(4294967296); got != 4294967297 { + fmt.Printf("add_uint64 4294967296+1 = %d, wanted 4294967297\n", got) failed = true } - if got := div_uint64_4294967296_ssa(4294967296); got != 1 { - fmt.Printf("div_uint64 4294967296/4294967296 = %d, wanted 1\n", got) + if got := add_1_uint64_ssa(18446744073709551615); got != 0 { + fmt.Printf("add_uint64 1+18446744073709551615 = %d, wanted 0\n", got) failed = true } - if got := div_4294967296_uint64_ssa(18446744073709551615); got != 0 { - fmt.Printf("div_uint64 4294967296/18446744073709551615 = %d, wanted 0\n", got) + if got := add_uint64_1_ssa(18446744073709551615); got != 0 { + fmt.Printf("add_uint64 18446744073709551615+1 = %d, wanted 0\n", got) failed = true } - if got := div_uint64_4294967296_ssa(18446744073709551615); got != 4294967295 { - fmt.Printf("div_uint64 18446744073709551615/4294967296 = %d, wanted 4294967295\n", got) + if got := add_4294967296_uint64_ssa(0); got != 4294967296 { + fmt.Printf("add_uint64 4294967296+0 = %d, wanted 4294967296\n", got) failed = true } - if got := div_uint64_18446744073709551615_ssa(0); got != 0 { - fmt.Printf("div_uint64 0/18446744073709551615 = %d, wanted 0\n", got) + if got := add_uint64_4294967296_ssa(0); got != 4294967296 { + fmt.Printf("add_uint64 0+4294967296 = %d, wanted 4294967296\n", got) failed = true } - if got := div_18446744073709551615_uint64_ssa(1); got != 18446744073709551615 { - fmt.Printf("div_uint64 18446744073709551615/1 = %d, wanted 18446744073709551615\n", got) + if got := add_4294967296_uint64_ssa(1); got != 4294967297 { + fmt.Printf("add_uint64 4294967296+1 = %d, wanted 4294967297\n", got) failed = true } - if got := div_uint64_18446744073709551615_ssa(1); got != 0 { - fmt.Printf("div_uint64 1/18446744073709551615 = %d, wanted 0\n", got) + if got := add_uint64_4294967296_ssa(1); got != 4294967297 { + fmt.Printf("add_uint64 1+4294967296 = %d, wanted 4294967297\n", got) failed = true } - if got := div_18446744073709551615_uint64_ssa(4294967296); got != 4294967295 { - fmt.Printf("div_uint64 18446744073709551615/4294967296 = %d, wanted 4294967295\n", got) + if got := add_4294967296_uint64_ssa(4294967296); got != 8589934592 { + fmt.Printf("add_uint64 4294967296+4294967296 = %d, wanted 8589934592\n", got) failed = true } - if got := div_uint64_18446744073709551615_ssa(4294967296); got != 0 { - fmt.Printf("div_uint64 4294967296/18446744073709551615 = %d, wanted 0\n", got) + if got := add_uint64_4294967296_ssa(4294967296); got != 8589934592 { + fmt.Printf("add_uint64 4294967296+4294967296 = %d, wanted 8589934592\n", got) failed = true } - if got := div_18446744073709551615_uint64_ssa(18446744073709551615); got != 1 { - fmt.Printf("div_uint64 18446744073709551615/18446744073709551615 = %d, wanted 1\n", got) + if got := add_4294967296_uint64_ssa(18446744073709551615); got != 4294967295 { + fmt.Printf("add_uint64 4294967296+18446744073709551615 = %d, wanted 4294967295\n", got) failed = true } - if got := div_uint64_18446744073709551615_ssa(18446744073709551615); got != 1 { - fmt.Printf("div_uint64 18446744073709551615/18446744073709551615 = %d, wanted 1\n", got) + if got := add_uint64_4294967296_ssa(18446744073709551615); got != 4294967295 { + fmt.Printf("add_uint64 18446744073709551615+4294967296 = %d, wanted 4294967295\n", got) failed = true } - if got := div_Neg9223372036854775808_int64_ssa(-9223372036854775808); got != 1 { - fmt.Printf("div_int64 -9223372036854775808/-9223372036854775808 = %d, wanted 1\n", got) + if got := add_18446744073709551615_uint64_ssa(0); got != 18446744073709551615 { + fmt.Printf("add_uint64 18446744073709551615+0 = %d, wanted 18446744073709551615\n", got) failed = true } - if got := div_int64_Neg9223372036854775808_ssa(-9223372036854775808); got != 1 { - fmt.Printf("div_int64 -9223372036854775808/-9223372036854775808 = %d, wanted 1\n", got) + if got := add_uint64_18446744073709551615_ssa(0); got != 18446744073709551615 { + fmt.Printf("add_uint64 0+18446744073709551615 = %d, wanted 18446744073709551615\n", got) failed = true } - if got := div_Neg9223372036854775808_int64_ssa(-9223372036854775807); got != 1 { - fmt.Printf("div_int64 -9223372036854775808/-9223372036854775807 = %d, wanted 1\n", got) + if got := add_18446744073709551615_uint64_ssa(1); got != 0 { + fmt.Printf("add_uint64 18446744073709551615+1 = %d, wanted 0\n", got) failed = true } - if got := div_int64_Neg9223372036854775808_ssa(-9223372036854775807); got != 0 { - fmt.Printf("div_int64 -9223372036854775807/-9223372036854775808 = %d, wanted 0\n", got) + if got := add_uint64_18446744073709551615_ssa(1); got != 0 { + fmt.Printf("add_uint64 1+18446744073709551615 = %d, wanted 0\n", got) failed = true } - if got := div_Neg9223372036854775808_int64_ssa(-4294967296); got != 2147483648 { - fmt.Printf("div_int64 -9223372036854775808/-4294967296 = %d, wanted 2147483648\n", got) + if got := add_18446744073709551615_uint64_ssa(4294967296); got != 4294967295 { + fmt.Printf("add_uint64 18446744073709551615+4294967296 = %d, wanted 4294967295\n", got) failed = true } - if got := div_int64_Neg9223372036854775808_ssa(-4294967296); got != 0 { - fmt.Printf("div_int64 -4294967296/-9223372036854775808 = %d, wanted 0\n", got) + if got := add_uint64_18446744073709551615_ssa(4294967296); got != 4294967295 { + fmt.Printf("add_uint64 4294967296+18446744073709551615 = %d, wanted 4294967295\n", got) failed = true } - if got := div_Neg9223372036854775808_int64_ssa(-1); got != -9223372036854775808 { - fmt.Printf("div_int64 -9223372036854775808/-1 = %d, wanted -9223372036854775808\n", got) + if got := add_18446744073709551615_uint64_ssa(18446744073709551615); got != 18446744073709551614 { + fmt.Printf("add_uint64 18446744073709551615+18446744073709551615 = %d, wanted 18446744073709551614\n", got) failed = true } - if got := div_int64_Neg9223372036854775808_ssa(-1); got != 0 { - fmt.Printf("div_int64 -1/-9223372036854775808 = %d, wanted 0\n", got) + if got := add_uint64_18446744073709551615_ssa(18446744073709551615); got != 18446744073709551614 { + fmt.Printf("add_uint64 18446744073709551615+18446744073709551615 = %d, wanted 18446744073709551614\n", got) failed = true } - if got := div_int64_Neg9223372036854775808_ssa(0); got != 0 { - fmt.Printf("div_int64 0/-9223372036854775808 = %d, wanted 0\n", got) + if got := sub_0_uint64_ssa(0); got != 0 { + fmt.Printf("sub_uint64 0-0 = %d, wanted 0\n", got) failed = true } - if got := div_Neg9223372036854775808_int64_ssa(1); got != -9223372036854775808 { - fmt.Printf("div_int64 -9223372036854775808/1 = %d, wanted -9223372036854775808\n", got) + if got := sub_uint64_0_ssa(0); got != 0 { + fmt.Printf("sub_uint64 0-0 = %d, wanted 0\n", got) failed = true } - if got := div_int64_Neg9223372036854775808_ssa(1); got != 0 { - fmt.Printf("div_int64 1/-9223372036854775808 = %d, wanted 0\n", got) + if got := sub_0_uint64_ssa(1); got != 18446744073709551615 { + fmt.Printf("sub_uint64 0-1 = %d, wanted 18446744073709551615\n", got) failed = true } - if got := div_Neg9223372036854775808_int64_ssa(4294967296); got != -2147483648 { - fmt.Printf("div_int64 -9223372036854775808/4294967296 = %d, wanted -2147483648\n", got) + if got := sub_uint64_0_ssa(1); got != 1 { + fmt.Printf("sub_uint64 1-0 = %d, wanted 1\n", got) failed = true } - if got := div_int64_Neg9223372036854775808_ssa(4294967296); got != 0 { - fmt.Printf("div_int64 4294967296/-9223372036854775808 = %d, wanted 0\n", got) + if got := sub_0_uint64_ssa(4294967296); got != 18446744069414584320 { + fmt.Printf("sub_uint64 0-4294967296 = %d, wanted 18446744069414584320\n", got) failed = true } - if got := div_Neg9223372036854775808_int64_ssa(9223372036854775806); got != -1 { - fmt.Printf("div_int64 -9223372036854775808/9223372036854775806 = %d, wanted -1\n", got) + if got := sub_uint64_0_ssa(4294967296); got != 4294967296 { + fmt.Printf("sub_uint64 4294967296-0 = %d, wanted 4294967296\n", got) failed = true } - if got := div_int64_Neg9223372036854775808_ssa(9223372036854775806); got != 0 { - fmt.Printf("div_int64 9223372036854775806/-9223372036854775808 = %d, wanted 0\n", got) + if got := sub_0_uint64_ssa(18446744073709551615); got != 1 { + fmt.Printf("sub_uint64 0-18446744073709551615 = %d, wanted 1\n", got) failed = true } - if got := div_Neg9223372036854775808_int64_ssa(9223372036854775807); got != -1 { - fmt.Printf("div_int64 -9223372036854775808/9223372036854775807 = %d, wanted -1\n", got) + if got := sub_uint64_0_ssa(18446744073709551615); got != 18446744073709551615 { + fmt.Printf("sub_uint64 18446744073709551615-0 = %d, wanted 18446744073709551615\n", got) failed = true } - if got := div_int64_Neg9223372036854775808_ssa(9223372036854775807); got != 0 { - fmt.Printf("div_int64 9223372036854775807/-9223372036854775808 = %d, wanted 0\n", got) + if got := sub_1_uint64_ssa(0); got != 1 { + fmt.Printf("sub_uint64 1-0 = %d, wanted 1\n", got) failed = true } - if got := div_Neg9223372036854775807_int64_ssa(-9223372036854775808); got != 0 { - fmt.Printf("div_int64 -9223372036854775807/-9223372036854775808 = %d, wanted 0\n", got) + if got := sub_uint64_1_ssa(0); got != 18446744073709551615 { + fmt.Printf("sub_uint64 0-1 = %d, wanted 18446744073709551615\n", got) failed = true } - if got := div_int64_Neg9223372036854775807_ssa(-9223372036854775808); got != 1 { - fmt.Printf("div_int64 -9223372036854775808/-9223372036854775807 = %d, wanted 1\n", got) + if got := sub_1_uint64_ssa(1); got != 0 { + fmt.Printf("sub_uint64 1-1 = %d, wanted 0\n", got) failed = true } - if got := div_Neg9223372036854775807_int64_ssa(-9223372036854775807); got != 1 { - fmt.Printf("div_int64 -9223372036854775807/-9223372036854775807 = %d, wanted 1\n", got) + if got := sub_uint64_1_ssa(1); got != 0 { + fmt.Printf("sub_uint64 1-1 = %d, wanted 0\n", got) failed = true } - if got := div_int64_Neg9223372036854775807_ssa(-9223372036854775807); got != 1 { - fmt.Printf("div_int64 -9223372036854775807/-9223372036854775807 = %d, wanted 1\n", got) + if got := sub_1_uint64_ssa(4294967296); got != 18446744069414584321 { + fmt.Printf("sub_uint64 1-4294967296 = %d, wanted 18446744069414584321\n", got) failed = true } - if got := div_Neg9223372036854775807_int64_ssa(-4294967296); got != 2147483647 { - fmt.Printf("div_int64 -9223372036854775807/-4294967296 = %d, wanted 2147483647\n", got) + if got := sub_uint64_1_ssa(4294967296); got != 4294967295 { + fmt.Printf("sub_uint64 4294967296-1 = %d, wanted 4294967295\n", got) failed = true } - if got := div_int64_Neg9223372036854775807_ssa(-4294967296); got != 0 { - fmt.Printf("div_int64 -4294967296/-9223372036854775807 = %d, wanted 0\n", got) + if got := sub_1_uint64_ssa(18446744073709551615); got != 2 { + fmt.Printf("sub_uint64 1-18446744073709551615 = %d, wanted 2\n", got) failed = true } - if got := div_Neg9223372036854775807_int64_ssa(-1); got != 9223372036854775807 { - fmt.Printf("div_int64 -9223372036854775807/-1 = %d, wanted 9223372036854775807\n", got) + if got := sub_uint64_1_ssa(18446744073709551615); got != 18446744073709551614 { + fmt.Printf("sub_uint64 18446744073709551615-1 = %d, wanted 18446744073709551614\n", got) failed = true } - if got := div_int64_Neg9223372036854775807_ssa(-1); got != 0 { - fmt.Printf("div_int64 -1/-9223372036854775807 = %d, wanted 0\n", got) + if got := sub_4294967296_uint64_ssa(0); got != 4294967296 { + fmt.Printf("sub_uint64 4294967296-0 = %d, wanted 4294967296\n", got) failed = true } - if got := div_int64_Neg9223372036854775807_ssa(0); got != 0 { - fmt.Printf("div_int64 0/-9223372036854775807 = %d, wanted 0\n", got) + if got := sub_uint64_4294967296_ssa(0); got != 18446744069414584320 { + fmt.Printf("sub_uint64 0-4294967296 = %d, wanted 18446744069414584320\n", got) failed = true } - if got := div_Neg9223372036854775807_int64_ssa(1); got != -9223372036854775807 { - fmt.Printf("div_int64 -9223372036854775807/1 = %d, wanted -9223372036854775807\n", got) + if got := sub_4294967296_uint64_ssa(1); got != 4294967295 { + fmt.Printf("sub_uint64 4294967296-1 = %d, wanted 4294967295\n", got) failed = true } - if got := div_int64_Neg9223372036854775807_ssa(1); got != 0 { - fmt.Printf("div_int64 1/-9223372036854775807 = %d, wanted 0\n", got) + if got := sub_uint64_4294967296_ssa(1); got != 18446744069414584321 { + fmt.Printf("sub_uint64 1-4294967296 = %d, wanted 18446744069414584321\n", got) failed = true } - if got := div_Neg9223372036854775807_int64_ssa(4294967296); got != -2147483647 { - fmt.Printf("div_int64 -9223372036854775807/4294967296 = %d, wanted -2147483647\n", got) + if got := sub_4294967296_uint64_ssa(4294967296); got != 0 { + fmt.Printf("sub_uint64 4294967296-4294967296 = %d, wanted 0\n", got) failed = true } - if got := div_int64_Neg9223372036854775807_ssa(4294967296); got != 0 { - fmt.Printf("div_int64 4294967296/-9223372036854775807 = %d, wanted 0\n", got) + if got := sub_uint64_4294967296_ssa(4294967296); got != 0 { + fmt.Printf("sub_uint64 4294967296-4294967296 = %d, wanted 0\n", got) failed = true } - if got := div_Neg9223372036854775807_int64_ssa(9223372036854775806); got != -1 { - fmt.Printf("div_int64 -9223372036854775807/9223372036854775806 = %d, wanted -1\n", got) + if got := sub_4294967296_uint64_ssa(18446744073709551615); got != 4294967297 { + fmt.Printf("sub_uint64 4294967296-18446744073709551615 = %d, wanted 4294967297\n", got) failed = true } - if got := div_int64_Neg9223372036854775807_ssa(9223372036854775806); got != 0 { - fmt.Printf("div_int64 9223372036854775806/-9223372036854775807 = %d, wanted 0\n", got) + if got := sub_uint64_4294967296_ssa(18446744073709551615); got != 18446744069414584319 { + fmt.Printf("sub_uint64 18446744073709551615-4294967296 = %d, wanted 18446744069414584319\n", got) failed = true } - if got := div_Neg9223372036854775807_int64_ssa(9223372036854775807); got != -1 { - fmt.Printf("div_int64 -9223372036854775807/9223372036854775807 = %d, wanted -1\n", got) + if got := sub_18446744073709551615_uint64_ssa(0); got != 18446744073709551615 { + fmt.Printf("sub_uint64 18446744073709551615-0 = %d, wanted 18446744073709551615\n", got) failed = true } - if got := div_int64_Neg9223372036854775807_ssa(9223372036854775807); got != -1 { - fmt.Printf("div_int64 9223372036854775807/-9223372036854775807 = %d, wanted -1\n", got) + if got := sub_uint64_18446744073709551615_ssa(0); got != 1 { + fmt.Printf("sub_uint64 0-18446744073709551615 = %d, wanted 1\n", got) failed = true } - if got := div_Neg4294967296_int64_ssa(-9223372036854775808); got != 0 { - fmt.Printf("div_int64 -4294967296/-9223372036854775808 = %d, wanted 0\n", got) + if got := sub_18446744073709551615_uint64_ssa(1); got != 18446744073709551614 { + fmt.Printf("sub_uint64 18446744073709551615-1 = %d, wanted 18446744073709551614\n", got) failed = true } - if got := div_int64_Neg4294967296_ssa(-9223372036854775808); got != 2147483648 { - fmt.Printf("div_int64 -9223372036854775808/-4294967296 = %d, wanted 2147483648\n", got) + if got := sub_uint64_18446744073709551615_ssa(1); got != 2 { + fmt.Printf("sub_uint64 1-18446744073709551615 = %d, wanted 2\n", got) failed = true } - if got := div_Neg4294967296_int64_ssa(-9223372036854775807); got != 0 { - fmt.Printf("div_int64 -4294967296/-9223372036854775807 = %d, wanted 0\n", got) + if got := sub_18446744073709551615_uint64_ssa(4294967296); got != 18446744069414584319 { + fmt.Printf("sub_uint64 18446744073709551615-4294967296 = %d, wanted 18446744069414584319\n", got) failed = true } - if got := div_int64_Neg4294967296_ssa(-9223372036854775807); got != 2147483647 { - fmt.Printf("div_int64 -9223372036854775807/-4294967296 = %d, wanted 2147483647\n", got) + if got := sub_uint64_18446744073709551615_ssa(4294967296); got != 4294967297 { + fmt.Printf("sub_uint64 4294967296-18446744073709551615 = %d, wanted 4294967297\n", got) failed = true } - if got := div_Neg4294967296_int64_ssa(-4294967296); got != 1 { - fmt.Printf("div_int64 -4294967296/-4294967296 = %d, wanted 1\n", got) + if got := sub_18446744073709551615_uint64_ssa(18446744073709551615); got != 0 { + fmt.Printf("sub_uint64 18446744073709551615-18446744073709551615 = %d, wanted 0\n", got) failed = true } - if got := div_int64_Neg4294967296_ssa(-4294967296); got != 1 { - fmt.Printf("div_int64 -4294967296/-4294967296 = %d, wanted 1\n", got) + if got := sub_uint64_18446744073709551615_ssa(18446744073709551615); got != 0 { + fmt.Printf("sub_uint64 18446744073709551615-18446744073709551615 = %d, wanted 0\n", got) failed = true } - if got := div_Neg4294967296_int64_ssa(-1); got != 4294967296 { - fmt.Printf("div_int64 -4294967296/-1 = %d, wanted 4294967296\n", got) + if got := div_0_uint64_ssa(1); got != 0 { + fmt.Printf("div_uint64 0/1 = %d, wanted 0\n", got) failed = true } - if got := div_int64_Neg4294967296_ssa(-1); got != 0 { - fmt.Printf("div_int64 -1/-4294967296 = %d, wanted 0\n", got) + if got := div_0_uint64_ssa(4294967296); got != 0 { + fmt.Printf("div_uint64 0/4294967296 = %d, wanted 0\n", got) failed = true } - if got := div_int64_Neg4294967296_ssa(0); got != 0 { - fmt.Printf("div_int64 0/-4294967296 = %d, wanted 0\n", got) + if got := div_0_uint64_ssa(18446744073709551615); got != 0 { + fmt.Printf("div_uint64 0/18446744073709551615 = %d, wanted 0\n", got) failed = true } - if got := div_Neg4294967296_int64_ssa(1); got != -4294967296 { - fmt.Printf("div_int64 -4294967296/1 = %d, wanted -4294967296\n", got) + if got := div_uint64_1_ssa(0); got != 0 { + fmt.Printf("div_uint64 0/1 = %d, wanted 0\n", got) failed = true } - if got := div_int64_Neg4294967296_ssa(1); got != 0 { - fmt.Printf("div_int64 1/-4294967296 = %d, wanted 0\n", got) + if got := div_1_uint64_ssa(1); got != 1 { + fmt.Printf("div_uint64 1/1 = %d, wanted 1\n", got) failed = true } - if got := div_Neg4294967296_int64_ssa(4294967296); got != -1 { - fmt.Printf("div_int64 -4294967296/4294967296 = %d, wanted -1\n", got) + if got := div_uint64_1_ssa(1); got != 1 { + fmt.Printf("div_uint64 1/1 = %d, wanted 1\n", got) failed = true } - if got := div_int64_Neg4294967296_ssa(4294967296); got != -1 { - fmt.Printf("div_int64 4294967296/-4294967296 = %d, wanted -1\n", got) + if got := div_1_uint64_ssa(4294967296); got != 0 { + fmt.Printf("div_uint64 1/4294967296 = %d, wanted 0\n", got) failed = true } - if got := div_Neg4294967296_int64_ssa(9223372036854775806); got != 0 { - fmt.Printf("div_int64 -4294967296/9223372036854775806 = %d, wanted 0\n", got) + if got := div_uint64_1_ssa(4294967296); got != 4294967296 { + fmt.Printf("div_uint64 4294967296/1 = %d, wanted 4294967296\n", got) failed = true } - if got := div_int64_Neg4294967296_ssa(9223372036854775806); got != -2147483647 { - fmt.Printf("div_int64 9223372036854775806/-4294967296 = %d, wanted -2147483647\n", got) + if got := div_1_uint64_ssa(18446744073709551615); got != 0 { + fmt.Printf("div_uint64 1/18446744073709551615 = %d, wanted 0\n", got) failed = true } - if got := div_Neg4294967296_int64_ssa(9223372036854775807); got != 0 { - fmt.Printf("div_int64 -4294967296/9223372036854775807 = %d, wanted 0\n", got) + if got := div_uint64_1_ssa(18446744073709551615); got != 18446744073709551615 { + fmt.Printf("div_uint64 18446744073709551615/1 = %d, wanted 18446744073709551615\n", got) failed = true } - if got := div_int64_Neg4294967296_ssa(9223372036854775807); got != -2147483647 { - fmt.Printf("div_int64 9223372036854775807/-4294967296 = %d, wanted -2147483647\n", got) + if got := div_uint64_4294967296_ssa(0); got != 0 { + fmt.Printf("div_uint64 0/4294967296 = %d, wanted 0\n", got) failed = true } - if got := div_Neg1_int64_ssa(-9223372036854775808); got != 0 { - fmt.Printf("div_int64 -1/-9223372036854775808 = %d, wanted 0\n", got) + if got := div_4294967296_uint64_ssa(1); got != 4294967296 { + fmt.Printf("div_uint64 4294967296/1 = %d, wanted 4294967296\n", got) failed = true } - if got := div_int64_Neg1_ssa(-9223372036854775808); got != -9223372036854775808 { - fmt.Printf("div_int64 -9223372036854775808/-1 = %d, wanted -9223372036854775808\n", got) + if got := div_uint64_4294967296_ssa(1); got != 0 { + fmt.Printf("div_uint64 1/4294967296 = %d, wanted 0\n", got) failed = true } - if got := div_Neg1_int64_ssa(-9223372036854775807); got != 0 { - fmt.Printf("div_int64 -1/-9223372036854775807 = %d, wanted 0\n", got) + if got := div_4294967296_uint64_ssa(4294967296); got != 1 { + fmt.Printf("div_uint64 4294967296/4294967296 = %d, wanted 1\n", got) failed = true } - if got := div_int64_Neg1_ssa(-9223372036854775807); got != 9223372036854775807 { - fmt.Printf("div_int64 -9223372036854775807/-1 = %d, wanted 9223372036854775807\n", got) + if got := div_uint64_4294967296_ssa(4294967296); got != 1 { + fmt.Printf("div_uint64 4294967296/4294967296 = %d, wanted 1\n", got) failed = true } - if got := div_Neg1_int64_ssa(-4294967296); got != 0 { - fmt.Printf("div_int64 -1/-4294967296 = %d, wanted 0\n", got) + if got := div_4294967296_uint64_ssa(18446744073709551615); got != 0 { + fmt.Printf("div_uint64 4294967296/18446744073709551615 = %d, wanted 0\n", got) failed = true } - if got := div_int64_Neg1_ssa(-4294967296); got != 4294967296 { - fmt.Printf("div_int64 -4294967296/-1 = %d, wanted 4294967296\n", got) + if got := div_uint64_4294967296_ssa(18446744073709551615); got != 4294967295 { + fmt.Printf("div_uint64 18446744073709551615/4294967296 = %d, wanted 4294967295\n", got) failed = true } - if got := div_Neg1_int64_ssa(-1); got != 1 { - fmt.Printf("div_int64 -1/-1 = %d, wanted 1\n", got) + if got := div_uint64_18446744073709551615_ssa(0); got != 0 { + fmt.Printf("div_uint64 0/18446744073709551615 = %d, wanted 0\n", got) failed = true } - if got := div_int64_Neg1_ssa(-1); got != 1 { - fmt.Printf("div_int64 -1/-1 = %d, wanted 1\n", got) + if got := div_18446744073709551615_uint64_ssa(1); got != 18446744073709551615 { + fmt.Printf("div_uint64 18446744073709551615/1 = %d, wanted 18446744073709551615\n", got) failed = true } - if got := div_int64_Neg1_ssa(0); got != 0 { - fmt.Printf("div_int64 0/-1 = %d, wanted 0\n", got) + if got := div_uint64_18446744073709551615_ssa(1); got != 0 { + fmt.Printf("div_uint64 1/18446744073709551615 = %d, wanted 0\n", got) failed = true } - if got := div_Neg1_int64_ssa(1); got != -1 { - fmt.Printf("div_int64 -1/1 = %d, wanted -1\n", got) + if got := div_18446744073709551615_uint64_ssa(4294967296); got != 4294967295 { + fmt.Printf("div_uint64 18446744073709551615/4294967296 = %d, wanted 4294967295\n", got) failed = true } - if got := div_int64_Neg1_ssa(1); got != -1 { - fmt.Printf("div_int64 1/-1 = %d, wanted -1\n", got) + if got := div_uint64_18446744073709551615_ssa(4294967296); got != 0 { + fmt.Printf("div_uint64 4294967296/18446744073709551615 = %d, wanted 0\n", got) failed = true } - if got := div_Neg1_int64_ssa(4294967296); got != 0 { - fmt.Printf("div_int64 -1/4294967296 = %d, wanted 0\n", got) + if got := div_18446744073709551615_uint64_ssa(18446744073709551615); got != 1 { + fmt.Printf("div_uint64 18446744073709551615/18446744073709551615 = %d, wanted 1\n", got) failed = true } - if got := div_int64_Neg1_ssa(4294967296); got != -4294967296 { - fmt.Printf("div_int64 4294967296/-1 = %d, wanted -4294967296\n", got) + if got := div_uint64_18446744073709551615_ssa(18446744073709551615); got != 1 { + fmt.Printf("div_uint64 18446744073709551615/18446744073709551615 = %d, wanted 1\n", got) failed = true } - if got := div_Neg1_int64_ssa(9223372036854775806); got != 0 { - fmt.Printf("div_int64 -1/9223372036854775806 = %d, wanted 0\n", got) + if got := mul_0_uint64_ssa(0); got != 0 { + fmt.Printf("mul_uint64 0*0 = %d, wanted 0\n", got) failed = true } - if got := div_int64_Neg1_ssa(9223372036854775806); got != -9223372036854775806 { - fmt.Printf("div_int64 9223372036854775806/-1 = %d, wanted -9223372036854775806\n", got) + if got := mul_uint64_0_ssa(0); got != 0 { + fmt.Printf("mul_uint64 0*0 = %d, wanted 0\n", got) failed = true } - if got := div_Neg1_int64_ssa(9223372036854775807); got != 0 { - fmt.Printf("div_int64 -1/9223372036854775807 = %d, wanted 0\n", got) + if got := mul_0_uint64_ssa(1); got != 0 { + fmt.Printf("mul_uint64 0*1 = %d, wanted 0\n", got) failed = true } - if got := div_int64_Neg1_ssa(9223372036854775807); got != -9223372036854775807 { - fmt.Printf("div_int64 9223372036854775807/-1 = %d, wanted -9223372036854775807\n", got) + if got := mul_uint64_0_ssa(1); got != 0 { + fmt.Printf("mul_uint64 1*0 = %d, wanted 0\n", got) failed = true } - if got := div_0_int64_ssa(-9223372036854775808); got != 0 { - fmt.Printf("div_int64 0/-9223372036854775808 = %d, wanted 0\n", got) + if got := mul_0_uint64_ssa(4294967296); got != 0 { + fmt.Printf("mul_uint64 0*4294967296 = %d, wanted 0\n", got) failed = true } - if got := div_0_int64_ssa(-9223372036854775807); got != 0 { - fmt.Printf("div_int64 0/-9223372036854775807 = %d, wanted 0\n", got) + if got := mul_uint64_0_ssa(4294967296); got != 0 { + fmt.Printf("mul_uint64 4294967296*0 = %d, wanted 0\n", got) failed = true } - if got := div_0_int64_ssa(-4294967296); got != 0 { - fmt.Printf("div_int64 0/-4294967296 = %d, wanted 0\n", got) + if got := mul_0_uint64_ssa(18446744073709551615); got != 0 { + fmt.Printf("mul_uint64 0*18446744073709551615 = %d, wanted 0\n", got) failed = true } - if got := div_0_int64_ssa(-1); got != 0 { - fmt.Printf("div_int64 0/-1 = %d, wanted 0\n", got) + if got := mul_uint64_0_ssa(18446744073709551615); got != 0 { + fmt.Printf("mul_uint64 18446744073709551615*0 = %d, wanted 0\n", got) failed = true } - if got := div_0_int64_ssa(1); got != 0 { - fmt.Printf("div_int64 0/1 = %d, wanted 0\n", got) + if got := mul_1_uint64_ssa(0); got != 0 { + fmt.Printf("mul_uint64 1*0 = %d, wanted 0\n", got) failed = true } - if got := div_0_int64_ssa(4294967296); got != 0 { - fmt.Printf("div_int64 0/4294967296 = %d, wanted 0\n", got) + if got := mul_uint64_1_ssa(0); got != 0 { + fmt.Printf("mul_uint64 0*1 = %d, wanted 0\n", got) failed = true } - if got := div_0_int64_ssa(9223372036854775806); got != 0 { - fmt.Printf("div_int64 0/9223372036854775806 = %d, wanted 0\n", got) + if got := mul_1_uint64_ssa(1); got != 1 { + fmt.Printf("mul_uint64 1*1 = %d, wanted 1\n", got) failed = true } - if got := div_0_int64_ssa(9223372036854775807); got != 0 { - fmt.Printf("div_int64 0/9223372036854775807 = %d, wanted 0\n", got) + if got := mul_uint64_1_ssa(1); got != 1 { + fmt.Printf("mul_uint64 1*1 = %d, wanted 1\n", got) failed = true } - if got := div_1_int64_ssa(-9223372036854775808); got != 0 { - fmt.Printf("div_int64 1/-9223372036854775808 = %d, wanted 0\n", got) + if got := mul_1_uint64_ssa(4294967296); got != 4294967296 { + fmt.Printf("mul_uint64 1*4294967296 = %d, wanted 4294967296\n", got) failed = true } - if got := div_int64_1_ssa(-9223372036854775808); got != -9223372036854775808 { - fmt.Printf("div_int64 -9223372036854775808/1 = %d, wanted -9223372036854775808\n", got) + if got := mul_uint64_1_ssa(4294967296); got != 4294967296 { + fmt.Printf("mul_uint64 4294967296*1 = %d, wanted 4294967296\n", got) failed = true } - if got := div_1_int64_ssa(-9223372036854775807); got != 0 { - fmt.Printf("div_int64 1/-9223372036854775807 = %d, wanted 0\n", got) + if got := mul_1_uint64_ssa(18446744073709551615); got != 18446744073709551615 { + fmt.Printf("mul_uint64 1*18446744073709551615 = %d, wanted 18446744073709551615\n", got) failed = true } - if got := div_int64_1_ssa(-9223372036854775807); got != -9223372036854775807 { - fmt.Printf("div_int64 -9223372036854775807/1 = %d, wanted -9223372036854775807\n", got) + if got := mul_uint64_1_ssa(18446744073709551615); got != 18446744073709551615 { + fmt.Printf("mul_uint64 18446744073709551615*1 = %d, wanted 18446744073709551615\n", got) failed = true } - if got := div_1_int64_ssa(-4294967296); got != 0 { - fmt.Printf("div_int64 1/-4294967296 = %d, wanted 0\n", got) + if got := mul_4294967296_uint64_ssa(0); got != 0 { + fmt.Printf("mul_uint64 4294967296*0 = %d, wanted 0\n", got) failed = true } - if got := div_int64_1_ssa(-4294967296); got != -4294967296 { - fmt.Printf("div_int64 -4294967296/1 = %d, wanted -4294967296\n", got) + if got := mul_uint64_4294967296_ssa(0); got != 0 { + fmt.Printf("mul_uint64 0*4294967296 = %d, wanted 0\n", got) failed = true } - if got := div_1_int64_ssa(-1); got != -1 { - fmt.Printf("div_int64 1/-1 = %d, wanted -1\n", got) + if got := mul_4294967296_uint64_ssa(1); got != 4294967296 { + fmt.Printf("mul_uint64 4294967296*1 = %d, wanted 4294967296\n", got) failed = true } - if got := div_int64_1_ssa(-1); got != -1 { - fmt.Printf("div_int64 -1/1 = %d, wanted -1\n", got) + if got := mul_uint64_4294967296_ssa(1); got != 4294967296 { + fmt.Printf("mul_uint64 1*4294967296 = %d, wanted 4294967296\n", got) failed = true } - if got := div_int64_1_ssa(0); got != 0 { - fmt.Printf("div_int64 0/1 = %d, wanted 0\n", got) + if got := mul_4294967296_uint64_ssa(4294967296); got != 0 { + fmt.Printf("mul_uint64 4294967296*4294967296 = %d, wanted 0\n", got) failed = true } - if got := div_1_int64_ssa(1); got != 1 { - fmt.Printf("div_int64 1/1 = %d, wanted 1\n", got) + if got := mul_uint64_4294967296_ssa(4294967296); got != 0 { + fmt.Printf("mul_uint64 4294967296*4294967296 = %d, wanted 0\n", got) failed = true } - if got := div_int64_1_ssa(1); got != 1 { - fmt.Printf("div_int64 1/1 = %d, wanted 1\n", got) + if got := mul_4294967296_uint64_ssa(18446744073709551615); got != 18446744069414584320 { + fmt.Printf("mul_uint64 4294967296*18446744073709551615 = %d, wanted 18446744069414584320\n", got) failed = true } - if got := div_1_int64_ssa(4294967296); got != 0 { - fmt.Printf("div_int64 1/4294967296 = %d, wanted 0\n", got) + if got := mul_uint64_4294967296_ssa(18446744073709551615); got != 18446744069414584320 { + fmt.Printf("mul_uint64 18446744073709551615*4294967296 = %d, wanted 18446744069414584320\n", got) failed = true } - if got := div_int64_1_ssa(4294967296); got != 4294967296 { - fmt.Printf("div_int64 4294967296/1 = %d, wanted 4294967296\n", got) + if got := mul_18446744073709551615_uint64_ssa(0); got != 0 { + fmt.Printf("mul_uint64 18446744073709551615*0 = %d, wanted 0\n", got) failed = true } - if got := div_1_int64_ssa(9223372036854775806); got != 0 { - fmt.Printf("div_int64 1/9223372036854775806 = %d, wanted 0\n", got) + if got := mul_uint64_18446744073709551615_ssa(0); got != 0 { + fmt.Printf("mul_uint64 0*18446744073709551615 = %d, wanted 0\n", got) failed = true } - if got := div_int64_1_ssa(9223372036854775806); got != 9223372036854775806 { - fmt.Printf("div_int64 9223372036854775806/1 = %d, wanted 9223372036854775806\n", got) + if got := mul_18446744073709551615_uint64_ssa(1); got != 18446744073709551615 { + fmt.Printf("mul_uint64 18446744073709551615*1 = %d, wanted 18446744073709551615\n", got) failed = true } - if got := div_1_int64_ssa(9223372036854775807); got != 0 { - fmt.Printf("div_int64 1/9223372036854775807 = %d, wanted 0\n", got) + if got := mul_uint64_18446744073709551615_ssa(1); got != 18446744073709551615 { + fmt.Printf("mul_uint64 1*18446744073709551615 = %d, wanted 18446744073709551615\n", got) failed = true } - if got := div_int64_1_ssa(9223372036854775807); got != 9223372036854775807 { - fmt.Printf("div_int64 9223372036854775807/1 = %d, wanted 9223372036854775807\n", got) + if got := mul_18446744073709551615_uint64_ssa(4294967296); got != 18446744069414584320 { + fmt.Printf("mul_uint64 18446744073709551615*4294967296 = %d, wanted 18446744069414584320\n", got) failed = true } - if got := div_4294967296_int64_ssa(-9223372036854775808); got != 0 { - fmt.Printf("div_int64 4294967296/-9223372036854775808 = %d, wanted 0\n", got) + if got := mul_uint64_18446744073709551615_ssa(4294967296); got != 18446744069414584320 { + fmt.Printf("mul_uint64 4294967296*18446744073709551615 = %d, wanted 18446744069414584320\n", got) failed = true } - if got := div_int64_4294967296_ssa(-9223372036854775808); got != -2147483648 { - fmt.Printf("div_int64 -9223372036854775808/4294967296 = %d, wanted -2147483648\n", got) + if got := mul_18446744073709551615_uint64_ssa(18446744073709551615); got != 1 { + fmt.Printf("mul_uint64 18446744073709551615*18446744073709551615 = %d, wanted 1\n", got) failed = true } - if got := div_4294967296_int64_ssa(-9223372036854775807); got != 0 { - fmt.Printf("div_int64 4294967296/-9223372036854775807 = %d, wanted 0\n", got) + if got := mul_uint64_18446744073709551615_ssa(18446744073709551615); got != 1 { + fmt.Printf("mul_uint64 18446744073709551615*18446744073709551615 = %d, wanted 1\n", got) failed = true } - if got := div_int64_4294967296_ssa(-9223372036854775807); got != -2147483647 { - fmt.Printf("div_int64 -9223372036854775807/4294967296 = %d, wanted -2147483647\n", got) + if got := lsh_0_uint64_ssa(0); got != 0 { + fmt.Printf("lsh_uint64 0<<0 = %d, wanted 0\n", got) failed = true } - if got := div_4294967296_int64_ssa(-4294967296); got != -1 { - fmt.Printf("div_int64 4294967296/-4294967296 = %d, wanted -1\n", got) + if got := lsh_uint64_0_ssa(0); got != 0 { + fmt.Printf("lsh_uint64 0<<0 = %d, wanted 0\n", got) failed = true } - if got := div_int64_4294967296_ssa(-4294967296); got != -1 { - fmt.Printf("div_int64 -4294967296/4294967296 = %d, wanted -1\n", got) + if got := lsh_0_uint64_ssa(1); got != 0 { + fmt.Printf("lsh_uint64 0<<1 = %d, wanted 0\n", got) failed = true } - if got := div_4294967296_int64_ssa(-1); got != -4294967296 { - fmt.Printf("div_int64 4294967296/-1 = %d, wanted -4294967296\n", got) + if got := lsh_uint64_0_ssa(1); got != 1 { + fmt.Printf("lsh_uint64 1<<0 = %d, wanted 1\n", got) failed = true } - if got := div_int64_4294967296_ssa(-1); got != 0 { - fmt.Printf("div_int64 -1/4294967296 = %d, wanted 0\n", got) + if got := lsh_0_uint64_ssa(4294967296); got != 0 { + fmt.Printf("lsh_uint64 0<<4294967296 = %d, wanted 0\n", got) failed = true } - if got := div_int64_4294967296_ssa(0); got != 0 { - fmt.Printf("div_int64 0/4294967296 = %d, wanted 0\n", got) + if got := lsh_uint64_0_ssa(4294967296); got != 4294967296 { + fmt.Printf("lsh_uint64 4294967296<<0 = %d, wanted 4294967296\n", got) failed = true } - if got := div_4294967296_int64_ssa(1); got != 4294967296 { - fmt.Printf("div_int64 4294967296/1 = %d, wanted 4294967296\n", got) + if got := lsh_0_uint64_ssa(18446744073709551615); got != 0 { + fmt.Printf("lsh_uint64 0<<18446744073709551615 = %d, wanted 0\n", got) failed = true } - if got := div_int64_4294967296_ssa(1); got != 0 { - fmt.Printf("div_int64 1/4294967296 = %d, wanted 0\n", got) + if got := lsh_uint64_0_ssa(18446744073709551615); got != 18446744073709551615 { + fmt.Printf("lsh_uint64 18446744073709551615<<0 = %d, wanted 18446744073709551615\n", got) failed = true } - if got := div_4294967296_int64_ssa(4294967296); got != 1 { - fmt.Printf("div_int64 4294967296/4294967296 = %d, wanted 1\n", got) + if got := lsh_1_uint64_ssa(0); got != 1 { + fmt.Printf("lsh_uint64 1<<0 = %d, wanted 1\n", got) failed = true } - if got := div_int64_4294967296_ssa(4294967296); got != 1 { - fmt.Printf("div_int64 4294967296/4294967296 = %d, wanted 1\n", got) + if got := lsh_uint64_1_ssa(0); got != 0 { + fmt.Printf("lsh_uint64 0<<1 = %d, wanted 0\n", got) failed = true } - if got := div_4294967296_int64_ssa(9223372036854775806); got != 0 { - fmt.Printf("div_int64 4294967296/9223372036854775806 = %d, wanted 0\n", got) + if got := lsh_1_uint64_ssa(1); got != 2 { + fmt.Printf("lsh_uint64 1<<1 = %d, wanted 2\n", got) failed = true } - if got := div_int64_4294967296_ssa(9223372036854775806); got != 2147483647 { - fmt.Printf("div_int64 9223372036854775806/4294967296 = %d, wanted 2147483647\n", got) + if got := lsh_uint64_1_ssa(1); got != 2 { + fmt.Printf("lsh_uint64 1<<1 = %d, wanted 2\n", got) failed = true } - if got := div_4294967296_int64_ssa(9223372036854775807); got != 0 { - fmt.Printf("div_int64 4294967296/9223372036854775807 = %d, wanted 0\n", got) + if got := lsh_1_uint64_ssa(4294967296); got != 0 { + fmt.Printf("lsh_uint64 1<<4294967296 = %d, wanted 0\n", got) failed = true } - if got := div_int64_4294967296_ssa(9223372036854775807); got != 2147483647 { - fmt.Printf("div_int64 9223372036854775807/4294967296 = %d, wanted 2147483647\n", got) + if got := lsh_uint64_1_ssa(4294967296); got != 8589934592 { + fmt.Printf("lsh_uint64 4294967296<<1 = %d, wanted 8589934592\n", got) failed = true } - if got := div_9223372036854775806_int64_ssa(-9223372036854775808); got != 0 { - fmt.Printf("div_int64 9223372036854775806/-9223372036854775808 = %d, wanted 0\n", got) + if got := lsh_1_uint64_ssa(18446744073709551615); got != 0 { + fmt.Printf("lsh_uint64 1<<18446744073709551615 = %d, wanted 0\n", got) failed = true } - if got := div_int64_9223372036854775806_ssa(-9223372036854775808); got != -1 { - fmt.Printf("div_int64 -9223372036854775808/9223372036854775806 = %d, wanted -1\n", got) + if got := lsh_uint64_1_ssa(18446744073709551615); got != 18446744073709551614 { + fmt.Printf("lsh_uint64 18446744073709551615<<1 = %d, wanted 18446744073709551614\n", got) failed = true } - if got := div_9223372036854775806_int64_ssa(-9223372036854775807); got != 0 { - fmt.Printf("div_int64 9223372036854775806/-9223372036854775807 = %d, wanted 0\n", got) + if got := lsh_4294967296_uint64_ssa(0); got != 4294967296 { + fmt.Printf("lsh_uint64 4294967296<<0 = %d, wanted 4294967296\n", got) failed = true } - if got := div_int64_9223372036854775806_ssa(-9223372036854775807); got != -1 { - fmt.Printf("div_int64 -9223372036854775807/9223372036854775806 = %d, wanted -1\n", got) + if got := lsh_uint64_4294967296_ssa(0); got != 0 { + fmt.Printf("lsh_uint64 0<<4294967296 = %d, wanted 0\n", got) failed = true } - if got := div_9223372036854775806_int64_ssa(-4294967296); got != -2147483647 { - fmt.Printf("div_int64 9223372036854775806/-4294967296 = %d, wanted -2147483647\n", got) + if got := lsh_4294967296_uint64_ssa(1); got != 8589934592 { + fmt.Printf("lsh_uint64 4294967296<<1 = %d, wanted 8589934592\n", got) failed = true } - if got := div_int64_9223372036854775806_ssa(-4294967296); got != 0 { - fmt.Printf("div_int64 -4294967296/9223372036854775806 = %d, wanted 0\n", got) + if got := lsh_uint64_4294967296_ssa(1); got != 0 { + fmt.Printf("lsh_uint64 1<<4294967296 = %d, wanted 0\n", got) failed = true } - if got := div_9223372036854775806_int64_ssa(-1); got != -9223372036854775806 { - fmt.Printf("div_int64 9223372036854775806/-1 = %d, wanted -9223372036854775806\n", got) + if got := lsh_4294967296_uint64_ssa(4294967296); got != 0 { + fmt.Printf("lsh_uint64 4294967296<<4294967296 = %d, wanted 0\n", got) failed = true } - if got := div_int64_9223372036854775806_ssa(-1); got != 0 { - fmt.Printf("div_int64 -1/9223372036854775806 = %d, wanted 0\n", got) + if got := lsh_uint64_4294967296_ssa(4294967296); got != 0 { + fmt.Printf("lsh_uint64 4294967296<<4294967296 = %d, wanted 0\n", got) failed = true } - if got := div_int64_9223372036854775806_ssa(0); got != 0 { - fmt.Printf("div_int64 0/9223372036854775806 = %d, wanted 0\n", got) + if got := lsh_4294967296_uint64_ssa(18446744073709551615); got != 0 { + fmt.Printf("lsh_uint64 4294967296<<18446744073709551615 = %d, wanted 0\n", got) failed = true } - if got := div_9223372036854775806_int64_ssa(1); got != 9223372036854775806 { - fmt.Printf("div_int64 9223372036854775806/1 = %d, wanted 9223372036854775806\n", got) + if got := lsh_uint64_4294967296_ssa(18446744073709551615); got != 0 { + fmt.Printf("lsh_uint64 18446744073709551615<<4294967296 = %d, wanted 0\n", got) failed = true } - if got := div_int64_9223372036854775806_ssa(1); got != 0 { - fmt.Printf("div_int64 1/9223372036854775806 = %d, wanted 0\n", got) + if got := lsh_18446744073709551615_uint64_ssa(0); got != 18446744073709551615 { + fmt.Printf("lsh_uint64 18446744073709551615<<0 = %d, wanted 18446744073709551615\n", got) failed = true } - if got := div_9223372036854775806_int64_ssa(4294967296); got != 2147483647 { - fmt.Printf("div_int64 9223372036854775806/4294967296 = %d, wanted 2147483647\n", got) + if got := lsh_uint64_18446744073709551615_ssa(0); got != 0 { + fmt.Printf("lsh_uint64 0<<18446744073709551615 = %d, wanted 0\n", got) failed = true } - if got := div_int64_9223372036854775806_ssa(4294967296); got != 0 { - fmt.Printf("div_int64 4294967296/9223372036854775806 = %d, wanted 0\n", got) + if got := lsh_18446744073709551615_uint64_ssa(1); got != 18446744073709551614 { + fmt.Printf("lsh_uint64 18446744073709551615<<1 = %d, wanted 18446744073709551614\n", got) failed = true } - if got := div_9223372036854775806_int64_ssa(9223372036854775806); got != 1 { - fmt.Printf("div_int64 9223372036854775806/9223372036854775806 = %d, wanted 1\n", got) + if got := lsh_uint64_18446744073709551615_ssa(1); got != 0 { + fmt.Printf("lsh_uint64 1<<18446744073709551615 = %d, wanted 0\n", got) failed = true } - if got := div_int64_9223372036854775806_ssa(9223372036854775806); got != 1 { - fmt.Printf("div_int64 9223372036854775806/9223372036854775806 = %d, wanted 1\n", got) + if got := lsh_18446744073709551615_uint64_ssa(4294967296); got != 0 { + fmt.Printf("lsh_uint64 18446744073709551615<<4294967296 = %d, wanted 0\n", got) failed = true } - if got := div_9223372036854775806_int64_ssa(9223372036854775807); got != 0 { - fmt.Printf("div_int64 9223372036854775806/9223372036854775807 = %d, wanted 0\n", got) + if got := lsh_uint64_18446744073709551615_ssa(4294967296); got != 0 { + fmt.Printf("lsh_uint64 4294967296<<18446744073709551615 = %d, wanted 0\n", got) failed = true } - if got := div_int64_9223372036854775806_ssa(9223372036854775807); got != 1 { - fmt.Printf("div_int64 9223372036854775807/9223372036854775806 = %d, wanted 1\n", got) + if got := lsh_18446744073709551615_uint64_ssa(18446744073709551615); got != 0 { + fmt.Printf("lsh_uint64 18446744073709551615<<18446744073709551615 = %d, wanted 0\n", got) failed = true } - if got := div_9223372036854775807_int64_ssa(-9223372036854775808); got != 0 { - fmt.Printf("div_int64 9223372036854775807/-9223372036854775808 = %d, wanted 0\n", got) + if got := lsh_uint64_18446744073709551615_ssa(18446744073709551615); got != 0 { + fmt.Printf("lsh_uint64 18446744073709551615<<18446744073709551615 = %d, wanted 0\n", got) failed = true } - if got := div_int64_9223372036854775807_ssa(-9223372036854775808); got != -1 { - fmt.Printf("div_int64 -9223372036854775808/9223372036854775807 = %d, wanted -1\n", got) + if got := rsh_0_uint64_ssa(0); got != 0 { + fmt.Printf("rsh_uint64 0>>0 = %d, wanted 0\n", got) failed = true } - if got := div_9223372036854775807_int64_ssa(-9223372036854775807); got != -1 { - fmt.Printf("div_int64 9223372036854775807/-9223372036854775807 = %d, wanted -1\n", got) + if got := rsh_uint64_0_ssa(0); got != 0 { + fmt.Printf("rsh_uint64 0>>0 = %d, wanted 0\n", got) failed = true } - if got := div_int64_9223372036854775807_ssa(-9223372036854775807); got != -1 { - fmt.Printf("div_int64 -9223372036854775807/9223372036854775807 = %d, wanted -1\n", got) + if got := rsh_0_uint64_ssa(1); got != 0 { + fmt.Printf("rsh_uint64 0>>1 = %d, wanted 0\n", got) failed = true } - if got := div_9223372036854775807_int64_ssa(-4294967296); got != -2147483647 { - fmt.Printf("div_int64 9223372036854775807/-4294967296 = %d, wanted -2147483647\n", got) + if got := rsh_uint64_0_ssa(1); got != 1 { + fmt.Printf("rsh_uint64 1>>0 = %d, wanted 1\n", got) failed = true } - if got := div_int64_9223372036854775807_ssa(-4294967296); got != 0 { - fmt.Printf("div_int64 -4294967296/9223372036854775807 = %d, wanted 0\n", got) + if got := rsh_0_uint64_ssa(4294967296); got != 0 { + fmt.Printf("rsh_uint64 0>>4294967296 = %d, wanted 0\n", got) failed = true } - if got := div_9223372036854775807_int64_ssa(-1); got != -9223372036854775807 { - fmt.Printf("div_int64 9223372036854775807/-1 = %d, wanted -9223372036854775807\n", got) + if got := rsh_uint64_0_ssa(4294967296); got != 4294967296 { + fmt.Printf("rsh_uint64 4294967296>>0 = %d, wanted 4294967296\n", got) failed = true } - if got := div_int64_9223372036854775807_ssa(-1); got != 0 { - fmt.Printf("div_int64 -1/9223372036854775807 = %d, wanted 0\n", got) + if got := rsh_0_uint64_ssa(18446744073709551615); got != 0 { + fmt.Printf("rsh_uint64 0>>18446744073709551615 = %d, wanted 0\n", got) failed = true } - if got := div_int64_9223372036854775807_ssa(0); got != 0 { - fmt.Printf("div_int64 0/9223372036854775807 = %d, wanted 0\n", got) + if got := rsh_uint64_0_ssa(18446744073709551615); got != 18446744073709551615 { + fmt.Printf("rsh_uint64 18446744073709551615>>0 = %d, wanted 18446744073709551615\n", got) failed = true } - if got := div_9223372036854775807_int64_ssa(1); got != 9223372036854775807 { - fmt.Printf("div_int64 9223372036854775807/1 = %d, wanted 9223372036854775807\n", got) + if got := rsh_1_uint64_ssa(0); got != 1 { + fmt.Printf("rsh_uint64 1>>0 = %d, wanted 1\n", got) failed = true } - if got := div_int64_9223372036854775807_ssa(1); got != 0 { - fmt.Printf("div_int64 1/9223372036854775807 = %d, wanted 0\n", got) + if got := rsh_uint64_1_ssa(0); got != 0 { + fmt.Printf("rsh_uint64 0>>1 = %d, wanted 0\n", got) failed = true } - if got := div_9223372036854775807_int64_ssa(4294967296); got != 2147483647 { - fmt.Printf("div_int64 9223372036854775807/4294967296 = %d, wanted 2147483647\n", got) + if got := rsh_1_uint64_ssa(1); got != 0 { + fmt.Printf("rsh_uint64 1>>1 = %d, wanted 0\n", got) failed = true } - if got := div_int64_9223372036854775807_ssa(4294967296); got != 0 { - fmt.Printf("div_int64 4294967296/9223372036854775807 = %d, wanted 0\n", got) + if got := rsh_uint64_1_ssa(1); got != 0 { + fmt.Printf("rsh_uint64 1>>1 = %d, wanted 0\n", got) failed = true } - if got := div_9223372036854775807_int64_ssa(9223372036854775806); got != 1 { - fmt.Printf("div_int64 9223372036854775807/9223372036854775806 = %d, wanted 1\n", got) + if got := rsh_1_uint64_ssa(4294967296); got != 0 { + fmt.Printf("rsh_uint64 1>>4294967296 = %d, wanted 0\n", got) failed = true } - if got := div_int64_9223372036854775807_ssa(9223372036854775806); got != 0 { - fmt.Printf("div_int64 9223372036854775806/9223372036854775807 = %d, wanted 0\n", got) + if got := rsh_uint64_1_ssa(4294967296); got != 2147483648 { + fmt.Printf("rsh_uint64 4294967296>>1 = %d, wanted 2147483648\n", got) failed = true } - if got := div_9223372036854775807_int64_ssa(9223372036854775807); got != 1 { - fmt.Printf("div_int64 9223372036854775807/9223372036854775807 = %d, wanted 1\n", got) + if got := rsh_1_uint64_ssa(18446744073709551615); got != 0 { + fmt.Printf("rsh_uint64 1>>18446744073709551615 = %d, wanted 0\n", got) failed = true } - if got := div_int64_9223372036854775807_ssa(9223372036854775807); got != 1 { - fmt.Printf("div_int64 9223372036854775807/9223372036854775807 = %d, wanted 1\n", got) + if got := rsh_uint64_1_ssa(18446744073709551615); got != 9223372036854775807 { + fmt.Printf("rsh_uint64 18446744073709551615>>1 = %d, wanted 9223372036854775807\n", got) failed = true } - if got := div_0_uint32_ssa(1); got != 0 { - fmt.Printf("div_uint32 0/1 = %d, wanted 0\n", got) + if got := rsh_4294967296_uint64_ssa(0); got != 4294967296 { + fmt.Printf("rsh_uint64 4294967296>>0 = %d, wanted 4294967296\n", got) failed = true } - if got := div_0_uint32_ssa(4294967295); got != 0 { - fmt.Printf("div_uint32 0/4294967295 = %d, wanted 0\n", got) + if got := rsh_uint64_4294967296_ssa(0); got != 0 { + fmt.Printf("rsh_uint64 0>>4294967296 = %d, wanted 0\n", got) failed = true } - if got := div_uint32_1_ssa(0); got != 0 { - fmt.Printf("div_uint32 0/1 = %d, wanted 0\n", got) + if got := rsh_4294967296_uint64_ssa(1); got != 2147483648 { + fmt.Printf("rsh_uint64 4294967296>>1 = %d, wanted 2147483648\n", got) failed = true } - if got := div_1_uint32_ssa(1); got != 1 { - fmt.Printf("div_uint32 1/1 = %d, wanted 1\n", got) + if got := rsh_uint64_4294967296_ssa(1); got != 0 { + fmt.Printf("rsh_uint64 1>>4294967296 = %d, wanted 0\n", got) failed = true } - if got := div_uint32_1_ssa(1); got != 1 { - fmt.Printf("div_uint32 1/1 = %d, wanted 1\n", got) + if got := rsh_4294967296_uint64_ssa(4294967296); got != 0 { + fmt.Printf("rsh_uint64 4294967296>>4294967296 = %d, wanted 0\n", got) failed = true } - if got := div_1_uint32_ssa(4294967295); got != 0 { - fmt.Printf("div_uint32 1/4294967295 = %d, wanted 0\n", got) + if got := rsh_uint64_4294967296_ssa(4294967296); got != 0 { + fmt.Printf("rsh_uint64 4294967296>>4294967296 = %d, wanted 0\n", got) failed = true } - if got := div_uint32_1_ssa(4294967295); got != 4294967295 { - fmt.Printf("div_uint32 4294967295/1 = %d, wanted 4294967295\n", got) + if got := rsh_4294967296_uint64_ssa(18446744073709551615); got != 0 { + fmt.Printf("rsh_uint64 4294967296>>18446744073709551615 = %d, wanted 0\n", got) failed = true } - if got := div_uint32_4294967295_ssa(0); got != 0 { - fmt.Printf("div_uint32 0/4294967295 = %d, wanted 0\n", got) + if got := rsh_uint64_4294967296_ssa(18446744073709551615); got != 0 { + fmt.Printf("rsh_uint64 18446744073709551615>>4294967296 = %d, wanted 0\n", got) failed = true } - if got := div_4294967295_uint32_ssa(1); got != 4294967295 { - fmt.Printf("div_uint32 4294967295/1 = %d, wanted 4294967295\n", got) + if got := rsh_18446744073709551615_uint64_ssa(0); got != 18446744073709551615 { + fmt.Printf("rsh_uint64 18446744073709551615>>0 = %d, wanted 18446744073709551615\n", got) failed = true } - if got := div_uint32_4294967295_ssa(1); got != 0 { - fmt.Printf("div_uint32 1/4294967295 = %d, wanted 0\n", got) + if got := rsh_uint64_18446744073709551615_ssa(0); got != 0 { + fmt.Printf("rsh_uint64 0>>18446744073709551615 = %d, wanted 0\n", got) failed = true } - if got := div_4294967295_uint32_ssa(4294967295); got != 1 { - fmt.Printf("div_uint32 4294967295/4294967295 = %d, wanted 1\n", got) + if got := rsh_18446744073709551615_uint64_ssa(1); got != 9223372036854775807 { + fmt.Printf("rsh_uint64 18446744073709551615>>1 = %d, wanted 9223372036854775807\n", got) failed = true } - if got := div_uint32_4294967295_ssa(4294967295); got != 1 { - fmt.Printf("div_uint32 4294967295/4294967295 = %d, wanted 1\n", got) + if got := rsh_uint64_18446744073709551615_ssa(1); got != 0 { + fmt.Printf("rsh_uint64 1>>18446744073709551615 = %d, wanted 0\n", got) failed = true } - if got := div_Neg2147483648_int32_ssa(-2147483648); got != 1 { - fmt.Printf("div_int32 -2147483648/-2147483648 = %d, wanted 1\n", got) + if got := rsh_18446744073709551615_uint64_ssa(4294967296); got != 0 { + fmt.Printf("rsh_uint64 18446744073709551615>>4294967296 = %d, wanted 0\n", got) failed = true } - if got := div_int32_Neg2147483648_ssa(-2147483648); got != 1 { - fmt.Printf("div_int32 -2147483648/-2147483648 = %d, wanted 1\n", got) + if got := rsh_uint64_18446744073709551615_ssa(4294967296); got != 0 { + fmt.Printf("rsh_uint64 4294967296>>18446744073709551615 = %d, wanted 0\n", got) failed = true } - if got := div_Neg2147483648_int32_ssa(-2147483647); got != 1 { - fmt.Printf("div_int32 -2147483648/-2147483647 = %d, wanted 1\n", got) + if got := rsh_18446744073709551615_uint64_ssa(18446744073709551615); got != 0 { + fmt.Printf("rsh_uint64 18446744073709551615>>18446744073709551615 = %d, wanted 0\n", got) failed = true } - if got := div_int32_Neg2147483648_ssa(-2147483647); got != 0 { - fmt.Printf("div_int32 -2147483647/-2147483648 = %d, wanted 0\n", got) + if got := rsh_uint64_18446744073709551615_ssa(18446744073709551615); got != 0 { + fmt.Printf("rsh_uint64 18446744073709551615>>18446744073709551615 = %d, wanted 0\n", got) failed = true } - if got := div_Neg2147483648_int32_ssa(-1); got != -2147483648 { - fmt.Printf("div_int32 -2147483648/-1 = %d, wanted -2147483648\n", got) + if got := add_Neg9223372036854775808_int64_ssa(-9223372036854775808); got != 0 { + fmt.Printf("add_int64 -9223372036854775808+-9223372036854775808 = %d, wanted 0\n", got) failed = true } - if got := div_int32_Neg2147483648_ssa(-1); got != 0 { - fmt.Printf("div_int32 -1/-2147483648 = %d, wanted 0\n", got) + if got := add_int64_Neg9223372036854775808_ssa(-9223372036854775808); got != 0 { + fmt.Printf("add_int64 -9223372036854775808+-9223372036854775808 = %d, wanted 0\n", got) failed = true } - if got := div_int32_Neg2147483648_ssa(0); got != 0 { - fmt.Printf("div_int32 0/-2147483648 = %d, wanted 0\n", got) + if got := add_Neg9223372036854775808_int64_ssa(-9223372036854775807); got != 1 { + fmt.Printf("add_int64 -9223372036854775808+-9223372036854775807 = %d, wanted 1\n", got) failed = true } - if got := div_Neg2147483648_int32_ssa(1); got != -2147483648 { - fmt.Printf("div_int32 -2147483648/1 = %d, wanted -2147483648\n", got) + if got := add_int64_Neg9223372036854775808_ssa(-9223372036854775807); got != 1 { + fmt.Printf("add_int64 -9223372036854775807+-9223372036854775808 = %d, wanted 1\n", got) failed = true } - if got := div_int32_Neg2147483648_ssa(1); got != 0 { - fmt.Printf("div_int32 1/-2147483648 = %d, wanted 0\n", got) + if got := add_Neg9223372036854775808_int64_ssa(-4294967296); got != 9223372032559808512 { + fmt.Printf("add_int64 -9223372036854775808+-4294967296 = %d, wanted 9223372032559808512\n", got) failed = true } - if got := div_Neg2147483648_int32_ssa(2147483647); got != -1 { - fmt.Printf("div_int32 -2147483648/2147483647 = %d, wanted -1\n", got) + if got := add_int64_Neg9223372036854775808_ssa(-4294967296); got != 9223372032559808512 { + fmt.Printf("add_int64 -4294967296+-9223372036854775808 = %d, wanted 9223372032559808512\n", got) failed = true } - if got := div_int32_Neg2147483648_ssa(2147483647); got != 0 { - fmt.Printf("div_int32 2147483647/-2147483648 = %d, wanted 0\n", got) + if got := add_Neg9223372036854775808_int64_ssa(-1); got != 9223372036854775807 { + fmt.Printf("add_int64 -9223372036854775808+-1 = %d, wanted 9223372036854775807\n", got) failed = true } - if got := div_Neg2147483647_int32_ssa(-2147483648); got != 0 { - fmt.Printf("div_int32 -2147483647/-2147483648 = %d, wanted 0\n", got) + if got := add_int64_Neg9223372036854775808_ssa(-1); got != 9223372036854775807 { + fmt.Printf("add_int64 -1+-9223372036854775808 = %d, wanted 9223372036854775807\n", got) failed = true } - if got := div_int32_Neg2147483647_ssa(-2147483648); got != 1 { - fmt.Printf("div_int32 -2147483648/-2147483647 = %d, wanted 1\n", got) + if got := add_Neg9223372036854775808_int64_ssa(0); got != -9223372036854775808 { + fmt.Printf("add_int64 -9223372036854775808+0 = %d, wanted -9223372036854775808\n", got) failed = true } - if got := div_Neg2147483647_int32_ssa(-2147483647); got != 1 { - fmt.Printf("div_int32 -2147483647/-2147483647 = %d, wanted 1\n", got) + if got := add_int64_Neg9223372036854775808_ssa(0); got != -9223372036854775808 { + fmt.Printf("add_int64 0+-9223372036854775808 = %d, wanted -9223372036854775808\n", got) failed = true } - if got := div_int32_Neg2147483647_ssa(-2147483647); got != 1 { - fmt.Printf("div_int32 -2147483647/-2147483647 = %d, wanted 1\n", got) + if got := add_Neg9223372036854775808_int64_ssa(1); got != -9223372036854775807 { + fmt.Printf("add_int64 -9223372036854775808+1 = %d, wanted -9223372036854775807\n", got) failed = true } - if got := div_Neg2147483647_int32_ssa(-1); got != 2147483647 { - fmt.Printf("div_int32 -2147483647/-1 = %d, wanted 2147483647\n", got) + if got := add_int64_Neg9223372036854775808_ssa(1); got != -9223372036854775807 { + fmt.Printf("add_int64 1+-9223372036854775808 = %d, wanted -9223372036854775807\n", got) failed = true } - if got := div_int32_Neg2147483647_ssa(-1); got != 0 { - fmt.Printf("div_int32 -1/-2147483647 = %d, wanted 0\n", got) + if got := add_Neg9223372036854775808_int64_ssa(4294967296); got != -9223372032559808512 { + fmt.Printf("add_int64 -9223372036854775808+4294967296 = %d, wanted -9223372032559808512\n", got) failed = true } - if got := div_int32_Neg2147483647_ssa(0); got != 0 { - fmt.Printf("div_int32 0/-2147483647 = %d, wanted 0\n", got) + if got := add_int64_Neg9223372036854775808_ssa(4294967296); got != -9223372032559808512 { + fmt.Printf("add_int64 4294967296+-9223372036854775808 = %d, wanted -9223372032559808512\n", got) failed = true } - if got := div_Neg2147483647_int32_ssa(1); got != -2147483647 { - fmt.Printf("div_int32 -2147483647/1 = %d, wanted -2147483647\n", got) + if got := add_Neg9223372036854775808_int64_ssa(9223372036854775806); got != -2 { + fmt.Printf("add_int64 -9223372036854775808+9223372036854775806 = %d, wanted -2\n", got) failed = true } - if got := div_int32_Neg2147483647_ssa(1); got != 0 { - fmt.Printf("div_int32 1/-2147483647 = %d, wanted 0\n", got) + if got := add_int64_Neg9223372036854775808_ssa(9223372036854775806); got != -2 { + fmt.Printf("add_int64 9223372036854775806+-9223372036854775808 = %d, wanted -2\n", got) failed = true } - if got := div_Neg2147483647_int32_ssa(2147483647); got != -1 { - fmt.Printf("div_int32 -2147483647/2147483647 = %d, wanted -1\n", got) + if got := add_Neg9223372036854775808_int64_ssa(9223372036854775807); got != -1 { + fmt.Printf("add_int64 -9223372036854775808+9223372036854775807 = %d, wanted -1\n", got) failed = true } - if got := div_int32_Neg2147483647_ssa(2147483647); got != -1 { - fmt.Printf("div_int32 2147483647/-2147483647 = %d, wanted -1\n", got) + if got := add_int64_Neg9223372036854775808_ssa(9223372036854775807); got != -1 { + fmt.Printf("add_int64 9223372036854775807+-9223372036854775808 = %d, wanted -1\n", got) failed = true } - if got := div_Neg1_int32_ssa(-2147483648); got != 0 { - fmt.Printf("div_int32 -1/-2147483648 = %d, wanted 0\n", got) + if got := add_Neg9223372036854775807_int64_ssa(-9223372036854775808); got != 1 { + fmt.Printf("add_int64 -9223372036854775807+-9223372036854775808 = %d, wanted 1\n", got) failed = true } - if got := div_int32_Neg1_ssa(-2147483648); got != -2147483648 { - fmt.Printf("div_int32 -2147483648/-1 = %d, wanted -2147483648\n", got) + if got := add_int64_Neg9223372036854775807_ssa(-9223372036854775808); got != 1 { + fmt.Printf("add_int64 -9223372036854775808+-9223372036854775807 = %d, wanted 1\n", got) failed = true } - if got := div_Neg1_int32_ssa(-2147483647); got != 0 { - fmt.Printf("div_int32 -1/-2147483647 = %d, wanted 0\n", got) + if got := add_Neg9223372036854775807_int64_ssa(-9223372036854775807); got != 2 { + fmt.Printf("add_int64 -9223372036854775807+-9223372036854775807 = %d, wanted 2\n", got) failed = true } - if got := div_int32_Neg1_ssa(-2147483647); got != 2147483647 { - fmt.Printf("div_int32 -2147483647/-1 = %d, wanted 2147483647\n", got) + if got := add_int64_Neg9223372036854775807_ssa(-9223372036854775807); got != 2 { + fmt.Printf("add_int64 -9223372036854775807+-9223372036854775807 = %d, wanted 2\n", got) failed = true } - if got := div_Neg1_int32_ssa(-1); got != 1 { - fmt.Printf("div_int32 -1/-1 = %d, wanted 1\n", got) + if got := add_Neg9223372036854775807_int64_ssa(-4294967296); got != 9223372032559808513 { + fmt.Printf("add_int64 -9223372036854775807+-4294967296 = %d, wanted 9223372032559808513\n", got) failed = true } - if got := div_int32_Neg1_ssa(-1); got != 1 { - fmt.Printf("div_int32 -1/-1 = %d, wanted 1\n", got) + if got := add_int64_Neg9223372036854775807_ssa(-4294967296); got != 9223372032559808513 { + fmt.Printf("add_int64 -4294967296+-9223372036854775807 = %d, wanted 9223372032559808513\n", got) failed = true } - if got := div_int32_Neg1_ssa(0); got != 0 { - fmt.Printf("div_int32 0/-1 = %d, wanted 0\n", got) + if got := add_Neg9223372036854775807_int64_ssa(-1); got != -9223372036854775808 { + fmt.Printf("add_int64 -9223372036854775807+-1 = %d, wanted -9223372036854775808\n", got) failed = true } - if got := div_Neg1_int32_ssa(1); got != -1 { - fmt.Printf("div_int32 -1/1 = %d, wanted -1\n", got) + if got := add_int64_Neg9223372036854775807_ssa(-1); got != -9223372036854775808 { + fmt.Printf("add_int64 -1+-9223372036854775807 = %d, wanted -9223372036854775808\n", got) failed = true } - if got := div_int32_Neg1_ssa(1); got != -1 { - fmt.Printf("div_int32 1/-1 = %d, wanted -1\n", got) + if got := add_Neg9223372036854775807_int64_ssa(0); got != -9223372036854775807 { + fmt.Printf("add_int64 -9223372036854775807+0 = %d, wanted -9223372036854775807\n", got) failed = true } - if got := div_Neg1_int32_ssa(2147483647); got != 0 { - fmt.Printf("div_int32 -1/2147483647 = %d, wanted 0\n", got) + if got := add_int64_Neg9223372036854775807_ssa(0); got != -9223372036854775807 { + fmt.Printf("add_int64 0+-9223372036854775807 = %d, wanted -9223372036854775807\n", got) failed = true } - if got := div_int32_Neg1_ssa(2147483647); got != -2147483647 { - fmt.Printf("div_int32 2147483647/-1 = %d, wanted -2147483647\n", got) + if got := add_Neg9223372036854775807_int64_ssa(1); got != -9223372036854775806 { + fmt.Printf("add_int64 -9223372036854775807+1 = %d, wanted -9223372036854775806\n", got) failed = true } - if got := div_0_int32_ssa(-2147483648); got != 0 { - fmt.Printf("div_int32 0/-2147483648 = %d, wanted 0\n", got) + if got := add_int64_Neg9223372036854775807_ssa(1); got != -9223372036854775806 { + fmt.Printf("add_int64 1+-9223372036854775807 = %d, wanted -9223372036854775806\n", got) failed = true } - if got := div_0_int32_ssa(-2147483647); got != 0 { - fmt.Printf("div_int32 0/-2147483647 = %d, wanted 0\n", got) + if got := add_Neg9223372036854775807_int64_ssa(4294967296); got != -9223372032559808511 { + fmt.Printf("add_int64 -9223372036854775807+4294967296 = %d, wanted -9223372032559808511\n", got) failed = true } - if got := div_0_int32_ssa(-1); got != 0 { - fmt.Printf("div_int32 0/-1 = %d, wanted 0\n", got) + if got := add_int64_Neg9223372036854775807_ssa(4294967296); got != -9223372032559808511 { + fmt.Printf("add_int64 4294967296+-9223372036854775807 = %d, wanted -9223372032559808511\n", got) failed = true } - if got := div_0_int32_ssa(1); got != 0 { - fmt.Printf("div_int32 0/1 = %d, wanted 0\n", got) + if got := add_Neg9223372036854775807_int64_ssa(9223372036854775806); got != -1 { + fmt.Printf("add_int64 -9223372036854775807+9223372036854775806 = %d, wanted -1\n", got) failed = true } - if got := div_0_int32_ssa(2147483647); got != 0 { - fmt.Printf("div_int32 0/2147483647 = %d, wanted 0\n", got) + if got := add_int64_Neg9223372036854775807_ssa(9223372036854775806); got != -1 { + fmt.Printf("add_int64 9223372036854775806+-9223372036854775807 = %d, wanted -1\n", got) failed = true } - if got := div_1_int32_ssa(-2147483648); got != 0 { - fmt.Printf("div_int32 1/-2147483648 = %d, wanted 0\n", got) + if got := add_Neg9223372036854775807_int64_ssa(9223372036854775807); got != 0 { + fmt.Printf("add_int64 -9223372036854775807+9223372036854775807 = %d, wanted 0\n", got) failed = true } - if got := div_int32_1_ssa(-2147483648); got != -2147483648 { - fmt.Printf("div_int32 -2147483648/1 = %d, wanted -2147483648\n", got) + if got := add_int64_Neg9223372036854775807_ssa(9223372036854775807); got != 0 { + fmt.Printf("add_int64 9223372036854775807+-9223372036854775807 = %d, wanted 0\n", got) failed = true } - if got := div_1_int32_ssa(-2147483647); got != 0 { - fmt.Printf("div_int32 1/-2147483647 = %d, wanted 0\n", got) + if got := add_Neg4294967296_int64_ssa(-9223372036854775808); got != 9223372032559808512 { + fmt.Printf("add_int64 -4294967296+-9223372036854775808 = %d, wanted 9223372032559808512\n", got) failed = true } - if got := div_int32_1_ssa(-2147483647); got != -2147483647 { - fmt.Printf("div_int32 -2147483647/1 = %d, wanted -2147483647\n", got) + if got := add_int64_Neg4294967296_ssa(-9223372036854775808); got != 9223372032559808512 { + fmt.Printf("add_int64 -9223372036854775808+-4294967296 = %d, wanted 9223372032559808512\n", got) failed = true } - if got := div_1_int32_ssa(-1); got != -1 { - fmt.Printf("div_int32 1/-1 = %d, wanted -1\n", got) + if got := add_Neg4294967296_int64_ssa(-9223372036854775807); got != 9223372032559808513 { + fmt.Printf("add_int64 -4294967296+-9223372036854775807 = %d, wanted 9223372032559808513\n", got) failed = true } - if got := div_int32_1_ssa(-1); got != -1 { - fmt.Printf("div_int32 -1/1 = %d, wanted -1\n", got) + if got := add_int64_Neg4294967296_ssa(-9223372036854775807); got != 9223372032559808513 { + fmt.Printf("add_int64 -9223372036854775807+-4294967296 = %d, wanted 9223372032559808513\n", got) failed = true } - if got := div_int32_1_ssa(0); got != 0 { - fmt.Printf("div_int32 0/1 = %d, wanted 0\n", got) + if got := add_Neg4294967296_int64_ssa(-4294967296); got != -8589934592 { + fmt.Printf("add_int64 -4294967296+-4294967296 = %d, wanted -8589934592\n", got) failed = true } - if got := div_1_int32_ssa(1); got != 1 { - fmt.Printf("div_int32 1/1 = %d, wanted 1\n", got) + if got := add_int64_Neg4294967296_ssa(-4294967296); got != -8589934592 { + fmt.Printf("add_int64 -4294967296+-4294967296 = %d, wanted -8589934592\n", got) failed = true } - if got := div_int32_1_ssa(1); got != 1 { - fmt.Printf("div_int32 1/1 = %d, wanted 1\n", got) + if got := add_Neg4294967296_int64_ssa(-1); got != -4294967297 { + fmt.Printf("add_int64 -4294967296+-1 = %d, wanted -4294967297\n", got) failed = true } - if got := div_1_int32_ssa(2147483647); got != 0 { - fmt.Printf("div_int32 1/2147483647 = %d, wanted 0\n", got) + if got := add_int64_Neg4294967296_ssa(-1); got != -4294967297 { + fmt.Printf("add_int64 -1+-4294967296 = %d, wanted -4294967297\n", got) failed = true } - if got := div_int32_1_ssa(2147483647); got != 2147483647 { - fmt.Printf("div_int32 2147483647/1 = %d, wanted 2147483647\n", got) + if got := add_Neg4294967296_int64_ssa(0); got != -4294967296 { + fmt.Printf("add_int64 -4294967296+0 = %d, wanted -4294967296\n", got) failed = true } - if got := div_2147483647_int32_ssa(-2147483648); got != 0 { - fmt.Printf("div_int32 2147483647/-2147483648 = %d, wanted 0\n", got) + if got := add_int64_Neg4294967296_ssa(0); got != -4294967296 { + fmt.Printf("add_int64 0+-4294967296 = %d, wanted -4294967296\n", got) failed = true } - if got := div_int32_2147483647_ssa(-2147483648); got != -1 { - fmt.Printf("div_int32 -2147483648/2147483647 = %d, wanted -1\n", got) + if got := add_Neg4294967296_int64_ssa(1); got != -4294967295 { + fmt.Printf("add_int64 -4294967296+1 = %d, wanted -4294967295\n", got) failed = true } - if got := div_2147483647_int32_ssa(-2147483647); got != -1 { - fmt.Printf("div_int32 2147483647/-2147483647 = %d, wanted -1\n", got) + if got := add_int64_Neg4294967296_ssa(1); got != -4294967295 { + fmt.Printf("add_int64 1+-4294967296 = %d, wanted -4294967295\n", got) failed = true } - if got := div_int32_2147483647_ssa(-2147483647); got != -1 { - fmt.Printf("div_int32 -2147483647/2147483647 = %d, wanted -1\n", got) + if got := add_Neg4294967296_int64_ssa(4294967296); got != 0 { + fmt.Printf("add_int64 -4294967296+4294967296 = %d, wanted 0\n", got) failed = true } - if got := div_2147483647_int32_ssa(-1); got != -2147483647 { - fmt.Printf("div_int32 2147483647/-1 = %d, wanted -2147483647\n", got) + if got := add_int64_Neg4294967296_ssa(4294967296); got != 0 { + fmt.Printf("add_int64 4294967296+-4294967296 = %d, wanted 0\n", got) failed = true } - if got := div_int32_2147483647_ssa(-1); got != 0 { - fmt.Printf("div_int32 -1/2147483647 = %d, wanted 0\n", got) + if got := add_Neg4294967296_int64_ssa(9223372036854775806); got != 9223372032559808510 { + fmt.Printf("add_int64 -4294967296+9223372036854775806 = %d, wanted 9223372032559808510\n", got) failed = true } - if got := div_int32_2147483647_ssa(0); got != 0 { - fmt.Printf("div_int32 0/2147483647 = %d, wanted 0\n", got) + if got := add_int64_Neg4294967296_ssa(9223372036854775806); got != 9223372032559808510 { + fmt.Printf("add_int64 9223372036854775806+-4294967296 = %d, wanted 9223372032559808510\n", got) failed = true } - if got := div_2147483647_int32_ssa(1); got != 2147483647 { - fmt.Printf("div_int32 2147483647/1 = %d, wanted 2147483647\n", got) + if got := add_Neg4294967296_int64_ssa(9223372036854775807); got != 9223372032559808511 { + fmt.Printf("add_int64 -4294967296+9223372036854775807 = %d, wanted 9223372032559808511\n", got) failed = true } - if got := div_int32_2147483647_ssa(1); got != 0 { - fmt.Printf("div_int32 1/2147483647 = %d, wanted 0\n", got) + if got := add_int64_Neg4294967296_ssa(9223372036854775807); got != 9223372032559808511 { + fmt.Printf("add_int64 9223372036854775807+-4294967296 = %d, wanted 9223372032559808511\n", got) failed = true } - if got := div_2147483647_int32_ssa(2147483647); got != 1 { - fmt.Printf("div_int32 2147483647/2147483647 = %d, wanted 1\n", got) + if got := add_Neg1_int64_ssa(-9223372036854775808); got != 9223372036854775807 { + fmt.Printf("add_int64 -1+-9223372036854775808 = %d, wanted 9223372036854775807\n", got) failed = true } - if got := div_int32_2147483647_ssa(2147483647); got != 1 { - fmt.Printf("div_int32 2147483647/2147483647 = %d, wanted 1\n", got) + if got := add_int64_Neg1_ssa(-9223372036854775808); got != 9223372036854775807 { + fmt.Printf("add_int64 -9223372036854775808+-1 = %d, wanted 9223372036854775807\n", got) failed = true } - if got := div_0_uint16_ssa(1); got != 0 { - fmt.Printf("div_uint16 0/1 = %d, wanted 0\n", got) + if got := add_Neg1_int64_ssa(-9223372036854775807); got != -9223372036854775808 { + fmt.Printf("add_int64 -1+-9223372036854775807 = %d, wanted -9223372036854775808\n", got) failed = true } - if got := div_0_uint16_ssa(65535); got != 0 { - fmt.Printf("div_uint16 0/65535 = %d, wanted 0\n", got) + if got := add_int64_Neg1_ssa(-9223372036854775807); got != -9223372036854775808 { + fmt.Printf("add_int64 -9223372036854775807+-1 = %d, wanted -9223372036854775808\n", got) failed = true } - if got := div_uint16_1_ssa(0); got != 0 { - fmt.Printf("div_uint16 0/1 = %d, wanted 0\n", got) + if got := add_Neg1_int64_ssa(-4294967296); got != -4294967297 { + fmt.Printf("add_int64 -1+-4294967296 = %d, wanted -4294967297\n", got) failed = true } - if got := div_1_uint16_ssa(1); got != 1 { - fmt.Printf("div_uint16 1/1 = %d, wanted 1\n", got) + if got := add_int64_Neg1_ssa(-4294967296); got != -4294967297 { + fmt.Printf("add_int64 -4294967296+-1 = %d, wanted -4294967297\n", got) failed = true } - if got := div_uint16_1_ssa(1); got != 1 { - fmt.Printf("div_uint16 1/1 = %d, wanted 1\n", got) + if got := add_Neg1_int64_ssa(-1); got != -2 { + fmt.Printf("add_int64 -1+-1 = %d, wanted -2\n", got) failed = true } - if got := div_1_uint16_ssa(65535); got != 0 { - fmt.Printf("div_uint16 1/65535 = %d, wanted 0\n", got) + if got := add_int64_Neg1_ssa(-1); got != -2 { + fmt.Printf("add_int64 -1+-1 = %d, wanted -2\n", got) failed = true } - if got := div_uint16_1_ssa(65535); got != 65535 { - fmt.Printf("div_uint16 65535/1 = %d, wanted 65535\n", got) + if got := add_Neg1_int64_ssa(0); got != -1 { + fmt.Printf("add_int64 -1+0 = %d, wanted -1\n", got) failed = true } - if got := div_uint16_65535_ssa(0); got != 0 { - fmt.Printf("div_uint16 0/65535 = %d, wanted 0\n", got) + if got := add_int64_Neg1_ssa(0); got != -1 { + fmt.Printf("add_int64 0+-1 = %d, wanted -1\n", got) failed = true } - if got := div_65535_uint16_ssa(1); got != 65535 { - fmt.Printf("div_uint16 65535/1 = %d, wanted 65535\n", got) + if got := add_Neg1_int64_ssa(1); got != 0 { + fmt.Printf("add_int64 -1+1 = %d, wanted 0\n", got) failed = true } - if got := div_uint16_65535_ssa(1); got != 0 { - fmt.Printf("div_uint16 1/65535 = %d, wanted 0\n", got) + if got := add_int64_Neg1_ssa(1); got != 0 { + fmt.Printf("add_int64 1+-1 = %d, wanted 0\n", got) failed = true } - if got := div_65535_uint16_ssa(65535); got != 1 { - fmt.Printf("div_uint16 65535/65535 = %d, wanted 1\n", got) + if got := add_Neg1_int64_ssa(4294967296); got != 4294967295 { + fmt.Printf("add_int64 -1+4294967296 = %d, wanted 4294967295\n", got) failed = true } - if got := div_uint16_65535_ssa(65535); got != 1 { - fmt.Printf("div_uint16 65535/65535 = %d, wanted 1\n", got) + if got := add_int64_Neg1_ssa(4294967296); got != 4294967295 { + fmt.Printf("add_int64 4294967296+-1 = %d, wanted 4294967295\n", got) failed = true } - if got := div_Neg32768_int16_ssa(-32768); got != 1 { - fmt.Printf("div_int16 -32768/-32768 = %d, wanted 1\n", got) + if got := add_Neg1_int64_ssa(9223372036854775806); got != 9223372036854775805 { + fmt.Printf("add_int64 -1+9223372036854775806 = %d, wanted 9223372036854775805\n", got) failed = true } - if got := div_int16_Neg32768_ssa(-32768); got != 1 { - fmt.Printf("div_int16 -32768/-32768 = %d, wanted 1\n", got) + if got := add_int64_Neg1_ssa(9223372036854775806); got != 9223372036854775805 { + fmt.Printf("add_int64 9223372036854775806+-1 = %d, wanted 9223372036854775805\n", got) failed = true } - if got := div_Neg32768_int16_ssa(-32767); got != 1 { - fmt.Printf("div_int16 -32768/-32767 = %d, wanted 1\n", got) + if got := add_Neg1_int64_ssa(9223372036854775807); got != 9223372036854775806 { + fmt.Printf("add_int64 -1+9223372036854775807 = %d, wanted 9223372036854775806\n", got) failed = true } - if got := div_int16_Neg32768_ssa(-32767); got != 0 { - fmt.Printf("div_int16 -32767/-32768 = %d, wanted 0\n", got) + if got := add_int64_Neg1_ssa(9223372036854775807); got != 9223372036854775806 { + fmt.Printf("add_int64 9223372036854775807+-1 = %d, wanted 9223372036854775806\n", got) failed = true } - if got := div_Neg32768_int16_ssa(-1); got != -32768 { - fmt.Printf("div_int16 -32768/-1 = %d, wanted -32768\n", got) + if got := add_0_int64_ssa(-9223372036854775808); got != -9223372036854775808 { + fmt.Printf("add_int64 0+-9223372036854775808 = %d, wanted -9223372036854775808\n", got) failed = true } - if got := div_int16_Neg32768_ssa(-1); got != 0 { - fmt.Printf("div_int16 -1/-32768 = %d, wanted 0\n", got) + if got := add_int64_0_ssa(-9223372036854775808); got != -9223372036854775808 { + fmt.Printf("add_int64 -9223372036854775808+0 = %d, wanted -9223372036854775808\n", got) failed = true } - if got := div_int16_Neg32768_ssa(0); got != 0 { - fmt.Printf("div_int16 0/-32768 = %d, wanted 0\n", got) + if got := add_0_int64_ssa(-9223372036854775807); got != -9223372036854775807 { + fmt.Printf("add_int64 0+-9223372036854775807 = %d, wanted -9223372036854775807\n", got) failed = true } - if got := div_Neg32768_int16_ssa(1); got != -32768 { - fmt.Printf("div_int16 -32768/1 = %d, wanted -32768\n", got) + if got := add_int64_0_ssa(-9223372036854775807); got != -9223372036854775807 { + fmt.Printf("add_int64 -9223372036854775807+0 = %d, wanted -9223372036854775807\n", got) failed = true } - if got := div_int16_Neg32768_ssa(1); got != 0 { - fmt.Printf("div_int16 1/-32768 = %d, wanted 0\n", got) + if got := add_0_int64_ssa(-4294967296); got != -4294967296 { + fmt.Printf("add_int64 0+-4294967296 = %d, wanted -4294967296\n", got) failed = true } - if got := div_Neg32768_int16_ssa(32766); got != -1 { - fmt.Printf("div_int16 -32768/32766 = %d, wanted -1\n", got) + if got := add_int64_0_ssa(-4294967296); got != -4294967296 { + fmt.Printf("add_int64 -4294967296+0 = %d, wanted -4294967296\n", got) failed = true } - if got := div_int16_Neg32768_ssa(32766); got != 0 { - fmt.Printf("div_int16 32766/-32768 = %d, wanted 0\n", got) + if got := add_0_int64_ssa(-1); got != -1 { + fmt.Printf("add_int64 0+-1 = %d, wanted -1\n", got) failed = true } - if got := div_Neg32768_int16_ssa(32767); got != -1 { - fmt.Printf("div_int16 -32768/32767 = %d, wanted -1\n", got) + if got := add_int64_0_ssa(-1); got != -1 { + fmt.Printf("add_int64 -1+0 = %d, wanted -1\n", got) failed = true } - if got := div_int16_Neg32768_ssa(32767); got != 0 { - fmt.Printf("div_int16 32767/-32768 = %d, wanted 0\n", got) + if got := add_0_int64_ssa(0); got != 0 { + fmt.Printf("add_int64 0+0 = %d, wanted 0\n", got) failed = true } - if got := div_Neg32767_int16_ssa(-32768); got != 0 { - fmt.Printf("div_int16 -32767/-32768 = %d, wanted 0\n", got) + if got := add_int64_0_ssa(0); got != 0 { + fmt.Printf("add_int64 0+0 = %d, wanted 0\n", got) failed = true } - if got := div_int16_Neg32767_ssa(-32768); got != 1 { - fmt.Printf("div_int16 -32768/-32767 = %d, wanted 1\n", got) + if got := add_0_int64_ssa(1); got != 1 { + fmt.Printf("add_int64 0+1 = %d, wanted 1\n", got) failed = true } - if got := div_Neg32767_int16_ssa(-32767); got != 1 { - fmt.Printf("div_int16 -32767/-32767 = %d, wanted 1\n", got) + if got := add_int64_0_ssa(1); got != 1 { + fmt.Printf("add_int64 1+0 = %d, wanted 1\n", got) failed = true } - if got := div_int16_Neg32767_ssa(-32767); got != 1 { - fmt.Printf("div_int16 -32767/-32767 = %d, wanted 1\n", got) + if got := add_0_int64_ssa(4294967296); got != 4294967296 { + fmt.Printf("add_int64 0+4294967296 = %d, wanted 4294967296\n", got) failed = true } - if got := div_Neg32767_int16_ssa(-1); got != 32767 { - fmt.Printf("div_int16 -32767/-1 = %d, wanted 32767\n", got) + if got := add_int64_0_ssa(4294967296); got != 4294967296 { + fmt.Printf("add_int64 4294967296+0 = %d, wanted 4294967296\n", got) failed = true } - if got := div_int16_Neg32767_ssa(-1); got != 0 { - fmt.Printf("div_int16 -1/-32767 = %d, wanted 0\n", got) + if got := add_0_int64_ssa(9223372036854775806); got != 9223372036854775806 { + fmt.Printf("add_int64 0+9223372036854775806 = %d, wanted 9223372036854775806\n", got) failed = true } - if got := div_int16_Neg32767_ssa(0); got != 0 { - fmt.Printf("div_int16 0/-32767 = %d, wanted 0\n", got) + if got := add_int64_0_ssa(9223372036854775806); got != 9223372036854775806 { + fmt.Printf("add_int64 9223372036854775806+0 = %d, wanted 9223372036854775806\n", got) failed = true } - if got := div_Neg32767_int16_ssa(1); got != -32767 { - fmt.Printf("div_int16 -32767/1 = %d, wanted -32767\n", got) + if got := add_0_int64_ssa(9223372036854775807); got != 9223372036854775807 { + fmt.Printf("add_int64 0+9223372036854775807 = %d, wanted 9223372036854775807\n", got) failed = true } - if got := div_int16_Neg32767_ssa(1); got != 0 { - fmt.Printf("div_int16 1/-32767 = %d, wanted 0\n", got) + if got := add_int64_0_ssa(9223372036854775807); got != 9223372036854775807 { + fmt.Printf("add_int64 9223372036854775807+0 = %d, wanted 9223372036854775807\n", got) failed = true } - if got := div_Neg32767_int16_ssa(32766); got != -1 { - fmt.Printf("div_int16 -32767/32766 = %d, wanted -1\n", got) + if got := add_1_int64_ssa(-9223372036854775808); got != -9223372036854775807 { + fmt.Printf("add_int64 1+-9223372036854775808 = %d, wanted -9223372036854775807\n", got) failed = true } - if got := div_int16_Neg32767_ssa(32766); got != 0 { - fmt.Printf("div_int16 32766/-32767 = %d, wanted 0\n", got) + if got := add_int64_1_ssa(-9223372036854775808); got != -9223372036854775807 { + fmt.Printf("add_int64 -9223372036854775808+1 = %d, wanted -9223372036854775807\n", got) failed = true } - if got := div_Neg32767_int16_ssa(32767); got != -1 { - fmt.Printf("div_int16 -32767/32767 = %d, wanted -1\n", got) + if got := add_1_int64_ssa(-9223372036854775807); got != -9223372036854775806 { + fmt.Printf("add_int64 1+-9223372036854775807 = %d, wanted -9223372036854775806\n", got) failed = true } - if got := div_int16_Neg32767_ssa(32767); got != -1 { - fmt.Printf("div_int16 32767/-32767 = %d, wanted -1\n", got) + if got := add_int64_1_ssa(-9223372036854775807); got != -9223372036854775806 { + fmt.Printf("add_int64 -9223372036854775807+1 = %d, wanted -9223372036854775806\n", got) failed = true } - if got := div_Neg1_int16_ssa(-32768); got != 0 { - fmt.Printf("div_int16 -1/-32768 = %d, wanted 0\n", got) + if got := add_1_int64_ssa(-4294967296); got != -4294967295 { + fmt.Printf("add_int64 1+-4294967296 = %d, wanted -4294967295\n", got) failed = true } - if got := div_int16_Neg1_ssa(-32768); got != -32768 { - fmt.Printf("div_int16 -32768/-1 = %d, wanted -32768\n", got) + if got := add_int64_1_ssa(-4294967296); got != -4294967295 { + fmt.Printf("add_int64 -4294967296+1 = %d, wanted -4294967295\n", got) failed = true } - if got := div_Neg1_int16_ssa(-32767); got != 0 { - fmt.Printf("div_int16 -1/-32767 = %d, wanted 0\n", got) + if got := add_1_int64_ssa(-1); got != 0 { + fmt.Printf("add_int64 1+-1 = %d, wanted 0\n", got) failed = true } - if got := div_int16_Neg1_ssa(-32767); got != 32767 { - fmt.Printf("div_int16 -32767/-1 = %d, wanted 32767\n", got) + if got := add_int64_1_ssa(-1); got != 0 { + fmt.Printf("add_int64 -1+1 = %d, wanted 0\n", got) failed = true } - if got := div_Neg1_int16_ssa(-1); got != 1 { - fmt.Printf("div_int16 -1/-1 = %d, wanted 1\n", got) + if got := add_1_int64_ssa(0); got != 1 { + fmt.Printf("add_int64 1+0 = %d, wanted 1\n", got) failed = true } - if got := div_int16_Neg1_ssa(-1); got != 1 { - fmt.Printf("div_int16 -1/-1 = %d, wanted 1\n", got) + if got := add_int64_1_ssa(0); got != 1 { + fmt.Printf("add_int64 0+1 = %d, wanted 1\n", got) failed = true } - if got := div_int16_Neg1_ssa(0); got != 0 { - fmt.Printf("div_int16 0/-1 = %d, wanted 0\n", got) + if got := add_1_int64_ssa(1); got != 2 { + fmt.Printf("add_int64 1+1 = %d, wanted 2\n", got) failed = true } - if got := div_Neg1_int16_ssa(1); got != -1 { - fmt.Printf("div_int16 -1/1 = %d, wanted -1\n", got) + if got := add_int64_1_ssa(1); got != 2 { + fmt.Printf("add_int64 1+1 = %d, wanted 2\n", got) failed = true } - if got := div_int16_Neg1_ssa(1); got != -1 { - fmt.Printf("div_int16 1/-1 = %d, wanted -1\n", got) + if got := add_1_int64_ssa(4294967296); got != 4294967297 { + fmt.Printf("add_int64 1+4294967296 = %d, wanted 4294967297\n", got) failed = true } - if got := div_Neg1_int16_ssa(32766); got != 0 { - fmt.Printf("div_int16 -1/32766 = %d, wanted 0\n", got) + if got := add_int64_1_ssa(4294967296); got != 4294967297 { + fmt.Printf("add_int64 4294967296+1 = %d, wanted 4294967297\n", got) failed = true } - if got := div_int16_Neg1_ssa(32766); got != -32766 { - fmt.Printf("div_int16 32766/-1 = %d, wanted -32766\n", got) + if got := add_1_int64_ssa(9223372036854775806); got != 9223372036854775807 { + fmt.Printf("add_int64 1+9223372036854775806 = %d, wanted 9223372036854775807\n", got) failed = true } - if got := div_Neg1_int16_ssa(32767); got != 0 { - fmt.Printf("div_int16 -1/32767 = %d, wanted 0\n", got) + if got := add_int64_1_ssa(9223372036854775806); got != 9223372036854775807 { + fmt.Printf("add_int64 9223372036854775806+1 = %d, wanted 9223372036854775807\n", got) failed = true } - if got := div_int16_Neg1_ssa(32767); got != -32767 { - fmt.Printf("div_int16 32767/-1 = %d, wanted -32767\n", got) + if got := add_1_int64_ssa(9223372036854775807); got != -9223372036854775808 { + fmt.Printf("add_int64 1+9223372036854775807 = %d, wanted -9223372036854775808\n", got) failed = true } - if got := div_0_int16_ssa(-32768); got != 0 { - fmt.Printf("div_int16 0/-32768 = %d, wanted 0\n", got) + if got := add_int64_1_ssa(9223372036854775807); got != -9223372036854775808 { + fmt.Printf("add_int64 9223372036854775807+1 = %d, wanted -9223372036854775808\n", got) failed = true } - if got := div_0_int16_ssa(-32767); got != 0 { - fmt.Printf("div_int16 0/-32767 = %d, wanted 0\n", got) + if got := add_4294967296_int64_ssa(-9223372036854775808); got != -9223372032559808512 { + fmt.Printf("add_int64 4294967296+-9223372036854775808 = %d, wanted -9223372032559808512\n", got) failed = true } - if got := div_0_int16_ssa(-1); got != 0 { - fmt.Printf("div_int16 0/-1 = %d, wanted 0\n", got) + if got := add_int64_4294967296_ssa(-9223372036854775808); got != -9223372032559808512 { + fmt.Printf("add_int64 -9223372036854775808+4294967296 = %d, wanted -9223372032559808512\n", got) failed = true } - if got := div_0_int16_ssa(1); got != 0 { - fmt.Printf("div_int16 0/1 = %d, wanted 0\n", got) + if got := add_4294967296_int64_ssa(-9223372036854775807); got != -9223372032559808511 { + fmt.Printf("add_int64 4294967296+-9223372036854775807 = %d, wanted -9223372032559808511\n", got) failed = true } - if got := div_0_int16_ssa(32766); got != 0 { - fmt.Printf("div_int16 0/32766 = %d, wanted 0\n", got) + if got := add_int64_4294967296_ssa(-9223372036854775807); got != -9223372032559808511 { + fmt.Printf("add_int64 -9223372036854775807+4294967296 = %d, wanted -9223372032559808511\n", got) failed = true } - if got := div_0_int16_ssa(32767); got != 0 { - fmt.Printf("div_int16 0/32767 = %d, wanted 0\n", got) + if got := add_4294967296_int64_ssa(-4294967296); got != 0 { + fmt.Printf("add_int64 4294967296+-4294967296 = %d, wanted 0\n", got) failed = true } - if got := div_1_int16_ssa(-32768); got != 0 { - fmt.Printf("div_int16 1/-32768 = %d, wanted 0\n", got) + if got := add_int64_4294967296_ssa(-4294967296); got != 0 { + fmt.Printf("add_int64 -4294967296+4294967296 = %d, wanted 0\n", got) failed = true } - if got := div_int16_1_ssa(-32768); got != -32768 { - fmt.Printf("div_int16 -32768/1 = %d, wanted -32768\n", got) + if got := add_4294967296_int64_ssa(-1); got != 4294967295 { + fmt.Printf("add_int64 4294967296+-1 = %d, wanted 4294967295\n", got) failed = true } - if got := div_1_int16_ssa(-32767); got != 0 { - fmt.Printf("div_int16 1/-32767 = %d, wanted 0\n", got) + if got := add_int64_4294967296_ssa(-1); got != 4294967295 { + fmt.Printf("add_int64 -1+4294967296 = %d, wanted 4294967295\n", got) failed = true } - if got := div_int16_1_ssa(-32767); got != -32767 { - fmt.Printf("div_int16 -32767/1 = %d, wanted -32767\n", got) + if got := add_4294967296_int64_ssa(0); got != 4294967296 { + fmt.Printf("add_int64 4294967296+0 = %d, wanted 4294967296\n", got) failed = true } - if got := div_1_int16_ssa(-1); got != -1 { - fmt.Printf("div_int16 1/-1 = %d, wanted -1\n", got) + if got := add_int64_4294967296_ssa(0); got != 4294967296 { + fmt.Printf("add_int64 0+4294967296 = %d, wanted 4294967296\n", got) failed = true } - if got := div_int16_1_ssa(-1); got != -1 { - fmt.Printf("div_int16 -1/1 = %d, wanted -1\n", got) + if got := add_4294967296_int64_ssa(1); got != 4294967297 { + fmt.Printf("add_int64 4294967296+1 = %d, wanted 4294967297\n", got) failed = true } - if got := div_int16_1_ssa(0); got != 0 { - fmt.Printf("div_int16 0/1 = %d, wanted 0\n", got) + if got := add_int64_4294967296_ssa(1); got != 4294967297 { + fmt.Printf("add_int64 1+4294967296 = %d, wanted 4294967297\n", got) failed = true } - if got := div_1_int16_ssa(1); got != 1 { - fmt.Printf("div_int16 1/1 = %d, wanted 1\n", got) + if got := add_4294967296_int64_ssa(4294967296); got != 8589934592 { + fmt.Printf("add_int64 4294967296+4294967296 = %d, wanted 8589934592\n", got) + failed = true + } + + if got := add_int64_4294967296_ssa(4294967296); got != 8589934592 { + fmt.Printf("add_int64 4294967296+4294967296 = %d, wanted 8589934592\n", got) + failed = true + } + + if got := add_4294967296_int64_ssa(9223372036854775806); got != -9223372032559808514 { + fmt.Printf("add_int64 4294967296+9223372036854775806 = %d, wanted -9223372032559808514\n", got) + failed = true + } + + if got := add_int64_4294967296_ssa(9223372036854775806); got != -9223372032559808514 { + fmt.Printf("add_int64 9223372036854775806+4294967296 = %d, wanted -9223372032559808514\n", got) + failed = true + } + + if got := add_4294967296_int64_ssa(9223372036854775807); got != -9223372032559808513 { + fmt.Printf("add_int64 4294967296+9223372036854775807 = %d, wanted -9223372032559808513\n", got) + failed = true + } + + if got := add_int64_4294967296_ssa(9223372036854775807); got != -9223372032559808513 { + fmt.Printf("add_int64 9223372036854775807+4294967296 = %d, wanted -9223372032559808513\n", got) + failed = true + } + + if got := add_9223372036854775806_int64_ssa(-9223372036854775808); got != -2 { + fmt.Printf("add_int64 9223372036854775806+-9223372036854775808 = %d, wanted -2\n", got) + failed = true + } + + if got := add_int64_9223372036854775806_ssa(-9223372036854775808); got != -2 { + fmt.Printf("add_int64 -9223372036854775808+9223372036854775806 = %d, wanted -2\n", got) + failed = true + } + + if got := add_9223372036854775806_int64_ssa(-9223372036854775807); got != -1 { + fmt.Printf("add_int64 9223372036854775806+-9223372036854775807 = %d, wanted -1\n", got) + failed = true + } + + if got := add_int64_9223372036854775806_ssa(-9223372036854775807); got != -1 { + fmt.Printf("add_int64 -9223372036854775807+9223372036854775806 = %d, wanted -1\n", got) + failed = true + } + + if got := add_9223372036854775806_int64_ssa(-4294967296); got != 9223372032559808510 { + fmt.Printf("add_int64 9223372036854775806+-4294967296 = %d, wanted 9223372032559808510\n", got) + failed = true + } + + if got := add_int64_9223372036854775806_ssa(-4294967296); got != 9223372032559808510 { + fmt.Printf("add_int64 -4294967296+9223372036854775806 = %d, wanted 9223372032559808510\n", got) + failed = true + } + + if got := add_9223372036854775806_int64_ssa(-1); got != 9223372036854775805 { + fmt.Printf("add_int64 9223372036854775806+-1 = %d, wanted 9223372036854775805\n", got) + failed = true + } + + if got := add_int64_9223372036854775806_ssa(-1); got != 9223372036854775805 { + fmt.Printf("add_int64 -1+9223372036854775806 = %d, wanted 9223372036854775805\n", got) + failed = true + } + + if got := add_9223372036854775806_int64_ssa(0); got != 9223372036854775806 { + fmt.Printf("add_int64 9223372036854775806+0 = %d, wanted 9223372036854775806\n", got) + failed = true + } + + if got := add_int64_9223372036854775806_ssa(0); got != 9223372036854775806 { + fmt.Printf("add_int64 0+9223372036854775806 = %d, wanted 9223372036854775806\n", got) + failed = true + } + + if got := add_9223372036854775806_int64_ssa(1); got != 9223372036854775807 { + fmt.Printf("add_int64 9223372036854775806+1 = %d, wanted 9223372036854775807\n", got) + failed = true + } + + if got := add_int64_9223372036854775806_ssa(1); got != 9223372036854775807 { + fmt.Printf("add_int64 1+9223372036854775806 = %d, wanted 9223372036854775807\n", got) + failed = true + } + + if got := add_9223372036854775806_int64_ssa(4294967296); got != -9223372032559808514 { + fmt.Printf("add_int64 9223372036854775806+4294967296 = %d, wanted -9223372032559808514\n", got) + failed = true + } + + if got := add_int64_9223372036854775806_ssa(4294967296); got != -9223372032559808514 { + fmt.Printf("add_int64 4294967296+9223372036854775806 = %d, wanted -9223372032559808514\n", got) + failed = true + } + + if got := add_9223372036854775806_int64_ssa(9223372036854775806); got != -4 { + fmt.Printf("add_int64 9223372036854775806+9223372036854775806 = %d, wanted -4\n", got) + failed = true + } + + if got := add_int64_9223372036854775806_ssa(9223372036854775806); got != -4 { + fmt.Printf("add_int64 9223372036854775806+9223372036854775806 = %d, wanted -4\n", got) + failed = true + } + + if got := add_9223372036854775806_int64_ssa(9223372036854775807); got != -3 { + fmt.Printf("add_int64 9223372036854775806+9223372036854775807 = %d, wanted -3\n", got) + failed = true + } + + if got := add_int64_9223372036854775806_ssa(9223372036854775807); got != -3 { + fmt.Printf("add_int64 9223372036854775807+9223372036854775806 = %d, wanted -3\n", got) + failed = true + } + + if got := add_9223372036854775807_int64_ssa(-9223372036854775808); got != -1 { + fmt.Printf("add_int64 9223372036854775807+-9223372036854775808 = %d, wanted -1\n", got) + failed = true + } + + if got := add_int64_9223372036854775807_ssa(-9223372036854775808); got != -1 { + fmt.Printf("add_int64 -9223372036854775808+9223372036854775807 = %d, wanted -1\n", got) + failed = true + } + + if got := add_9223372036854775807_int64_ssa(-9223372036854775807); got != 0 { + fmt.Printf("add_int64 9223372036854775807+-9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := add_int64_9223372036854775807_ssa(-9223372036854775807); got != 0 { + fmt.Printf("add_int64 -9223372036854775807+9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := add_9223372036854775807_int64_ssa(-4294967296); got != 9223372032559808511 { + fmt.Printf("add_int64 9223372036854775807+-4294967296 = %d, wanted 9223372032559808511\n", got) + failed = true + } + + if got := add_int64_9223372036854775807_ssa(-4294967296); got != 9223372032559808511 { + fmt.Printf("add_int64 -4294967296+9223372036854775807 = %d, wanted 9223372032559808511\n", got) + failed = true + } + + if got := add_9223372036854775807_int64_ssa(-1); got != 9223372036854775806 { + fmt.Printf("add_int64 9223372036854775807+-1 = %d, wanted 9223372036854775806\n", got) + failed = true + } + + if got := add_int64_9223372036854775807_ssa(-1); got != 9223372036854775806 { + fmt.Printf("add_int64 -1+9223372036854775807 = %d, wanted 9223372036854775806\n", got) + failed = true + } + + if got := add_9223372036854775807_int64_ssa(0); got != 9223372036854775807 { + fmt.Printf("add_int64 9223372036854775807+0 = %d, wanted 9223372036854775807\n", got) + failed = true + } + + if got := add_int64_9223372036854775807_ssa(0); got != 9223372036854775807 { + fmt.Printf("add_int64 0+9223372036854775807 = %d, wanted 9223372036854775807\n", got) + failed = true + } + + if got := add_9223372036854775807_int64_ssa(1); got != -9223372036854775808 { + fmt.Printf("add_int64 9223372036854775807+1 = %d, wanted -9223372036854775808\n", got) + failed = true + } + + if got := add_int64_9223372036854775807_ssa(1); got != -9223372036854775808 { + fmt.Printf("add_int64 1+9223372036854775807 = %d, wanted -9223372036854775808\n", got) + failed = true + } + + if got := add_9223372036854775807_int64_ssa(4294967296); got != -9223372032559808513 { + fmt.Printf("add_int64 9223372036854775807+4294967296 = %d, wanted -9223372032559808513\n", got) + failed = true + } + + if got := add_int64_9223372036854775807_ssa(4294967296); got != -9223372032559808513 { + fmt.Printf("add_int64 4294967296+9223372036854775807 = %d, wanted -9223372032559808513\n", got) + failed = true + } + + if got := add_9223372036854775807_int64_ssa(9223372036854775806); got != -3 { + fmt.Printf("add_int64 9223372036854775807+9223372036854775806 = %d, wanted -3\n", got) + failed = true + } + + if got := add_int64_9223372036854775807_ssa(9223372036854775806); got != -3 { + fmt.Printf("add_int64 9223372036854775806+9223372036854775807 = %d, wanted -3\n", got) + failed = true + } + + if got := add_9223372036854775807_int64_ssa(9223372036854775807); got != -2 { + fmt.Printf("add_int64 9223372036854775807+9223372036854775807 = %d, wanted -2\n", got) + failed = true + } + + if got := add_int64_9223372036854775807_ssa(9223372036854775807); got != -2 { + fmt.Printf("add_int64 9223372036854775807+9223372036854775807 = %d, wanted -2\n", got) + failed = true + } + + if got := sub_Neg9223372036854775808_int64_ssa(-9223372036854775808); got != 0 { + fmt.Printf("sub_int64 -9223372036854775808--9223372036854775808 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_int64_Neg9223372036854775808_ssa(-9223372036854775808); got != 0 { + fmt.Printf("sub_int64 -9223372036854775808--9223372036854775808 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_Neg9223372036854775808_int64_ssa(-9223372036854775807); got != -1 { + fmt.Printf("sub_int64 -9223372036854775808--9223372036854775807 = %d, wanted -1\n", got) + failed = true + } + + if got := sub_int64_Neg9223372036854775808_ssa(-9223372036854775807); got != 1 { + fmt.Printf("sub_int64 -9223372036854775807--9223372036854775808 = %d, wanted 1\n", got) + failed = true + } + + if got := sub_Neg9223372036854775808_int64_ssa(-4294967296); got != -9223372032559808512 { + fmt.Printf("sub_int64 -9223372036854775808--4294967296 = %d, wanted -9223372032559808512\n", got) + failed = true + } + + if got := sub_int64_Neg9223372036854775808_ssa(-4294967296); got != 9223372032559808512 { + fmt.Printf("sub_int64 -4294967296--9223372036854775808 = %d, wanted 9223372032559808512\n", got) + failed = true + } + + if got := sub_Neg9223372036854775808_int64_ssa(-1); got != -9223372036854775807 { + fmt.Printf("sub_int64 -9223372036854775808--1 = %d, wanted -9223372036854775807\n", got) + failed = true + } + + if got := sub_int64_Neg9223372036854775808_ssa(-1); got != 9223372036854775807 { + fmt.Printf("sub_int64 -1--9223372036854775808 = %d, wanted 9223372036854775807\n", got) + failed = true + } + + if got := sub_Neg9223372036854775808_int64_ssa(0); got != -9223372036854775808 { + fmt.Printf("sub_int64 -9223372036854775808-0 = %d, wanted -9223372036854775808\n", got) + failed = true + } + + if got := sub_int64_Neg9223372036854775808_ssa(0); got != -9223372036854775808 { + fmt.Printf("sub_int64 0--9223372036854775808 = %d, wanted -9223372036854775808\n", got) + failed = true + } + + if got := sub_Neg9223372036854775808_int64_ssa(1); got != 9223372036854775807 { + fmt.Printf("sub_int64 -9223372036854775808-1 = %d, wanted 9223372036854775807\n", got) + failed = true + } + + if got := sub_int64_Neg9223372036854775808_ssa(1); got != -9223372036854775807 { + fmt.Printf("sub_int64 1--9223372036854775808 = %d, wanted -9223372036854775807\n", got) + failed = true + } + + if got := sub_Neg9223372036854775808_int64_ssa(4294967296); got != 9223372032559808512 { + fmt.Printf("sub_int64 -9223372036854775808-4294967296 = %d, wanted 9223372032559808512\n", got) + failed = true + } + + if got := sub_int64_Neg9223372036854775808_ssa(4294967296); got != -9223372032559808512 { + fmt.Printf("sub_int64 4294967296--9223372036854775808 = %d, wanted -9223372032559808512\n", got) + failed = true + } + + if got := sub_Neg9223372036854775808_int64_ssa(9223372036854775806); got != 2 { + fmt.Printf("sub_int64 -9223372036854775808-9223372036854775806 = %d, wanted 2\n", got) + failed = true + } + + if got := sub_int64_Neg9223372036854775808_ssa(9223372036854775806); got != -2 { + fmt.Printf("sub_int64 9223372036854775806--9223372036854775808 = %d, wanted -2\n", got) + failed = true + } + + if got := sub_Neg9223372036854775808_int64_ssa(9223372036854775807); got != 1 { + fmt.Printf("sub_int64 -9223372036854775808-9223372036854775807 = %d, wanted 1\n", got) + failed = true + } + + if got := sub_int64_Neg9223372036854775808_ssa(9223372036854775807); got != -1 { + fmt.Printf("sub_int64 9223372036854775807--9223372036854775808 = %d, wanted -1\n", got) + failed = true + } + + if got := sub_Neg9223372036854775807_int64_ssa(-9223372036854775808); got != 1 { + fmt.Printf("sub_int64 -9223372036854775807--9223372036854775808 = %d, wanted 1\n", got) + failed = true + } + + if got := sub_int64_Neg9223372036854775807_ssa(-9223372036854775808); got != -1 { + fmt.Printf("sub_int64 -9223372036854775808--9223372036854775807 = %d, wanted -1\n", got) + failed = true + } + + if got := sub_Neg9223372036854775807_int64_ssa(-9223372036854775807); got != 0 { + fmt.Printf("sub_int64 -9223372036854775807--9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_int64_Neg9223372036854775807_ssa(-9223372036854775807); got != 0 { + fmt.Printf("sub_int64 -9223372036854775807--9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_Neg9223372036854775807_int64_ssa(-4294967296); got != -9223372032559808511 { + fmt.Printf("sub_int64 -9223372036854775807--4294967296 = %d, wanted -9223372032559808511\n", got) + failed = true + } + + if got := sub_int64_Neg9223372036854775807_ssa(-4294967296); got != 9223372032559808511 { + fmt.Printf("sub_int64 -4294967296--9223372036854775807 = %d, wanted 9223372032559808511\n", got) + failed = true + } + + if got := sub_Neg9223372036854775807_int64_ssa(-1); got != -9223372036854775806 { + fmt.Printf("sub_int64 -9223372036854775807--1 = %d, wanted -9223372036854775806\n", got) + failed = true + } + + if got := sub_int64_Neg9223372036854775807_ssa(-1); got != 9223372036854775806 { + fmt.Printf("sub_int64 -1--9223372036854775807 = %d, wanted 9223372036854775806\n", got) + failed = true + } + + if got := sub_Neg9223372036854775807_int64_ssa(0); got != -9223372036854775807 { + fmt.Printf("sub_int64 -9223372036854775807-0 = %d, wanted -9223372036854775807\n", got) + failed = true + } + + if got := sub_int64_Neg9223372036854775807_ssa(0); got != 9223372036854775807 { + fmt.Printf("sub_int64 0--9223372036854775807 = %d, wanted 9223372036854775807\n", got) + failed = true + } + + if got := sub_Neg9223372036854775807_int64_ssa(1); got != -9223372036854775808 { + fmt.Printf("sub_int64 -9223372036854775807-1 = %d, wanted -9223372036854775808\n", got) + failed = true + } + + if got := sub_int64_Neg9223372036854775807_ssa(1); got != -9223372036854775808 { + fmt.Printf("sub_int64 1--9223372036854775807 = %d, wanted -9223372036854775808\n", got) + failed = true + } + + if got := sub_Neg9223372036854775807_int64_ssa(4294967296); got != 9223372032559808513 { + fmt.Printf("sub_int64 -9223372036854775807-4294967296 = %d, wanted 9223372032559808513\n", got) + failed = true + } + + if got := sub_int64_Neg9223372036854775807_ssa(4294967296); got != -9223372032559808513 { + fmt.Printf("sub_int64 4294967296--9223372036854775807 = %d, wanted -9223372032559808513\n", got) + failed = true + } + + if got := sub_Neg9223372036854775807_int64_ssa(9223372036854775806); got != 3 { + fmt.Printf("sub_int64 -9223372036854775807-9223372036854775806 = %d, wanted 3\n", got) + failed = true + } + + if got := sub_int64_Neg9223372036854775807_ssa(9223372036854775806); got != -3 { + fmt.Printf("sub_int64 9223372036854775806--9223372036854775807 = %d, wanted -3\n", got) + failed = true + } + + if got := sub_Neg9223372036854775807_int64_ssa(9223372036854775807); got != 2 { + fmt.Printf("sub_int64 -9223372036854775807-9223372036854775807 = %d, wanted 2\n", got) + failed = true + } + + if got := sub_int64_Neg9223372036854775807_ssa(9223372036854775807); got != -2 { + fmt.Printf("sub_int64 9223372036854775807--9223372036854775807 = %d, wanted -2\n", got) + failed = true + } + + if got := sub_Neg4294967296_int64_ssa(-9223372036854775808); got != 9223372032559808512 { + fmt.Printf("sub_int64 -4294967296--9223372036854775808 = %d, wanted 9223372032559808512\n", got) + failed = true + } + + if got := sub_int64_Neg4294967296_ssa(-9223372036854775808); got != -9223372032559808512 { + fmt.Printf("sub_int64 -9223372036854775808--4294967296 = %d, wanted -9223372032559808512\n", got) + failed = true + } + + if got := sub_Neg4294967296_int64_ssa(-9223372036854775807); got != 9223372032559808511 { + fmt.Printf("sub_int64 -4294967296--9223372036854775807 = %d, wanted 9223372032559808511\n", got) + failed = true + } + + if got := sub_int64_Neg4294967296_ssa(-9223372036854775807); got != -9223372032559808511 { + fmt.Printf("sub_int64 -9223372036854775807--4294967296 = %d, wanted -9223372032559808511\n", got) + failed = true + } + + if got := sub_Neg4294967296_int64_ssa(-4294967296); got != 0 { + fmt.Printf("sub_int64 -4294967296--4294967296 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_int64_Neg4294967296_ssa(-4294967296); got != 0 { + fmt.Printf("sub_int64 -4294967296--4294967296 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_Neg4294967296_int64_ssa(-1); got != -4294967295 { + fmt.Printf("sub_int64 -4294967296--1 = %d, wanted -4294967295\n", got) + failed = true + } + + if got := sub_int64_Neg4294967296_ssa(-1); got != 4294967295 { + fmt.Printf("sub_int64 -1--4294967296 = %d, wanted 4294967295\n", got) + failed = true + } + + if got := sub_Neg4294967296_int64_ssa(0); got != -4294967296 { + fmt.Printf("sub_int64 -4294967296-0 = %d, wanted -4294967296\n", got) + failed = true + } + + if got := sub_int64_Neg4294967296_ssa(0); got != 4294967296 { + fmt.Printf("sub_int64 0--4294967296 = %d, wanted 4294967296\n", got) + failed = true + } + + if got := sub_Neg4294967296_int64_ssa(1); got != -4294967297 { + fmt.Printf("sub_int64 -4294967296-1 = %d, wanted -4294967297\n", got) + failed = true + } + + if got := sub_int64_Neg4294967296_ssa(1); got != 4294967297 { + fmt.Printf("sub_int64 1--4294967296 = %d, wanted 4294967297\n", got) + failed = true + } + + if got := sub_Neg4294967296_int64_ssa(4294967296); got != -8589934592 { + fmt.Printf("sub_int64 -4294967296-4294967296 = %d, wanted -8589934592\n", got) + failed = true + } + + if got := sub_int64_Neg4294967296_ssa(4294967296); got != 8589934592 { + fmt.Printf("sub_int64 4294967296--4294967296 = %d, wanted 8589934592\n", got) + failed = true + } + + if got := sub_Neg4294967296_int64_ssa(9223372036854775806); got != 9223372032559808514 { + fmt.Printf("sub_int64 -4294967296-9223372036854775806 = %d, wanted 9223372032559808514\n", got) + failed = true + } + + if got := sub_int64_Neg4294967296_ssa(9223372036854775806); got != -9223372032559808514 { + fmt.Printf("sub_int64 9223372036854775806--4294967296 = %d, wanted -9223372032559808514\n", got) + failed = true + } + + if got := sub_Neg4294967296_int64_ssa(9223372036854775807); got != 9223372032559808513 { + fmt.Printf("sub_int64 -4294967296-9223372036854775807 = %d, wanted 9223372032559808513\n", got) + failed = true + } + + if got := sub_int64_Neg4294967296_ssa(9223372036854775807); got != -9223372032559808513 { + fmt.Printf("sub_int64 9223372036854775807--4294967296 = %d, wanted -9223372032559808513\n", got) + failed = true + } + + if got := sub_Neg1_int64_ssa(-9223372036854775808); got != 9223372036854775807 { + fmt.Printf("sub_int64 -1--9223372036854775808 = %d, wanted 9223372036854775807\n", got) + failed = true + } + + if got := sub_int64_Neg1_ssa(-9223372036854775808); got != -9223372036854775807 { + fmt.Printf("sub_int64 -9223372036854775808--1 = %d, wanted -9223372036854775807\n", got) + failed = true + } + + if got := sub_Neg1_int64_ssa(-9223372036854775807); got != 9223372036854775806 { + fmt.Printf("sub_int64 -1--9223372036854775807 = %d, wanted 9223372036854775806\n", got) + failed = true + } + + if got := sub_int64_Neg1_ssa(-9223372036854775807); got != -9223372036854775806 { + fmt.Printf("sub_int64 -9223372036854775807--1 = %d, wanted -9223372036854775806\n", got) + failed = true + } + + if got := sub_Neg1_int64_ssa(-4294967296); got != 4294967295 { + fmt.Printf("sub_int64 -1--4294967296 = %d, wanted 4294967295\n", got) + failed = true + } + + if got := sub_int64_Neg1_ssa(-4294967296); got != -4294967295 { + fmt.Printf("sub_int64 -4294967296--1 = %d, wanted -4294967295\n", got) + failed = true + } + + if got := sub_Neg1_int64_ssa(-1); got != 0 { + fmt.Printf("sub_int64 -1--1 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_int64_Neg1_ssa(-1); got != 0 { + fmt.Printf("sub_int64 -1--1 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_Neg1_int64_ssa(0); got != -1 { + fmt.Printf("sub_int64 -1-0 = %d, wanted -1\n", got) + failed = true + } + + if got := sub_int64_Neg1_ssa(0); got != 1 { + fmt.Printf("sub_int64 0--1 = %d, wanted 1\n", got) + failed = true + } + + if got := sub_Neg1_int64_ssa(1); got != -2 { + fmt.Printf("sub_int64 -1-1 = %d, wanted -2\n", got) + failed = true + } + + if got := sub_int64_Neg1_ssa(1); got != 2 { + fmt.Printf("sub_int64 1--1 = %d, wanted 2\n", got) + failed = true + } + + if got := sub_Neg1_int64_ssa(4294967296); got != -4294967297 { + fmt.Printf("sub_int64 -1-4294967296 = %d, wanted -4294967297\n", got) + failed = true + } + + if got := sub_int64_Neg1_ssa(4294967296); got != 4294967297 { + fmt.Printf("sub_int64 4294967296--1 = %d, wanted 4294967297\n", got) + failed = true + } + + if got := sub_Neg1_int64_ssa(9223372036854775806); got != -9223372036854775807 { + fmt.Printf("sub_int64 -1-9223372036854775806 = %d, wanted -9223372036854775807\n", got) + failed = true + } + + if got := sub_int64_Neg1_ssa(9223372036854775806); got != 9223372036854775807 { + fmt.Printf("sub_int64 9223372036854775806--1 = %d, wanted 9223372036854775807\n", got) + failed = true + } + + if got := sub_Neg1_int64_ssa(9223372036854775807); got != -9223372036854775808 { + fmt.Printf("sub_int64 -1-9223372036854775807 = %d, wanted -9223372036854775808\n", got) + failed = true + } + + if got := sub_int64_Neg1_ssa(9223372036854775807); got != -9223372036854775808 { + fmt.Printf("sub_int64 9223372036854775807--1 = %d, wanted -9223372036854775808\n", got) + failed = true + } + + if got := sub_0_int64_ssa(-9223372036854775808); got != -9223372036854775808 { + fmt.Printf("sub_int64 0--9223372036854775808 = %d, wanted -9223372036854775808\n", got) + failed = true + } + + if got := sub_int64_0_ssa(-9223372036854775808); got != -9223372036854775808 { + fmt.Printf("sub_int64 -9223372036854775808-0 = %d, wanted -9223372036854775808\n", got) + failed = true + } + + if got := sub_0_int64_ssa(-9223372036854775807); got != 9223372036854775807 { + fmt.Printf("sub_int64 0--9223372036854775807 = %d, wanted 9223372036854775807\n", got) + failed = true + } + + if got := sub_int64_0_ssa(-9223372036854775807); got != -9223372036854775807 { + fmt.Printf("sub_int64 -9223372036854775807-0 = %d, wanted -9223372036854775807\n", got) + failed = true + } + + if got := sub_0_int64_ssa(-4294967296); got != 4294967296 { + fmt.Printf("sub_int64 0--4294967296 = %d, wanted 4294967296\n", got) + failed = true + } + + if got := sub_int64_0_ssa(-4294967296); got != -4294967296 { + fmt.Printf("sub_int64 -4294967296-0 = %d, wanted -4294967296\n", got) + failed = true + } + + if got := sub_0_int64_ssa(-1); got != 1 { + fmt.Printf("sub_int64 0--1 = %d, wanted 1\n", got) + failed = true + } + + if got := sub_int64_0_ssa(-1); got != -1 { + fmt.Printf("sub_int64 -1-0 = %d, wanted -1\n", got) + failed = true + } + + if got := sub_0_int64_ssa(0); got != 0 { + fmt.Printf("sub_int64 0-0 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_int64_0_ssa(0); got != 0 { + fmt.Printf("sub_int64 0-0 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_0_int64_ssa(1); got != -1 { + fmt.Printf("sub_int64 0-1 = %d, wanted -1\n", got) + failed = true + } + + if got := sub_int64_0_ssa(1); got != 1 { + fmt.Printf("sub_int64 1-0 = %d, wanted 1\n", got) + failed = true + } + + if got := sub_0_int64_ssa(4294967296); got != -4294967296 { + fmt.Printf("sub_int64 0-4294967296 = %d, wanted -4294967296\n", got) + failed = true + } + + if got := sub_int64_0_ssa(4294967296); got != 4294967296 { + fmt.Printf("sub_int64 4294967296-0 = %d, wanted 4294967296\n", got) + failed = true + } + + if got := sub_0_int64_ssa(9223372036854775806); got != -9223372036854775806 { + fmt.Printf("sub_int64 0-9223372036854775806 = %d, wanted -9223372036854775806\n", got) + failed = true + } + + if got := sub_int64_0_ssa(9223372036854775806); got != 9223372036854775806 { + fmt.Printf("sub_int64 9223372036854775806-0 = %d, wanted 9223372036854775806\n", got) + failed = true + } + + if got := sub_0_int64_ssa(9223372036854775807); got != -9223372036854775807 { + fmt.Printf("sub_int64 0-9223372036854775807 = %d, wanted -9223372036854775807\n", got) + failed = true + } + + if got := sub_int64_0_ssa(9223372036854775807); got != 9223372036854775807 { + fmt.Printf("sub_int64 9223372036854775807-0 = %d, wanted 9223372036854775807\n", got) + failed = true + } + + if got := sub_1_int64_ssa(-9223372036854775808); got != -9223372036854775807 { + fmt.Printf("sub_int64 1--9223372036854775808 = %d, wanted -9223372036854775807\n", got) + failed = true + } + + if got := sub_int64_1_ssa(-9223372036854775808); got != 9223372036854775807 { + fmt.Printf("sub_int64 -9223372036854775808-1 = %d, wanted 9223372036854775807\n", got) + failed = true + } + + if got := sub_1_int64_ssa(-9223372036854775807); got != -9223372036854775808 { + fmt.Printf("sub_int64 1--9223372036854775807 = %d, wanted -9223372036854775808\n", got) + failed = true + } + + if got := sub_int64_1_ssa(-9223372036854775807); got != -9223372036854775808 { + fmt.Printf("sub_int64 -9223372036854775807-1 = %d, wanted -9223372036854775808\n", got) + failed = true + } + + if got := sub_1_int64_ssa(-4294967296); got != 4294967297 { + fmt.Printf("sub_int64 1--4294967296 = %d, wanted 4294967297\n", got) + failed = true + } + + if got := sub_int64_1_ssa(-4294967296); got != -4294967297 { + fmt.Printf("sub_int64 -4294967296-1 = %d, wanted -4294967297\n", got) + failed = true + } + + if got := sub_1_int64_ssa(-1); got != 2 { + fmt.Printf("sub_int64 1--1 = %d, wanted 2\n", got) + failed = true + } + + if got := sub_int64_1_ssa(-1); got != -2 { + fmt.Printf("sub_int64 -1-1 = %d, wanted -2\n", got) + failed = true + } + + if got := sub_1_int64_ssa(0); got != 1 { + fmt.Printf("sub_int64 1-0 = %d, wanted 1\n", got) + failed = true + } + + if got := sub_int64_1_ssa(0); got != -1 { + fmt.Printf("sub_int64 0-1 = %d, wanted -1\n", got) + failed = true + } + + if got := sub_1_int64_ssa(1); got != 0 { + fmt.Printf("sub_int64 1-1 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_int64_1_ssa(1); got != 0 { + fmt.Printf("sub_int64 1-1 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_1_int64_ssa(4294967296); got != -4294967295 { + fmt.Printf("sub_int64 1-4294967296 = %d, wanted -4294967295\n", got) + failed = true + } + + if got := sub_int64_1_ssa(4294967296); got != 4294967295 { + fmt.Printf("sub_int64 4294967296-1 = %d, wanted 4294967295\n", got) + failed = true + } + + if got := sub_1_int64_ssa(9223372036854775806); got != -9223372036854775805 { + fmt.Printf("sub_int64 1-9223372036854775806 = %d, wanted -9223372036854775805\n", got) + failed = true + } + + if got := sub_int64_1_ssa(9223372036854775806); got != 9223372036854775805 { + fmt.Printf("sub_int64 9223372036854775806-1 = %d, wanted 9223372036854775805\n", got) + failed = true + } + + if got := sub_1_int64_ssa(9223372036854775807); got != -9223372036854775806 { + fmt.Printf("sub_int64 1-9223372036854775807 = %d, wanted -9223372036854775806\n", got) + failed = true + } + + if got := sub_int64_1_ssa(9223372036854775807); got != 9223372036854775806 { + fmt.Printf("sub_int64 9223372036854775807-1 = %d, wanted 9223372036854775806\n", got) + failed = true + } + + if got := sub_4294967296_int64_ssa(-9223372036854775808); got != -9223372032559808512 { + fmt.Printf("sub_int64 4294967296--9223372036854775808 = %d, wanted -9223372032559808512\n", got) + failed = true + } + + if got := sub_int64_4294967296_ssa(-9223372036854775808); got != 9223372032559808512 { + fmt.Printf("sub_int64 -9223372036854775808-4294967296 = %d, wanted 9223372032559808512\n", got) + failed = true + } + + if got := sub_4294967296_int64_ssa(-9223372036854775807); got != -9223372032559808513 { + fmt.Printf("sub_int64 4294967296--9223372036854775807 = %d, wanted -9223372032559808513\n", got) + failed = true + } + + if got := sub_int64_4294967296_ssa(-9223372036854775807); got != 9223372032559808513 { + fmt.Printf("sub_int64 -9223372036854775807-4294967296 = %d, wanted 9223372032559808513\n", got) + failed = true + } + + if got := sub_4294967296_int64_ssa(-4294967296); got != 8589934592 { + fmt.Printf("sub_int64 4294967296--4294967296 = %d, wanted 8589934592\n", got) + failed = true + } + + if got := sub_int64_4294967296_ssa(-4294967296); got != -8589934592 { + fmt.Printf("sub_int64 -4294967296-4294967296 = %d, wanted -8589934592\n", got) + failed = true + } + + if got := sub_4294967296_int64_ssa(-1); got != 4294967297 { + fmt.Printf("sub_int64 4294967296--1 = %d, wanted 4294967297\n", got) + failed = true + } + + if got := sub_int64_4294967296_ssa(-1); got != -4294967297 { + fmt.Printf("sub_int64 -1-4294967296 = %d, wanted -4294967297\n", got) + failed = true + } + + if got := sub_4294967296_int64_ssa(0); got != 4294967296 { + fmt.Printf("sub_int64 4294967296-0 = %d, wanted 4294967296\n", got) + failed = true + } + + if got := sub_int64_4294967296_ssa(0); got != -4294967296 { + fmt.Printf("sub_int64 0-4294967296 = %d, wanted -4294967296\n", got) + failed = true + } + + if got := sub_4294967296_int64_ssa(1); got != 4294967295 { + fmt.Printf("sub_int64 4294967296-1 = %d, wanted 4294967295\n", got) + failed = true + } + + if got := sub_int64_4294967296_ssa(1); got != -4294967295 { + fmt.Printf("sub_int64 1-4294967296 = %d, wanted -4294967295\n", got) + failed = true + } + + if got := sub_4294967296_int64_ssa(4294967296); got != 0 { + fmt.Printf("sub_int64 4294967296-4294967296 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_int64_4294967296_ssa(4294967296); got != 0 { + fmt.Printf("sub_int64 4294967296-4294967296 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_4294967296_int64_ssa(9223372036854775806); got != -9223372032559808510 { + fmt.Printf("sub_int64 4294967296-9223372036854775806 = %d, wanted -9223372032559808510\n", got) + failed = true + } + + if got := sub_int64_4294967296_ssa(9223372036854775806); got != 9223372032559808510 { + fmt.Printf("sub_int64 9223372036854775806-4294967296 = %d, wanted 9223372032559808510\n", got) + failed = true + } + + if got := sub_4294967296_int64_ssa(9223372036854775807); got != -9223372032559808511 { + fmt.Printf("sub_int64 4294967296-9223372036854775807 = %d, wanted -9223372032559808511\n", got) + failed = true + } + + if got := sub_int64_4294967296_ssa(9223372036854775807); got != 9223372032559808511 { + fmt.Printf("sub_int64 9223372036854775807-4294967296 = %d, wanted 9223372032559808511\n", got) + failed = true + } + + if got := sub_9223372036854775806_int64_ssa(-9223372036854775808); got != -2 { + fmt.Printf("sub_int64 9223372036854775806--9223372036854775808 = %d, wanted -2\n", got) + failed = true + } + + if got := sub_int64_9223372036854775806_ssa(-9223372036854775808); got != 2 { + fmt.Printf("sub_int64 -9223372036854775808-9223372036854775806 = %d, wanted 2\n", got) + failed = true + } + + if got := sub_9223372036854775806_int64_ssa(-9223372036854775807); got != -3 { + fmt.Printf("sub_int64 9223372036854775806--9223372036854775807 = %d, wanted -3\n", got) + failed = true + } + + if got := sub_int64_9223372036854775806_ssa(-9223372036854775807); got != 3 { + fmt.Printf("sub_int64 -9223372036854775807-9223372036854775806 = %d, wanted 3\n", got) + failed = true + } + + if got := sub_9223372036854775806_int64_ssa(-4294967296); got != -9223372032559808514 { + fmt.Printf("sub_int64 9223372036854775806--4294967296 = %d, wanted -9223372032559808514\n", got) + failed = true + } + + if got := sub_int64_9223372036854775806_ssa(-4294967296); got != 9223372032559808514 { + fmt.Printf("sub_int64 -4294967296-9223372036854775806 = %d, wanted 9223372032559808514\n", got) + failed = true + } + + if got := sub_9223372036854775806_int64_ssa(-1); got != 9223372036854775807 { + fmt.Printf("sub_int64 9223372036854775806--1 = %d, wanted 9223372036854775807\n", got) + failed = true + } + + if got := sub_int64_9223372036854775806_ssa(-1); got != -9223372036854775807 { + fmt.Printf("sub_int64 -1-9223372036854775806 = %d, wanted -9223372036854775807\n", got) + failed = true + } + + if got := sub_9223372036854775806_int64_ssa(0); got != 9223372036854775806 { + fmt.Printf("sub_int64 9223372036854775806-0 = %d, wanted 9223372036854775806\n", got) + failed = true + } + + if got := sub_int64_9223372036854775806_ssa(0); got != -9223372036854775806 { + fmt.Printf("sub_int64 0-9223372036854775806 = %d, wanted -9223372036854775806\n", got) + failed = true + } + + if got := sub_9223372036854775806_int64_ssa(1); got != 9223372036854775805 { + fmt.Printf("sub_int64 9223372036854775806-1 = %d, wanted 9223372036854775805\n", got) + failed = true + } + + if got := sub_int64_9223372036854775806_ssa(1); got != -9223372036854775805 { + fmt.Printf("sub_int64 1-9223372036854775806 = %d, wanted -9223372036854775805\n", got) + failed = true + } + + if got := sub_9223372036854775806_int64_ssa(4294967296); got != 9223372032559808510 { + fmt.Printf("sub_int64 9223372036854775806-4294967296 = %d, wanted 9223372032559808510\n", got) + failed = true + } + + if got := sub_int64_9223372036854775806_ssa(4294967296); got != -9223372032559808510 { + fmt.Printf("sub_int64 4294967296-9223372036854775806 = %d, wanted -9223372032559808510\n", got) + failed = true + } + + if got := sub_9223372036854775806_int64_ssa(9223372036854775806); got != 0 { + fmt.Printf("sub_int64 9223372036854775806-9223372036854775806 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_int64_9223372036854775806_ssa(9223372036854775806); got != 0 { + fmt.Printf("sub_int64 9223372036854775806-9223372036854775806 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_9223372036854775806_int64_ssa(9223372036854775807); got != -1 { + fmt.Printf("sub_int64 9223372036854775806-9223372036854775807 = %d, wanted -1\n", got) + failed = true + } + + if got := sub_int64_9223372036854775806_ssa(9223372036854775807); got != 1 { + fmt.Printf("sub_int64 9223372036854775807-9223372036854775806 = %d, wanted 1\n", got) + failed = true + } + + if got := sub_9223372036854775807_int64_ssa(-9223372036854775808); got != -1 { + fmt.Printf("sub_int64 9223372036854775807--9223372036854775808 = %d, wanted -1\n", got) + failed = true + } + + if got := sub_int64_9223372036854775807_ssa(-9223372036854775808); got != 1 { + fmt.Printf("sub_int64 -9223372036854775808-9223372036854775807 = %d, wanted 1\n", got) + failed = true + } + + if got := sub_9223372036854775807_int64_ssa(-9223372036854775807); got != -2 { + fmt.Printf("sub_int64 9223372036854775807--9223372036854775807 = %d, wanted -2\n", got) + failed = true + } + + if got := sub_int64_9223372036854775807_ssa(-9223372036854775807); got != 2 { + fmt.Printf("sub_int64 -9223372036854775807-9223372036854775807 = %d, wanted 2\n", got) + failed = true + } + + if got := sub_9223372036854775807_int64_ssa(-4294967296); got != -9223372032559808513 { + fmt.Printf("sub_int64 9223372036854775807--4294967296 = %d, wanted -9223372032559808513\n", got) + failed = true + } + + if got := sub_int64_9223372036854775807_ssa(-4294967296); got != 9223372032559808513 { + fmt.Printf("sub_int64 -4294967296-9223372036854775807 = %d, wanted 9223372032559808513\n", got) + failed = true + } + + if got := sub_9223372036854775807_int64_ssa(-1); got != -9223372036854775808 { + fmt.Printf("sub_int64 9223372036854775807--1 = %d, wanted -9223372036854775808\n", got) + failed = true + } + + if got := sub_int64_9223372036854775807_ssa(-1); got != -9223372036854775808 { + fmt.Printf("sub_int64 -1-9223372036854775807 = %d, wanted -9223372036854775808\n", got) + failed = true + } + + if got := sub_9223372036854775807_int64_ssa(0); got != 9223372036854775807 { + fmt.Printf("sub_int64 9223372036854775807-0 = %d, wanted 9223372036854775807\n", got) + failed = true + } + + if got := sub_int64_9223372036854775807_ssa(0); got != -9223372036854775807 { + fmt.Printf("sub_int64 0-9223372036854775807 = %d, wanted -9223372036854775807\n", got) + failed = true + } + + if got := sub_9223372036854775807_int64_ssa(1); got != 9223372036854775806 { + fmt.Printf("sub_int64 9223372036854775807-1 = %d, wanted 9223372036854775806\n", got) + failed = true + } + + if got := sub_int64_9223372036854775807_ssa(1); got != -9223372036854775806 { + fmt.Printf("sub_int64 1-9223372036854775807 = %d, wanted -9223372036854775806\n", got) + failed = true + } + + if got := sub_9223372036854775807_int64_ssa(4294967296); got != 9223372032559808511 { + fmt.Printf("sub_int64 9223372036854775807-4294967296 = %d, wanted 9223372032559808511\n", got) + failed = true + } + + if got := sub_int64_9223372036854775807_ssa(4294967296); got != -9223372032559808511 { + fmt.Printf("sub_int64 4294967296-9223372036854775807 = %d, wanted -9223372032559808511\n", got) + failed = true + } + + if got := sub_9223372036854775807_int64_ssa(9223372036854775806); got != 1 { + fmt.Printf("sub_int64 9223372036854775807-9223372036854775806 = %d, wanted 1\n", got) + failed = true + } + + if got := sub_int64_9223372036854775807_ssa(9223372036854775806); got != -1 { + fmt.Printf("sub_int64 9223372036854775806-9223372036854775807 = %d, wanted -1\n", got) + failed = true + } + + if got := sub_9223372036854775807_int64_ssa(9223372036854775807); got != 0 { + fmt.Printf("sub_int64 9223372036854775807-9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_int64_9223372036854775807_ssa(9223372036854775807); got != 0 { + fmt.Printf("sub_int64 9223372036854775807-9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg9223372036854775808_int64_ssa(-9223372036854775808); got != 1 { + fmt.Printf("div_int64 -9223372036854775808/-9223372036854775808 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int64_Neg9223372036854775808_ssa(-9223372036854775808); got != 1 { + fmt.Printf("div_int64 -9223372036854775808/-9223372036854775808 = %d, wanted 1\n", got) + failed = true + } + + if got := div_Neg9223372036854775808_int64_ssa(-9223372036854775807); got != 1 { + fmt.Printf("div_int64 -9223372036854775808/-9223372036854775807 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int64_Neg9223372036854775808_ssa(-9223372036854775807); got != 0 { + fmt.Printf("div_int64 -9223372036854775807/-9223372036854775808 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg9223372036854775808_int64_ssa(-4294967296); got != 2147483648 { + fmt.Printf("div_int64 -9223372036854775808/-4294967296 = %d, wanted 2147483648\n", got) + failed = true + } + + if got := div_int64_Neg9223372036854775808_ssa(-4294967296); got != 0 { + fmt.Printf("div_int64 -4294967296/-9223372036854775808 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg9223372036854775808_int64_ssa(-1); got != -9223372036854775808 { + fmt.Printf("div_int64 -9223372036854775808/-1 = %d, wanted -9223372036854775808\n", got) + failed = true + } + + if got := div_int64_Neg9223372036854775808_ssa(-1); got != 0 { + fmt.Printf("div_int64 -1/-9223372036854775808 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_Neg9223372036854775808_ssa(0); got != 0 { + fmt.Printf("div_int64 0/-9223372036854775808 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg9223372036854775808_int64_ssa(1); got != -9223372036854775808 { + fmt.Printf("div_int64 -9223372036854775808/1 = %d, wanted -9223372036854775808\n", got) + failed = true + } + + if got := div_int64_Neg9223372036854775808_ssa(1); got != 0 { + fmt.Printf("div_int64 1/-9223372036854775808 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg9223372036854775808_int64_ssa(4294967296); got != -2147483648 { + fmt.Printf("div_int64 -9223372036854775808/4294967296 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := div_int64_Neg9223372036854775808_ssa(4294967296); got != 0 { + fmt.Printf("div_int64 4294967296/-9223372036854775808 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg9223372036854775808_int64_ssa(9223372036854775806); got != -1 { + fmt.Printf("div_int64 -9223372036854775808/9223372036854775806 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int64_Neg9223372036854775808_ssa(9223372036854775806); got != 0 { + fmt.Printf("div_int64 9223372036854775806/-9223372036854775808 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg9223372036854775808_int64_ssa(9223372036854775807); got != -1 { + fmt.Printf("div_int64 -9223372036854775808/9223372036854775807 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int64_Neg9223372036854775808_ssa(9223372036854775807); got != 0 { + fmt.Printf("div_int64 9223372036854775807/-9223372036854775808 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg9223372036854775807_int64_ssa(-9223372036854775808); got != 0 { + fmt.Printf("div_int64 -9223372036854775807/-9223372036854775808 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_Neg9223372036854775807_ssa(-9223372036854775808); got != 1 { + fmt.Printf("div_int64 -9223372036854775808/-9223372036854775807 = %d, wanted 1\n", got) + failed = true + } + + if got := div_Neg9223372036854775807_int64_ssa(-9223372036854775807); got != 1 { + fmt.Printf("div_int64 -9223372036854775807/-9223372036854775807 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int64_Neg9223372036854775807_ssa(-9223372036854775807); got != 1 { + fmt.Printf("div_int64 -9223372036854775807/-9223372036854775807 = %d, wanted 1\n", got) + failed = true + } + + if got := div_Neg9223372036854775807_int64_ssa(-4294967296); got != 2147483647 { + fmt.Printf("div_int64 -9223372036854775807/-4294967296 = %d, wanted 2147483647\n", got) + failed = true + } + + if got := div_int64_Neg9223372036854775807_ssa(-4294967296); got != 0 { + fmt.Printf("div_int64 -4294967296/-9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg9223372036854775807_int64_ssa(-1); got != 9223372036854775807 { + fmt.Printf("div_int64 -9223372036854775807/-1 = %d, wanted 9223372036854775807\n", got) + failed = true + } + + if got := div_int64_Neg9223372036854775807_ssa(-1); got != 0 { + fmt.Printf("div_int64 -1/-9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_Neg9223372036854775807_ssa(0); got != 0 { + fmt.Printf("div_int64 0/-9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg9223372036854775807_int64_ssa(1); got != -9223372036854775807 { + fmt.Printf("div_int64 -9223372036854775807/1 = %d, wanted -9223372036854775807\n", got) + failed = true + } + + if got := div_int64_Neg9223372036854775807_ssa(1); got != 0 { + fmt.Printf("div_int64 1/-9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg9223372036854775807_int64_ssa(4294967296); got != -2147483647 { + fmt.Printf("div_int64 -9223372036854775807/4294967296 = %d, wanted -2147483647\n", got) + failed = true + } + + if got := div_int64_Neg9223372036854775807_ssa(4294967296); got != 0 { + fmt.Printf("div_int64 4294967296/-9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg9223372036854775807_int64_ssa(9223372036854775806); got != -1 { + fmt.Printf("div_int64 -9223372036854775807/9223372036854775806 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int64_Neg9223372036854775807_ssa(9223372036854775806); got != 0 { + fmt.Printf("div_int64 9223372036854775806/-9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg9223372036854775807_int64_ssa(9223372036854775807); got != -1 { + fmt.Printf("div_int64 -9223372036854775807/9223372036854775807 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int64_Neg9223372036854775807_ssa(9223372036854775807); got != -1 { + fmt.Printf("div_int64 9223372036854775807/-9223372036854775807 = %d, wanted -1\n", got) + failed = true + } + + if got := div_Neg4294967296_int64_ssa(-9223372036854775808); got != 0 { + fmt.Printf("div_int64 -4294967296/-9223372036854775808 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_Neg4294967296_ssa(-9223372036854775808); got != 2147483648 { + fmt.Printf("div_int64 -9223372036854775808/-4294967296 = %d, wanted 2147483648\n", got) + failed = true + } + + if got := div_Neg4294967296_int64_ssa(-9223372036854775807); got != 0 { + fmt.Printf("div_int64 -4294967296/-9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_Neg4294967296_ssa(-9223372036854775807); got != 2147483647 { + fmt.Printf("div_int64 -9223372036854775807/-4294967296 = %d, wanted 2147483647\n", got) + failed = true + } + + if got := div_Neg4294967296_int64_ssa(-4294967296); got != 1 { + fmt.Printf("div_int64 -4294967296/-4294967296 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int64_Neg4294967296_ssa(-4294967296); got != 1 { + fmt.Printf("div_int64 -4294967296/-4294967296 = %d, wanted 1\n", got) + failed = true + } + + if got := div_Neg4294967296_int64_ssa(-1); got != 4294967296 { + fmt.Printf("div_int64 -4294967296/-1 = %d, wanted 4294967296\n", got) + failed = true + } + + if got := div_int64_Neg4294967296_ssa(-1); got != 0 { + fmt.Printf("div_int64 -1/-4294967296 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_Neg4294967296_ssa(0); got != 0 { + fmt.Printf("div_int64 0/-4294967296 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg4294967296_int64_ssa(1); got != -4294967296 { + fmt.Printf("div_int64 -4294967296/1 = %d, wanted -4294967296\n", got) + failed = true + } + + if got := div_int64_Neg4294967296_ssa(1); got != 0 { + fmt.Printf("div_int64 1/-4294967296 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg4294967296_int64_ssa(4294967296); got != -1 { + fmt.Printf("div_int64 -4294967296/4294967296 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int64_Neg4294967296_ssa(4294967296); got != -1 { + fmt.Printf("div_int64 4294967296/-4294967296 = %d, wanted -1\n", got) + failed = true + } + + if got := div_Neg4294967296_int64_ssa(9223372036854775806); got != 0 { + fmt.Printf("div_int64 -4294967296/9223372036854775806 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_Neg4294967296_ssa(9223372036854775806); got != -2147483647 { + fmt.Printf("div_int64 9223372036854775806/-4294967296 = %d, wanted -2147483647\n", got) + failed = true + } + + if got := div_Neg4294967296_int64_ssa(9223372036854775807); got != 0 { + fmt.Printf("div_int64 -4294967296/9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_Neg4294967296_ssa(9223372036854775807); got != -2147483647 { + fmt.Printf("div_int64 9223372036854775807/-4294967296 = %d, wanted -2147483647\n", got) + failed = true + } + + if got := div_Neg1_int64_ssa(-9223372036854775808); got != 0 { + fmt.Printf("div_int64 -1/-9223372036854775808 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_Neg1_ssa(-9223372036854775808); got != -9223372036854775808 { + fmt.Printf("div_int64 -9223372036854775808/-1 = %d, wanted -9223372036854775808\n", got) + failed = true + } + + if got := div_Neg1_int64_ssa(-9223372036854775807); got != 0 { + fmt.Printf("div_int64 -1/-9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_Neg1_ssa(-9223372036854775807); got != 9223372036854775807 { + fmt.Printf("div_int64 -9223372036854775807/-1 = %d, wanted 9223372036854775807\n", got) + failed = true + } + + if got := div_Neg1_int64_ssa(-4294967296); got != 0 { + fmt.Printf("div_int64 -1/-4294967296 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_Neg1_ssa(-4294967296); got != 4294967296 { + fmt.Printf("div_int64 -4294967296/-1 = %d, wanted 4294967296\n", got) + failed = true + } + + if got := div_Neg1_int64_ssa(-1); got != 1 { + fmt.Printf("div_int64 -1/-1 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int64_Neg1_ssa(-1); got != 1 { + fmt.Printf("div_int64 -1/-1 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int64_Neg1_ssa(0); got != 0 { + fmt.Printf("div_int64 0/-1 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg1_int64_ssa(1); got != -1 { + fmt.Printf("div_int64 -1/1 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int64_Neg1_ssa(1); got != -1 { + fmt.Printf("div_int64 1/-1 = %d, wanted -1\n", got) + failed = true + } + + if got := div_Neg1_int64_ssa(4294967296); got != 0 { + fmt.Printf("div_int64 -1/4294967296 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_Neg1_ssa(4294967296); got != -4294967296 { + fmt.Printf("div_int64 4294967296/-1 = %d, wanted -4294967296\n", got) + failed = true + } + + if got := div_Neg1_int64_ssa(9223372036854775806); got != 0 { + fmt.Printf("div_int64 -1/9223372036854775806 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_Neg1_ssa(9223372036854775806); got != -9223372036854775806 { + fmt.Printf("div_int64 9223372036854775806/-1 = %d, wanted -9223372036854775806\n", got) + failed = true + } + + if got := div_Neg1_int64_ssa(9223372036854775807); got != 0 { + fmt.Printf("div_int64 -1/9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_Neg1_ssa(9223372036854775807); got != -9223372036854775807 { + fmt.Printf("div_int64 9223372036854775807/-1 = %d, wanted -9223372036854775807\n", got) + failed = true + } + + if got := div_0_int64_ssa(-9223372036854775808); got != 0 { + fmt.Printf("div_int64 0/-9223372036854775808 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_int64_ssa(-9223372036854775807); got != 0 { + fmt.Printf("div_int64 0/-9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_int64_ssa(-4294967296); got != 0 { + fmt.Printf("div_int64 0/-4294967296 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_int64_ssa(-1); got != 0 { + fmt.Printf("div_int64 0/-1 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_int64_ssa(1); got != 0 { + fmt.Printf("div_int64 0/1 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_int64_ssa(4294967296); got != 0 { + fmt.Printf("div_int64 0/4294967296 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_int64_ssa(9223372036854775806); got != 0 { + fmt.Printf("div_int64 0/9223372036854775806 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_int64_ssa(9223372036854775807); got != 0 { + fmt.Printf("div_int64 0/9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := div_1_int64_ssa(-9223372036854775808); got != 0 { + fmt.Printf("div_int64 1/-9223372036854775808 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_1_ssa(-9223372036854775808); got != -9223372036854775808 { + fmt.Printf("div_int64 -9223372036854775808/1 = %d, wanted -9223372036854775808\n", got) + failed = true + } + + if got := div_1_int64_ssa(-9223372036854775807); got != 0 { + fmt.Printf("div_int64 1/-9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_1_ssa(-9223372036854775807); got != -9223372036854775807 { + fmt.Printf("div_int64 -9223372036854775807/1 = %d, wanted -9223372036854775807\n", got) + failed = true + } + + if got := div_1_int64_ssa(-4294967296); got != 0 { + fmt.Printf("div_int64 1/-4294967296 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_1_ssa(-4294967296); got != -4294967296 { + fmt.Printf("div_int64 -4294967296/1 = %d, wanted -4294967296\n", got) + failed = true + } + + if got := div_1_int64_ssa(-1); got != -1 { + fmt.Printf("div_int64 1/-1 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int64_1_ssa(-1); got != -1 { + fmt.Printf("div_int64 -1/1 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int64_1_ssa(0); got != 0 { + fmt.Printf("div_int64 0/1 = %d, wanted 0\n", got) + failed = true + } + + if got := div_1_int64_ssa(1); got != 1 { + fmt.Printf("div_int64 1/1 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int64_1_ssa(1); got != 1 { + fmt.Printf("div_int64 1/1 = %d, wanted 1\n", got) + failed = true + } + + if got := div_1_int64_ssa(4294967296); got != 0 { + fmt.Printf("div_int64 1/4294967296 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_1_ssa(4294967296); got != 4294967296 { + fmt.Printf("div_int64 4294967296/1 = %d, wanted 4294967296\n", got) + failed = true + } + + if got := div_1_int64_ssa(9223372036854775806); got != 0 { + fmt.Printf("div_int64 1/9223372036854775806 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_1_ssa(9223372036854775806); got != 9223372036854775806 { + fmt.Printf("div_int64 9223372036854775806/1 = %d, wanted 9223372036854775806\n", got) + failed = true + } + + if got := div_1_int64_ssa(9223372036854775807); got != 0 { + fmt.Printf("div_int64 1/9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_1_ssa(9223372036854775807); got != 9223372036854775807 { + fmt.Printf("div_int64 9223372036854775807/1 = %d, wanted 9223372036854775807\n", got) + failed = true + } + + if got := div_4294967296_int64_ssa(-9223372036854775808); got != 0 { + fmt.Printf("div_int64 4294967296/-9223372036854775808 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_4294967296_ssa(-9223372036854775808); got != -2147483648 { + fmt.Printf("div_int64 -9223372036854775808/4294967296 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := div_4294967296_int64_ssa(-9223372036854775807); got != 0 { + fmt.Printf("div_int64 4294967296/-9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_4294967296_ssa(-9223372036854775807); got != -2147483647 { + fmt.Printf("div_int64 -9223372036854775807/4294967296 = %d, wanted -2147483647\n", got) + failed = true + } + + if got := div_4294967296_int64_ssa(-4294967296); got != -1 { + fmt.Printf("div_int64 4294967296/-4294967296 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int64_4294967296_ssa(-4294967296); got != -1 { + fmt.Printf("div_int64 -4294967296/4294967296 = %d, wanted -1\n", got) + failed = true + } + + if got := div_4294967296_int64_ssa(-1); got != -4294967296 { + fmt.Printf("div_int64 4294967296/-1 = %d, wanted -4294967296\n", got) + failed = true + } + + if got := div_int64_4294967296_ssa(-1); got != 0 { + fmt.Printf("div_int64 -1/4294967296 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_4294967296_ssa(0); got != 0 { + fmt.Printf("div_int64 0/4294967296 = %d, wanted 0\n", got) + failed = true + } + + if got := div_4294967296_int64_ssa(1); got != 4294967296 { + fmt.Printf("div_int64 4294967296/1 = %d, wanted 4294967296\n", got) + failed = true + } + + if got := div_int64_4294967296_ssa(1); got != 0 { + fmt.Printf("div_int64 1/4294967296 = %d, wanted 0\n", got) + failed = true + } + + if got := div_4294967296_int64_ssa(4294967296); got != 1 { + fmt.Printf("div_int64 4294967296/4294967296 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int64_4294967296_ssa(4294967296); got != 1 { + fmt.Printf("div_int64 4294967296/4294967296 = %d, wanted 1\n", got) + failed = true + } + + if got := div_4294967296_int64_ssa(9223372036854775806); got != 0 { + fmt.Printf("div_int64 4294967296/9223372036854775806 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_4294967296_ssa(9223372036854775806); got != 2147483647 { + fmt.Printf("div_int64 9223372036854775806/4294967296 = %d, wanted 2147483647\n", got) + failed = true + } + + if got := div_4294967296_int64_ssa(9223372036854775807); got != 0 { + fmt.Printf("div_int64 4294967296/9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_4294967296_ssa(9223372036854775807); got != 2147483647 { + fmt.Printf("div_int64 9223372036854775807/4294967296 = %d, wanted 2147483647\n", got) + failed = true + } + + if got := div_9223372036854775806_int64_ssa(-9223372036854775808); got != 0 { + fmt.Printf("div_int64 9223372036854775806/-9223372036854775808 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_9223372036854775806_ssa(-9223372036854775808); got != -1 { + fmt.Printf("div_int64 -9223372036854775808/9223372036854775806 = %d, wanted -1\n", got) + failed = true + } + + if got := div_9223372036854775806_int64_ssa(-9223372036854775807); got != 0 { + fmt.Printf("div_int64 9223372036854775806/-9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_9223372036854775806_ssa(-9223372036854775807); got != -1 { + fmt.Printf("div_int64 -9223372036854775807/9223372036854775806 = %d, wanted -1\n", got) + failed = true + } + + if got := div_9223372036854775806_int64_ssa(-4294967296); got != -2147483647 { + fmt.Printf("div_int64 9223372036854775806/-4294967296 = %d, wanted -2147483647\n", got) + failed = true + } + + if got := div_int64_9223372036854775806_ssa(-4294967296); got != 0 { + fmt.Printf("div_int64 -4294967296/9223372036854775806 = %d, wanted 0\n", got) + failed = true + } + + if got := div_9223372036854775806_int64_ssa(-1); got != -9223372036854775806 { + fmt.Printf("div_int64 9223372036854775806/-1 = %d, wanted -9223372036854775806\n", got) + failed = true + } + + if got := div_int64_9223372036854775806_ssa(-1); got != 0 { + fmt.Printf("div_int64 -1/9223372036854775806 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_9223372036854775806_ssa(0); got != 0 { + fmt.Printf("div_int64 0/9223372036854775806 = %d, wanted 0\n", got) + failed = true + } + + if got := div_9223372036854775806_int64_ssa(1); got != 9223372036854775806 { + fmt.Printf("div_int64 9223372036854775806/1 = %d, wanted 9223372036854775806\n", got) + failed = true + } + + if got := div_int64_9223372036854775806_ssa(1); got != 0 { + fmt.Printf("div_int64 1/9223372036854775806 = %d, wanted 0\n", got) + failed = true + } + + if got := div_9223372036854775806_int64_ssa(4294967296); got != 2147483647 { + fmt.Printf("div_int64 9223372036854775806/4294967296 = %d, wanted 2147483647\n", got) + failed = true + } + + if got := div_int64_9223372036854775806_ssa(4294967296); got != 0 { + fmt.Printf("div_int64 4294967296/9223372036854775806 = %d, wanted 0\n", got) + failed = true + } + + if got := div_9223372036854775806_int64_ssa(9223372036854775806); got != 1 { + fmt.Printf("div_int64 9223372036854775806/9223372036854775806 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int64_9223372036854775806_ssa(9223372036854775806); got != 1 { + fmt.Printf("div_int64 9223372036854775806/9223372036854775806 = %d, wanted 1\n", got) + failed = true + } + + if got := div_9223372036854775806_int64_ssa(9223372036854775807); got != 0 { + fmt.Printf("div_int64 9223372036854775806/9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_9223372036854775806_ssa(9223372036854775807); got != 1 { + fmt.Printf("div_int64 9223372036854775807/9223372036854775806 = %d, wanted 1\n", got) + failed = true + } + + if got := div_9223372036854775807_int64_ssa(-9223372036854775808); got != 0 { + fmt.Printf("div_int64 9223372036854775807/-9223372036854775808 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_9223372036854775807_ssa(-9223372036854775808); got != -1 { + fmt.Printf("div_int64 -9223372036854775808/9223372036854775807 = %d, wanted -1\n", got) + failed = true + } + + if got := div_9223372036854775807_int64_ssa(-9223372036854775807); got != -1 { + fmt.Printf("div_int64 9223372036854775807/-9223372036854775807 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int64_9223372036854775807_ssa(-9223372036854775807); got != -1 { + fmt.Printf("div_int64 -9223372036854775807/9223372036854775807 = %d, wanted -1\n", got) + failed = true + } + + if got := div_9223372036854775807_int64_ssa(-4294967296); got != -2147483647 { + fmt.Printf("div_int64 9223372036854775807/-4294967296 = %d, wanted -2147483647\n", got) + failed = true + } + + if got := div_int64_9223372036854775807_ssa(-4294967296); got != 0 { + fmt.Printf("div_int64 -4294967296/9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := div_9223372036854775807_int64_ssa(-1); got != -9223372036854775807 { + fmt.Printf("div_int64 9223372036854775807/-1 = %d, wanted -9223372036854775807\n", got) + failed = true + } + + if got := div_int64_9223372036854775807_ssa(-1); got != 0 { + fmt.Printf("div_int64 -1/9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int64_9223372036854775807_ssa(0); got != 0 { + fmt.Printf("div_int64 0/9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := div_9223372036854775807_int64_ssa(1); got != 9223372036854775807 { + fmt.Printf("div_int64 9223372036854775807/1 = %d, wanted 9223372036854775807\n", got) + failed = true + } + + if got := div_int64_9223372036854775807_ssa(1); got != 0 { + fmt.Printf("div_int64 1/9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := div_9223372036854775807_int64_ssa(4294967296); got != 2147483647 { + fmt.Printf("div_int64 9223372036854775807/4294967296 = %d, wanted 2147483647\n", got) + failed = true + } + + if got := div_int64_9223372036854775807_ssa(4294967296); got != 0 { + fmt.Printf("div_int64 4294967296/9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := div_9223372036854775807_int64_ssa(9223372036854775806); got != 1 { + fmt.Printf("div_int64 9223372036854775807/9223372036854775806 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int64_9223372036854775807_ssa(9223372036854775806); got != 0 { + fmt.Printf("div_int64 9223372036854775806/9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := div_9223372036854775807_int64_ssa(9223372036854775807); got != 1 { + fmt.Printf("div_int64 9223372036854775807/9223372036854775807 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int64_9223372036854775807_ssa(9223372036854775807); got != 1 { + fmt.Printf("div_int64 9223372036854775807/9223372036854775807 = %d, wanted 1\n", got) + failed = true + } + + if got := mul_Neg9223372036854775808_int64_ssa(-9223372036854775808); got != 0 { + fmt.Printf("mul_int64 -9223372036854775808*-9223372036854775808 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int64_Neg9223372036854775808_ssa(-9223372036854775808); got != 0 { + fmt.Printf("mul_int64 -9223372036854775808*-9223372036854775808 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_Neg9223372036854775808_int64_ssa(-9223372036854775807); got != -9223372036854775808 { + fmt.Printf("mul_int64 -9223372036854775808*-9223372036854775807 = %d, wanted -9223372036854775808\n", got) + failed = true + } + + if got := mul_int64_Neg9223372036854775808_ssa(-9223372036854775807); got != -9223372036854775808 { + fmt.Printf("mul_int64 -9223372036854775807*-9223372036854775808 = %d, wanted -9223372036854775808\n", got) + failed = true + } + + if got := mul_Neg9223372036854775808_int64_ssa(-4294967296); got != 0 { + fmt.Printf("mul_int64 -9223372036854775808*-4294967296 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int64_Neg9223372036854775808_ssa(-4294967296); got != 0 { + fmt.Printf("mul_int64 -4294967296*-9223372036854775808 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_Neg9223372036854775808_int64_ssa(-1); got != -9223372036854775808 { + fmt.Printf("mul_int64 -9223372036854775808*-1 = %d, wanted -9223372036854775808\n", got) + failed = true + } + + if got := mul_int64_Neg9223372036854775808_ssa(-1); got != -9223372036854775808 { + fmt.Printf("mul_int64 -1*-9223372036854775808 = %d, wanted -9223372036854775808\n", got) + failed = true + } + + if got := mul_Neg9223372036854775808_int64_ssa(0); got != 0 { + fmt.Printf("mul_int64 -9223372036854775808*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int64_Neg9223372036854775808_ssa(0); got != 0 { + fmt.Printf("mul_int64 0*-9223372036854775808 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_Neg9223372036854775808_int64_ssa(1); got != -9223372036854775808 { + fmt.Printf("mul_int64 -9223372036854775808*1 = %d, wanted -9223372036854775808\n", got) + failed = true + } + + if got := mul_int64_Neg9223372036854775808_ssa(1); got != -9223372036854775808 { + fmt.Printf("mul_int64 1*-9223372036854775808 = %d, wanted -9223372036854775808\n", got) + failed = true + } + + if got := mul_Neg9223372036854775808_int64_ssa(4294967296); got != 0 { + fmt.Printf("mul_int64 -9223372036854775808*4294967296 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int64_Neg9223372036854775808_ssa(4294967296); got != 0 { + fmt.Printf("mul_int64 4294967296*-9223372036854775808 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_Neg9223372036854775808_int64_ssa(9223372036854775806); got != 0 { + fmt.Printf("mul_int64 -9223372036854775808*9223372036854775806 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int64_Neg9223372036854775808_ssa(9223372036854775806); got != 0 { + fmt.Printf("mul_int64 9223372036854775806*-9223372036854775808 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_Neg9223372036854775808_int64_ssa(9223372036854775807); got != -9223372036854775808 { + fmt.Printf("mul_int64 -9223372036854775808*9223372036854775807 = %d, wanted -9223372036854775808\n", got) + failed = true + } + + if got := mul_int64_Neg9223372036854775808_ssa(9223372036854775807); got != -9223372036854775808 { + fmt.Printf("mul_int64 9223372036854775807*-9223372036854775808 = %d, wanted -9223372036854775808\n", got) + failed = true + } + + if got := mul_Neg9223372036854775807_int64_ssa(-9223372036854775808); got != -9223372036854775808 { + fmt.Printf("mul_int64 -9223372036854775807*-9223372036854775808 = %d, wanted -9223372036854775808\n", got) + failed = true + } + + if got := mul_int64_Neg9223372036854775807_ssa(-9223372036854775808); got != -9223372036854775808 { + fmt.Printf("mul_int64 -9223372036854775808*-9223372036854775807 = %d, wanted -9223372036854775808\n", got) + failed = true + } + + if got := mul_Neg9223372036854775807_int64_ssa(-9223372036854775807); got != 1 { + fmt.Printf("mul_int64 -9223372036854775807*-9223372036854775807 = %d, wanted 1\n", got) + failed = true + } + + if got := mul_int64_Neg9223372036854775807_ssa(-9223372036854775807); got != 1 { + fmt.Printf("mul_int64 -9223372036854775807*-9223372036854775807 = %d, wanted 1\n", got) + failed = true + } + + if got := mul_Neg9223372036854775807_int64_ssa(-4294967296); got != -4294967296 { + fmt.Printf("mul_int64 -9223372036854775807*-4294967296 = %d, wanted -4294967296\n", got) + failed = true + } + + if got := mul_int64_Neg9223372036854775807_ssa(-4294967296); got != -4294967296 { + fmt.Printf("mul_int64 -4294967296*-9223372036854775807 = %d, wanted -4294967296\n", got) + failed = true + } + + if got := mul_Neg9223372036854775807_int64_ssa(-1); got != 9223372036854775807 { + fmt.Printf("mul_int64 -9223372036854775807*-1 = %d, wanted 9223372036854775807\n", got) + failed = true + } + + if got := mul_int64_Neg9223372036854775807_ssa(-1); got != 9223372036854775807 { + fmt.Printf("mul_int64 -1*-9223372036854775807 = %d, wanted 9223372036854775807\n", got) + failed = true + } + + if got := mul_Neg9223372036854775807_int64_ssa(0); got != 0 { + fmt.Printf("mul_int64 -9223372036854775807*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int64_Neg9223372036854775807_ssa(0); got != 0 { + fmt.Printf("mul_int64 0*-9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_Neg9223372036854775807_int64_ssa(1); got != -9223372036854775807 { + fmt.Printf("mul_int64 -9223372036854775807*1 = %d, wanted -9223372036854775807\n", got) + failed = true + } + + if got := mul_int64_Neg9223372036854775807_ssa(1); got != -9223372036854775807 { + fmt.Printf("mul_int64 1*-9223372036854775807 = %d, wanted -9223372036854775807\n", got) + failed = true + } + + if got := mul_Neg9223372036854775807_int64_ssa(4294967296); got != 4294967296 { + fmt.Printf("mul_int64 -9223372036854775807*4294967296 = %d, wanted 4294967296\n", got) + failed = true + } + + if got := mul_int64_Neg9223372036854775807_ssa(4294967296); got != 4294967296 { + fmt.Printf("mul_int64 4294967296*-9223372036854775807 = %d, wanted 4294967296\n", got) + failed = true + } + + if got := mul_Neg9223372036854775807_int64_ssa(9223372036854775806); got != 9223372036854775806 { + fmt.Printf("mul_int64 -9223372036854775807*9223372036854775806 = %d, wanted 9223372036854775806\n", got) + failed = true + } + + if got := mul_int64_Neg9223372036854775807_ssa(9223372036854775806); got != 9223372036854775806 { + fmt.Printf("mul_int64 9223372036854775806*-9223372036854775807 = %d, wanted 9223372036854775806\n", got) + failed = true + } + + if got := mul_Neg9223372036854775807_int64_ssa(9223372036854775807); got != -1 { + fmt.Printf("mul_int64 -9223372036854775807*9223372036854775807 = %d, wanted -1\n", got) + failed = true + } + + if got := mul_int64_Neg9223372036854775807_ssa(9223372036854775807); got != -1 { + fmt.Printf("mul_int64 9223372036854775807*-9223372036854775807 = %d, wanted -1\n", got) + failed = true + } + + if got := mul_Neg4294967296_int64_ssa(-9223372036854775808); got != 0 { + fmt.Printf("mul_int64 -4294967296*-9223372036854775808 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int64_Neg4294967296_ssa(-9223372036854775808); got != 0 { + fmt.Printf("mul_int64 -9223372036854775808*-4294967296 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_Neg4294967296_int64_ssa(-9223372036854775807); got != -4294967296 { + fmt.Printf("mul_int64 -4294967296*-9223372036854775807 = %d, wanted -4294967296\n", got) + failed = true + } + + if got := mul_int64_Neg4294967296_ssa(-9223372036854775807); got != -4294967296 { + fmt.Printf("mul_int64 -9223372036854775807*-4294967296 = %d, wanted -4294967296\n", got) + failed = true + } + + if got := mul_Neg4294967296_int64_ssa(-4294967296); got != 0 { + fmt.Printf("mul_int64 -4294967296*-4294967296 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int64_Neg4294967296_ssa(-4294967296); got != 0 { + fmt.Printf("mul_int64 -4294967296*-4294967296 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_Neg4294967296_int64_ssa(-1); got != 4294967296 { + fmt.Printf("mul_int64 -4294967296*-1 = %d, wanted 4294967296\n", got) + failed = true + } + + if got := mul_int64_Neg4294967296_ssa(-1); got != 4294967296 { + fmt.Printf("mul_int64 -1*-4294967296 = %d, wanted 4294967296\n", got) + failed = true + } + + if got := mul_Neg4294967296_int64_ssa(0); got != 0 { + fmt.Printf("mul_int64 -4294967296*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int64_Neg4294967296_ssa(0); got != 0 { + fmt.Printf("mul_int64 0*-4294967296 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_Neg4294967296_int64_ssa(1); got != -4294967296 { + fmt.Printf("mul_int64 -4294967296*1 = %d, wanted -4294967296\n", got) + failed = true + } + + if got := mul_int64_Neg4294967296_ssa(1); got != -4294967296 { + fmt.Printf("mul_int64 1*-4294967296 = %d, wanted -4294967296\n", got) + failed = true + } + + if got := mul_Neg4294967296_int64_ssa(4294967296); got != 0 { + fmt.Printf("mul_int64 -4294967296*4294967296 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int64_Neg4294967296_ssa(4294967296); got != 0 { + fmt.Printf("mul_int64 4294967296*-4294967296 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_Neg4294967296_int64_ssa(9223372036854775806); got != 8589934592 { + fmt.Printf("mul_int64 -4294967296*9223372036854775806 = %d, wanted 8589934592\n", got) + failed = true + } + + if got := mul_int64_Neg4294967296_ssa(9223372036854775806); got != 8589934592 { + fmt.Printf("mul_int64 9223372036854775806*-4294967296 = %d, wanted 8589934592\n", got) + failed = true + } + + if got := mul_Neg4294967296_int64_ssa(9223372036854775807); got != 4294967296 { + fmt.Printf("mul_int64 -4294967296*9223372036854775807 = %d, wanted 4294967296\n", got) + failed = true + } + + if got := mul_int64_Neg4294967296_ssa(9223372036854775807); got != 4294967296 { + fmt.Printf("mul_int64 9223372036854775807*-4294967296 = %d, wanted 4294967296\n", got) + failed = true + } + + if got := mul_Neg1_int64_ssa(-9223372036854775808); got != -9223372036854775808 { + fmt.Printf("mul_int64 -1*-9223372036854775808 = %d, wanted -9223372036854775808\n", got) + failed = true + } + + if got := mul_int64_Neg1_ssa(-9223372036854775808); got != -9223372036854775808 { + fmt.Printf("mul_int64 -9223372036854775808*-1 = %d, wanted -9223372036854775808\n", got) + failed = true + } + + if got := mul_Neg1_int64_ssa(-9223372036854775807); got != 9223372036854775807 { + fmt.Printf("mul_int64 -1*-9223372036854775807 = %d, wanted 9223372036854775807\n", got) + failed = true + } + + if got := mul_int64_Neg1_ssa(-9223372036854775807); got != 9223372036854775807 { + fmt.Printf("mul_int64 -9223372036854775807*-1 = %d, wanted 9223372036854775807\n", got) + failed = true + } + + if got := mul_Neg1_int64_ssa(-4294967296); got != 4294967296 { + fmt.Printf("mul_int64 -1*-4294967296 = %d, wanted 4294967296\n", got) + failed = true + } + + if got := mul_int64_Neg1_ssa(-4294967296); got != 4294967296 { + fmt.Printf("mul_int64 -4294967296*-1 = %d, wanted 4294967296\n", got) + failed = true + } + + if got := mul_Neg1_int64_ssa(-1); got != 1 { + fmt.Printf("mul_int64 -1*-1 = %d, wanted 1\n", got) + failed = true + } + + if got := mul_int64_Neg1_ssa(-1); got != 1 { + fmt.Printf("mul_int64 -1*-1 = %d, wanted 1\n", got) + failed = true + } + + if got := mul_Neg1_int64_ssa(0); got != 0 { + fmt.Printf("mul_int64 -1*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int64_Neg1_ssa(0); got != 0 { + fmt.Printf("mul_int64 0*-1 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_Neg1_int64_ssa(1); got != -1 { + fmt.Printf("mul_int64 -1*1 = %d, wanted -1\n", got) + failed = true + } + + if got := mul_int64_Neg1_ssa(1); got != -1 { + fmt.Printf("mul_int64 1*-1 = %d, wanted -1\n", got) + failed = true + } + + if got := mul_Neg1_int64_ssa(4294967296); got != -4294967296 { + fmt.Printf("mul_int64 -1*4294967296 = %d, wanted -4294967296\n", got) + failed = true + } + + if got := mul_int64_Neg1_ssa(4294967296); got != -4294967296 { + fmt.Printf("mul_int64 4294967296*-1 = %d, wanted -4294967296\n", got) + failed = true + } + + if got := mul_Neg1_int64_ssa(9223372036854775806); got != -9223372036854775806 { + fmt.Printf("mul_int64 -1*9223372036854775806 = %d, wanted -9223372036854775806\n", got) + failed = true + } + + if got := mul_int64_Neg1_ssa(9223372036854775806); got != -9223372036854775806 { + fmt.Printf("mul_int64 9223372036854775806*-1 = %d, wanted -9223372036854775806\n", got) + failed = true + } + + if got := mul_Neg1_int64_ssa(9223372036854775807); got != -9223372036854775807 { + fmt.Printf("mul_int64 -1*9223372036854775807 = %d, wanted -9223372036854775807\n", got) + failed = true + } + + if got := mul_int64_Neg1_ssa(9223372036854775807); got != -9223372036854775807 { + fmt.Printf("mul_int64 9223372036854775807*-1 = %d, wanted -9223372036854775807\n", got) + failed = true + } + + if got := mul_0_int64_ssa(-9223372036854775808); got != 0 { + fmt.Printf("mul_int64 0*-9223372036854775808 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int64_0_ssa(-9223372036854775808); got != 0 { + fmt.Printf("mul_int64 -9223372036854775808*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_0_int64_ssa(-9223372036854775807); got != 0 { + fmt.Printf("mul_int64 0*-9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int64_0_ssa(-9223372036854775807); got != 0 { + fmt.Printf("mul_int64 -9223372036854775807*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_0_int64_ssa(-4294967296); got != 0 { + fmt.Printf("mul_int64 0*-4294967296 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int64_0_ssa(-4294967296); got != 0 { + fmt.Printf("mul_int64 -4294967296*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_0_int64_ssa(-1); got != 0 { + fmt.Printf("mul_int64 0*-1 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int64_0_ssa(-1); got != 0 { + fmt.Printf("mul_int64 -1*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_0_int64_ssa(0); got != 0 { + fmt.Printf("mul_int64 0*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int64_0_ssa(0); got != 0 { + fmt.Printf("mul_int64 0*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_0_int64_ssa(1); got != 0 { + fmt.Printf("mul_int64 0*1 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int64_0_ssa(1); got != 0 { + fmt.Printf("mul_int64 1*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_0_int64_ssa(4294967296); got != 0 { + fmt.Printf("mul_int64 0*4294967296 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int64_0_ssa(4294967296); got != 0 { + fmt.Printf("mul_int64 4294967296*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_0_int64_ssa(9223372036854775806); got != 0 { + fmt.Printf("mul_int64 0*9223372036854775806 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int64_0_ssa(9223372036854775806); got != 0 { + fmt.Printf("mul_int64 9223372036854775806*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_0_int64_ssa(9223372036854775807); got != 0 { + fmt.Printf("mul_int64 0*9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int64_0_ssa(9223372036854775807); got != 0 { + fmt.Printf("mul_int64 9223372036854775807*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_1_int64_ssa(-9223372036854775808); got != -9223372036854775808 { + fmt.Printf("mul_int64 1*-9223372036854775808 = %d, wanted -9223372036854775808\n", got) + failed = true + } + + if got := mul_int64_1_ssa(-9223372036854775808); got != -9223372036854775808 { + fmt.Printf("mul_int64 -9223372036854775808*1 = %d, wanted -9223372036854775808\n", got) + failed = true + } + + if got := mul_1_int64_ssa(-9223372036854775807); got != -9223372036854775807 { + fmt.Printf("mul_int64 1*-9223372036854775807 = %d, wanted -9223372036854775807\n", got) + failed = true + } + + if got := mul_int64_1_ssa(-9223372036854775807); got != -9223372036854775807 { + fmt.Printf("mul_int64 -9223372036854775807*1 = %d, wanted -9223372036854775807\n", got) + failed = true + } + + if got := mul_1_int64_ssa(-4294967296); got != -4294967296 { + fmt.Printf("mul_int64 1*-4294967296 = %d, wanted -4294967296\n", got) + failed = true + } + + if got := mul_int64_1_ssa(-4294967296); got != -4294967296 { + fmt.Printf("mul_int64 -4294967296*1 = %d, wanted -4294967296\n", got) + failed = true + } + + if got := mul_1_int64_ssa(-1); got != -1 { + fmt.Printf("mul_int64 1*-1 = %d, wanted -1\n", got) + failed = true + } + + if got := mul_int64_1_ssa(-1); got != -1 { + fmt.Printf("mul_int64 -1*1 = %d, wanted -1\n", got) + failed = true + } + + if got := mul_1_int64_ssa(0); got != 0 { + fmt.Printf("mul_int64 1*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int64_1_ssa(0); got != 0 { + fmt.Printf("mul_int64 0*1 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_1_int64_ssa(1); got != 1 { + fmt.Printf("mul_int64 1*1 = %d, wanted 1\n", got) + failed = true + } + + if got := mul_int64_1_ssa(1); got != 1 { + fmt.Printf("mul_int64 1*1 = %d, wanted 1\n", got) + failed = true + } + + if got := mul_1_int64_ssa(4294967296); got != 4294967296 { + fmt.Printf("mul_int64 1*4294967296 = %d, wanted 4294967296\n", got) + failed = true + } + + if got := mul_int64_1_ssa(4294967296); got != 4294967296 { + fmt.Printf("mul_int64 4294967296*1 = %d, wanted 4294967296\n", got) + failed = true + } + + if got := mul_1_int64_ssa(9223372036854775806); got != 9223372036854775806 { + fmt.Printf("mul_int64 1*9223372036854775806 = %d, wanted 9223372036854775806\n", got) + failed = true + } + + if got := mul_int64_1_ssa(9223372036854775806); got != 9223372036854775806 { + fmt.Printf("mul_int64 9223372036854775806*1 = %d, wanted 9223372036854775806\n", got) + failed = true + } + + if got := mul_1_int64_ssa(9223372036854775807); got != 9223372036854775807 { + fmt.Printf("mul_int64 1*9223372036854775807 = %d, wanted 9223372036854775807\n", got) + failed = true + } + + if got := mul_int64_1_ssa(9223372036854775807); got != 9223372036854775807 { + fmt.Printf("mul_int64 9223372036854775807*1 = %d, wanted 9223372036854775807\n", got) + failed = true + } + + if got := mul_4294967296_int64_ssa(-9223372036854775808); got != 0 { + fmt.Printf("mul_int64 4294967296*-9223372036854775808 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int64_4294967296_ssa(-9223372036854775808); got != 0 { + fmt.Printf("mul_int64 -9223372036854775808*4294967296 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_4294967296_int64_ssa(-9223372036854775807); got != 4294967296 { + fmt.Printf("mul_int64 4294967296*-9223372036854775807 = %d, wanted 4294967296\n", got) + failed = true + } + + if got := mul_int64_4294967296_ssa(-9223372036854775807); got != 4294967296 { + fmt.Printf("mul_int64 -9223372036854775807*4294967296 = %d, wanted 4294967296\n", got) + failed = true + } + + if got := mul_4294967296_int64_ssa(-4294967296); got != 0 { + fmt.Printf("mul_int64 4294967296*-4294967296 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int64_4294967296_ssa(-4294967296); got != 0 { + fmt.Printf("mul_int64 -4294967296*4294967296 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_4294967296_int64_ssa(-1); got != -4294967296 { + fmt.Printf("mul_int64 4294967296*-1 = %d, wanted -4294967296\n", got) + failed = true + } + + if got := mul_int64_4294967296_ssa(-1); got != -4294967296 { + fmt.Printf("mul_int64 -1*4294967296 = %d, wanted -4294967296\n", got) + failed = true + } + + if got := mul_4294967296_int64_ssa(0); got != 0 { + fmt.Printf("mul_int64 4294967296*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int64_4294967296_ssa(0); got != 0 { + fmt.Printf("mul_int64 0*4294967296 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_4294967296_int64_ssa(1); got != 4294967296 { + fmt.Printf("mul_int64 4294967296*1 = %d, wanted 4294967296\n", got) + failed = true + } + + if got := mul_int64_4294967296_ssa(1); got != 4294967296 { + fmt.Printf("mul_int64 1*4294967296 = %d, wanted 4294967296\n", got) + failed = true + } + + if got := mul_4294967296_int64_ssa(4294967296); got != 0 { + fmt.Printf("mul_int64 4294967296*4294967296 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int64_4294967296_ssa(4294967296); got != 0 { + fmt.Printf("mul_int64 4294967296*4294967296 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_4294967296_int64_ssa(9223372036854775806); got != -8589934592 { + fmt.Printf("mul_int64 4294967296*9223372036854775806 = %d, wanted -8589934592\n", got) + failed = true + } + + if got := mul_int64_4294967296_ssa(9223372036854775806); got != -8589934592 { + fmt.Printf("mul_int64 9223372036854775806*4294967296 = %d, wanted -8589934592\n", got) + failed = true + } + + if got := mul_4294967296_int64_ssa(9223372036854775807); got != -4294967296 { + fmt.Printf("mul_int64 4294967296*9223372036854775807 = %d, wanted -4294967296\n", got) + failed = true + } + + if got := mul_int64_4294967296_ssa(9223372036854775807); got != -4294967296 { + fmt.Printf("mul_int64 9223372036854775807*4294967296 = %d, wanted -4294967296\n", got) + failed = true + } + + if got := mul_9223372036854775806_int64_ssa(-9223372036854775808); got != 0 { + fmt.Printf("mul_int64 9223372036854775806*-9223372036854775808 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int64_9223372036854775806_ssa(-9223372036854775808); got != 0 { + fmt.Printf("mul_int64 -9223372036854775808*9223372036854775806 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_9223372036854775806_int64_ssa(-9223372036854775807); got != 9223372036854775806 { + fmt.Printf("mul_int64 9223372036854775806*-9223372036854775807 = %d, wanted 9223372036854775806\n", got) + failed = true + } + + if got := mul_int64_9223372036854775806_ssa(-9223372036854775807); got != 9223372036854775806 { + fmt.Printf("mul_int64 -9223372036854775807*9223372036854775806 = %d, wanted 9223372036854775806\n", got) + failed = true + } + + if got := mul_9223372036854775806_int64_ssa(-4294967296); got != 8589934592 { + fmt.Printf("mul_int64 9223372036854775806*-4294967296 = %d, wanted 8589934592\n", got) + failed = true + } + + if got := mul_int64_9223372036854775806_ssa(-4294967296); got != 8589934592 { + fmt.Printf("mul_int64 -4294967296*9223372036854775806 = %d, wanted 8589934592\n", got) + failed = true + } + + if got := mul_9223372036854775806_int64_ssa(-1); got != -9223372036854775806 { + fmt.Printf("mul_int64 9223372036854775806*-1 = %d, wanted -9223372036854775806\n", got) + failed = true + } + + if got := mul_int64_9223372036854775806_ssa(-1); got != -9223372036854775806 { + fmt.Printf("mul_int64 -1*9223372036854775806 = %d, wanted -9223372036854775806\n", got) + failed = true + } + + if got := mul_9223372036854775806_int64_ssa(0); got != 0 { + fmt.Printf("mul_int64 9223372036854775806*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int64_9223372036854775806_ssa(0); got != 0 { + fmt.Printf("mul_int64 0*9223372036854775806 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_9223372036854775806_int64_ssa(1); got != 9223372036854775806 { + fmt.Printf("mul_int64 9223372036854775806*1 = %d, wanted 9223372036854775806\n", got) + failed = true + } + + if got := mul_int64_9223372036854775806_ssa(1); got != 9223372036854775806 { + fmt.Printf("mul_int64 1*9223372036854775806 = %d, wanted 9223372036854775806\n", got) + failed = true + } + + if got := mul_9223372036854775806_int64_ssa(4294967296); got != -8589934592 { + fmt.Printf("mul_int64 9223372036854775806*4294967296 = %d, wanted -8589934592\n", got) + failed = true + } + + if got := mul_int64_9223372036854775806_ssa(4294967296); got != -8589934592 { + fmt.Printf("mul_int64 4294967296*9223372036854775806 = %d, wanted -8589934592\n", got) + failed = true + } + + if got := mul_9223372036854775806_int64_ssa(9223372036854775806); got != 4 { + fmt.Printf("mul_int64 9223372036854775806*9223372036854775806 = %d, wanted 4\n", got) + failed = true + } + + if got := mul_int64_9223372036854775806_ssa(9223372036854775806); got != 4 { + fmt.Printf("mul_int64 9223372036854775806*9223372036854775806 = %d, wanted 4\n", got) + failed = true + } + + if got := mul_9223372036854775806_int64_ssa(9223372036854775807); got != -9223372036854775806 { + fmt.Printf("mul_int64 9223372036854775806*9223372036854775807 = %d, wanted -9223372036854775806\n", got) + failed = true + } + + if got := mul_int64_9223372036854775806_ssa(9223372036854775807); got != -9223372036854775806 { + fmt.Printf("mul_int64 9223372036854775807*9223372036854775806 = %d, wanted -9223372036854775806\n", got) + failed = true + } + + if got := mul_9223372036854775807_int64_ssa(-9223372036854775808); got != -9223372036854775808 { + fmt.Printf("mul_int64 9223372036854775807*-9223372036854775808 = %d, wanted -9223372036854775808\n", got) + failed = true + } + + if got := mul_int64_9223372036854775807_ssa(-9223372036854775808); got != -9223372036854775808 { + fmt.Printf("mul_int64 -9223372036854775808*9223372036854775807 = %d, wanted -9223372036854775808\n", got) + failed = true + } + + if got := mul_9223372036854775807_int64_ssa(-9223372036854775807); got != -1 { + fmt.Printf("mul_int64 9223372036854775807*-9223372036854775807 = %d, wanted -1\n", got) + failed = true + } + + if got := mul_int64_9223372036854775807_ssa(-9223372036854775807); got != -1 { + fmt.Printf("mul_int64 -9223372036854775807*9223372036854775807 = %d, wanted -1\n", got) + failed = true + } + + if got := mul_9223372036854775807_int64_ssa(-4294967296); got != 4294967296 { + fmt.Printf("mul_int64 9223372036854775807*-4294967296 = %d, wanted 4294967296\n", got) + failed = true + } + + if got := mul_int64_9223372036854775807_ssa(-4294967296); got != 4294967296 { + fmt.Printf("mul_int64 -4294967296*9223372036854775807 = %d, wanted 4294967296\n", got) + failed = true + } + + if got := mul_9223372036854775807_int64_ssa(-1); got != -9223372036854775807 { + fmt.Printf("mul_int64 9223372036854775807*-1 = %d, wanted -9223372036854775807\n", got) + failed = true + } + + if got := mul_int64_9223372036854775807_ssa(-1); got != -9223372036854775807 { + fmt.Printf("mul_int64 -1*9223372036854775807 = %d, wanted -9223372036854775807\n", got) + failed = true + } + + if got := mul_9223372036854775807_int64_ssa(0); got != 0 { + fmt.Printf("mul_int64 9223372036854775807*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int64_9223372036854775807_ssa(0); got != 0 { + fmt.Printf("mul_int64 0*9223372036854775807 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_9223372036854775807_int64_ssa(1); got != 9223372036854775807 { + fmt.Printf("mul_int64 9223372036854775807*1 = %d, wanted 9223372036854775807\n", got) + failed = true + } + + if got := mul_int64_9223372036854775807_ssa(1); got != 9223372036854775807 { + fmt.Printf("mul_int64 1*9223372036854775807 = %d, wanted 9223372036854775807\n", got) + failed = true + } + + if got := mul_9223372036854775807_int64_ssa(4294967296); got != -4294967296 { + fmt.Printf("mul_int64 9223372036854775807*4294967296 = %d, wanted -4294967296\n", got) + failed = true + } + + if got := mul_int64_9223372036854775807_ssa(4294967296); got != -4294967296 { + fmt.Printf("mul_int64 4294967296*9223372036854775807 = %d, wanted -4294967296\n", got) + failed = true + } + + if got := mul_9223372036854775807_int64_ssa(9223372036854775806); got != -9223372036854775806 { + fmt.Printf("mul_int64 9223372036854775807*9223372036854775806 = %d, wanted -9223372036854775806\n", got) + failed = true + } + + if got := mul_int64_9223372036854775807_ssa(9223372036854775806); got != -9223372036854775806 { + fmt.Printf("mul_int64 9223372036854775806*9223372036854775807 = %d, wanted -9223372036854775806\n", got) + failed = true + } + + if got := mul_9223372036854775807_int64_ssa(9223372036854775807); got != 1 { + fmt.Printf("mul_int64 9223372036854775807*9223372036854775807 = %d, wanted 1\n", got) + failed = true + } + + if got := mul_int64_9223372036854775807_ssa(9223372036854775807); got != 1 { + fmt.Printf("mul_int64 9223372036854775807*9223372036854775807 = %d, wanted 1\n", got) + failed = true + } + + if got := add_0_uint32_ssa(0); got != 0 { + fmt.Printf("add_uint32 0+0 = %d, wanted 0\n", got) + failed = true + } + + if got := add_uint32_0_ssa(0); got != 0 { + fmt.Printf("add_uint32 0+0 = %d, wanted 0\n", got) + failed = true + } + + if got := add_0_uint32_ssa(1); got != 1 { + fmt.Printf("add_uint32 0+1 = %d, wanted 1\n", got) + failed = true + } + + if got := add_uint32_0_ssa(1); got != 1 { + fmt.Printf("add_uint32 1+0 = %d, wanted 1\n", got) + failed = true + } + + if got := add_0_uint32_ssa(4294967295); got != 4294967295 { + fmt.Printf("add_uint32 0+4294967295 = %d, wanted 4294967295\n", got) + failed = true + } + + if got := add_uint32_0_ssa(4294967295); got != 4294967295 { + fmt.Printf("add_uint32 4294967295+0 = %d, wanted 4294967295\n", got) + failed = true + } + + if got := add_1_uint32_ssa(0); got != 1 { + fmt.Printf("add_uint32 1+0 = %d, wanted 1\n", got) + failed = true + } + + if got := add_uint32_1_ssa(0); got != 1 { + fmt.Printf("add_uint32 0+1 = %d, wanted 1\n", got) + failed = true + } + + if got := add_1_uint32_ssa(1); got != 2 { + fmt.Printf("add_uint32 1+1 = %d, wanted 2\n", got) + failed = true + } + + if got := add_uint32_1_ssa(1); got != 2 { + fmt.Printf("add_uint32 1+1 = %d, wanted 2\n", got) + failed = true + } + + if got := add_1_uint32_ssa(4294967295); got != 0 { + fmt.Printf("add_uint32 1+4294967295 = %d, wanted 0\n", got) + failed = true + } + + if got := add_uint32_1_ssa(4294967295); got != 0 { + fmt.Printf("add_uint32 4294967295+1 = %d, wanted 0\n", got) + failed = true + } + + if got := add_4294967295_uint32_ssa(0); got != 4294967295 { + fmt.Printf("add_uint32 4294967295+0 = %d, wanted 4294967295\n", got) + failed = true + } + + if got := add_uint32_4294967295_ssa(0); got != 4294967295 { + fmt.Printf("add_uint32 0+4294967295 = %d, wanted 4294967295\n", got) + failed = true + } + + if got := add_4294967295_uint32_ssa(1); got != 0 { + fmt.Printf("add_uint32 4294967295+1 = %d, wanted 0\n", got) + failed = true + } + + if got := add_uint32_4294967295_ssa(1); got != 0 { + fmt.Printf("add_uint32 1+4294967295 = %d, wanted 0\n", got) + failed = true + } + + if got := add_4294967295_uint32_ssa(4294967295); got != 4294967294 { + fmt.Printf("add_uint32 4294967295+4294967295 = %d, wanted 4294967294\n", got) + failed = true + } + + if got := add_uint32_4294967295_ssa(4294967295); got != 4294967294 { + fmt.Printf("add_uint32 4294967295+4294967295 = %d, wanted 4294967294\n", got) + failed = true + } + + if got := sub_0_uint32_ssa(0); got != 0 { + fmt.Printf("sub_uint32 0-0 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_uint32_0_ssa(0); got != 0 { + fmt.Printf("sub_uint32 0-0 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_0_uint32_ssa(1); got != 4294967295 { + fmt.Printf("sub_uint32 0-1 = %d, wanted 4294967295\n", got) + failed = true + } + + if got := sub_uint32_0_ssa(1); got != 1 { + fmt.Printf("sub_uint32 1-0 = %d, wanted 1\n", got) + failed = true + } + + if got := sub_0_uint32_ssa(4294967295); got != 1 { + fmt.Printf("sub_uint32 0-4294967295 = %d, wanted 1\n", got) + failed = true + } + + if got := sub_uint32_0_ssa(4294967295); got != 4294967295 { + fmt.Printf("sub_uint32 4294967295-0 = %d, wanted 4294967295\n", got) + failed = true + } + + if got := sub_1_uint32_ssa(0); got != 1 { + fmt.Printf("sub_uint32 1-0 = %d, wanted 1\n", got) + failed = true + } + + if got := sub_uint32_1_ssa(0); got != 4294967295 { + fmt.Printf("sub_uint32 0-1 = %d, wanted 4294967295\n", got) + failed = true + } + + if got := sub_1_uint32_ssa(1); got != 0 { + fmt.Printf("sub_uint32 1-1 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_uint32_1_ssa(1); got != 0 { + fmt.Printf("sub_uint32 1-1 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_1_uint32_ssa(4294967295); got != 2 { + fmt.Printf("sub_uint32 1-4294967295 = %d, wanted 2\n", got) + failed = true + } + + if got := sub_uint32_1_ssa(4294967295); got != 4294967294 { + fmt.Printf("sub_uint32 4294967295-1 = %d, wanted 4294967294\n", got) + failed = true + } + + if got := sub_4294967295_uint32_ssa(0); got != 4294967295 { + fmt.Printf("sub_uint32 4294967295-0 = %d, wanted 4294967295\n", got) + failed = true + } + + if got := sub_uint32_4294967295_ssa(0); got != 1 { + fmt.Printf("sub_uint32 0-4294967295 = %d, wanted 1\n", got) + failed = true + } + + if got := sub_4294967295_uint32_ssa(1); got != 4294967294 { + fmt.Printf("sub_uint32 4294967295-1 = %d, wanted 4294967294\n", got) + failed = true + } + + if got := sub_uint32_4294967295_ssa(1); got != 2 { + fmt.Printf("sub_uint32 1-4294967295 = %d, wanted 2\n", got) + failed = true + } + + if got := sub_4294967295_uint32_ssa(4294967295); got != 0 { + fmt.Printf("sub_uint32 4294967295-4294967295 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_uint32_4294967295_ssa(4294967295); got != 0 { + fmt.Printf("sub_uint32 4294967295-4294967295 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_uint32_ssa(1); got != 0 { + fmt.Printf("div_uint32 0/1 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_uint32_ssa(4294967295); got != 0 { + fmt.Printf("div_uint32 0/4294967295 = %d, wanted 0\n", got) + failed = true + } + + if got := div_uint32_1_ssa(0); got != 0 { + fmt.Printf("div_uint32 0/1 = %d, wanted 0\n", got) + failed = true + } + + if got := div_1_uint32_ssa(1); got != 1 { + fmt.Printf("div_uint32 1/1 = %d, wanted 1\n", got) + failed = true + } + + if got := div_uint32_1_ssa(1); got != 1 { + fmt.Printf("div_uint32 1/1 = %d, wanted 1\n", got) + failed = true + } + + if got := div_1_uint32_ssa(4294967295); got != 0 { + fmt.Printf("div_uint32 1/4294967295 = %d, wanted 0\n", got) + failed = true + } + + if got := div_uint32_1_ssa(4294967295); got != 4294967295 { + fmt.Printf("div_uint32 4294967295/1 = %d, wanted 4294967295\n", got) + failed = true + } + + if got := div_uint32_4294967295_ssa(0); got != 0 { + fmt.Printf("div_uint32 0/4294967295 = %d, wanted 0\n", got) + failed = true + } + + if got := div_4294967295_uint32_ssa(1); got != 4294967295 { + fmt.Printf("div_uint32 4294967295/1 = %d, wanted 4294967295\n", got) + failed = true + } + + if got := div_uint32_4294967295_ssa(1); got != 0 { + fmt.Printf("div_uint32 1/4294967295 = %d, wanted 0\n", got) + failed = true + } + + if got := div_4294967295_uint32_ssa(4294967295); got != 1 { + fmt.Printf("div_uint32 4294967295/4294967295 = %d, wanted 1\n", got) + failed = true + } + + if got := div_uint32_4294967295_ssa(4294967295); got != 1 { + fmt.Printf("div_uint32 4294967295/4294967295 = %d, wanted 1\n", got) + failed = true + } + + if got := mul_0_uint32_ssa(0); got != 0 { + fmt.Printf("mul_uint32 0*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_uint32_0_ssa(0); got != 0 { + fmt.Printf("mul_uint32 0*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_0_uint32_ssa(1); got != 0 { + fmt.Printf("mul_uint32 0*1 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_uint32_0_ssa(1); got != 0 { + fmt.Printf("mul_uint32 1*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_0_uint32_ssa(4294967295); got != 0 { + fmt.Printf("mul_uint32 0*4294967295 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_uint32_0_ssa(4294967295); got != 0 { + fmt.Printf("mul_uint32 4294967295*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_1_uint32_ssa(0); got != 0 { + fmt.Printf("mul_uint32 1*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_uint32_1_ssa(0); got != 0 { + fmt.Printf("mul_uint32 0*1 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_1_uint32_ssa(1); got != 1 { + fmt.Printf("mul_uint32 1*1 = %d, wanted 1\n", got) + failed = true + } + + if got := mul_uint32_1_ssa(1); got != 1 { + fmt.Printf("mul_uint32 1*1 = %d, wanted 1\n", got) + failed = true + } + + if got := mul_1_uint32_ssa(4294967295); got != 4294967295 { + fmt.Printf("mul_uint32 1*4294967295 = %d, wanted 4294967295\n", got) + failed = true + } + + if got := mul_uint32_1_ssa(4294967295); got != 4294967295 { + fmt.Printf("mul_uint32 4294967295*1 = %d, wanted 4294967295\n", got) + failed = true + } + + if got := mul_4294967295_uint32_ssa(0); got != 0 { + fmt.Printf("mul_uint32 4294967295*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_uint32_4294967295_ssa(0); got != 0 { + fmt.Printf("mul_uint32 0*4294967295 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_4294967295_uint32_ssa(1); got != 4294967295 { + fmt.Printf("mul_uint32 4294967295*1 = %d, wanted 4294967295\n", got) + failed = true + } + + if got := mul_uint32_4294967295_ssa(1); got != 4294967295 { + fmt.Printf("mul_uint32 1*4294967295 = %d, wanted 4294967295\n", got) + failed = true + } + + if got := mul_4294967295_uint32_ssa(4294967295); got != 1 { + fmt.Printf("mul_uint32 4294967295*4294967295 = %d, wanted 1\n", got) + failed = true + } + + if got := mul_uint32_4294967295_ssa(4294967295); got != 1 { + fmt.Printf("mul_uint32 4294967295*4294967295 = %d, wanted 1\n", got) + failed = true + } + + if got := lsh_0_uint32_ssa(0); got != 0 { + fmt.Printf("lsh_uint32 0<<0 = %d, wanted 0\n", got) + failed = true + } + + if got := lsh_uint32_0_ssa(0); got != 0 { + fmt.Printf("lsh_uint32 0<<0 = %d, wanted 0\n", got) + failed = true + } + + if got := lsh_0_uint32_ssa(1); got != 0 { + fmt.Printf("lsh_uint32 0<<1 = %d, wanted 0\n", got) + failed = true + } + + if got := lsh_uint32_0_ssa(1); got != 1 { + fmt.Printf("lsh_uint32 1<<0 = %d, wanted 1\n", got) + failed = true + } + + if got := lsh_0_uint32_ssa(4294967295); got != 0 { + fmt.Printf("lsh_uint32 0<<4294967295 = %d, wanted 0\n", got) + failed = true + } + + if got := lsh_uint32_0_ssa(4294967295); got != 4294967295 { + fmt.Printf("lsh_uint32 4294967295<<0 = %d, wanted 4294967295\n", got) + failed = true + } + + if got := lsh_1_uint32_ssa(0); got != 1 { + fmt.Printf("lsh_uint32 1<<0 = %d, wanted 1\n", got) + failed = true + } + + if got := lsh_uint32_1_ssa(0); got != 0 { + fmt.Printf("lsh_uint32 0<<1 = %d, wanted 0\n", got) + failed = true + } + + if got := lsh_1_uint32_ssa(1); got != 2 { + fmt.Printf("lsh_uint32 1<<1 = %d, wanted 2\n", got) + failed = true + } + + if got := lsh_uint32_1_ssa(1); got != 2 { + fmt.Printf("lsh_uint32 1<<1 = %d, wanted 2\n", got) + failed = true + } + + if got := lsh_1_uint32_ssa(4294967295); got != 0 { + fmt.Printf("lsh_uint32 1<<4294967295 = %d, wanted 0\n", got) + failed = true + } + + if got := lsh_uint32_1_ssa(4294967295); got != 4294967294 { + fmt.Printf("lsh_uint32 4294967295<<1 = %d, wanted 4294967294\n", got) + failed = true + } + + if got := lsh_4294967295_uint32_ssa(0); got != 4294967295 { + fmt.Printf("lsh_uint32 4294967295<<0 = %d, wanted 4294967295\n", got) + failed = true + } + + if got := lsh_uint32_4294967295_ssa(0); got != 0 { + fmt.Printf("lsh_uint32 0<<4294967295 = %d, wanted 0\n", got) + failed = true + } + + if got := lsh_4294967295_uint32_ssa(1); got != 4294967294 { + fmt.Printf("lsh_uint32 4294967295<<1 = %d, wanted 4294967294\n", got) + failed = true + } + + if got := lsh_uint32_4294967295_ssa(1); got != 0 { + fmt.Printf("lsh_uint32 1<<4294967295 = %d, wanted 0\n", got) + failed = true + } + + if got := lsh_4294967295_uint32_ssa(4294967295); got != 0 { + fmt.Printf("lsh_uint32 4294967295<<4294967295 = %d, wanted 0\n", got) + failed = true + } + + if got := lsh_uint32_4294967295_ssa(4294967295); got != 0 { + fmt.Printf("lsh_uint32 4294967295<<4294967295 = %d, wanted 0\n", got) + failed = true + } + + if got := rsh_0_uint32_ssa(0); got != 0 { + fmt.Printf("rsh_uint32 0>>0 = %d, wanted 0\n", got) + failed = true + } + + if got := rsh_uint32_0_ssa(0); got != 0 { + fmt.Printf("rsh_uint32 0>>0 = %d, wanted 0\n", got) + failed = true + } + + if got := rsh_0_uint32_ssa(1); got != 0 { + fmt.Printf("rsh_uint32 0>>1 = %d, wanted 0\n", got) + failed = true + } + + if got := rsh_uint32_0_ssa(1); got != 1 { + fmt.Printf("rsh_uint32 1>>0 = %d, wanted 1\n", got) + failed = true + } + + if got := rsh_0_uint32_ssa(4294967295); got != 0 { + fmt.Printf("rsh_uint32 0>>4294967295 = %d, wanted 0\n", got) + failed = true + } + + if got := rsh_uint32_0_ssa(4294967295); got != 4294967295 { + fmt.Printf("rsh_uint32 4294967295>>0 = %d, wanted 4294967295\n", got) + failed = true + } + + if got := rsh_1_uint32_ssa(0); got != 1 { + fmt.Printf("rsh_uint32 1>>0 = %d, wanted 1\n", got) + failed = true + } + + if got := rsh_uint32_1_ssa(0); got != 0 { + fmt.Printf("rsh_uint32 0>>1 = %d, wanted 0\n", got) + failed = true + } + + if got := rsh_1_uint32_ssa(1); got != 0 { + fmt.Printf("rsh_uint32 1>>1 = %d, wanted 0\n", got) + failed = true + } + + if got := rsh_uint32_1_ssa(1); got != 0 { + fmt.Printf("rsh_uint32 1>>1 = %d, wanted 0\n", got) + failed = true + } + + if got := rsh_1_uint32_ssa(4294967295); got != 0 { + fmt.Printf("rsh_uint32 1>>4294967295 = %d, wanted 0\n", got) + failed = true + } + + if got := rsh_uint32_1_ssa(4294967295); got != 2147483647 { + fmt.Printf("rsh_uint32 4294967295>>1 = %d, wanted 2147483647\n", got) + failed = true + } + + if got := rsh_4294967295_uint32_ssa(0); got != 4294967295 { + fmt.Printf("rsh_uint32 4294967295>>0 = %d, wanted 4294967295\n", got) + failed = true + } + + if got := rsh_uint32_4294967295_ssa(0); got != 0 { + fmt.Printf("rsh_uint32 0>>4294967295 = %d, wanted 0\n", got) + failed = true + } + + if got := rsh_4294967295_uint32_ssa(1); got != 2147483647 { + fmt.Printf("rsh_uint32 4294967295>>1 = %d, wanted 2147483647\n", got) + failed = true + } + + if got := rsh_uint32_4294967295_ssa(1); got != 0 { + fmt.Printf("rsh_uint32 1>>4294967295 = %d, wanted 0\n", got) + failed = true + } + + if got := rsh_4294967295_uint32_ssa(4294967295); got != 0 { + fmt.Printf("rsh_uint32 4294967295>>4294967295 = %d, wanted 0\n", got) + failed = true + } + + if got := rsh_uint32_4294967295_ssa(4294967295); got != 0 { + fmt.Printf("rsh_uint32 4294967295>>4294967295 = %d, wanted 0\n", got) + failed = true + } + + if got := add_Neg2147483648_int32_ssa(-2147483648); got != 0 { + fmt.Printf("add_int32 -2147483648+-2147483648 = %d, wanted 0\n", got) + failed = true + } + + if got := add_int32_Neg2147483648_ssa(-2147483648); got != 0 { + fmt.Printf("add_int32 -2147483648+-2147483648 = %d, wanted 0\n", got) + failed = true + } + + if got := add_Neg2147483648_int32_ssa(-2147483647); got != 1 { + fmt.Printf("add_int32 -2147483648+-2147483647 = %d, wanted 1\n", got) + failed = true + } + + if got := add_int32_Neg2147483648_ssa(-2147483647); got != 1 { + fmt.Printf("add_int32 -2147483647+-2147483648 = %d, wanted 1\n", got) + failed = true + } + + if got := add_Neg2147483648_int32_ssa(-1); got != 2147483647 { + fmt.Printf("add_int32 -2147483648+-1 = %d, wanted 2147483647\n", got) + failed = true + } + + if got := add_int32_Neg2147483648_ssa(-1); got != 2147483647 { + fmt.Printf("add_int32 -1+-2147483648 = %d, wanted 2147483647\n", got) + failed = true + } + + if got := add_Neg2147483648_int32_ssa(0); got != -2147483648 { + fmt.Printf("add_int32 -2147483648+0 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := add_int32_Neg2147483648_ssa(0); got != -2147483648 { + fmt.Printf("add_int32 0+-2147483648 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := add_Neg2147483648_int32_ssa(1); got != -2147483647 { + fmt.Printf("add_int32 -2147483648+1 = %d, wanted -2147483647\n", got) + failed = true + } + + if got := add_int32_Neg2147483648_ssa(1); got != -2147483647 { + fmt.Printf("add_int32 1+-2147483648 = %d, wanted -2147483647\n", got) + failed = true + } + + if got := add_Neg2147483648_int32_ssa(2147483647); got != -1 { + fmt.Printf("add_int32 -2147483648+2147483647 = %d, wanted -1\n", got) + failed = true + } + + if got := add_int32_Neg2147483648_ssa(2147483647); got != -1 { + fmt.Printf("add_int32 2147483647+-2147483648 = %d, wanted -1\n", got) + failed = true + } + + if got := add_Neg2147483647_int32_ssa(-2147483648); got != 1 { + fmt.Printf("add_int32 -2147483647+-2147483648 = %d, wanted 1\n", got) + failed = true + } + + if got := add_int32_Neg2147483647_ssa(-2147483648); got != 1 { + fmt.Printf("add_int32 -2147483648+-2147483647 = %d, wanted 1\n", got) + failed = true + } + + if got := add_Neg2147483647_int32_ssa(-2147483647); got != 2 { + fmt.Printf("add_int32 -2147483647+-2147483647 = %d, wanted 2\n", got) + failed = true + } + + if got := add_int32_Neg2147483647_ssa(-2147483647); got != 2 { + fmt.Printf("add_int32 -2147483647+-2147483647 = %d, wanted 2\n", got) + failed = true + } + + if got := add_Neg2147483647_int32_ssa(-1); got != -2147483648 { + fmt.Printf("add_int32 -2147483647+-1 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := add_int32_Neg2147483647_ssa(-1); got != -2147483648 { + fmt.Printf("add_int32 -1+-2147483647 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := add_Neg2147483647_int32_ssa(0); got != -2147483647 { + fmt.Printf("add_int32 -2147483647+0 = %d, wanted -2147483647\n", got) + failed = true + } + + if got := add_int32_Neg2147483647_ssa(0); got != -2147483647 { + fmt.Printf("add_int32 0+-2147483647 = %d, wanted -2147483647\n", got) + failed = true + } + + if got := add_Neg2147483647_int32_ssa(1); got != -2147483646 { + fmt.Printf("add_int32 -2147483647+1 = %d, wanted -2147483646\n", got) + failed = true + } + + if got := add_int32_Neg2147483647_ssa(1); got != -2147483646 { + fmt.Printf("add_int32 1+-2147483647 = %d, wanted -2147483646\n", got) + failed = true + } + + if got := add_Neg2147483647_int32_ssa(2147483647); got != 0 { + fmt.Printf("add_int32 -2147483647+2147483647 = %d, wanted 0\n", got) + failed = true + } + + if got := add_int32_Neg2147483647_ssa(2147483647); got != 0 { + fmt.Printf("add_int32 2147483647+-2147483647 = %d, wanted 0\n", got) + failed = true + } + + if got := add_Neg1_int32_ssa(-2147483648); got != 2147483647 { + fmt.Printf("add_int32 -1+-2147483648 = %d, wanted 2147483647\n", got) + failed = true + } + + if got := add_int32_Neg1_ssa(-2147483648); got != 2147483647 { + fmt.Printf("add_int32 -2147483648+-1 = %d, wanted 2147483647\n", got) + failed = true + } + + if got := add_Neg1_int32_ssa(-2147483647); got != -2147483648 { + fmt.Printf("add_int32 -1+-2147483647 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := add_int32_Neg1_ssa(-2147483647); got != -2147483648 { + fmt.Printf("add_int32 -2147483647+-1 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := add_Neg1_int32_ssa(-1); got != -2 { + fmt.Printf("add_int32 -1+-1 = %d, wanted -2\n", got) + failed = true + } + + if got := add_int32_Neg1_ssa(-1); got != -2 { + fmt.Printf("add_int32 -1+-1 = %d, wanted -2\n", got) + failed = true + } + + if got := add_Neg1_int32_ssa(0); got != -1 { + fmt.Printf("add_int32 -1+0 = %d, wanted -1\n", got) + failed = true + } + + if got := add_int32_Neg1_ssa(0); got != -1 { + fmt.Printf("add_int32 0+-1 = %d, wanted -1\n", got) + failed = true + } + + if got := add_Neg1_int32_ssa(1); got != 0 { + fmt.Printf("add_int32 -1+1 = %d, wanted 0\n", got) + failed = true + } + + if got := add_int32_Neg1_ssa(1); got != 0 { + fmt.Printf("add_int32 1+-1 = %d, wanted 0\n", got) + failed = true + } + + if got := add_Neg1_int32_ssa(2147483647); got != 2147483646 { + fmt.Printf("add_int32 -1+2147483647 = %d, wanted 2147483646\n", got) + failed = true + } + + if got := add_int32_Neg1_ssa(2147483647); got != 2147483646 { + fmt.Printf("add_int32 2147483647+-1 = %d, wanted 2147483646\n", got) + failed = true + } + + if got := add_0_int32_ssa(-2147483648); got != -2147483648 { + fmt.Printf("add_int32 0+-2147483648 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := add_int32_0_ssa(-2147483648); got != -2147483648 { + fmt.Printf("add_int32 -2147483648+0 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := add_0_int32_ssa(-2147483647); got != -2147483647 { + fmt.Printf("add_int32 0+-2147483647 = %d, wanted -2147483647\n", got) + failed = true + } + + if got := add_int32_0_ssa(-2147483647); got != -2147483647 { + fmt.Printf("add_int32 -2147483647+0 = %d, wanted -2147483647\n", got) + failed = true + } + + if got := add_0_int32_ssa(-1); got != -1 { + fmt.Printf("add_int32 0+-1 = %d, wanted -1\n", got) + failed = true + } + + if got := add_int32_0_ssa(-1); got != -1 { + fmt.Printf("add_int32 -1+0 = %d, wanted -1\n", got) + failed = true + } + + if got := add_0_int32_ssa(0); got != 0 { + fmt.Printf("add_int32 0+0 = %d, wanted 0\n", got) + failed = true + } + + if got := add_int32_0_ssa(0); got != 0 { + fmt.Printf("add_int32 0+0 = %d, wanted 0\n", got) + failed = true + } + + if got := add_0_int32_ssa(1); got != 1 { + fmt.Printf("add_int32 0+1 = %d, wanted 1\n", got) + failed = true + } + + if got := add_int32_0_ssa(1); got != 1 { + fmt.Printf("add_int32 1+0 = %d, wanted 1\n", got) + failed = true + } + + if got := add_0_int32_ssa(2147483647); got != 2147483647 { + fmt.Printf("add_int32 0+2147483647 = %d, wanted 2147483647\n", got) + failed = true + } + + if got := add_int32_0_ssa(2147483647); got != 2147483647 { + fmt.Printf("add_int32 2147483647+0 = %d, wanted 2147483647\n", got) + failed = true + } + + if got := add_1_int32_ssa(-2147483648); got != -2147483647 { + fmt.Printf("add_int32 1+-2147483648 = %d, wanted -2147483647\n", got) + failed = true + } + + if got := add_int32_1_ssa(-2147483648); got != -2147483647 { + fmt.Printf("add_int32 -2147483648+1 = %d, wanted -2147483647\n", got) + failed = true + } + + if got := add_1_int32_ssa(-2147483647); got != -2147483646 { + fmt.Printf("add_int32 1+-2147483647 = %d, wanted -2147483646\n", got) + failed = true + } + + if got := add_int32_1_ssa(-2147483647); got != -2147483646 { + fmt.Printf("add_int32 -2147483647+1 = %d, wanted -2147483646\n", got) + failed = true + } + + if got := add_1_int32_ssa(-1); got != 0 { + fmt.Printf("add_int32 1+-1 = %d, wanted 0\n", got) + failed = true + } + + if got := add_int32_1_ssa(-1); got != 0 { + fmt.Printf("add_int32 -1+1 = %d, wanted 0\n", got) + failed = true + } + + if got := add_1_int32_ssa(0); got != 1 { + fmt.Printf("add_int32 1+0 = %d, wanted 1\n", got) + failed = true + } + + if got := add_int32_1_ssa(0); got != 1 { + fmt.Printf("add_int32 0+1 = %d, wanted 1\n", got) + failed = true + } + + if got := add_1_int32_ssa(1); got != 2 { + fmt.Printf("add_int32 1+1 = %d, wanted 2\n", got) + failed = true + } + + if got := add_int32_1_ssa(1); got != 2 { + fmt.Printf("add_int32 1+1 = %d, wanted 2\n", got) + failed = true + } + + if got := add_1_int32_ssa(2147483647); got != -2147483648 { + fmt.Printf("add_int32 1+2147483647 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := add_int32_1_ssa(2147483647); got != -2147483648 { + fmt.Printf("add_int32 2147483647+1 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := add_2147483647_int32_ssa(-2147483648); got != -1 { + fmt.Printf("add_int32 2147483647+-2147483648 = %d, wanted -1\n", got) + failed = true + } + + if got := add_int32_2147483647_ssa(-2147483648); got != -1 { + fmt.Printf("add_int32 -2147483648+2147483647 = %d, wanted -1\n", got) + failed = true + } + + if got := add_2147483647_int32_ssa(-2147483647); got != 0 { + fmt.Printf("add_int32 2147483647+-2147483647 = %d, wanted 0\n", got) + failed = true + } + + if got := add_int32_2147483647_ssa(-2147483647); got != 0 { + fmt.Printf("add_int32 -2147483647+2147483647 = %d, wanted 0\n", got) + failed = true + } + + if got := add_2147483647_int32_ssa(-1); got != 2147483646 { + fmt.Printf("add_int32 2147483647+-1 = %d, wanted 2147483646\n", got) + failed = true + } + + if got := add_int32_2147483647_ssa(-1); got != 2147483646 { + fmt.Printf("add_int32 -1+2147483647 = %d, wanted 2147483646\n", got) + failed = true + } + + if got := add_2147483647_int32_ssa(0); got != 2147483647 { + fmt.Printf("add_int32 2147483647+0 = %d, wanted 2147483647\n", got) + failed = true + } + + if got := add_int32_2147483647_ssa(0); got != 2147483647 { + fmt.Printf("add_int32 0+2147483647 = %d, wanted 2147483647\n", got) + failed = true + } + + if got := add_2147483647_int32_ssa(1); got != -2147483648 { + fmt.Printf("add_int32 2147483647+1 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := add_int32_2147483647_ssa(1); got != -2147483648 { + fmt.Printf("add_int32 1+2147483647 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := add_2147483647_int32_ssa(2147483647); got != -2 { + fmt.Printf("add_int32 2147483647+2147483647 = %d, wanted -2\n", got) + failed = true + } + + if got := add_int32_2147483647_ssa(2147483647); got != -2 { + fmt.Printf("add_int32 2147483647+2147483647 = %d, wanted -2\n", got) + failed = true + } + + if got := sub_Neg2147483648_int32_ssa(-2147483648); got != 0 { + fmt.Printf("sub_int32 -2147483648--2147483648 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_int32_Neg2147483648_ssa(-2147483648); got != 0 { + fmt.Printf("sub_int32 -2147483648--2147483648 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_Neg2147483648_int32_ssa(-2147483647); got != -1 { + fmt.Printf("sub_int32 -2147483648--2147483647 = %d, wanted -1\n", got) + failed = true + } + + if got := sub_int32_Neg2147483648_ssa(-2147483647); got != 1 { + fmt.Printf("sub_int32 -2147483647--2147483648 = %d, wanted 1\n", got) + failed = true + } + + if got := sub_Neg2147483648_int32_ssa(-1); got != -2147483647 { + fmt.Printf("sub_int32 -2147483648--1 = %d, wanted -2147483647\n", got) + failed = true + } + + if got := sub_int32_Neg2147483648_ssa(-1); got != 2147483647 { + fmt.Printf("sub_int32 -1--2147483648 = %d, wanted 2147483647\n", got) + failed = true + } + + if got := sub_Neg2147483648_int32_ssa(0); got != -2147483648 { + fmt.Printf("sub_int32 -2147483648-0 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := sub_int32_Neg2147483648_ssa(0); got != -2147483648 { + fmt.Printf("sub_int32 0--2147483648 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := sub_Neg2147483648_int32_ssa(1); got != 2147483647 { + fmt.Printf("sub_int32 -2147483648-1 = %d, wanted 2147483647\n", got) + failed = true + } + + if got := sub_int32_Neg2147483648_ssa(1); got != -2147483647 { + fmt.Printf("sub_int32 1--2147483648 = %d, wanted -2147483647\n", got) + failed = true + } + + if got := sub_Neg2147483648_int32_ssa(2147483647); got != 1 { + fmt.Printf("sub_int32 -2147483648-2147483647 = %d, wanted 1\n", got) + failed = true + } + + if got := sub_int32_Neg2147483648_ssa(2147483647); got != -1 { + fmt.Printf("sub_int32 2147483647--2147483648 = %d, wanted -1\n", got) + failed = true + } + + if got := sub_Neg2147483647_int32_ssa(-2147483648); got != 1 { + fmt.Printf("sub_int32 -2147483647--2147483648 = %d, wanted 1\n", got) + failed = true + } + + if got := sub_int32_Neg2147483647_ssa(-2147483648); got != -1 { + fmt.Printf("sub_int32 -2147483648--2147483647 = %d, wanted -1\n", got) + failed = true + } + + if got := sub_Neg2147483647_int32_ssa(-2147483647); got != 0 { + fmt.Printf("sub_int32 -2147483647--2147483647 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_int32_Neg2147483647_ssa(-2147483647); got != 0 { + fmt.Printf("sub_int32 -2147483647--2147483647 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_Neg2147483647_int32_ssa(-1); got != -2147483646 { + fmt.Printf("sub_int32 -2147483647--1 = %d, wanted -2147483646\n", got) + failed = true + } + + if got := sub_int32_Neg2147483647_ssa(-1); got != 2147483646 { + fmt.Printf("sub_int32 -1--2147483647 = %d, wanted 2147483646\n", got) + failed = true + } + + if got := sub_Neg2147483647_int32_ssa(0); got != -2147483647 { + fmt.Printf("sub_int32 -2147483647-0 = %d, wanted -2147483647\n", got) + failed = true + } + + if got := sub_int32_Neg2147483647_ssa(0); got != 2147483647 { + fmt.Printf("sub_int32 0--2147483647 = %d, wanted 2147483647\n", got) + failed = true + } + + if got := sub_Neg2147483647_int32_ssa(1); got != -2147483648 { + fmt.Printf("sub_int32 -2147483647-1 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := sub_int32_Neg2147483647_ssa(1); got != -2147483648 { + fmt.Printf("sub_int32 1--2147483647 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := sub_Neg2147483647_int32_ssa(2147483647); got != 2 { + fmt.Printf("sub_int32 -2147483647-2147483647 = %d, wanted 2\n", got) + failed = true + } + + if got := sub_int32_Neg2147483647_ssa(2147483647); got != -2 { + fmt.Printf("sub_int32 2147483647--2147483647 = %d, wanted -2\n", got) + failed = true + } + + if got := sub_Neg1_int32_ssa(-2147483648); got != 2147483647 { + fmt.Printf("sub_int32 -1--2147483648 = %d, wanted 2147483647\n", got) + failed = true + } + + if got := sub_int32_Neg1_ssa(-2147483648); got != -2147483647 { + fmt.Printf("sub_int32 -2147483648--1 = %d, wanted -2147483647\n", got) + failed = true + } + + if got := sub_Neg1_int32_ssa(-2147483647); got != 2147483646 { + fmt.Printf("sub_int32 -1--2147483647 = %d, wanted 2147483646\n", got) + failed = true + } + + if got := sub_int32_Neg1_ssa(-2147483647); got != -2147483646 { + fmt.Printf("sub_int32 -2147483647--1 = %d, wanted -2147483646\n", got) + failed = true + } + + if got := sub_Neg1_int32_ssa(-1); got != 0 { + fmt.Printf("sub_int32 -1--1 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_int32_Neg1_ssa(-1); got != 0 { + fmt.Printf("sub_int32 -1--1 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_Neg1_int32_ssa(0); got != -1 { + fmt.Printf("sub_int32 -1-0 = %d, wanted -1\n", got) + failed = true + } + + if got := sub_int32_Neg1_ssa(0); got != 1 { + fmt.Printf("sub_int32 0--1 = %d, wanted 1\n", got) + failed = true + } + + if got := sub_Neg1_int32_ssa(1); got != -2 { + fmt.Printf("sub_int32 -1-1 = %d, wanted -2\n", got) + failed = true + } + + if got := sub_int32_Neg1_ssa(1); got != 2 { + fmt.Printf("sub_int32 1--1 = %d, wanted 2\n", got) + failed = true + } + + if got := sub_Neg1_int32_ssa(2147483647); got != -2147483648 { + fmt.Printf("sub_int32 -1-2147483647 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := sub_int32_Neg1_ssa(2147483647); got != -2147483648 { + fmt.Printf("sub_int32 2147483647--1 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := sub_0_int32_ssa(-2147483648); got != -2147483648 { + fmt.Printf("sub_int32 0--2147483648 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := sub_int32_0_ssa(-2147483648); got != -2147483648 { + fmt.Printf("sub_int32 -2147483648-0 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := sub_0_int32_ssa(-2147483647); got != 2147483647 { + fmt.Printf("sub_int32 0--2147483647 = %d, wanted 2147483647\n", got) + failed = true + } + + if got := sub_int32_0_ssa(-2147483647); got != -2147483647 { + fmt.Printf("sub_int32 -2147483647-0 = %d, wanted -2147483647\n", got) + failed = true + } + + if got := sub_0_int32_ssa(-1); got != 1 { + fmt.Printf("sub_int32 0--1 = %d, wanted 1\n", got) + failed = true + } + + if got := sub_int32_0_ssa(-1); got != -1 { + fmt.Printf("sub_int32 -1-0 = %d, wanted -1\n", got) + failed = true + } + + if got := sub_0_int32_ssa(0); got != 0 { + fmt.Printf("sub_int32 0-0 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_int32_0_ssa(0); got != 0 { + fmt.Printf("sub_int32 0-0 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_0_int32_ssa(1); got != -1 { + fmt.Printf("sub_int32 0-1 = %d, wanted -1\n", got) + failed = true + } + + if got := sub_int32_0_ssa(1); got != 1 { + fmt.Printf("sub_int32 1-0 = %d, wanted 1\n", got) + failed = true + } + + if got := sub_0_int32_ssa(2147483647); got != -2147483647 { + fmt.Printf("sub_int32 0-2147483647 = %d, wanted -2147483647\n", got) + failed = true + } + + if got := sub_int32_0_ssa(2147483647); got != 2147483647 { + fmt.Printf("sub_int32 2147483647-0 = %d, wanted 2147483647\n", got) + failed = true + } + + if got := sub_1_int32_ssa(-2147483648); got != -2147483647 { + fmt.Printf("sub_int32 1--2147483648 = %d, wanted -2147483647\n", got) + failed = true + } + + if got := sub_int32_1_ssa(-2147483648); got != 2147483647 { + fmt.Printf("sub_int32 -2147483648-1 = %d, wanted 2147483647\n", got) + failed = true + } + + if got := sub_1_int32_ssa(-2147483647); got != -2147483648 { + fmt.Printf("sub_int32 1--2147483647 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := sub_int32_1_ssa(-2147483647); got != -2147483648 { + fmt.Printf("sub_int32 -2147483647-1 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := sub_1_int32_ssa(-1); got != 2 { + fmt.Printf("sub_int32 1--1 = %d, wanted 2\n", got) + failed = true + } + + if got := sub_int32_1_ssa(-1); got != -2 { + fmt.Printf("sub_int32 -1-1 = %d, wanted -2\n", got) + failed = true + } + + if got := sub_1_int32_ssa(0); got != 1 { + fmt.Printf("sub_int32 1-0 = %d, wanted 1\n", got) + failed = true + } + + if got := sub_int32_1_ssa(0); got != -1 { + fmt.Printf("sub_int32 0-1 = %d, wanted -1\n", got) + failed = true + } + + if got := sub_1_int32_ssa(1); got != 0 { + fmt.Printf("sub_int32 1-1 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_int32_1_ssa(1); got != 0 { + fmt.Printf("sub_int32 1-1 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_1_int32_ssa(2147483647); got != -2147483646 { + fmt.Printf("sub_int32 1-2147483647 = %d, wanted -2147483646\n", got) + failed = true + } + + if got := sub_int32_1_ssa(2147483647); got != 2147483646 { + fmt.Printf("sub_int32 2147483647-1 = %d, wanted 2147483646\n", got) + failed = true + } + + if got := sub_2147483647_int32_ssa(-2147483648); got != -1 { + fmt.Printf("sub_int32 2147483647--2147483648 = %d, wanted -1\n", got) + failed = true + } + + if got := sub_int32_2147483647_ssa(-2147483648); got != 1 { + fmt.Printf("sub_int32 -2147483648-2147483647 = %d, wanted 1\n", got) + failed = true + } + + if got := sub_2147483647_int32_ssa(-2147483647); got != -2 { + fmt.Printf("sub_int32 2147483647--2147483647 = %d, wanted -2\n", got) + failed = true + } + + if got := sub_int32_2147483647_ssa(-2147483647); got != 2 { + fmt.Printf("sub_int32 -2147483647-2147483647 = %d, wanted 2\n", got) + failed = true + } + + if got := sub_2147483647_int32_ssa(-1); got != -2147483648 { + fmt.Printf("sub_int32 2147483647--1 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := sub_int32_2147483647_ssa(-1); got != -2147483648 { + fmt.Printf("sub_int32 -1-2147483647 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := sub_2147483647_int32_ssa(0); got != 2147483647 { + fmt.Printf("sub_int32 2147483647-0 = %d, wanted 2147483647\n", got) + failed = true + } + + if got := sub_int32_2147483647_ssa(0); got != -2147483647 { + fmt.Printf("sub_int32 0-2147483647 = %d, wanted -2147483647\n", got) + failed = true + } + + if got := sub_2147483647_int32_ssa(1); got != 2147483646 { + fmt.Printf("sub_int32 2147483647-1 = %d, wanted 2147483646\n", got) + failed = true + } + + if got := sub_int32_2147483647_ssa(1); got != -2147483646 { + fmt.Printf("sub_int32 1-2147483647 = %d, wanted -2147483646\n", got) + failed = true + } + + if got := sub_2147483647_int32_ssa(2147483647); got != 0 { + fmt.Printf("sub_int32 2147483647-2147483647 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_int32_2147483647_ssa(2147483647); got != 0 { + fmt.Printf("sub_int32 2147483647-2147483647 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg2147483648_int32_ssa(-2147483648); got != 1 { + fmt.Printf("div_int32 -2147483648/-2147483648 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int32_Neg2147483648_ssa(-2147483648); got != 1 { + fmt.Printf("div_int32 -2147483648/-2147483648 = %d, wanted 1\n", got) + failed = true + } + + if got := div_Neg2147483648_int32_ssa(-2147483647); got != 1 { + fmt.Printf("div_int32 -2147483648/-2147483647 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int32_Neg2147483648_ssa(-2147483647); got != 0 { + fmt.Printf("div_int32 -2147483647/-2147483648 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg2147483648_int32_ssa(-1); got != -2147483648 { + fmt.Printf("div_int32 -2147483648/-1 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := div_int32_Neg2147483648_ssa(-1); got != 0 { + fmt.Printf("div_int32 -1/-2147483648 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int32_Neg2147483648_ssa(0); got != 0 { + fmt.Printf("div_int32 0/-2147483648 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg2147483648_int32_ssa(1); got != -2147483648 { + fmt.Printf("div_int32 -2147483648/1 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := div_int32_Neg2147483648_ssa(1); got != 0 { + fmt.Printf("div_int32 1/-2147483648 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg2147483648_int32_ssa(2147483647); got != -1 { + fmt.Printf("div_int32 -2147483648/2147483647 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int32_Neg2147483648_ssa(2147483647); got != 0 { + fmt.Printf("div_int32 2147483647/-2147483648 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg2147483647_int32_ssa(-2147483648); got != 0 { + fmt.Printf("div_int32 -2147483647/-2147483648 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int32_Neg2147483647_ssa(-2147483648); got != 1 { + fmt.Printf("div_int32 -2147483648/-2147483647 = %d, wanted 1\n", got) + failed = true + } + + if got := div_Neg2147483647_int32_ssa(-2147483647); got != 1 { + fmt.Printf("div_int32 -2147483647/-2147483647 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int32_Neg2147483647_ssa(-2147483647); got != 1 { + fmt.Printf("div_int32 -2147483647/-2147483647 = %d, wanted 1\n", got) + failed = true + } + + if got := div_Neg2147483647_int32_ssa(-1); got != 2147483647 { + fmt.Printf("div_int32 -2147483647/-1 = %d, wanted 2147483647\n", got) + failed = true + } + + if got := div_int32_Neg2147483647_ssa(-1); got != 0 { + fmt.Printf("div_int32 -1/-2147483647 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int32_Neg2147483647_ssa(0); got != 0 { + fmt.Printf("div_int32 0/-2147483647 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg2147483647_int32_ssa(1); got != -2147483647 { + fmt.Printf("div_int32 -2147483647/1 = %d, wanted -2147483647\n", got) + failed = true + } + + if got := div_int32_Neg2147483647_ssa(1); got != 0 { + fmt.Printf("div_int32 1/-2147483647 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg2147483647_int32_ssa(2147483647); got != -1 { + fmt.Printf("div_int32 -2147483647/2147483647 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int32_Neg2147483647_ssa(2147483647); got != -1 { + fmt.Printf("div_int32 2147483647/-2147483647 = %d, wanted -1\n", got) + failed = true + } + + if got := div_Neg1_int32_ssa(-2147483648); got != 0 { + fmt.Printf("div_int32 -1/-2147483648 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int32_Neg1_ssa(-2147483648); got != -2147483648 { + fmt.Printf("div_int32 -2147483648/-1 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := div_Neg1_int32_ssa(-2147483647); got != 0 { + fmt.Printf("div_int32 -1/-2147483647 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int32_Neg1_ssa(-2147483647); got != 2147483647 { + fmt.Printf("div_int32 -2147483647/-1 = %d, wanted 2147483647\n", got) + failed = true + } + + if got := div_Neg1_int32_ssa(-1); got != 1 { + fmt.Printf("div_int32 -1/-1 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int32_Neg1_ssa(-1); got != 1 { + fmt.Printf("div_int32 -1/-1 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int32_Neg1_ssa(0); got != 0 { + fmt.Printf("div_int32 0/-1 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg1_int32_ssa(1); got != -1 { + fmt.Printf("div_int32 -1/1 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int32_Neg1_ssa(1); got != -1 { + fmt.Printf("div_int32 1/-1 = %d, wanted -1\n", got) + failed = true + } + + if got := div_Neg1_int32_ssa(2147483647); got != 0 { + fmt.Printf("div_int32 -1/2147483647 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int32_Neg1_ssa(2147483647); got != -2147483647 { + fmt.Printf("div_int32 2147483647/-1 = %d, wanted -2147483647\n", got) + failed = true + } + + if got := div_0_int32_ssa(-2147483648); got != 0 { + fmt.Printf("div_int32 0/-2147483648 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_int32_ssa(-2147483647); got != 0 { + fmt.Printf("div_int32 0/-2147483647 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_int32_ssa(-1); got != 0 { + fmt.Printf("div_int32 0/-1 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_int32_ssa(1); got != 0 { + fmt.Printf("div_int32 0/1 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_int32_ssa(2147483647); got != 0 { + fmt.Printf("div_int32 0/2147483647 = %d, wanted 0\n", got) + failed = true + } + + if got := div_1_int32_ssa(-2147483648); got != 0 { + fmt.Printf("div_int32 1/-2147483648 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int32_1_ssa(-2147483648); got != -2147483648 { + fmt.Printf("div_int32 -2147483648/1 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := div_1_int32_ssa(-2147483647); got != 0 { + fmt.Printf("div_int32 1/-2147483647 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int32_1_ssa(-2147483647); got != -2147483647 { + fmt.Printf("div_int32 -2147483647/1 = %d, wanted -2147483647\n", got) + failed = true + } + + if got := div_1_int32_ssa(-1); got != -1 { + fmt.Printf("div_int32 1/-1 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int32_1_ssa(-1); got != -1 { + fmt.Printf("div_int32 -1/1 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int32_1_ssa(0); got != 0 { + fmt.Printf("div_int32 0/1 = %d, wanted 0\n", got) + failed = true + } + + if got := div_1_int32_ssa(1); got != 1 { + fmt.Printf("div_int32 1/1 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int32_1_ssa(1); got != 1 { + fmt.Printf("div_int32 1/1 = %d, wanted 1\n", got) + failed = true + } + + if got := div_1_int32_ssa(2147483647); got != 0 { + fmt.Printf("div_int32 1/2147483647 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int32_1_ssa(2147483647); got != 2147483647 { + fmt.Printf("div_int32 2147483647/1 = %d, wanted 2147483647\n", got) + failed = true + } + + if got := div_2147483647_int32_ssa(-2147483648); got != 0 { + fmt.Printf("div_int32 2147483647/-2147483648 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int32_2147483647_ssa(-2147483648); got != -1 { + fmt.Printf("div_int32 -2147483648/2147483647 = %d, wanted -1\n", got) + failed = true + } + + if got := div_2147483647_int32_ssa(-2147483647); got != -1 { + fmt.Printf("div_int32 2147483647/-2147483647 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int32_2147483647_ssa(-2147483647); got != -1 { + fmt.Printf("div_int32 -2147483647/2147483647 = %d, wanted -1\n", got) + failed = true + } + + if got := div_2147483647_int32_ssa(-1); got != -2147483647 { + fmt.Printf("div_int32 2147483647/-1 = %d, wanted -2147483647\n", got) + failed = true + } + + if got := div_int32_2147483647_ssa(-1); got != 0 { + fmt.Printf("div_int32 -1/2147483647 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int32_2147483647_ssa(0); got != 0 { + fmt.Printf("div_int32 0/2147483647 = %d, wanted 0\n", got) + failed = true + } + + if got := div_2147483647_int32_ssa(1); got != 2147483647 { + fmt.Printf("div_int32 2147483647/1 = %d, wanted 2147483647\n", got) + failed = true + } + + if got := div_int32_2147483647_ssa(1); got != 0 { + fmt.Printf("div_int32 1/2147483647 = %d, wanted 0\n", got) + failed = true + } + + if got := div_2147483647_int32_ssa(2147483647); got != 1 { + fmt.Printf("div_int32 2147483647/2147483647 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int32_2147483647_ssa(2147483647); got != 1 { + fmt.Printf("div_int32 2147483647/2147483647 = %d, wanted 1\n", got) + failed = true + } + + if got := mul_Neg2147483648_int32_ssa(-2147483648); got != 0 { + fmt.Printf("mul_int32 -2147483648*-2147483648 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int32_Neg2147483648_ssa(-2147483648); got != 0 { + fmt.Printf("mul_int32 -2147483648*-2147483648 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_Neg2147483648_int32_ssa(-2147483647); got != -2147483648 { + fmt.Printf("mul_int32 -2147483648*-2147483647 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := mul_int32_Neg2147483648_ssa(-2147483647); got != -2147483648 { + fmt.Printf("mul_int32 -2147483647*-2147483648 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := mul_Neg2147483648_int32_ssa(-1); got != -2147483648 { + fmt.Printf("mul_int32 -2147483648*-1 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := mul_int32_Neg2147483648_ssa(-1); got != -2147483648 { + fmt.Printf("mul_int32 -1*-2147483648 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := mul_Neg2147483648_int32_ssa(0); got != 0 { + fmt.Printf("mul_int32 -2147483648*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int32_Neg2147483648_ssa(0); got != 0 { + fmt.Printf("mul_int32 0*-2147483648 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_Neg2147483648_int32_ssa(1); got != -2147483648 { + fmt.Printf("mul_int32 -2147483648*1 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := mul_int32_Neg2147483648_ssa(1); got != -2147483648 { + fmt.Printf("mul_int32 1*-2147483648 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := mul_Neg2147483648_int32_ssa(2147483647); got != -2147483648 { + fmt.Printf("mul_int32 -2147483648*2147483647 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := mul_int32_Neg2147483648_ssa(2147483647); got != -2147483648 { + fmt.Printf("mul_int32 2147483647*-2147483648 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := mul_Neg2147483647_int32_ssa(-2147483648); got != -2147483648 { + fmt.Printf("mul_int32 -2147483647*-2147483648 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := mul_int32_Neg2147483647_ssa(-2147483648); got != -2147483648 { + fmt.Printf("mul_int32 -2147483648*-2147483647 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := mul_Neg2147483647_int32_ssa(-2147483647); got != 1 { + fmt.Printf("mul_int32 -2147483647*-2147483647 = %d, wanted 1\n", got) + failed = true + } + + if got := mul_int32_Neg2147483647_ssa(-2147483647); got != 1 { + fmt.Printf("mul_int32 -2147483647*-2147483647 = %d, wanted 1\n", got) + failed = true + } + + if got := mul_Neg2147483647_int32_ssa(-1); got != 2147483647 { + fmt.Printf("mul_int32 -2147483647*-1 = %d, wanted 2147483647\n", got) + failed = true + } + + if got := mul_int32_Neg2147483647_ssa(-1); got != 2147483647 { + fmt.Printf("mul_int32 -1*-2147483647 = %d, wanted 2147483647\n", got) + failed = true + } + + if got := mul_Neg2147483647_int32_ssa(0); got != 0 { + fmt.Printf("mul_int32 -2147483647*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int32_Neg2147483647_ssa(0); got != 0 { + fmt.Printf("mul_int32 0*-2147483647 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_Neg2147483647_int32_ssa(1); got != -2147483647 { + fmt.Printf("mul_int32 -2147483647*1 = %d, wanted -2147483647\n", got) + failed = true + } + + if got := mul_int32_Neg2147483647_ssa(1); got != -2147483647 { + fmt.Printf("mul_int32 1*-2147483647 = %d, wanted -2147483647\n", got) + failed = true + } + + if got := mul_Neg2147483647_int32_ssa(2147483647); got != -1 { + fmt.Printf("mul_int32 -2147483647*2147483647 = %d, wanted -1\n", got) + failed = true + } + + if got := mul_int32_Neg2147483647_ssa(2147483647); got != -1 { + fmt.Printf("mul_int32 2147483647*-2147483647 = %d, wanted -1\n", got) + failed = true + } + + if got := mul_Neg1_int32_ssa(-2147483648); got != -2147483648 { + fmt.Printf("mul_int32 -1*-2147483648 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := mul_int32_Neg1_ssa(-2147483648); got != -2147483648 { + fmt.Printf("mul_int32 -2147483648*-1 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := mul_Neg1_int32_ssa(-2147483647); got != 2147483647 { + fmt.Printf("mul_int32 -1*-2147483647 = %d, wanted 2147483647\n", got) + failed = true + } + + if got := mul_int32_Neg1_ssa(-2147483647); got != 2147483647 { + fmt.Printf("mul_int32 -2147483647*-1 = %d, wanted 2147483647\n", got) + failed = true + } + + if got := mul_Neg1_int32_ssa(-1); got != 1 { + fmt.Printf("mul_int32 -1*-1 = %d, wanted 1\n", got) + failed = true + } + + if got := mul_int32_Neg1_ssa(-1); got != 1 { + fmt.Printf("mul_int32 -1*-1 = %d, wanted 1\n", got) + failed = true + } + + if got := mul_Neg1_int32_ssa(0); got != 0 { + fmt.Printf("mul_int32 -1*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int32_Neg1_ssa(0); got != 0 { + fmt.Printf("mul_int32 0*-1 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_Neg1_int32_ssa(1); got != -1 { + fmt.Printf("mul_int32 -1*1 = %d, wanted -1\n", got) + failed = true + } + + if got := mul_int32_Neg1_ssa(1); got != -1 { + fmt.Printf("mul_int32 1*-1 = %d, wanted -1\n", got) + failed = true + } + + if got := mul_Neg1_int32_ssa(2147483647); got != -2147483647 { + fmt.Printf("mul_int32 -1*2147483647 = %d, wanted -2147483647\n", got) + failed = true + } + + if got := mul_int32_Neg1_ssa(2147483647); got != -2147483647 { + fmt.Printf("mul_int32 2147483647*-1 = %d, wanted -2147483647\n", got) + failed = true + } + + if got := mul_0_int32_ssa(-2147483648); got != 0 { + fmt.Printf("mul_int32 0*-2147483648 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int32_0_ssa(-2147483648); got != 0 { + fmt.Printf("mul_int32 -2147483648*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_0_int32_ssa(-2147483647); got != 0 { + fmt.Printf("mul_int32 0*-2147483647 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int32_0_ssa(-2147483647); got != 0 { + fmt.Printf("mul_int32 -2147483647*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_0_int32_ssa(-1); got != 0 { + fmt.Printf("mul_int32 0*-1 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int32_0_ssa(-1); got != 0 { + fmt.Printf("mul_int32 -1*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_0_int32_ssa(0); got != 0 { + fmt.Printf("mul_int32 0*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int32_0_ssa(0); got != 0 { + fmt.Printf("mul_int32 0*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_0_int32_ssa(1); got != 0 { + fmt.Printf("mul_int32 0*1 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int32_0_ssa(1); got != 0 { + fmt.Printf("mul_int32 1*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_0_int32_ssa(2147483647); got != 0 { + fmt.Printf("mul_int32 0*2147483647 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int32_0_ssa(2147483647); got != 0 { + fmt.Printf("mul_int32 2147483647*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_1_int32_ssa(-2147483648); got != -2147483648 { + fmt.Printf("mul_int32 1*-2147483648 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := mul_int32_1_ssa(-2147483648); got != -2147483648 { + fmt.Printf("mul_int32 -2147483648*1 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := mul_1_int32_ssa(-2147483647); got != -2147483647 { + fmt.Printf("mul_int32 1*-2147483647 = %d, wanted -2147483647\n", got) + failed = true + } + + if got := mul_int32_1_ssa(-2147483647); got != -2147483647 { + fmt.Printf("mul_int32 -2147483647*1 = %d, wanted -2147483647\n", got) + failed = true + } + + if got := mul_1_int32_ssa(-1); got != -1 { + fmt.Printf("mul_int32 1*-1 = %d, wanted -1\n", got) + failed = true + } + + if got := mul_int32_1_ssa(-1); got != -1 { + fmt.Printf("mul_int32 -1*1 = %d, wanted -1\n", got) + failed = true + } + + if got := mul_1_int32_ssa(0); got != 0 { + fmt.Printf("mul_int32 1*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int32_1_ssa(0); got != 0 { + fmt.Printf("mul_int32 0*1 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_1_int32_ssa(1); got != 1 { + fmt.Printf("mul_int32 1*1 = %d, wanted 1\n", got) + failed = true + } + + if got := mul_int32_1_ssa(1); got != 1 { + fmt.Printf("mul_int32 1*1 = %d, wanted 1\n", got) + failed = true + } + + if got := mul_1_int32_ssa(2147483647); got != 2147483647 { + fmt.Printf("mul_int32 1*2147483647 = %d, wanted 2147483647\n", got) + failed = true + } + + if got := mul_int32_1_ssa(2147483647); got != 2147483647 { + fmt.Printf("mul_int32 2147483647*1 = %d, wanted 2147483647\n", got) + failed = true + } + + if got := mul_2147483647_int32_ssa(-2147483648); got != -2147483648 { + fmt.Printf("mul_int32 2147483647*-2147483648 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := mul_int32_2147483647_ssa(-2147483648); got != -2147483648 { + fmt.Printf("mul_int32 -2147483648*2147483647 = %d, wanted -2147483648\n", got) + failed = true + } + + if got := mul_2147483647_int32_ssa(-2147483647); got != -1 { + fmt.Printf("mul_int32 2147483647*-2147483647 = %d, wanted -1\n", got) + failed = true + } + + if got := mul_int32_2147483647_ssa(-2147483647); got != -1 { + fmt.Printf("mul_int32 -2147483647*2147483647 = %d, wanted -1\n", got) + failed = true + } + + if got := mul_2147483647_int32_ssa(-1); got != -2147483647 { + fmt.Printf("mul_int32 2147483647*-1 = %d, wanted -2147483647\n", got) + failed = true + } + + if got := mul_int32_2147483647_ssa(-1); got != -2147483647 { + fmt.Printf("mul_int32 -1*2147483647 = %d, wanted -2147483647\n", got) + failed = true + } + + if got := mul_2147483647_int32_ssa(0); got != 0 { + fmt.Printf("mul_int32 2147483647*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int32_2147483647_ssa(0); got != 0 { + fmt.Printf("mul_int32 0*2147483647 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_2147483647_int32_ssa(1); got != 2147483647 { + fmt.Printf("mul_int32 2147483647*1 = %d, wanted 2147483647\n", got) + failed = true + } + + if got := mul_int32_2147483647_ssa(1); got != 2147483647 { + fmt.Printf("mul_int32 1*2147483647 = %d, wanted 2147483647\n", got) + failed = true + } + + if got := mul_2147483647_int32_ssa(2147483647); got != 1 { + fmt.Printf("mul_int32 2147483647*2147483647 = %d, wanted 1\n", got) + failed = true + } + + if got := mul_int32_2147483647_ssa(2147483647); got != 1 { + fmt.Printf("mul_int32 2147483647*2147483647 = %d, wanted 1\n", got) + failed = true + } + + if got := add_0_uint16_ssa(0); got != 0 { + fmt.Printf("add_uint16 0+0 = %d, wanted 0\n", got) + failed = true + } + + if got := add_uint16_0_ssa(0); got != 0 { + fmt.Printf("add_uint16 0+0 = %d, wanted 0\n", got) + failed = true + } + + if got := add_0_uint16_ssa(1); got != 1 { + fmt.Printf("add_uint16 0+1 = %d, wanted 1\n", got) + failed = true + } + + if got := add_uint16_0_ssa(1); got != 1 { + fmt.Printf("add_uint16 1+0 = %d, wanted 1\n", got) + failed = true + } + + if got := add_0_uint16_ssa(65535); got != 65535 { + fmt.Printf("add_uint16 0+65535 = %d, wanted 65535\n", got) + failed = true + } + + if got := add_uint16_0_ssa(65535); got != 65535 { + fmt.Printf("add_uint16 65535+0 = %d, wanted 65535\n", got) + failed = true + } + + if got := add_1_uint16_ssa(0); got != 1 { + fmt.Printf("add_uint16 1+0 = %d, wanted 1\n", got) + failed = true + } + + if got := add_uint16_1_ssa(0); got != 1 { + fmt.Printf("add_uint16 0+1 = %d, wanted 1\n", got) + failed = true + } + + if got := add_1_uint16_ssa(1); got != 2 { + fmt.Printf("add_uint16 1+1 = %d, wanted 2\n", got) + failed = true + } + + if got := add_uint16_1_ssa(1); got != 2 { + fmt.Printf("add_uint16 1+1 = %d, wanted 2\n", got) + failed = true + } + + if got := add_1_uint16_ssa(65535); got != 0 { + fmt.Printf("add_uint16 1+65535 = %d, wanted 0\n", got) + failed = true + } + + if got := add_uint16_1_ssa(65535); got != 0 { + fmt.Printf("add_uint16 65535+1 = %d, wanted 0\n", got) + failed = true + } + + if got := add_65535_uint16_ssa(0); got != 65535 { + fmt.Printf("add_uint16 65535+0 = %d, wanted 65535\n", got) + failed = true + } + + if got := add_uint16_65535_ssa(0); got != 65535 { + fmt.Printf("add_uint16 0+65535 = %d, wanted 65535\n", got) + failed = true + } + + if got := add_65535_uint16_ssa(1); got != 0 { + fmt.Printf("add_uint16 65535+1 = %d, wanted 0\n", got) + failed = true + } + + if got := add_uint16_65535_ssa(1); got != 0 { + fmt.Printf("add_uint16 1+65535 = %d, wanted 0\n", got) + failed = true + } + + if got := add_65535_uint16_ssa(65535); got != 65534 { + fmt.Printf("add_uint16 65535+65535 = %d, wanted 65534\n", got) + failed = true + } + + if got := add_uint16_65535_ssa(65535); got != 65534 { + fmt.Printf("add_uint16 65535+65535 = %d, wanted 65534\n", got) + failed = true + } + + if got := sub_0_uint16_ssa(0); got != 0 { + fmt.Printf("sub_uint16 0-0 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_uint16_0_ssa(0); got != 0 { + fmt.Printf("sub_uint16 0-0 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_0_uint16_ssa(1); got != 65535 { + fmt.Printf("sub_uint16 0-1 = %d, wanted 65535\n", got) + failed = true + } + + if got := sub_uint16_0_ssa(1); got != 1 { + fmt.Printf("sub_uint16 1-0 = %d, wanted 1\n", got) + failed = true + } + + if got := sub_0_uint16_ssa(65535); got != 1 { + fmt.Printf("sub_uint16 0-65535 = %d, wanted 1\n", got) + failed = true + } + + if got := sub_uint16_0_ssa(65535); got != 65535 { + fmt.Printf("sub_uint16 65535-0 = %d, wanted 65535\n", got) + failed = true + } + + if got := sub_1_uint16_ssa(0); got != 1 { + fmt.Printf("sub_uint16 1-0 = %d, wanted 1\n", got) + failed = true + } + + if got := sub_uint16_1_ssa(0); got != 65535 { + fmt.Printf("sub_uint16 0-1 = %d, wanted 65535\n", got) + failed = true + } + + if got := sub_1_uint16_ssa(1); got != 0 { + fmt.Printf("sub_uint16 1-1 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_uint16_1_ssa(1); got != 0 { + fmt.Printf("sub_uint16 1-1 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_1_uint16_ssa(65535); got != 2 { + fmt.Printf("sub_uint16 1-65535 = %d, wanted 2\n", got) + failed = true + } + + if got := sub_uint16_1_ssa(65535); got != 65534 { + fmt.Printf("sub_uint16 65535-1 = %d, wanted 65534\n", got) + failed = true + } + + if got := sub_65535_uint16_ssa(0); got != 65535 { + fmt.Printf("sub_uint16 65535-0 = %d, wanted 65535\n", got) + failed = true + } + + if got := sub_uint16_65535_ssa(0); got != 1 { + fmt.Printf("sub_uint16 0-65535 = %d, wanted 1\n", got) + failed = true + } + + if got := sub_65535_uint16_ssa(1); got != 65534 { + fmt.Printf("sub_uint16 65535-1 = %d, wanted 65534\n", got) + failed = true + } + + if got := sub_uint16_65535_ssa(1); got != 2 { + fmt.Printf("sub_uint16 1-65535 = %d, wanted 2\n", got) + failed = true + } + + if got := sub_65535_uint16_ssa(65535); got != 0 { + fmt.Printf("sub_uint16 65535-65535 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_uint16_65535_ssa(65535); got != 0 { + fmt.Printf("sub_uint16 65535-65535 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_uint16_ssa(1); got != 0 { + fmt.Printf("div_uint16 0/1 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_uint16_ssa(65535); got != 0 { + fmt.Printf("div_uint16 0/65535 = %d, wanted 0\n", got) + failed = true + } + + if got := div_uint16_1_ssa(0); got != 0 { + fmt.Printf("div_uint16 0/1 = %d, wanted 0\n", got) + failed = true + } + + if got := div_1_uint16_ssa(1); got != 1 { + fmt.Printf("div_uint16 1/1 = %d, wanted 1\n", got) + failed = true + } + + if got := div_uint16_1_ssa(1); got != 1 { + fmt.Printf("div_uint16 1/1 = %d, wanted 1\n", got) + failed = true + } + + if got := div_1_uint16_ssa(65535); got != 0 { + fmt.Printf("div_uint16 1/65535 = %d, wanted 0\n", got) + failed = true + } + + if got := div_uint16_1_ssa(65535); got != 65535 { + fmt.Printf("div_uint16 65535/1 = %d, wanted 65535\n", got) + failed = true + } + + if got := div_uint16_65535_ssa(0); got != 0 { + fmt.Printf("div_uint16 0/65535 = %d, wanted 0\n", got) + failed = true + } + + if got := div_65535_uint16_ssa(1); got != 65535 { + fmt.Printf("div_uint16 65535/1 = %d, wanted 65535\n", got) + failed = true + } + + if got := div_uint16_65535_ssa(1); got != 0 { + fmt.Printf("div_uint16 1/65535 = %d, wanted 0\n", got) + failed = true + } + + if got := div_65535_uint16_ssa(65535); got != 1 { + fmt.Printf("div_uint16 65535/65535 = %d, wanted 1\n", got) + failed = true + } + + if got := div_uint16_65535_ssa(65535); got != 1 { + fmt.Printf("div_uint16 65535/65535 = %d, wanted 1\n", got) + failed = true + } + + if got := mul_0_uint16_ssa(0); got != 0 { + fmt.Printf("mul_uint16 0*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_uint16_0_ssa(0); got != 0 { + fmt.Printf("mul_uint16 0*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_0_uint16_ssa(1); got != 0 { + fmt.Printf("mul_uint16 0*1 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_uint16_0_ssa(1); got != 0 { + fmt.Printf("mul_uint16 1*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_0_uint16_ssa(65535); got != 0 { + fmt.Printf("mul_uint16 0*65535 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_uint16_0_ssa(65535); got != 0 { + fmt.Printf("mul_uint16 65535*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_1_uint16_ssa(0); got != 0 { + fmt.Printf("mul_uint16 1*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_uint16_1_ssa(0); got != 0 { + fmt.Printf("mul_uint16 0*1 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_1_uint16_ssa(1); got != 1 { + fmt.Printf("mul_uint16 1*1 = %d, wanted 1\n", got) + failed = true + } + + if got := mul_uint16_1_ssa(1); got != 1 { + fmt.Printf("mul_uint16 1*1 = %d, wanted 1\n", got) + failed = true + } + + if got := mul_1_uint16_ssa(65535); got != 65535 { + fmt.Printf("mul_uint16 1*65535 = %d, wanted 65535\n", got) + failed = true + } + + if got := mul_uint16_1_ssa(65535); got != 65535 { + fmt.Printf("mul_uint16 65535*1 = %d, wanted 65535\n", got) + failed = true + } + + if got := mul_65535_uint16_ssa(0); got != 0 { + fmt.Printf("mul_uint16 65535*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_uint16_65535_ssa(0); got != 0 { + fmt.Printf("mul_uint16 0*65535 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_65535_uint16_ssa(1); got != 65535 { + fmt.Printf("mul_uint16 65535*1 = %d, wanted 65535\n", got) + failed = true + } + + if got := mul_uint16_65535_ssa(1); got != 65535 { + fmt.Printf("mul_uint16 1*65535 = %d, wanted 65535\n", got) + failed = true + } + + if got := mul_65535_uint16_ssa(65535); got != 1 { + fmt.Printf("mul_uint16 65535*65535 = %d, wanted 1\n", got) + failed = true + } + + if got := mul_uint16_65535_ssa(65535); got != 1 { + fmt.Printf("mul_uint16 65535*65535 = %d, wanted 1\n", got) + failed = true + } + + if got := lsh_0_uint16_ssa(0); got != 0 { + fmt.Printf("lsh_uint16 0<<0 = %d, wanted 0\n", got) + failed = true + } + + if got := lsh_uint16_0_ssa(0); got != 0 { + fmt.Printf("lsh_uint16 0<<0 = %d, wanted 0\n", got) + failed = true + } + + if got := lsh_0_uint16_ssa(1); got != 0 { + fmt.Printf("lsh_uint16 0<<1 = %d, wanted 0\n", got) + failed = true + } + + if got := lsh_uint16_0_ssa(1); got != 1 { + fmt.Printf("lsh_uint16 1<<0 = %d, wanted 1\n", got) + failed = true + } + + if got := lsh_0_uint16_ssa(65535); got != 0 { + fmt.Printf("lsh_uint16 0<<65535 = %d, wanted 0\n", got) + failed = true + } + + if got := lsh_uint16_0_ssa(65535); got != 65535 { + fmt.Printf("lsh_uint16 65535<<0 = %d, wanted 65535\n", got) + failed = true + } + + if got := lsh_1_uint16_ssa(0); got != 1 { + fmt.Printf("lsh_uint16 1<<0 = %d, wanted 1\n", got) + failed = true + } + + if got := lsh_uint16_1_ssa(0); got != 0 { + fmt.Printf("lsh_uint16 0<<1 = %d, wanted 0\n", got) + failed = true + } + + if got := lsh_1_uint16_ssa(1); got != 2 { + fmt.Printf("lsh_uint16 1<<1 = %d, wanted 2\n", got) + failed = true + } + + if got := lsh_uint16_1_ssa(1); got != 2 { + fmt.Printf("lsh_uint16 1<<1 = %d, wanted 2\n", got) + failed = true + } + + if got := lsh_1_uint16_ssa(65535); got != 0 { + fmt.Printf("lsh_uint16 1<<65535 = %d, wanted 0\n", got) + failed = true + } + + if got := lsh_uint16_1_ssa(65535); got != 65534 { + fmt.Printf("lsh_uint16 65535<<1 = %d, wanted 65534\n", got) + failed = true + } + + if got := lsh_65535_uint16_ssa(0); got != 65535 { + fmt.Printf("lsh_uint16 65535<<0 = %d, wanted 65535\n", got) + failed = true + } + + if got := lsh_uint16_65535_ssa(0); got != 0 { + fmt.Printf("lsh_uint16 0<<65535 = %d, wanted 0\n", got) + failed = true + } + + if got := lsh_65535_uint16_ssa(1); got != 65534 { + fmt.Printf("lsh_uint16 65535<<1 = %d, wanted 65534\n", got) + failed = true + } + + if got := lsh_uint16_65535_ssa(1); got != 0 { + fmt.Printf("lsh_uint16 1<<65535 = %d, wanted 0\n", got) + failed = true + } + + if got := lsh_65535_uint16_ssa(65535); got != 0 { + fmt.Printf("lsh_uint16 65535<<65535 = %d, wanted 0\n", got) + failed = true + } + + if got := lsh_uint16_65535_ssa(65535); got != 0 { + fmt.Printf("lsh_uint16 65535<<65535 = %d, wanted 0\n", got) + failed = true + } + + if got := rsh_0_uint16_ssa(0); got != 0 { + fmt.Printf("rsh_uint16 0>>0 = %d, wanted 0\n", got) + failed = true + } + + if got := rsh_uint16_0_ssa(0); got != 0 { + fmt.Printf("rsh_uint16 0>>0 = %d, wanted 0\n", got) + failed = true + } + + if got := rsh_0_uint16_ssa(1); got != 0 { + fmt.Printf("rsh_uint16 0>>1 = %d, wanted 0\n", got) + failed = true + } + + if got := rsh_uint16_0_ssa(1); got != 1 { + fmt.Printf("rsh_uint16 1>>0 = %d, wanted 1\n", got) + failed = true + } + + if got := rsh_0_uint16_ssa(65535); got != 0 { + fmt.Printf("rsh_uint16 0>>65535 = %d, wanted 0\n", got) + failed = true + } + + if got := rsh_uint16_0_ssa(65535); got != 65535 { + fmt.Printf("rsh_uint16 65535>>0 = %d, wanted 65535\n", got) + failed = true + } + + if got := rsh_1_uint16_ssa(0); got != 1 { + fmt.Printf("rsh_uint16 1>>0 = %d, wanted 1\n", got) + failed = true + } + + if got := rsh_uint16_1_ssa(0); got != 0 { + fmt.Printf("rsh_uint16 0>>1 = %d, wanted 0\n", got) + failed = true + } + + if got := rsh_1_uint16_ssa(1); got != 0 { + fmt.Printf("rsh_uint16 1>>1 = %d, wanted 0\n", got) + failed = true + } + + if got := rsh_uint16_1_ssa(1); got != 0 { + fmt.Printf("rsh_uint16 1>>1 = %d, wanted 0\n", got) + failed = true + } + + if got := rsh_1_uint16_ssa(65535); got != 0 { + fmt.Printf("rsh_uint16 1>>65535 = %d, wanted 0\n", got) + failed = true + } + + if got := rsh_uint16_1_ssa(65535); got != 32767 { + fmt.Printf("rsh_uint16 65535>>1 = %d, wanted 32767\n", got) + failed = true + } + + if got := rsh_65535_uint16_ssa(0); got != 65535 { + fmt.Printf("rsh_uint16 65535>>0 = %d, wanted 65535\n", got) + failed = true + } + + if got := rsh_uint16_65535_ssa(0); got != 0 { + fmt.Printf("rsh_uint16 0>>65535 = %d, wanted 0\n", got) + failed = true + } + + if got := rsh_65535_uint16_ssa(1); got != 32767 { + fmt.Printf("rsh_uint16 65535>>1 = %d, wanted 32767\n", got) + failed = true + } + + if got := rsh_uint16_65535_ssa(1); got != 0 { + fmt.Printf("rsh_uint16 1>>65535 = %d, wanted 0\n", got) + failed = true + } + + if got := rsh_65535_uint16_ssa(65535); got != 0 { + fmt.Printf("rsh_uint16 65535>>65535 = %d, wanted 0\n", got) + failed = true + } + + if got := rsh_uint16_65535_ssa(65535); got != 0 { + fmt.Printf("rsh_uint16 65535>>65535 = %d, wanted 0\n", got) + failed = true + } + + if got := add_Neg32768_int16_ssa(-32768); got != 0 { + fmt.Printf("add_int16 -32768+-32768 = %d, wanted 0\n", got) + failed = true + } + + if got := add_int16_Neg32768_ssa(-32768); got != 0 { + fmt.Printf("add_int16 -32768+-32768 = %d, wanted 0\n", got) + failed = true + } + + if got := add_Neg32768_int16_ssa(-32767); got != 1 { + fmt.Printf("add_int16 -32768+-32767 = %d, wanted 1\n", got) + failed = true + } + + if got := add_int16_Neg32768_ssa(-32767); got != 1 { + fmt.Printf("add_int16 -32767+-32768 = %d, wanted 1\n", got) + failed = true + } + + if got := add_Neg32768_int16_ssa(-1); got != 32767 { + fmt.Printf("add_int16 -32768+-1 = %d, wanted 32767\n", got) + failed = true + } + + if got := add_int16_Neg32768_ssa(-1); got != 32767 { + fmt.Printf("add_int16 -1+-32768 = %d, wanted 32767\n", got) + failed = true + } + + if got := add_Neg32768_int16_ssa(0); got != -32768 { + fmt.Printf("add_int16 -32768+0 = %d, wanted -32768\n", got) + failed = true + } + + if got := add_int16_Neg32768_ssa(0); got != -32768 { + fmt.Printf("add_int16 0+-32768 = %d, wanted -32768\n", got) + failed = true + } + + if got := add_Neg32768_int16_ssa(1); got != -32767 { + fmt.Printf("add_int16 -32768+1 = %d, wanted -32767\n", got) + failed = true + } + + if got := add_int16_Neg32768_ssa(1); got != -32767 { + fmt.Printf("add_int16 1+-32768 = %d, wanted -32767\n", got) + failed = true + } + + if got := add_Neg32768_int16_ssa(32766); got != -2 { + fmt.Printf("add_int16 -32768+32766 = %d, wanted -2\n", got) + failed = true + } + + if got := add_int16_Neg32768_ssa(32766); got != -2 { + fmt.Printf("add_int16 32766+-32768 = %d, wanted -2\n", got) + failed = true + } + + if got := add_Neg32768_int16_ssa(32767); got != -1 { + fmt.Printf("add_int16 -32768+32767 = %d, wanted -1\n", got) + failed = true + } + + if got := add_int16_Neg32768_ssa(32767); got != -1 { + fmt.Printf("add_int16 32767+-32768 = %d, wanted -1\n", got) + failed = true + } + + if got := add_Neg32767_int16_ssa(-32768); got != 1 { + fmt.Printf("add_int16 -32767+-32768 = %d, wanted 1\n", got) + failed = true + } + + if got := add_int16_Neg32767_ssa(-32768); got != 1 { + fmt.Printf("add_int16 -32768+-32767 = %d, wanted 1\n", got) + failed = true + } + + if got := add_Neg32767_int16_ssa(-32767); got != 2 { + fmt.Printf("add_int16 -32767+-32767 = %d, wanted 2\n", got) + failed = true + } + + if got := add_int16_Neg32767_ssa(-32767); got != 2 { + fmt.Printf("add_int16 -32767+-32767 = %d, wanted 2\n", got) + failed = true + } + + if got := add_Neg32767_int16_ssa(-1); got != -32768 { + fmt.Printf("add_int16 -32767+-1 = %d, wanted -32768\n", got) + failed = true + } + + if got := add_int16_Neg32767_ssa(-1); got != -32768 { + fmt.Printf("add_int16 -1+-32767 = %d, wanted -32768\n", got) + failed = true + } + + if got := add_Neg32767_int16_ssa(0); got != -32767 { + fmt.Printf("add_int16 -32767+0 = %d, wanted -32767\n", got) + failed = true + } + + if got := add_int16_Neg32767_ssa(0); got != -32767 { + fmt.Printf("add_int16 0+-32767 = %d, wanted -32767\n", got) + failed = true + } + + if got := add_Neg32767_int16_ssa(1); got != -32766 { + fmt.Printf("add_int16 -32767+1 = %d, wanted -32766\n", got) + failed = true + } + + if got := add_int16_Neg32767_ssa(1); got != -32766 { + fmt.Printf("add_int16 1+-32767 = %d, wanted -32766\n", got) + failed = true + } + + if got := add_Neg32767_int16_ssa(32766); got != -1 { + fmt.Printf("add_int16 -32767+32766 = %d, wanted -1\n", got) + failed = true + } + + if got := add_int16_Neg32767_ssa(32766); got != -1 { + fmt.Printf("add_int16 32766+-32767 = %d, wanted -1\n", got) + failed = true + } + + if got := add_Neg32767_int16_ssa(32767); got != 0 { + fmt.Printf("add_int16 -32767+32767 = %d, wanted 0\n", got) + failed = true + } + + if got := add_int16_Neg32767_ssa(32767); got != 0 { + fmt.Printf("add_int16 32767+-32767 = %d, wanted 0\n", got) + failed = true + } + + if got := add_Neg1_int16_ssa(-32768); got != 32767 { + fmt.Printf("add_int16 -1+-32768 = %d, wanted 32767\n", got) + failed = true + } + + if got := add_int16_Neg1_ssa(-32768); got != 32767 { + fmt.Printf("add_int16 -32768+-1 = %d, wanted 32767\n", got) + failed = true + } + + if got := add_Neg1_int16_ssa(-32767); got != -32768 { + fmt.Printf("add_int16 -1+-32767 = %d, wanted -32768\n", got) + failed = true + } + + if got := add_int16_Neg1_ssa(-32767); got != -32768 { + fmt.Printf("add_int16 -32767+-1 = %d, wanted -32768\n", got) + failed = true + } + + if got := add_Neg1_int16_ssa(-1); got != -2 { + fmt.Printf("add_int16 -1+-1 = %d, wanted -2\n", got) + failed = true + } + + if got := add_int16_Neg1_ssa(-1); got != -2 { + fmt.Printf("add_int16 -1+-1 = %d, wanted -2\n", got) + failed = true + } + + if got := add_Neg1_int16_ssa(0); got != -1 { + fmt.Printf("add_int16 -1+0 = %d, wanted -1\n", got) + failed = true + } + + if got := add_int16_Neg1_ssa(0); got != -1 { + fmt.Printf("add_int16 0+-1 = %d, wanted -1\n", got) + failed = true + } + + if got := add_Neg1_int16_ssa(1); got != 0 { + fmt.Printf("add_int16 -1+1 = %d, wanted 0\n", got) + failed = true + } + + if got := add_int16_Neg1_ssa(1); got != 0 { + fmt.Printf("add_int16 1+-1 = %d, wanted 0\n", got) + failed = true + } + + if got := add_Neg1_int16_ssa(32766); got != 32765 { + fmt.Printf("add_int16 -1+32766 = %d, wanted 32765\n", got) + failed = true + } + + if got := add_int16_Neg1_ssa(32766); got != 32765 { + fmt.Printf("add_int16 32766+-1 = %d, wanted 32765\n", got) + failed = true + } + + if got := add_Neg1_int16_ssa(32767); got != 32766 { + fmt.Printf("add_int16 -1+32767 = %d, wanted 32766\n", got) + failed = true + } + + if got := add_int16_Neg1_ssa(32767); got != 32766 { + fmt.Printf("add_int16 32767+-1 = %d, wanted 32766\n", got) + failed = true + } + + if got := add_0_int16_ssa(-32768); got != -32768 { + fmt.Printf("add_int16 0+-32768 = %d, wanted -32768\n", got) + failed = true + } + + if got := add_int16_0_ssa(-32768); got != -32768 { + fmt.Printf("add_int16 -32768+0 = %d, wanted -32768\n", got) + failed = true + } + + if got := add_0_int16_ssa(-32767); got != -32767 { + fmt.Printf("add_int16 0+-32767 = %d, wanted -32767\n", got) + failed = true + } + + if got := add_int16_0_ssa(-32767); got != -32767 { + fmt.Printf("add_int16 -32767+0 = %d, wanted -32767\n", got) + failed = true + } + + if got := add_0_int16_ssa(-1); got != -1 { + fmt.Printf("add_int16 0+-1 = %d, wanted -1\n", got) + failed = true + } + + if got := add_int16_0_ssa(-1); got != -1 { + fmt.Printf("add_int16 -1+0 = %d, wanted -1\n", got) + failed = true + } + + if got := add_0_int16_ssa(0); got != 0 { + fmt.Printf("add_int16 0+0 = %d, wanted 0\n", got) + failed = true + } + + if got := add_int16_0_ssa(0); got != 0 { + fmt.Printf("add_int16 0+0 = %d, wanted 0\n", got) + failed = true + } + + if got := add_0_int16_ssa(1); got != 1 { + fmt.Printf("add_int16 0+1 = %d, wanted 1\n", got) + failed = true + } + + if got := add_int16_0_ssa(1); got != 1 { + fmt.Printf("add_int16 1+0 = %d, wanted 1\n", got) + failed = true + } + + if got := add_0_int16_ssa(32766); got != 32766 { + fmt.Printf("add_int16 0+32766 = %d, wanted 32766\n", got) + failed = true + } + + if got := add_int16_0_ssa(32766); got != 32766 { + fmt.Printf("add_int16 32766+0 = %d, wanted 32766\n", got) + failed = true + } + + if got := add_0_int16_ssa(32767); got != 32767 { + fmt.Printf("add_int16 0+32767 = %d, wanted 32767\n", got) + failed = true + } + + if got := add_int16_0_ssa(32767); got != 32767 { + fmt.Printf("add_int16 32767+0 = %d, wanted 32767\n", got) + failed = true + } + + if got := add_1_int16_ssa(-32768); got != -32767 { + fmt.Printf("add_int16 1+-32768 = %d, wanted -32767\n", got) + failed = true + } + + if got := add_int16_1_ssa(-32768); got != -32767 { + fmt.Printf("add_int16 -32768+1 = %d, wanted -32767\n", got) + failed = true + } + + if got := add_1_int16_ssa(-32767); got != -32766 { + fmt.Printf("add_int16 1+-32767 = %d, wanted -32766\n", got) + failed = true + } + + if got := add_int16_1_ssa(-32767); got != -32766 { + fmt.Printf("add_int16 -32767+1 = %d, wanted -32766\n", got) + failed = true + } + + if got := add_1_int16_ssa(-1); got != 0 { + fmt.Printf("add_int16 1+-1 = %d, wanted 0\n", got) + failed = true + } + + if got := add_int16_1_ssa(-1); got != 0 { + fmt.Printf("add_int16 -1+1 = %d, wanted 0\n", got) + failed = true + } + + if got := add_1_int16_ssa(0); got != 1 { + fmt.Printf("add_int16 1+0 = %d, wanted 1\n", got) + failed = true + } + + if got := add_int16_1_ssa(0); got != 1 { + fmt.Printf("add_int16 0+1 = %d, wanted 1\n", got) + failed = true + } + + if got := add_1_int16_ssa(1); got != 2 { + fmt.Printf("add_int16 1+1 = %d, wanted 2\n", got) + failed = true + } + + if got := add_int16_1_ssa(1); got != 2 { + fmt.Printf("add_int16 1+1 = %d, wanted 2\n", got) + failed = true + } + + if got := add_1_int16_ssa(32766); got != 32767 { + fmt.Printf("add_int16 1+32766 = %d, wanted 32767\n", got) + failed = true + } + + if got := add_int16_1_ssa(32766); got != 32767 { + fmt.Printf("add_int16 32766+1 = %d, wanted 32767\n", got) + failed = true + } + + if got := add_1_int16_ssa(32767); got != -32768 { + fmt.Printf("add_int16 1+32767 = %d, wanted -32768\n", got) + failed = true + } + + if got := add_int16_1_ssa(32767); got != -32768 { + fmt.Printf("add_int16 32767+1 = %d, wanted -32768\n", got) + failed = true + } + + if got := add_32766_int16_ssa(-32768); got != -2 { + fmt.Printf("add_int16 32766+-32768 = %d, wanted -2\n", got) + failed = true + } + + if got := add_int16_32766_ssa(-32768); got != -2 { + fmt.Printf("add_int16 -32768+32766 = %d, wanted -2\n", got) + failed = true + } + + if got := add_32766_int16_ssa(-32767); got != -1 { + fmt.Printf("add_int16 32766+-32767 = %d, wanted -1\n", got) + failed = true + } + + if got := add_int16_32766_ssa(-32767); got != -1 { + fmt.Printf("add_int16 -32767+32766 = %d, wanted -1\n", got) + failed = true + } + + if got := add_32766_int16_ssa(-1); got != 32765 { + fmt.Printf("add_int16 32766+-1 = %d, wanted 32765\n", got) + failed = true + } + + if got := add_int16_32766_ssa(-1); got != 32765 { + fmt.Printf("add_int16 -1+32766 = %d, wanted 32765\n", got) + failed = true + } + + if got := add_32766_int16_ssa(0); got != 32766 { + fmt.Printf("add_int16 32766+0 = %d, wanted 32766\n", got) + failed = true + } + + if got := add_int16_32766_ssa(0); got != 32766 { + fmt.Printf("add_int16 0+32766 = %d, wanted 32766\n", got) + failed = true + } + + if got := add_32766_int16_ssa(1); got != 32767 { + fmt.Printf("add_int16 32766+1 = %d, wanted 32767\n", got) + failed = true + } + + if got := add_int16_32766_ssa(1); got != 32767 { + fmt.Printf("add_int16 1+32766 = %d, wanted 32767\n", got) + failed = true + } + + if got := add_32766_int16_ssa(32766); got != -4 { + fmt.Printf("add_int16 32766+32766 = %d, wanted -4\n", got) + failed = true + } + + if got := add_int16_32766_ssa(32766); got != -4 { + fmt.Printf("add_int16 32766+32766 = %d, wanted -4\n", got) + failed = true + } + + if got := add_32766_int16_ssa(32767); got != -3 { + fmt.Printf("add_int16 32766+32767 = %d, wanted -3\n", got) + failed = true + } + + if got := add_int16_32766_ssa(32767); got != -3 { + fmt.Printf("add_int16 32767+32766 = %d, wanted -3\n", got) + failed = true + } + + if got := add_32767_int16_ssa(-32768); got != -1 { + fmt.Printf("add_int16 32767+-32768 = %d, wanted -1\n", got) + failed = true + } + + if got := add_int16_32767_ssa(-32768); got != -1 { + fmt.Printf("add_int16 -32768+32767 = %d, wanted -1\n", got) + failed = true + } + + if got := add_32767_int16_ssa(-32767); got != 0 { + fmt.Printf("add_int16 32767+-32767 = %d, wanted 0\n", got) + failed = true + } + + if got := add_int16_32767_ssa(-32767); got != 0 { + fmt.Printf("add_int16 -32767+32767 = %d, wanted 0\n", got) + failed = true + } + + if got := add_32767_int16_ssa(-1); got != 32766 { + fmt.Printf("add_int16 32767+-1 = %d, wanted 32766\n", got) + failed = true + } + + if got := add_int16_32767_ssa(-1); got != 32766 { + fmt.Printf("add_int16 -1+32767 = %d, wanted 32766\n", got) + failed = true + } + + if got := add_32767_int16_ssa(0); got != 32767 { + fmt.Printf("add_int16 32767+0 = %d, wanted 32767\n", got) + failed = true + } + + if got := add_int16_32767_ssa(0); got != 32767 { + fmt.Printf("add_int16 0+32767 = %d, wanted 32767\n", got) + failed = true + } + + if got := add_32767_int16_ssa(1); got != -32768 { + fmt.Printf("add_int16 32767+1 = %d, wanted -32768\n", got) + failed = true + } + + if got := add_int16_32767_ssa(1); got != -32768 { + fmt.Printf("add_int16 1+32767 = %d, wanted -32768\n", got) + failed = true + } + + if got := add_32767_int16_ssa(32766); got != -3 { + fmt.Printf("add_int16 32767+32766 = %d, wanted -3\n", got) + failed = true + } + + if got := add_int16_32767_ssa(32766); got != -3 { + fmt.Printf("add_int16 32766+32767 = %d, wanted -3\n", got) + failed = true + } + + if got := add_32767_int16_ssa(32767); got != -2 { + fmt.Printf("add_int16 32767+32767 = %d, wanted -2\n", got) + failed = true + } + + if got := add_int16_32767_ssa(32767); got != -2 { + fmt.Printf("add_int16 32767+32767 = %d, wanted -2\n", got) + failed = true + } + + if got := sub_Neg32768_int16_ssa(-32768); got != 0 { + fmt.Printf("sub_int16 -32768--32768 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_int16_Neg32768_ssa(-32768); got != 0 { + fmt.Printf("sub_int16 -32768--32768 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_Neg32768_int16_ssa(-32767); got != -1 { + fmt.Printf("sub_int16 -32768--32767 = %d, wanted -1\n", got) + failed = true + } + + if got := sub_int16_Neg32768_ssa(-32767); got != 1 { + fmt.Printf("sub_int16 -32767--32768 = %d, wanted 1\n", got) + failed = true + } + + if got := sub_Neg32768_int16_ssa(-1); got != -32767 { + fmt.Printf("sub_int16 -32768--1 = %d, wanted -32767\n", got) + failed = true + } + + if got := sub_int16_Neg32768_ssa(-1); got != 32767 { + fmt.Printf("sub_int16 -1--32768 = %d, wanted 32767\n", got) + failed = true + } + + if got := sub_Neg32768_int16_ssa(0); got != -32768 { + fmt.Printf("sub_int16 -32768-0 = %d, wanted -32768\n", got) + failed = true + } + + if got := sub_int16_Neg32768_ssa(0); got != -32768 { + fmt.Printf("sub_int16 0--32768 = %d, wanted -32768\n", got) + failed = true + } + + if got := sub_Neg32768_int16_ssa(1); got != 32767 { + fmt.Printf("sub_int16 -32768-1 = %d, wanted 32767\n", got) + failed = true + } + + if got := sub_int16_Neg32768_ssa(1); got != -32767 { + fmt.Printf("sub_int16 1--32768 = %d, wanted -32767\n", got) + failed = true + } + + if got := sub_Neg32768_int16_ssa(32766); got != 2 { + fmt.Printf("sub_int16 -32768-32766 = %d, wanted 2\n", got) + failed = true + } + + if got := sub_int16_Neg32768_ssa(32766); got != -2 { + fmt.Printf("sub_int16 32766--32768 = %d, wanted -2\n", got) + failed = true + } + + if got := sub_Neg32768_int16_ssa(32767); got != 1 { + fmt.Printf("sub_int16 -32768-32767 = %d, wanted 1\n", got) + failed = true + } + + if got := sub_int16_Neg32768_ssa(32767); got != -1 { + fmt.Printf("sub_int16 32767--32768 = %d, wanted -1\n", got) + failed = true + } + + if got := sub_Neg32767_int16_ssa(-32768); got != 1 { + fmt.Printf("sub_int16 -32767--32768 = %d, wanted 1\n", got) + failed = true + } + + if got := sub_int16_Neg32767_ssa(-32768); got != -1 { + fmt.Printf("sub_int16 -32768--32767 = %d, wanted -1\n", got) + failed = true + } + + if got := sub_Neg32767_int16_ssa(-32767); got != 0 { + fmt.Printf("sub_int16 -32767--32767 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_int16_Neg32767_ssa(-32767); got != 0 { + fmt.Printf("sub_int16 -32767--32767 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_Neg32767_int16_ssa(-1); got != -32766 { + fmt.Printf("sub_int16 -32767--1 = %d, wanted -32766\n", got) + failed = true + } + + if got := sub_int16_Neg32767_ssa(-1); got != 32766 { + fmt.Printf("sub_int16 -1--32767 = %d, wanted 32766\n", got) + failed = true + } + + if got := sub_Neg32767_int16_ssa(0); got != -32767 { + fmt.Printf("sub_int16 -32767-0 = %d, wanted -32767\n", got) + failed = true + } + + if got := sub_int16_Neg32767_ssa(0); got != 32767 { + fmt.Printf("sub_int16 0--32767 = %d, wanted 32767\n", got) + failed = true + } + + if got := sub_Neg32767_int16_ssa(1); got != -32768 { + fmt.Printf("sub_int16 -32767-1 = %d, wanted -32768\n", got) + failed = true + } + + if got := sub_int16_Neg32767_ssa(1); got != -32768 { + fmt.Printf("sub_int16 1--32767 = %d, wanted -32768\n", got) + failed = true + } + + if got := sub_Neg32767_int16_ssa(32766); got != 3 { + fmt.Printf("sub_int16 -32767-32766 = %d, wanted 3\n", got) + failed = true + } + + if got := sub_int16_Neg32767_ssa(32766); got != -3 { + fmt.Printf("sub_int16 32766--32767 = %d, wanted -3\n", got) + failed = true + } + + if got := sub_Neg32767_int16_ssa(32767); got != 2 { + fmt.Printf("sub_int16 -32767-32767 = %d, wanted 2\n", got) + failed = true + } + + if got := sub_int16_Neg32767_ssa(32767); got != -2 { + fmt.Printf("sub_int16 32767--32767 = %d, wanted -2\n", got) + failed = true + } + + if got := sub_Neg1_int16_ssa(-32768); got != 32767 { + fmt.Printf("sub_int16 -1--32768 = %d, wanted 32767\n", got) + failed = true + } + + if got := sub_int16_Neg1_ssa(-32768); got != -32767 { + fmt.Printf("sub_int16 -32768--1 = %d, wanted -32767\n", got) + failed = true + } + + if got := sub_Neg1_int16_ssa(-32767); got != 32766 { + fmt.Printf("sub_int16 -1--32767 = %d, wanted 32766\n", got) + failed = true + } + + if got := sub_int16_Neg1_ssa(-32767); got != -32766 { + fmt.Printf("sub_int16 -32767--1 = %d, wanted -32766\n", got) + failed = true + } + + if got := sub_Neg1_int16_ssa(-1); got != 0 { + fmt.Printf("sub_int16 -1--1 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_int16_Neg1_ssa(-1); got != 0 { + fmt.Printf("sub_int16 -1--1 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_Neg1_int16_ssa(0); got != -1 { + fmt.Printf("sub_int16 -1-0 = %d, wanted -1\n", got) + failed = true + } + + if got := sub_int16_Neg1_ssa(0); got != 1 { + fmt.Printf("sub_int16 0--1 = %d, wanted 1\n", got) + failed = true + } + + if got := sub_Neg1_int16_ssa(1); got != -2 { + fmt.Printf("sub_int16 -1-1 = %d, wanted -2\n", got) + failed = true + } + + if got := sub_int16_Neg1_ssa(1); got != 2 { + fmt.Printf("sub_int16 1--1 = %d, wanted 2\n", got) + failed = true + } + + if got := sub_Neg1_int16_ssa(32766); got != -32767 { + fmt.Printf("sub_int16 -1-32766 = %d, wanted -32767\n", got) + failed = true + } + + if got := sub_int16_Neg1_ssa(32766); got != 32767 { + fmt.Printf("sub_int16 32766--1 = %d, wanted 32767\n", got) + failed = true + } + + if got := sub_Neg1_int16_ssa(32767); got != -32768 { + fmt.Printf("sub_int16 -1-32767 = %d, wanted -32768\n", got) + failed = true + } + + if got := sub_int16_Neg1_ssa(32767); got != -32768 { + fmt.Printf("sub_int16 32767--1 = %d, wanted -32768\n", got) + failed = true + } + + if got := sub_0_int16_ssa(-32768); got != -32768 { + fmt.Printf("sub_int16 0--32768 = %d, wanted -32768\n", got) + failed = true + } + + if got := sub_int16_0_ssa(-32768); got != -32768 { + fmt.Printf("sub_int16 -32768-0 = %d, wanted -32768\n", got) + failed = true + } + + if got := sub_0_int16_ssa(-32767); got != 32767 { + fmt.Printf("sub_int16 0--32767 = %d, wanted 32767\n", got) + failed = true + } + + if got := sub_int16_0_ssa(-32767); got != -32767 { + fmt.Printf("sub_int16 -32767-0 = %d, wanted -32767\n", got) + failed = true + } + + if got := sub_0_int16_ssa(-1); got != 1 { + fmt.Printf("sub_int16 0--1 = %d, wanted 1\n", got) + failed = true + } + + if got := sub_int16_0_ssa(-1); got != -1 { + fmt.Printf("sub_int16 -1-0 = %d, wanted -1\n", got) + failed = true + } + + if got := sub_0_int16_ssa(0); got != 0 { + fmt.Printf("sub_int16 0-0 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_int16_0_ssa(0); got != 0 { + fmt.Printf("sub_int16 0-0 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_0_int16_ssa(1); got != -1 { + fmt.Printf("sub_int16 0-1 = %d, wanted -1\n", got) + failed = true + } + + if got := sub_int16_0_ssa(1); got != 1 { + fmt.Printf("sub_int16 1-0 = %d, wanted 1\n", got) + failed = true + } + + if got := sub_0_int16_ssa(32766); got != -32766 { + fmt.Printf("sub_int16 0-32766 = %d, wanted -32766\n", got) + failed = true + } + + if got := sub_int16_0_ssa(32766); got != 32766 { + fmt.Printf("sub_int16 32766-0 = %d, wanted 32766\n", got) + failed = true + } + + if got := sub_0_int16_ssa(32767); got != -32767 { + fmt.Printf("sub_int16 0-32767 = %d, wanted -32767\n", got) + failed = true + } + + if got := sub_int16_0_ssa(32767); got != 32767 { + fmt.Printf("sub_int16 32767-0 = %d, wanted 32767\n", got) + failed = true + } + + if got := sub_1_int16_ssa(-32768); got != -32767 { + fmt.Printf("sub_int16 1--32768 = %d, wanted -32767\n", got) + failed = true + } + + if got := sub_int16_1_ssa(-32768); got != 32767 { + fmt.Printf("sub_int16 -32768-1 = %d, wanted 32767\n", got) + failed = true + } + + if got := sub_1_int16_ssa(-32767); got != -32768 { + fmt.Printf("sub_int16 1--32767 = %d, wanted -32768\n", got) + failed = true + } + + if got := sub_int16_1_ssa(-32767); got != -32768 { + fmt.Printf("sub_int16 -32767-1 = %d, wanted -32768\n", got) + failed = true + } + + if got := sub_1_int16_ssa(-1); got != 2 { + fmt.Printf("sub_int16 1--1 = %d, wanted 2\n", got) + failed = true + } + + if got := sub_int16_1_ssa(-1); got != -2 { + fmt.Printf("sub_int16 -1-1 = %d, wanted -2\n", got) + failed = true + } + + if got := sub_1_int16_ssa(0); got != 1 { + fmt.Printf("sub_int16 1-0 = %d, wanted 1\n", got) + failed = true + } + + if got := sub_int16_1_ssa(0); got != -1 { + fmt.Printf("sub_int16 0-1 = %d, wanted -1\n", got) + failed = true + } + + if got := sub_1_int16_ssa(1); got != 0 { + fmt.Printf("sub_int16 1-1 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_int16_1_ssa(1); got != 0 { + fmt.Printf("sub_int16 1-1 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_1_int16_ssa(32766); got != -32765 { + fmt.Printf("sub_int16 1-32766 = %d, wanted -32765\n", got) + failed = true + } + + if got := sub_int16_1_ssa(32766); got != 32765 { + fmt.Printf("sub_int16 32766-1 = %d, wanted 32765\n", got) + failed = true + } + + if got := sub_1_int16_ssa(32767); got != -32766 { + fmt.Printf("sub_int16 1-32767 = %d, wanted -32766\n", got) + failed = true + } + + if got := sub_int16_1_ssa(32767); got != 32766 { + fmt.Printf("sub_int16 32767-1 = %d, wanted 32766\n", got) + failed = true + } + + if got := sub_32766_int16_ssa(-32768); got != -2 { + fmt.Printf("sub_int16 32766--32768 = %d, wanted -2\n", got) + failed = true + } + + if got := sub_int16_32766_ssa(-32768); got != 2 { + fmt.Printf("sub_int16 -32768-32766 = %d, wanted 2\n", got) + failed = true + } + + if got := sub_32766_int16_ssa(-32767); got != -3 { + fmt.Printf("sub_int16 32766--32767 = %d, wanted -3\n", got) + failed = true + } + + if got := sub_int16_32766_ssa(-32767); got != 3 { + fmt.Printf("sub_int16 -32767-32766 = %d, wanted 3\n", got) + failed = true + } + + if got := sub_32766_int16_ssa(-1); got != 32767 { + fmt.Printf("sub_int16 32766--1 = %d, wanted 32767\n", got) + failed = true + } + + if got := sub_int16_32766_ssa(-1); got != -32767 { + fmt.Printf("sub_int16 -1-32766 = %d, wanted -32767\n", got) + failed = true + } + + if got := sub_32766_int16_ssa(0); got != 32766 { + fmt.Printf("sub_int16 32766-0 = %d, wanted 32766\n", got) + failed = true + } + + if got := sub_int16_32766_ssa(0); got != -32766 { + fmt.Printf("sub_int16 0-32766 = %d, wanted -32766\n", got) + failed = true + } + + if got := sub_32766_int16_ssa(1); got != 32765 { + fmt.Printf("sub_int16 32766-1 = %d, wanted 32765\n", got) + failed = true + } + + if got := sub_int16_32766_ssa(1); got != -32765 { + fmt.Printf("sub_int16 1-32766 = %d, wanted -32765\n", got) + failed = true + } + + if got := sub_32766_int16_ssa(32766); got != 0 { + fmt.Printf("sub_int16 32766-32766 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_int16_32766_ssa(32766); got != 0 { + fmt.Printf("sub_int16 32766-32766 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_32766_int16_ssa(32767); got != -1 { + fmt.Printf("sub_int16 32766-32767 = %d, wanted -1\n", got) + failed = true + } + + if got := sub_int16_32766_ssa(32767); got != 1 { + fmt.Printf("sub_int16 32767-32766 = %d, wanted 1\n", got) + failed = true + } + + if got := sub_32767_int16_ssa(-32768); got != -1 { + fmt.Printf("sub_int16 32767--32768 = %d, wanted -1\n", got) + failed = true + } + + if got := sub_int16_32767_ssa(-32768); got != 1 { + fmt.Printf("sub_int16 -32768-32767 = %d, wanted 1\n", got) + failed = true + } + + if got := sub_32767_int16_ssa(-32767); got != -2 { + fmt.Printf("sub_int16 32767--32767 = %d, wanted -2\n", got) + failed = true + } + + if got := sub_int16_32767_ssa(-32767); got != 2 { + fmt.Printf("sub_int16 -32767-32767 = %d, wanted 2\n", got) + failed = true + } + + if got := sub_32767_int16_ssa(-1); got != -32768 { + fmt.Printf("sub_int16 32767--1 = %d, wanted -32768\n", got) + failed = true + } + + if got := sub_int16_32767_ssa(-1); got != -32768 { + fmt.Printf("sub_int16 -1-32767 = %d, wanted -32768\n", got) + failed = true + } + + if got := sub_32767_int16_ssa(0); got != 32767 { + fmt.Printf("sub_int16 32767-0 = %d, wanted 32767\n", got) + failed = true + } + + if got := sub_int16_32767_ssa(0); got != -32767 { + fmt.Printf("sub_int16 0-32767 = %d, wanted -32767\n", got) + failed = true + } + + if got := sub_32767_int16_ssa(1); got != 32766 { + fmt.Printf("sub_int16 32767-1 = %d, wanted 32766\n", got) + failed = true + } + + if got := sub_int16_32767_ssa(1); got != -32766 { + fmt.Printf("sub_int16 1-32767 = %d, wanted -32766\n", got) + failed = true + } + + if got := sub_32767_int16_ssa(32766); got != 1 { + fmt.Printf("sub_int16 32767-32766 = %d, wanted 1\n", got) + failed = true + } + + if got := sub_int16_32767_ssa(32766); got != -1 { + fmt.Printf("sub_int16 32766-32767 = %d, wanted -1\n", got) + failed = true + } + + if got := sub_32767_int16_ssa(32767); got != 0 { + fmt.Printf("sub_int16 32767-32767 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_int16_32767_ssa(32767); got != 0 { + fmt.Printf("sub_int16 32767-32767 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg32768_int16_ssa(-32768); got != 1 { + fmt.Printf("div_int16 -32768/-32768 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int16_Neg32768_ssa(-32768); got != 1 { + fmt.Printf("div_int16 -32768/-32768 = %d, wanted 1\n", got) + failed = true + } + + if got := div_Neg32768_int16_ssa(-32767); got != 1 { + fmt.Printf("div_int16 -32768/-32767 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int16_Neg32768_ssa(-32767); got != 0 { + fmt.Printf("div_int16 -32767/-32768 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg32768_int16_ssa(-1); got != -32768 { + fmt.Printf("div_int16 -32768/-1 = %d, wanted -32768\n", got) + failed = true + } + + if got := div_int16_Neg32768_ssa(-1); got != 0 { + fmt.Printf("div_int16 -1/-32768 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int16_Neg32768_ssa(0); got != 0 { + fmt.Printf("div_int16 0/-32768 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg32768_int16_ssa(1); got != -32768 { + fmt.Printf("div_int16 -32768/1 = %d, wanted -32768\n", got) + failed = true + } + + if got := div_int16_Neg32768_ssa(1); got != 0 { + fmt.Printf("div_int16 1/-32768 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg32768_int16_ssa(32766); got != -1 { + fmt.Printf("div_int16 -32768/32766 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int16_Neg32768_ssa(32766); got != 0 { + fmt.Printf("div_int16 32766/-32768 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg32768_int16_ssa(32767); got != -1 { + fmt.Printf("div_int16 -32768/32767 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int16_Neg32768_ssa(32767); got != 0 { + fmt.Printf("div_int16 32767/-32768 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg32767_int16_ssa(-32768); got != 0 { + fmt.Printf("div_int16 -32767/-32768 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int16_Neg32767_ssa(-32768); got != 1 { + fmt.Printf("div_int16 -32768/-32767 = %d, wanted 1\n", got) + failed = true + } + + if got := div_Neg32767_int16_ssa(-32767); got != 1 { + fmt.Printf("div_int16 -32767/-32767 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int16_Neg32767_ssa(-32767); got != 1 { + fmt.Printf("div_int16 -32767/-32767 = %d, wanted 1\n", got) + failed = true + } + + if got := div_Neg32767_int16_ssa(-1); got != 32767 { + fmt.Printf("div_int16 -32767/-1 = %d, wanted 32767\n", got) + failed = true + } + + if got := div_int16_Neg32767_ssa(-1); got != 0 { + fmt.Printf("div_int16 -1/-32767 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int16_Neg32767_ssa(0); got != 0 { + fmt.Printf("div_int16 0/-32767 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg32767_int16_ssa(1); got != -32767 { + fmt.Printf("div_int16 -32767/1 = %d, wanted -32767\n", got) + failed = true + } + + if got := div_int16_Neg32767_ssa(1); got != 0 { + fmt.Printf("div_int16 1/-32767 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg32767_int16_ssa(32766); got != -1 { + fmt.Printf("div_int16 -32767/32766 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int16_Neg32767_ssa(32766); got != 0 { + fmt.Printf("div_int16 32766/-32767 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg32767_int16_ssa(32767); got != -1 { + fmt.Printf("div_int16 -32767/32767 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int16_Neg32767_ssa(32767); got != -1 { + fmt.Printf("div_int16 32767/-32767 = %d, wanted -1\n", got) + failed = true + } + + if got := div_Neg1_int16_ssa(-32768); got != 0 { + fmt.Printf("div_int16 -1/-32768 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int16_Neg1_ssa(-32768); got != -32768 { + fmt.Printf("div_int16 -32768/-1 = %d, wanted -32768\n", got) + failed = true + } + + if got := div_Neg1_int16_ssa(-32767); got != 0 { + fmt.Printf("div_int16 -1/-32767 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int16_Neg1_ssa(-32767); got != 32767 { + fmt.Printf("div_int16 -32767/-1 = %d, wanted 32767\n", got) + failed = true + } + + if got := div_Neg1_int16_ssa(-1); got != 1 { + fmt.Printf("div_int16 -1/-1 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int16_Neg1_ssa(-1); got != 1 { + fmt.Printf("div_int16 -1/-1 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int16_Neg1_ssa(0); got != 0 { + fmt.Printf("div_int16 0/-1 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg1_int16_ssa(1); got != -1 { + fmt.Printf("div_int16 -1/1 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int16_Neg1_ssa(1); got != -1 { + fmt.Printf("div_int16 1/-1 = %d, wanted -1\n", got) + failed = true + } + + if got := div_Neg1_int16_ssa(32766); got != 0 { + fmt.Printf("div_int16 -1/32766 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int16_Neg1_ssa(32766); got != -32766 { + fmt.Printf("div_int16 32766/-1 = %d, wanted -32766\n", got) + failed = true + } + + if got := div_Neg1_int16_ssa(32767); got != 0 { + fmt.Printf("div_int16 -1/32767 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int16_Neg1_ssa(32767); got != -32767 { + fmt.Printf("div_int16 32767/-1 = %d, wanted -32767\n", got) + failed = true + } + + if got := div_0_int16_ssa(-32768); got != 0 { + fmt.Printf("div_int16 0/-32768 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_int16_ssa(-32767); got != 0 { + fmt.Printf("div_int16 0/-32767 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_int16_ssa(-1); got != 0 { + fmt.Printf("div_int16 0/-1 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_int16_ssa(1); got != 0 { + fmt.Printf("div_int16 0/1 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_int16_ssa(32766); got != 0 { + fmt.Printf("div_int16 0/32766 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_int16_ssa(32767); got != 0 { + fmt.Printf("div_int16 0/32767 = %d, wanted 0\n", got) + failed = true + } + + if got := div_1_int16_ssa(-32768); got != 0 { + fmt.Printf("div_int16 1/-32768 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int16_1_ssa(-32768); got != -32768 { + fmt.Printf("div_int16 -32768/1 = %d, wanted -32768\n", got) + failed = true + } + + if got := div_1_int16_ssa(-32767); got != 0 { + fmt.Printf("div_int16 1/-32767 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int16_1_ssa(-32767); got != -32767 { + fmt.Printf("div_int16 -32767/1 = %d, wanted -32767\n", got) + failed = true + } + + if got := div_1_int16_ssa(-1); got != -1 { + fmt.Printf("div_int16 1/-1 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int16_1_ssa(-1); got != -1 { + fmt.Printf("div_int16 -1/1 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int16_1_ssa(0); got != 0 { + fmt.Printf("div_int16 0/1 = %d, wanted 0\n", got) + failed = true + } + + if got := div_1_int16_ssa(1); got != 1 { + fmt.Printf("div_int16 1/1 = %d, wanted 1\n", got) failed = true } @@ -3344,633 +9626,3043 @@ func main() { failed = true } - if got := div_1_int16_ssa(32766); got != 0 { - fmt.Printf("div_int16 1/32766 = %d, wanted 0\n", got) + if got := div_1_int16_ssa(32766); got != 0 { + fmt.Printf("div_int16 1/32766 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int16_1_ssa(32766); got != 32766 { + fmt.Printf("div_int16 32766/1 = %d, wanted 32766\n", got) + failed = true + } + + if got := div_1_int16_ssa(32767); got != 0 { + fmt.Printf("div_int16 1/32767 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int16_1_ssa(32767); got != 32767 { + fmt.Printf("div_int16 32767/1 = %d, wanted 32767\n", got) + failed = true + } + + if got := div_32766_int16_ssa(-32768); got != 0 { + fmt.Printf("div_int16 32766/-32768 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int16_32766_ssa(-32768); got != -1 { + fmt.Printf("div_int16 -32768/32766 = %d, wanted -1\n", got) + failed = true + } + + if got := div_32766_int16_ssa(-32767); got != 0 { + fmt.Printf("div_int16 32766/-32767 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int16_32766_ssa(-32767); got != -1 { + fmt.Printf("div_int16 -32767/32766 = %d, wanted -1\n", got) + failed = true + } + + if got := div_32766_int16_ssa(-1); got != -32766 { + fmt.Printf("div_int16 32766/-1 = %d, wanted -32766\n", got) + failed = true + } + + if got := div_int16_32766_ssa(-1); got != 0 { + fmt.Printf("div_int16 -1/32766 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int16_32766_ssa(0); got != 0 { + fmt.Printf("div_int16 0/32766 = %d, wanted 0\n", got) + failed = true + } + + if got := div_32766_int16_ssa(1); got != 32766 { + fmt.Printf("div_int16 32766/1 = %d, wanted 32766\n", got) + failed = true + } + + if got := div_int16_32766_ssa(1); got != 0 { + fmt.Printf("div_int16 1/32766 = %d, wanted 0\n", got) + failed = true + } + + if got := div_32766_int16_ssa(32766); got != 1 { + fmt.Printf("div_int16 32766/32766 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int16_32766_ssa(32766); got != 1 { + fmt.Printf("div_int16 32766/32766 = %d, wanted 1\n", got) + failed = true + } + + if got := div_32766_int16_ssa(32767); got != 0 { + fmt.Printf("div_int16 32766/32767 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int16_32766_ssa(32767); got != 1 { + fmt.Printf("div_int16 32767/32766 = %d, wanted 1\n", got) + failed = true + } + + if got := div_32767_int16_ssa(-32768); got != 0 { + fmt.Printf("div_int16 32767/-32768 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int16_32767_ssa(-32768); got != -1 { + fmt.Printf("div_int16 -32768/32767 = %d, wanted -1\n", got) + failed = true + } + + if got := div_32767_int16_ssa(-32767); got != -1 { + fmt.Printf("div_int16 32767/-32767 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int16_32767_ssa(-32767); got != -1 { + fmt.Printf("div_int16 -32767/32767 = %d, wanted -1\n", got) + failed = true + } + + if got := div_32767_int16_ssa(-1); got != -32767 { + fmt.Printf("div_int16 32767/-1 = %d, wanted -32767\n", got) + failed = true + } + + if got := div_int16_32767_ssa(-1); got != 0 { + fmt.Printf("div_int16 -1/32767 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int16_32767_ssa(0); got != 0 { + fmt.Printf("div_int16 0/32767 = %d, wanted 0\n", got) + failed = true + } + + if got := div_32767_int16_ssa(1); got != 32767 { + fmt.Printf("div_int16 32767/1 = %d, wanted 32767\n", got) + failed = true + } + + if got := div_int16_32767_ssa(1); got != 0 { + fmt.Printf("div_int16 1/32767 = %d, wanted 0\n", got) + failed = true + } + + if got := div_32767_int16_ssa(32766); got != 1 { + fmt.Printf("div_int16 32767/32766 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int16_32767_ssa(32766); got != 0 { + fmt.Printf("div_int16 32766/32767 = %d, wanted 0\n", got) + failed = true + } + + if got := div_32767_int16_ssa(32767); got != 1 { + fmt.Printf("div_int16 32767/32767 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int16_32767_ssa(32767); got != 1 { + fmt.Printf("div_int16 32767/32767 = %d, wanted 1\n", got) + failed = true + } + + if got := mul_Neg32768_int16_ssa(-32768); got != 0 { + fmt.Printf("mul_int16 -32768*-32768 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int16_Neg32768_ssa(-32768); got != 0 { + fmt.Printf("mul_int16 -32768*-32768 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_Neg32768_int16_ssa(-32767); got != -32768 { + fmt.Printf("mul_int16 -32768*-32767 = %d, wanted -32768\n", got) + failed = true + } + + if got := mul_int16_Neg32768_ssa(-32767); got != -32768 { + fmt.Printf("mul_int16 -32767*-32768 = %d, wanted -32768\n", got) + failed = true + } + + if got := mul_Neg32768_int16_ssa(-1); got != -32768 { + fmt.Printf("mul_int16 -32768*-1 = %d, wanted -32768\n", got) + failed = true + } + + if got := mul_int16_Neg32768_ssa(-1); got != -32768 { + fmt.Printf("mul_int16 -1*-32768 = %d, wanted -32768\n", got) + failed = true + } + + if got := mul_Neg32768_int16_ssa(0); got != 0 { + fmt.Printf("mul_int16 -32768*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int16_Neg32768_ssa(0); got != 0 { + fmt.Printf("mul_int16 0*-32768 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_Neg32768_int16_ssa(1); got != -32768 { + fmt.Printf("mul_int16 -32768*1 = %d, wanted -32768\n", got) + failed = true + } + + if got := mul_int16_Neg32768_ssa(1); got != -32768 { + fmt.Printf("mul_int16 1*-32768 = %d, wanted -32768\n", got) + failed = true + } + + if got := mul_Neg32768_int16_ssa(32766); got != 0 { + fmt.Printf("mul_int16 -32768*32766 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int16_Neg32768_ssa(32766); got != 0 { + fmt.Printf("mul_int16 32766*-32768 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_Neg32768_int16_ssa(32767); got != -32768 { + fmt.Printf("mul_int16 -32768*32767 = %d, wanted -32768\n", got) + failed = true + } + + if got := mul_int16_Neg32768_ssa(32767); got != -32768 { + fmt.Printf("mul_int16 32767*-32768 = %d, wanted -32768\n", got) + failed = true + } + + if got := mul_Neg32767_int16_ssa(-32768); got != -32768 { + fmt.Printf("mul_int16 -32767*-32768 = %d, wanted -32768\n", got) + failed = true + } + + if got := mul_int16_Neg32767_ssa(-32768); got != -32768 { + fmt.Printf("mul_int16 -32768*-32767 = %d, wanted -32768\n", got) + failed = true + } + + if got := mul_Neg32767_int16_ssa(-32767); got != 1 { + fmt.Printf("mul_int16 -32767*-32767 = %d, wanted 1\n", got) + failed = true + } + + if got := mul_int16_Neg32767_ssa(-32767); got != 1 { + fmt.Printf("mul_int16 -32767*-32767 = %d, wanted 1\n", got) + failed = true + } + + if got := mul_Neg32767_int16_ssa(-1); got != 32767 { + fmt.Printf("mul_int16 -32767*-1 = %d, wanted 32767\n", got) + failed = true + } + + if got := mul_int16_Neg32767_ssa(-1); got != 32767 { + fmt.Printf("mul_int16 -1*-32767 = %d, wanted 32767\n", got) + failed = true + } + + if got := mul_Neg32767_int16_ssa(0); got != 0 { + fmt.Printf("mul_int16 -32767*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int16_Neg32767_ssa(0); got != 0 { + fmt.Printf("mul_int16 0*-32767 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_Neg32767_int16_ssa(1); got != -32767 { + fmt.Printf("mul_int16 -32767*1 = %d, wanted -32767\n", got) + failed = true + } + + if got := mul_int16_Neg32767_ssa(1); got != -32767 { + fmt.Printf("mul_int16 1*-32767 = %d, wanted -32767\n", got) + failed = true + } + + if got := mul_Neg32767_int16_ssa(32766); got != 32766 { + fmt.Printf("mul_int16 -32767*32766 = %d, wanted 32766\n", got) + failed = true + } + + if got := mul_int16_Neg32767_ssa(32766); got != 32766 { + fmt.Printf("mul_int16 32766*-32767 = %d, wanted 32766\n", got) + failed = true + } + + if got := mul_Neg32767_int16_ssa(32767); got != -1 { + fmt.Printf("mul_int16 -32767*32767 = %d, wanted -1\n", got) + failed = true + } + + if got := mul_int16_Neg32767_ssa(32767); got != -1 { + fmt.Printf("mul_int16 32767*-32767 = %d, wanted -1\n", got) + failed = true + } + + if got := mul_Neg1_int16_ssa(-32768); got != -32768 { + fmt.Printf("mul_int16 -1*-32768 = %d, wanted -32768\n", got) + failed = true + } + + if got := mul_int16_Neg1_ssa(-32768); got != -32768 { + fmt.Printf("mul_int16 -32768*-1 = %d, wanted -32768\n", got) + failed = true + } + + if got := mul_Neg1_int16_ssa(-32767); got != 32767 { + fmt.Printf("mul_int16 -1*-32767 = %d, wanted 32767\n", got) + failed = true + } + + if got := mul_int16_Neg1_ssa(-32767); got != 32767 { + fmt.Printf("mul_int16 -32767*-1 = %d, wanted 32767\n", got) + failed = true + } + + if got := mul_Neg1_int16_ssa(-1); got != 1 { + fmt.Printf("mul_int16 -1*-1 = %d, wanted 1\n", got) + failed = true + } + + if got := mul_int16_Neg1_ssa(-1); got != 1 { + fmt.Printf("mul_int16 -1*-1 = %d, wanted 1\n", got) + failed = true + } + + if got := mul_Neg1_int16_ssa(0); got != 0 { + fmt.Printf("mul_int16 -1*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int16_Neg1_ssa(0); got != 0 { + fmt.Printf("mul_int16 0*-1 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_Neg1_int16_ssa(1); got != -1 { + fmt.Printf("mul_int16 -1*1 = %d, wanted -1\n", got) + failed = true + } + + if got := mul_int16_Neg1_ssa(1); got != -1 { + fmt.Printf("mul_int16 1*-1 = %d, wanted -1\n", got) + failed = true + } + + if got := mul_Neg1_int16_ssa(32766); got != -32766 { + fmt.Printf("mul_int16 -1*32766 = %d, wanted -32766\n", got) + failed = true + } + + if got := mul_int16_Neg1_ssa(32766); got != -32766 { + fmt.Printf("mul_int16 32766*-1 = %d, wanted -32766\n", got) + failed = true + } + + if got := mul_Neg1_int16_ssa(32767); got != -32767 { + fmt.Printf("mul_int16 -1*32767 = %d, wanted -32767\n", got) + failed = true + } + + if got := mul_int16_Neg1_ssa(32767); got != -32767 { + fmt.Printf("mul_int16 32767*-1 = %d, wanted -32767\n", got) + failed = true + } + + if got := mul_0_int16_ssa(-32768); got != 0 { + fmt.Printf("mul_int16 0*-32768 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int16_0_ssa(-32768); got != 0 { + fmt.Printf("mul_int16 -32768*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_0_int16_ssa(-32767); got != 0 { + fmt.Printf("mul_int16 0*-32767 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int16_0_ssa(-32767); got != 0 { + fmt.Printf("mul_int16 -32767*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_0_int16_ssa(-1); got != 0 { + fmt.Printf("mul_int16 0*-1 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int16_0_ssa(-1); got != 0 { + fmt.Printf("mul_int16 -1*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_0_int16_ssa(0); got != 0 { + fmt.Printf("mul_int16 0*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int16_0_ssa(0); got != 0 { + fmt.Printf("mul_int16 0*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_0_int16_ssa(1); got != 0 { + fmt.Printf("mul_int16 0*1 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int16_0_ssa(1); got != 0 { + fmt.Printf("mul_int16 1*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_0_int16_ssa(32766); got != 0 { + fmt.Printf("mul_int16 0*32766 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int16_0_ssa(32766); got != 0 { + fmt.Printf("mul_int16 32766*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_0_int16_ssa(32767); got != 0 { + fmt.Printf("mul_int16 0*32767 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int16_0_ssa(32767); got != 0 { + fmt.Printf("mul_int16 32767*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_1_int16_ssa(-32768); got != -32768 { + fmt.Printf("mul_int16 1*-32768 = %d, wanted -32768\n", got) + failed = true + } + + if got := mul_int16_1_ssa(-32768); got != -32768 { + fmt.Printf("mul_int16 -32768*1 = %d, wanted -32768\n", got) + failed = true + } + + if got := mul_1_int16_ssa(-32767); got != -32767 { + fmt.Printf("mul_int16 1*-32767 = %d, wanted -32767\n", got) + failed = true + } + + if got := mul_int16_1_ssa(-32767); got != -32767 { + fmt.Printf("mul_int16 -32767*1 = %d, wanted -32767\n", got) + failed = true + } + + if got := mul_1_int16_ssa(-1); got != -1 { + fmt.Printf("mul_int16 1*-1 = %d, wanted -1\n", got) + failed = true + } + + if got := mul_int16_1_ssa(-1); got != -1 { + fmt.Printf("mul_int16 -1*1 = %d, wanted -1\n", got) + failed = true + } + + if got := mul_1_int16_ssa(0); got != 0 { + fmt.Printf("mul_int16 1*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int16_1_ssa(0); got != 0 { + fmt.Printf("mul_int16 0*1 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_1_int16_ssa(1); got != 1 { + fmt.Printf("mul_int16 1*1 = %d, wanted 1\n", got) + failed = true + } + + if got := mul_int16_1_ssa(1); got != 1 { + fmt.Printf("mul_int16 1*1 = %d, wanted 1\n", got) + failed = true + } + + if got := mul_1_int16_ssa(32766); got != 32766 { + fmt.Printf("mul_int16 1*32766 = %d, wanted 32766\n", got) + failed = true + } + + if got := mul_int16_1_ssa(32766); got != 32766 { + fmt.Printf("mul_int16 32766*1 = %d, wanted 32766\n", got) + failed = true + } + + if got := mul_1_int16_ssa(32767); got != 32767 { + fmt.Printf("mul_int16 1*32767 = %d, wanted 32767\n", got) + failed = true + } + + if got := mul_int16_1_ssa(32767); got != 32767 { + fmt.Printf("mul_int16 32767*1 = %d, wanted 32767\n", got) + failed = true + } + + if got := mul_32766_int16_ssa(-32768); got != 0 { + fmt.Printf("mul_int16 32766*-32768 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int16_32766_ssa(-32768); got != 0 { + fmt.Printf("mul_int16 -32768*32766 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_32766_int16_ssa(-32767); got != 32766 { + fmt.Printf("mul_int16 32766*-32767 = %d, wanted 32766\n", got) + failed = true + } + + if got := mul_int16_32766_ssa(-32767); got != 32766 { + fmt.Printf("mul_int16 -32767*32766 = %d, wanted 32766\n", got) + failed = true + } + + if got := mul_32766_int16_ssa(-1); got != -32766 { + fmt.Printf("mul_int16 32766*-1 = %d, wanted -32766\n", got) + failed = true + } + + if got := mul_int16_32766_ssa(-1); got != -32766 { + fmt.Printf("mul_int16 -1*32766 = %d, wanted -32766\n", got) + failed = true + } + + if got := mul_32766_int16_ssa(0); got != 0 { + fmt.Printf("mul_int16 32766*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int16_32766_ssa(0); got != 0 { + fmt.Printf("mul_int16 0*32766 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_32766_int16_ssa(1); got != 32766 { + fmt.Printf("mul_int16 32766*1 = %d, wanted 32766\n", got) + failed = true + } + + if got := mul_int16_32766_ssa(1); got != 32766 { + fmt.Printf("mul_int16 1*32766 = %d, wanted 32766\n", got) + failed = true + } + + if got := mul_32766_int16_ssa(32766); got != 4 { + fmt.Printf("mul_int16 32766*32766 = %d, wanted 4\n", got) + failed = true + } + + if got := mul_int16_32766_ssa(32766); got != 4 { + fmt.Printf("mul_int16 32766*32766 = %d, wanted 4\n", got) + failed = true + } + + if got := mul_32766_int16_ssa(32767); got != -32766 { + fmt.Printf("mul_int16 32766*32767 = %d, wanted -32766\n", got) + failed = true + } + + if got := mul_int16_32766_ssa(32767); got != -32766 { + fmt.Printf("mul_int16 32767*32766 = %d, wanted -32766\n", got) + failed = true + } + + if got := mul_32767_int16_ssa(-32768); got != -32768 { + fmt.Printf("mul_int16 32767*-32768 = %d, wanted -32768\n", got) + failed = true + } + + if got := mul_int16_32767_ssa(-32768); got != -32768 { + fmt.Printf("mul_int16 -32768*32767 = %d, wanted -32768\n", got) + failed = true + } + + if got := mul_32767_int16_ssa(-32767); got != -1 { + fmt.Printf("mul_int16 32767*-32767 = %d, wanted -1\n", got) + failed = true + } + + if got := mul_int16_32767_ssa(-32767); got != -1 { + fmt.Printf("mul_int16 -32767*32767 = %d, wanted -1\n", got) + failed = true + } + + if got := mul_32767_int16_ssa(-1); got != -32767 { + fmt.Printf("mul_int16 32767*-1 = %d, wanted -32767\n", got) + failed = true + } + + if got := mul_int16_32767_ssa(-1); got != -32767 { + fmt.Printf("mul_int16 -1*32767 = %d, wanted -32767\n", got) + failed = true + } + + if got := mul_32767_int16_ssa(0); got != 0 { + fmt.Printf("mul_int16 32767*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_int16_32767_ssa(0); got != 0 { + fmt.Printf("mul_int16 0*32767 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_32767_int16_ssa(1); got != 32767 { + fmt.Printf("mul_int16 32767*1 = %d, wanted 32767\n", got) + failed = true + } + + if got := mul_int16_32767_ssa(1); got != 32767 { + fmt.Printf("mul_int16 1*32767 = %d, wanted 32767\n", got) + failed = true + } + + if got := mul_32767_int16_ssa(32766); got != -32766 { + fmt.Printf("mul_int16 32767*32766 = %d, wanted -32766\n", got) + failed = true + } + + if got := mul_int16_32767_ssa(32766); got != -32766 { + fmt.Printf("mul_int16 32766*32767 = %d, wanted -32766\n", got) + failed = true + } + + if got := mul_32767_int16_ssa(32767); got != 1 { + fmt.Printf("mul_int16 32767*32767 = %d, wanted 1\n", got) + failed = true + } + + if got := mul_int16_32767_ssa(32767); got != 1 { + fmt.Printf("mul_int16 32767*32767 = %d, wanted 1\n", got) + failed = true + } + + if got := add_0_uint8_ssa(0); got != 0 { + fmt.Printf("add_uint8 0+0 = %d, wanted 0\n", got) + failed = true + } + + if got := add_uint8_0_ssa(0); got != 0 { + fmt.Printf("add_uint8 0+0 = %d, wanted 0\n", got) + failed = true + } + + if got := add_0_uint8_ssa(1); got != 1 { + fmt.Printf("add_uint8 0+1 = %d, wanted 1\n", got) + failed = true + } + + if got := add_uint8_0_ssa(1); got != 1 { + fmt.Printf("add_uint8 1+0 = %d, wanted 1\n", got) + failed = true + } + + if got := add_0_uint8_ssa(255); got != 255 { + fmt.Printf("add_uint8 0+255 = %d, wanted 255\n", got) + failed = true + } + + if got := add_uint8_0_ssa(255); got != 255 { + fmt.Printf("add_uint8 255+0 = %d, wanted 255\n", got) + failed = true + } + + if got := add_1_uint8_ssa(0); got != 1 { + fmt.Printf("add_uint8 1+0 = %d, wanted 1\n", got) + failed = true + } + + if got := add_uint8_1_ssa(0); got != 1 { + fmt.Printf("add_uint8 0+1 = %d, wanted 1\n", got) + failed = true + } + + if got := add_1_uint8_ssa(1); got != 2 { + fmt.Printf("add_uint8 1+1 = %d, wanted 2\n", got) + failed = true + } + + if got := add_uint8_1_ssa(1); got != 2 { + fmt.Printf("add_uint8 1+1 = %d, wanted 2\n", got) + failed = true + } + + if got := add_1_uint8_ssa(255); got != 0 { + fmt.Printf("add_uint8 1+255 = %d, wanted 0\n", got) + failed = true + } + + if got := add_uint8_1_ssa(255); got != 0 { + fmt.Printf("add_uint8 255+1 = %d, wanted 0\n", got) + failed = true + } + + if got := add_255_uint8_ssa(0); got != 255 { + fmt.Printf("add_uint8 255+0 = %d, wanted 255\n", got) + failed = true + } + + if got := add_uint8_255_ssa(0); got != 255 { + fmt.Printf("add_uint8 0+255 = %d, wanted 255\n", got) + failed = true + } + + if got := add_255_uint8_ssa(1); got != 0 { + fmt.Printf("add_uint8 255+1 = %d, wanted 0\n", got) + failed = true + } + + if got := add_uint8_255_ssa(1); got != 0 { + fmt.Printf("add_uint8 1+255 = %d, wanted 0\n", got) + failed = true + } + + if got := add_255_uint8_ssa(255); got != 254 { + fmt.Printf("add_uint8 255+255 = %d, wanted 254\n", got) + failed = true + } + + if got := add_uint8_255_ssa(255); got != 254 { + fmt.Printf("add_uint8 255+255 = %d, wanted 254\n", got) + failed = true + } + + if got := sub_0_uint8_ssa(0); got != 0 { + fmt.Printf("sub_uint8 0-0 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_uint8_0_ssa(0); got != 0 { + fmt.Printf("sub_uint8 0-0 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_0_uint8_ssa(1); got != 255 { + fmt.Printf("sub_uint8 0-1 = %d, wanted 255\n", got) + failed = true + } + + if got := sub_uint8_0_ssa(1); got != 1 { + fmt.Printf("sub_uint8 1-0 = %d, wanted 1\n", got) + failed = true + } + + if got := sub_0_uint8_ssa(255); got != 1 { + fmt.Printf("sub_uint8 0-255 = %d, wanted 1\n", got) + failed = true + } + + if got := sub_uint8_0_ssa(255); got != 255 { + fmt.Printf("sub_uint8 255-0 = %d, wanted 255\n", got) + failed = true + } + + if got := sub_1_uint8_ssa(0); got != 1 { + fmt.Printf("sub_uint8 1-0 = %d, wanted 1\n", got) + failed = true + } + + if got := sub_uint8_1_ssa(0); got != 255 { + fmt.Printf("sub_uint8 0-1 = %d, wanted 255\n", got) + failed = true + } + + if got := sub_1_uint8_ssa(1); got != 0 { + fmt.Printf("sub_uint8 1-1 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_uint8_1_ssa(1); got != 0 { + fmt.Printf("sub_uint8 1-1 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_1_uint8_ssa(255); got != 2 { + fmt.Printf("sub_uint8 1-255 = %d, wanted 2\n", got) + failed = true + } + + if got := sub_uint8_1_ssa(255); got != 254 { + fmt.Printf("sub_uint8 255-1 = %d, wanted 254\n", got) + failed = true + } + + if got := sub_255_uint8_ssa(0); got != 255 { + fmt.Printf("sub_uint8 255-0 = %d, wanted 255\n", got) + failed = true + } + + if got := sub_uint8_255_ssa(0); got != 1 { + fmt.Printf("sub_uint8 0-255 = %d, wanted 1\n", got) + failed = true + } + + if got := sub_255_uint8_ssa(1); got != 254 { + fmt.Printf("sub_uint8 255-1 = %d, wanted 254\n", got) + failed = true + } + + if got := sub_uint8_255_ssa(1); got != 2 { + fmt.Printf("sub_uint8 1-255 = %d, wanted 2\n", got) + failed = true + } + + if got := sub_255_uint8_ssa(255); got != 0 { + fmt.Printf("sub_uint8 255-255 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_uint8_255_ssa(255); got != 0 { + fmt.Printf("sub_uint8 255-255 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_uint8_ssa(1); got != 0 { + fmt.Printf("div_uint8 0/1 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_uint8_ssa(255); got != 0 { + fmt.Printf("div_uint8 0/255 = %d, wanted 0\n", got) + failed = true + } + + if got := div_uint8_1_ssa(0); got != 0 { + fmt.Printf("div_uint8 0/1 = %d, wanted 0\n", got) + failed = true + } + + if got := div_1_uint8_ssa(1); got != 1 { + fmt.Printf("div_uint8 1/1 = %d, wanted 1\n", got) + failed = true + } + + if got := div_uint8_1_ssa(1); got != 1 { + fmt.Printf("div_uint8 1/1 = %d, wanted 1\n", got) + failed = true + } + + if got := div_1_uint8_ssa(255); got != 0 { + fmt.Printf("div_uint8 1/255 = %d, wanted 0\n", got) + failed = true + } + + if got := div_uint8_1_ssa(255); got != 255 { + fmt.Printf("div_uint8 255/1 = %d, wanted 255\n", got) + failed = true + } + + if got := div_uint8_255_ssa(0); got != 0 { + fmt.Printf("div_uint8 0/255 = %d, wanted 0\n", got) + failed = true + } + + if got := div_255_uint8_ssa(1); got != 255 { + fmt.Printf("div_uint8 255/1 = %d, wanted 255\n", got) + failed = true + } + + if got := div_uint8_255_ssa(1); got != 0 { + fmt.Printf("div_uint8 1/255 = %d, wanted 0\n", got) + failed = true + } + + if got := div_255_uint8_ssa(255); got != 1 { + fmt.Printf("div_uint8 255/255 = %d, wanted 1\n", got) + failed = true + } + + if got := div_uint8_255_ssa(255); got != 1 { + fmt.Printf("div_uint8 255/255 = %d, wanted 1\n", got) + failed = true + } + + if got := mul_0_uint8_ssa(0); got != 0 { + fmt.Printf("mul_uint8 0*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_uint8_0_ssa(0); got != 0 { + fmt.Printf("mul_uint8 0*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_0_uint8_ssa(1); got != 0 { + fmt.Printf("mul_uint8 0*1 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_uint8_0_ssa(1); got != 0 { + fmt.Printf("mul_uint8 1*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_0_uint8_ssa(255); got != 0 { + fmt.Printf("mul_uint8 0*255 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_uint8_0_ssa(255); got != 0 { + fmt.Printf("mul_uint8 255*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_1_uint8_ssa(0); got != 0 { + fmt.Printf("mul_uint8 1*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_uint8_1_ssa(0); got != 0 { + fmt.Printf("mul_uint8 0*1 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_1_uint8_ssa(1); got != 1 { + fmt.Printf("mul_uint8 1*1 = %d, wanted 1\n", got) + failed = true + } + + if got := mul_uint8_1_ssa(1); got != 1 { + fmt.Printf("mul_uint8 1*1 = %d, wanted 1\n", got) + failed = true + } + + if got := mul_1_uint8_ssa(255); got != 255 { + fmt.Printf("mul_uint8 1*255 = %d, wanted 255\n", got) + failed = true + } + + if got := mul_uint8_1_ssa(255); got != 255 { + fmt.Printf("mul_uint8 255*1 = %d, wanted 255\n", got) + failed = true + } + + if got := mul_255_uint8_ssa(0); got != 0 { + fmt.Printf("mul_uint8 255*0 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_uint8_255_ssa(0); got != 0 { + fmt.Printf("mul_uint8 0*255 = %d, wanted 0\n", got) + failed = true + } + + if got := mul_255_uint8_ssa(1); got != 255 { + fmt.Printf("mul_uint8 255*1 = %d, wanted 255\n", got) + failed = true + } + + if got := mul_uint8_255_ssa(1); got != 255 { + fmt.Printf("mul_uint8 1*255 = %d, wanted 255\n", got) + failed = true + } + + if got := mul_255_uint8_ssa(255); got != 1 { + fmt.Printf("mul_uint8 255*255 = %d, wanted 1\n", got) + failed = true + } + + if got := mul_uint8_255_ssa(255); got != 1 { + fmt.Printf("mul_uint8 255*255 = %d, wanted 1\n", got) + failed = true + } + + if got := lsh_0_uint8_ssa(0); got != 0 { + fmt.Printf("lsh_uint8 0<<0 = %d, wanted 0\n", got) + failed = true + } + + if got := lsh_uint8_0_ssa(0); got != 0 { + fmt.Printf("lsh_uint8 0<<0 = %d, wanted 0\n", got) + failed = true + } + + if got := lsh_0_uint8_ssa(1); got != 0 { + fmt.Printf("lsh_uint8 0<<1 = %d, wanted 0\n", got) + failed = true + } + + if got := lsh_uint8_0_ssa(1); got != 1 { + fmt.Printf("lsh_uint8 1<<0 = %d, wanted 1\n", got) + failed = true + } + + if got := lsh_0_uint8_ssa(255); got != 0 { + fmt.Printf("lsh_uint8 0<<255 = %d, wanted 0\n", got) + failed = true + } + + if got := lsh_uint8_0_ssa(255); got != 255 { + fmt.Printf("lsh_uint8 255<<0 = %d, wanted 255\n", got) + failed = true + } + + if got := lsh_1_uint8_ssa(0); got != 1 { + fmt.Printf("lsh_uint8 1<<0 = %d, wanted 1\n", got) + failed = true + } + + if got := lsh_uint8_1_ssa(0); got != 0 { + fmt.Printf("lsh_uint8 0<<1 = %d, wanted 0\n", got) + failed = true + } + + if got := lsh_1_uint8_ssa(1); got != 2 { + fmt.Printf("lsh_uint8 1<<1 = %d, wanted 2\n", got) + failed = true + } + + if got := lsh_uint8_1_ssa(1); got != 2 { + fmt.Printf("lsh_uint8 1<<1 = %d, wanted 2\n", got) + failed = true + } + + if got := lsh_1_uint8_ssa(255); got != 0 { + fmt.Printf("lsh_uint8 1<<255 = %d, wanted 0\n", got) + failed = true + } + + if got := lsh_uint8_1_ssa(255); got != 254 { + fmt.Printf("lsh_uint8 255<<1 = %d, wanted 254\n", got) + failed = true + } + + if got := lsh_255_uint8_ssa(0); got != 255 { + fmt.Printf("lsh_uint8 255<<0 = %d, wanted 255\n", got) + failed = true + } + + if got := lsh_uint8_255_ssa(0); got != 0 { + fmt.Printf("lsh_uint8 0<<255 = %d, wanted 0\n", got) + failed = true + } + + if got := lsh_255_uint8_ssa(1); got != 254 { + fmt.Printf("lsh_uint8 255<<1 = %d, wanted 254\n", got) + failed = true + } + + if got := lsh_uint8_255_ssa(1); got != 0 { + fmt.Printf("lsh_uint8 1<<255 = %d, wanted 0\n", got) + failed = true + } + + if got := lsh_255_uint8_ssa(255); got != 0 { + fmt.Printf("lsh_uint8 255<<255 = %d, wanted 0\n", got) + failed = true + } + + if got := lsh_uint8_255_ssa(255); got != 0 { + fmt.Printf("lsh_uint8 255<<255 = %d, wanted 0\n", got) + failed = true + } + + if got := rsh_0_uint8_ssa(0); got != 0 { + fmt.Printf("rsh_uint8 0>>0 = %d, wanted 0\n", got) + failed = true + } + + if got := rsh_uint8_0_ssa(0); got != 0 { + fmt.Printf("rsh_uint8 0>>0 = %d, wanted 0\n", got) + failed = true + } + + if got := rsh_0_uint8_ssa(1); got != 0 { + fmt.Printf("rsh_uint8 0>>1 = %d, wanted 0\n", got) + failed = true + } + + if got := rsh_uint8_0_ssa(1); got != 1 { + fmt.Printf("rsh_uint8 1>>0 = %d, wanted 1\n", got) + failed = true + } + + if got := rsh_0_uint8_ssa(255); got != 0 { + fmt.Printf("rsh_uint8 0>>255 = %d, wanted 0\n", got) + failed = true + } + + if got := rsh_uint8_0_ssa(255); got != 255 { + fmt.Printf("rsh_uint8 255>>0 = %d, wanted 255\n", got) + failed = true + } + + if got := rsh_1_uint8_ssa(0); got != 1 { + fmt.Printf("rsh_uint8 1>>0 = %d, wanted 1\n", got) + failed = true + } + + if got := rsh_uint8_1_ssa(0); got != 0 { + fmt.Printf("rsh_uint8 0>>1 = %d, wanted 0\n", got) + failed = true + } + + if got := rsh_1_uint8_ssa(1); got != 0 { + fmt.Printf("rsh_uint8 1>>1 = %d, wanted 0\n", got) + failed = true + } + + if got := rsh_uint8_1_ssa(1); got != 0 { + fmt.Printf("rsh_uint8 1>>1 = %d, wanted 0\n", got) + failed = true + } + + if got := rsh_1_uint8_ssa(255); got != 0 { + fmt.Printf("rsh_uint8 1>>255 = %d, wanted 0\n", got) + failed = true + } + + if got := rsh_uint8_1_ssa(255); got != 127 { + fmt.Printf("rsh_uint8 255>>1 = %d, wanted 127\n", got) + failed = true + } + + if got := rsh_255_uint8_ssa(0); got != 255 { + fmt.Printf("rsh_uint8 255>>0 = %d, wanted 255\n", got) + failed = true + } + + if got := rsh_uint8_255_ssa(0); got != 0 { + fmt.Printf("rsh_uint8 0>>255 = %d, wanted 0\n", got) + failed = true + } + + if got := rsh_255_uint8_ssa(1); got != 127 { + fmt.Printf("rsh_uint8 255>>1 = %d, wanted 127\n", got) + failed = true + } + + if got := rsh_uint8_255_ssa(1); got != 0 { + fmt.Printf("rsh_uint8 1>>255 = %d, wanted 0\n", got) + failed = true + } + + if got := rsh_255_uint8_ssa(255); got != 0 { + fmt.Printf("rsh_uint8 255>>255 = %d, wanted 0\n", got) + failed = true + } + + if got := rsh_uint8_255_ssa(255); got != 0 { + fmt.Printf("rsh_uint8 255>>255 = %d, wanted 0\n", got) + failed = true + } + + if got := add_Neg128_int8_ssa(-128); got != 0 { + fmt.Printf("add_int8 -128+-128 = %d, wanted 0\n", got) + failed = true + } + + if got := add_int8_Neg128_ssa(-128); got != 0 { + fmt.Printf("add_int8 -128+-128 = %d, wanted 0\n", got) + failed = true + } + + if got := add_Neg128_int8_ssa(-127); got != 1 { + fmt.Printf("add_int8 -128+-127 = %d, wanted 1\n", got) + failed = true + } + + if got := add_int8_Neg128_ssa(-127); got != 1 { + fmt.Printf("add_int8 -127+-128 = %d, wanted 1\n", got) + failed = true + } + + if got := add_Neg128_int8_ssa(-1); got != 127 { + fmt.Printf("add_int8 -128+-1 = %d, wanted 127\n", got) + failed = true + } + + if got := add_int8_Neg128_ssa(-1); got != 127 { + fmt.Printf("add_int8 -1+-128 = %d, wanted 127\n", got) + failed = true + } + + if got := add_Neg128_int8_ssa(0); got != -128 { + fmt.Printf("add_int8 -128+0 = %d, wanted -128\n", got) + failed = true + } + + if got := add_int8_Neg128_ssa(0); got != -128 { + fmt.Printf("add_int8 0+-128 = %d, wanted -128\n", got) + failed = true + } + + if got := add_Neg128_int8_ssa(1); got != -127 { + fmt.Printf("add_int8 -128+1 = %d, wanted -127\n", got) + failed = true + } + + if got := add_int8_Neg128_ssa(1); got != -127 { + fmt.Printf("add_int8 1+-128 = %d, wanted -127\n", got) + failed = true + } + + if got := add_Neg128_int8_ssa(126); got != -2 { + fmt.Printf("add_int8 -128+126 = %d, wanted -2\n", got) + failed = true + } + + if got := add_int8_Neg128_ssa(126); got != -2 { + fmt.Printf("add_int8 126+-128 = %d, wanted -2\n", got) + failed = true + } + + if got := add_Neg128_int8_ssa(127); got != -1 { + fmt.Printf("add_int8 -128+127 = %d, wanted -1\n", got) + failed = true + } + + if got := add_int8_Neg128_ssa(127); got != -1 { + fmt.Printf("add_int8 127+-128 = %d, wanted -1\n", got) + failed = true + } + + if got := add_Neg127_int8_ssa(-128); got != 1 { + fmt.Printf("add_int8 -127+-128 = %d, wanted 1\n", got) + failed = true + } + + if got := add_int8_Neg127_ssa(-128); got != 1 { + fmt.Printf("add_int8 -128+-127 = %d, wanted 1\n", got) + failed = true + } + + if got := add_Neg127_int8_ssa(-127); got != 2 { + fmt.Printf("add_int8 -127+-127 = %d, wanted 2\n", got) + failed = true + } + + if got := add_int8_Neg127_ssa(-127); got != 2 { + fmt.Printf("add_int8 -127+-127 = %d, wanted 2\n", got) + failed = true + } + + if got := add_Neg127_int8_ssa(-1); got != -128 { + fmt.Printf("add_int8 -127+-1 = %d, wanted -128\n", got) + failed = true + } + + if got := add_int8_Neg127_ssa(-1); got != -128 { + fmt.Printf("add_int8 -1+-127 = %d, wanted -128\n", got) + failed = true + } + + if got := add_Neg127_int8_ssa(0); got != -127 { + fmt.Printf("add_int8 -127+0 = %d, wanted -127\n", got) + failed = true + } + + if got := add_int8_Neg127_ssa(0); got != -127 { + fmt.Printf("add_int8 0+-127 = %d, wanted -127\n", got) + failed = true + } + + if got := add_Neg127_int8_ssa(1); got != -126 { + fmt.Printf("add_int8 -127+1 = %d, wanted -126\n", got) + failed = true + } + + if got := add_int8_Neg127_ssa(1); got != -126 { + fmt.Printf("add_int8 1+-127 = %d, wanted -126\n", got) + failed = true + } + + if got := add_Neg127_int8_ssa(126); got != -1 { + fmt.Printf("add_int8 -127+126 = %d, wanted -1\n", got) + failed = true + } + + if got := add_int8_Neg127_ssa(126); got != -1 { + fmt.Printf("add_int8 126+-127 = %d, wanted -1\n", got) + failed = true + } + + if got := add_Neg127_int8_ssa(127); got != 0 { + fmt.Printf("add_int8 -127+127 = %d, wanted 0\n", got) + failed = true + } + + if got := add_int8_Neg127_ssa(127); got != 0 { + fmt.Printf("add_int8 127+-127 = %d, wanted 0\n", got) + failed = true + } + + if got := add_Neg1_int8_ssa(-128); got != 127 { + fmt.Printf("add_int8 -1+-128 = %d, wanted 127\n", got) + failed = true + } + + if got := add_int8_Neg1_ssa(-128); got != 127 { + fmt.Printf("add_int8 -128+-1 = %d, wanted 127\n", got) + failed = true + } + + if got := add_Neg1_int8_ssa(-127); got != -128 { + fmt.Printf("add_int8 -1+-127 = %d, wanted -128\n", got) + failed = true + } + + if got := add_int8_Neg1_ssa(-127); got != -128 { + fmt.Printf("add_int8 -127+-1 = %d, wanted -128\n", got) + failed = true + } + + if got := add_Neg1_int8_ssa(-1); got != -2 { + fmt.Printf("add_int8 -1+-1 = %d, wanted -2\n", got) + failed = true + } + + if got := add_int8_Neg1_ssa(-1); got != -2 { + fmt.Printf("add_int8 -1+-1 = %d, wanted -2\n", got) + failed = true + } + + if got := add_Neg1_int8_ssa(0); got != -1 { + fmt.Printf("add_int8 -1+0 = %d, wanted -1\n", got) + failed = true + } + + if got := add_int8_Neg1_ssa(0); got != -1 { + fmt.Printf("add_int8 0+-1 = %d, wanted -1\n", got) + failed = true + } + + if got := add_Neg1_int8_ssa(1); got != 0 { + fmt.Printf("add_int8 -1+1 = %d, wanted 0\n", got) + failed = true + } + + if got := add_int8_Neg1_ssa(1); got != 0 { + fmt.Printf("add_int8 1+-1 = %d, wanted 0\n", got) + failed = true + } + + if got := add_Neg1_int8_ssa(126); got != 125 { + fmt.Printf("add_int8 -1+126 = %d, wanted 125\n", got) + failed = true + } + + if got := add_int8_Neg1_ssa(126); got != 125 { + fmt.Printf("add_int8 126+-1 = %d, wanted 125\n", got) + failed = true + } + + if got := add_Neg1_int8_ssa(127); got != 126 { + fmt.Printf("add_int8 -1+127 = %d, wanted 126\n", got) + failed = true + } + + if got := add_int8_Neg1_ssa(127); got != 126 { + fmt.Printf("add_int8 127+-1 = %d, wanted 126\n", got) + failed = true + } + + if got := add_0_int8_ssa(-128); got != -128 { + fmt.Printf("add_int8 0+-128 = %d, wanted -128\n", got) + failed = true + } + + if got := add_int8_0_ssa(-128); got != -128 { + fmt.Printf("add_int8 -128+0 = %d, wanted -128\n", got) + failed = true + } + + if got := add_0_int8_ssa(-127); got != -127 { + fmt.Printf("add_int8 0+-127 = %d, wanted -127\n", got) + failed = true + } + + if got := add_int8_0_ssa(-127); got != -127 { + fmt.Printf("add_int8 -127+0 = %d, wanted -127\n", got) + failed = true + } + + if got := add_0_int8_ssa(-1); got != -1 { + fmt.Printf("add_int8 0+-1 = %d, wanted -1\n", got) + failed = true + } + + if got := add_int8_0_ssa(-1); got != -1 { + fmt.Printf("add_int8 -1+0 = %d, wanted -1\n", got) + failed = true + } + + if got := add_0_int8_ssa(0); got != 0 { + fmt.Printf("add_int8 0+0 = %d, wanted 0\n", got) + failed = true + } + + if got := add_int8_0_ssa(0); got != 0 { + fmt.Printf("add_int8 0+0 = %d, wanted 0\n", got) + failed = true + } + + if got := add_0_int8_ssa(1); got != 1 { + fmt.Printf("add_int8 0+1 = %d, wanted 1\n", got) + failed = true + } + + if got := add_int8_0_ssa(1); got != 1 { + fmt.Printf("add_int8 1+0 = %d, wanted 1\n", got) + failed = true + } + + if got := add_0_int8_ssa(126); got != 126 { + fmt.Printf("add_int8 0+126 = %d, wanted 126\n", got) + failed = true + } + + if got := add_int8_0_ssa(126); got != 126 { + fmt.Printf("add_int8 126+0 = %d, wanted 126\n", got) + failed = true + } + + if got := add_0_int8_ssa(127); got != 127 { + fmt.Printf("add_int8 0+127 = %d, wanted 127\n", got) + failed = true + } + + if got := add_int8_0_ssa(127); got != 127 { + fmt.Printf("add_int8 127+0 = %d, wanted 127\n", got) + failed = true + } + + if got := add_1_int8_ssa(-128); got != -127 { + fmt.Printf("add_int8 1+-128 = %d, wanted -127\n", got) + failed = true + } + + if got := add_int8_1_ssa(-128); got != -127 { + fmt.Printf("add_int8 -128+1 = %d, wanted -127\n", got) + failed = true + } + + if got := add_1_int8_ssa(-127); got != -126 { + fmt.Printf("add_int8 1+-127 = %d, wanted -126\n", got) + failed = true + } + + if got := add_int8_1_ssa(-127); got != -126 { + fmt.Printf("add_int8 -127+1 = %d, wanted -126\n", got) + failed = true + } + + if got := add_1_int8_ssa(-1); got != 0 { + fmt.Printf("add_int8 1+-1 = %d, wanted 0\n", got) + failed = true + } + + if got := add_int8_1_ssa(-1); got != 0 { + fmt.Printf("add_int8 -1+1 = %d, wanted 0\n", got) + failed = true + } + + if got := add_1_int8_ssa(0); got != 1 { + fmt.Printf("add_int8 1+0 = %d, wanted 1\n", got) + failed = true + } + + if got := add_int8_1_ssa(0); got != 1 { + fmt.Printf("add_int8 0+1 = %d, wanted 1\n", got) + failed = true + } + + if got := add_1_int8_ssa(1); got != 2 { + fmt.Printf("add_int8 1+1 = %d, wanted 2\n", got) + failed = true + } + + if got := add_int8_1_ssa(1); got != 2 { + fmt.Printf("add_int8 1+1 = %d, wanted 2\n", got) + failed = true + } + + if got := add_1_int8_ssa(126); got != 127 { + fmt.Printf("add_int8 1+126 = %d, wanted 127\n", got) + failed = true + } + + if got := add_int8_1_ssa(126); got != 127 { + fmt.Printf("add_int8 126+1 = %d, wanted 127\n", got) + failed = true + } + + if got := add_1_int8_ssa(127); got != -128 { + fmt.Printf("add_int8 1+127 = %d, wanted -128\n", got) + failed = true + } + + if got := add_int8_1_ssa(127); got != -128 { + fmt.Printf("add_int8 127+1 = %d, wanted -128\n", got) + failed = true + } + + if got := add_126_int8_ssa(-128); got != -2 { + fmt.Printf("add_int8 126+-128 = %d, wanted -2\n", got) + failed = true + } + + if got := add_int8_126_ssa(-128); got != -2 { + fmt.Printf("add_int8 -128+126 = %d, wanted -2\n", got) + failed = true + } + + if got := add_126_int8_ssa(-127); got != -1 { + fmt.Printf("add_int8 126+-127 = %d, wanted -1\n", got) + failed = true + } + + if got := add_int8_126_ssa(-127); got != -1 { + fmt.Printf("add_int8 -127+126 = %d, wanted -1\n", got) + failed = true + } + + if got := add_126_int8_ssa(-1); got != 125 { + fmt.Printf("add_int8 126+-1 = %d, wanted 125\n", got) + failed = true + } + + if got := add_int8_126_ssa(-1); got != 125 { + fmt.Printf("add_int8 -1+126 = %d, wanted 125\n", got) + failed = true + } + + if got := add_126_int8_ssa(0); got != 126 { + fmt.Printf("add_int8 126+0 = %d, wanted 126\n", got) + failed = true + } + + if got := add_int8_126_ssa(0); got != 126 { + fmt.Printf("add_int8 0+126 = %d, wanted 126\n", got) + failed = true + } + + if got := add_126_int8_ssa(1); got != 127 { + fmt.Printf("add_int8 126+1 = %d, wanted 127\n", got) + failed = true + } + + if got := add_int8_126_ssa(1); got != 127 { + fmt.Printf("add_int8 1+126 = %d, wanted 127\n", got) + failed = true + } + + if got := add_126_int8_ssa(126); got != -4 { + fmt.Printf("add_int8 126+126 = %d, wanted -4\n", got) + failed = true + } + + if got := add_int8_126_ssa(126); got != -4 { + fmt.Printf("add_int8 126+126 = %d, wanted -4\n", got) + failed = true + } + + if got := add_126_int8_ssa(127); got != -3 { + fmt.Printf("add_int8 126+127 = %d, wanted -3\n", got) + failed = true + } + + if got := add_int8_126_ssa(127); got != -3 { + fmt.Printf("add_int8 127+126 = %d, wanted -3\n", got) + failed = true + } + + if got := add_127_int8_ssa(-128); got != -1 { + fmt.Printf("add_int8 127+-128 = %d, wanted -1\n", got) + failed = true + } + + if got := add_int8_127_ssa(-128); got != -1 { + fmt.Printf("add_int8 -128+127 = %d, wanted -1\n", got) + failed = true + } + + if got := add_127_int8_ssa(-127); got != 0 { + fmt.Printf("add_int8 127+-127 = %d, wanted 0\n", got) + failed = true + } + + if got := add_int8_127_ssa(-127); got != 0 { + fmt.Printf("add_int8 -127+127 = %d, wanted 0\n", got) + failed = true + } + + if got := add_127_int8_ssa(-1); got != 126 { + fmt.Printf("add_int8 127+-1 = %d, wanted 126\n", got) + failed = true + } + + if got := add_int8_127_ssa(-1); got != 126 { + fmt.Printf("add_int8 -1+127 = %d, wanted 126\n", got) + failed = true + } + + if got := add_127_int8_ssa(0); got != 127 { + fmt.Printf("add_int8 127+0 = %d, wanted 127\n", got) + failed = true + } + + if got := add_int8_127_ssa(0); got != 127 { + fmt.Printf("add_int8 0+127 = %d, wanted 127\n", got) + failed = true + } + + if got := add_127_int8_ssa(1); got != -128 { + fmt.Printf("add_int8 127+1 = %d, wanted -128\n", got) + failed = true + } + + if got := add_int8_127_ssa(1); got != -128 { + fmt.Printf("add_int8 1+127 = %d, wanted -128\n", got) + failed = true + } + + if got := add_127_int8_ssa(126); got != -3 { + fmt.Printf("add_int8 127+126 = %d, wanted -3\n", got) + failed = true + } + + if got := add_int8_127_ssa(126); got != -3 { + fmt.Printf("add_int8 126+127 = %d, wanted -3\n", got) + failed = true + } + + if got := add_127_int8_ssa(127); got != -2 { + fmt.Printf("add_int8 127+127 = %d, wanted -2\n", got) + failed = true + } + + if got := add_int8_127_ssa(127); got != -2 { + fmt.Printf("add_int8 127+127 = %d, wanted -2\n", got) + failed = true + } + + if got := sub_Neg128_int8_ssa(-128); got != 0 { + fmt.Printf("sub_int8 -128--128 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_int8_Neg128_ssa(-128); got != 0 { + fmt.Printf("sub_int8 -128--128 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_Neg128_int8_ssa(-127); got != -1 { + fmt.Printf("sub_int8 -128--127 = %d, wanted -1\n", got) + failed = true + } + + if got := sub_int8_Neg128_ssa(-127); got != 1 { + fmt.Printf("sub_int8 -127--128 = %d, wanted 1\n", got) + failed = true + } + + if got := sub_Neg128_int8_ssa(-1); got != -127 { + fmt.Printf("sub_int8 -128--1 = %d, wanted -127\n", got) + failed = true + } + + if got := sub_int8_Neg128_ssa(-1); got != 127 { + fmt.Printf("sub_int8 -1--128 = %d, wanted 127\n", got) + failed = true + } + + if got := sub_Neg128_int8_ssa(0); got != -128 { + fmt.Printf("sub_int8 -128-0 = %d, wanted -128\n", got) + failed = true + } + + if got := sub_int8_Neg128_ssa(0); got != -128 { + fmt.Printf("sub_int8 0--128 = %d, wanted -128\n", got) + failed = true + } + + if got := sub_Neg128_int8_ssa(1); got != 127 { + fmt.Printf("sub_int8 -128-1 = %d, wanted 127\n", got) + failed = true + } + + if got := sub_int8_Neg128_ssa(1); got != -127 { + fmt.Printf("sub_int8 1--128 = %d, wanted -127\n", got) + failed = true + } + + if got := sub_Neg128_int8_ssa(126); got != 2 { + fmt.Printf("sub_int8 -128-126 = %d, wanted 2\n", got) + failed = true + } + + if got := sub_int8_Neg128_ssa(126); got != -2 { + fmt.Printf("sub_int8 126--128 = %d, wanted -2\n", got) + failed = true + } + + if got := sub_Neg128_int8_ssa(127); got != 1 { + fmt.Printf("sub_int8 -128-127 = %d, wanted 1\n", got) + failed = true + } + + if got := sub_int8_Neg128_ssa(127); got != -1 { + fmt.Printf("sub_int8 127--128 = %d, wanted -1\n", got) + failed = true + } + + if got := sub_Neg127_int8_ssa(-128); got != 1 { + fmt.Printf("sub_int8 -127--128 = %d, wanted 1\n", got) + failed = true + } + + if got := sub_int8_Neg127_ssa(-128); got != -1 { + fmt.Printf("sub_int8 -128--127 = %d, wanted -1\n", got) + failed = true + } + + if got := sub_Neg127_int8_ssa(-127); got != 0 { + fmt.Printf("sub_int8 -127--127 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_int8_Neg127_ssa(-127); got != 0 { + fmt.Printf("sub_int8 -127--127 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_Neg127_int8_ssa(-1); got != -126 { + fmt.Printf("sub_int8 -127--1 = %d, wanted -126\n", got) + failed = true + } + + if got := sub_int8_Neg127_ssa(-1); got != 126 { + fmt.Printf("sub_int8 -1--127 = %d, wanted 126\n", got) + failed = true + } + + if got := sub_Neg127_int8_ssa(0); got != -127 { + fmt.Printf("sub_int8 -127-0 = %d, wanted -127\n", got) + failed = true + } + + if got := sub_int8_Neg127_ssa(0); got != 127 { + fmt.Printf("sub_int8 0--127 = %d, wanted 127\n", got) + failed = true + } + + if got := sub_Neg127_int8_ssa(1); got != -128 { + fmt.Printf("sub_int8 -127-1 = %d, wanted -128\n", got) + failed = true + } + + if got := sub_int8_Neg127_ssa(1); got != -128 { + fmt.Printf("sub_int8 1--127 = %d, wanted -128\n", got) + failed = true + } + + if got := sub_Neg127_int8_ssa(126); got != 3 { + fmt.Printf("sub_int8 -127-126 = %d, wanted 3\n", got) + failed = true + } + + if got := sub_int8_Neg127_ssa(126); got != -3 { + fmt.Printf("sub_int8 126--127 = %d, wanted -3\n", got) + failed = true + } + + if got := sub_Neg127_int8_ssa(127); got != 2 { + fmt.Printf("sub_int8 -127-127 = %d, wanted 2\n", got) + failed = true + } + + if got := sub_int8_Neg127_ssa(127); got != -2 { + fmt.Printf("sub_int8 127--127 = %d, wanted -2\n", got) + failed = true + } + + if got := sub_Neg1_int8_ssa(-128); got != 127 { + fmt.Printf("sub_int8 -1--128 = %d, wanted 127\n", got) + failed = true + } + + if got := sub_int8_Neg1_ssa(-128); got != -127 { + fmt.Printf("sub_int8 -128--1 = %d, wanted -127\n", got) + failed = true + } + + if got := sub_Neg1_int8_ssa(-127); got != 126 { + fmt.Printf("sub_int8 -1--127 = %d, wanted 126\n", got) + failed = true + } + + if got := sub_int8_Neg1_ssa(-127); got != -126 { + fmt.Printf("sub_int8 -127--1 = %d, wanted -126\n", got) + failed = true + } + + if got := sub_Neg1_int8_ssa(-1); got != 0 { + fmt.Printf("sub_int8 -1--1 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_int8_Neg1_ssa(-1); got != 0 { + fmt.Printf("sub_int8 -1--1 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_Neg1_int8_ssa(0); got != -1 { + fmt.Printf("sub_int8 -1-0 = %d, wanted -1\n", got) + failed = true + } + + if got := sub_int8_Neg1_ssa(0); got != 1 { + fmt.Printf("sub_int8 0--1 = %d, wanted 1\n", got) + failed = true + } + + if got := sub_Neg1_int8_ssa(1); got != -2 { + fmt.Printf("sub_int8 -1-1 = %d, wanted -2\n", got) + failed = true + } + + if got := sub_int8_Neg1_ssa(1); got != 2 { + fmt.Printf("sub_int8 1--1 = %d, wanted 2\n", got) + failed = true + } + + if got := sub_Neg1_int8_ssa(126); got != -127 { + fmt.Printf("sub_int8 -1-126 = %d, wanted -127\n", got) + failed = true + } + + if got := sub_int8_Neg1_ssa(126); got != 127 { + fmt.Printf("sub_int8 126--1 = %d, wanted 127\n", got) + failed = true + } + + if got := sub_Neg1_int8_ssa(127); got != -128 { + fmt.Printf("sub_int8 -1-127 = %d, wanted -128\n", got) + failed = true + } + + if got := sub_int8_Neg1_ssa(127); got != -128 { + fmt.Printf("sub_int8 127--1 = %d, wanted -128\n", got) + failed = true + } + + if got := sub_0_int8_ssa(-128); got != -128 { + fmt.Printf("sub_int8 0--128 = %d, wanted -128\n", got) + failed = true + } + + if got := sub_int8_0_ssa(-128); got != -128 { + fmt.Printf("sub_int8 -128-0 = %d, wanted -128\n", got) + failed = true + } + + if got := sub_0_int8_ssa(-127); got != 127 { + fmt.Printf("sub_int8 0--127 = %d, wanted 127\n", got) + failed = true + } + + if got := sub_int8_0_ssa(-127); got != -127 { + fmt.Printf("sub_int8 -127-0 = %d, wanted -127\n", got) + failed = true + } + + if got := sub_0_int8_ssa(-1); got != 1 { + fmt.Printf("sub_int8 0--1 = %d, wanted 1\n", got) + failed = true + } + + if got := sub_int8_0_ssa(-1); got != -1 { + fmt.Printf("sub_int8 -1-0 = %d, wanted -1\n", got) + failed = true + } + + if got := sub_0_int8_ssa(0); got != 0 { + fmt.Printf("sub_int8 0-0 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_int8_0_ssa(0); got != 0 { + fmt.Printf("sub_int8 0-0 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_0_int8_ssa(1); got != -1 { + fmt.Printf("sub_int8 0-1 = %d, wanted -1\n", got) + failed = true + } + + if got := sub_int8_0_ssa(1); got != 1 { + fmt.Printf("sub_int8 1-0 = %d, wanted 1\n", got) + failed = true + } + + if got := sub_0_int8_ssa(126); got != -126 { + fmt.Printf("sub_int8 0-126 = %d, wanted -126\n", got) + failed = true + } + + if got := sub_int8_0_ssa(126); got != 126 { + fmt.Printf("sub_int8 126-0 = %d, wanted 126\n", got) + failed = true + } + + if got := sub_0_int8_ssa(127); got != -127 { + fmt.Printf("sub_int8 0-127 = %d, wanted -127\n", got) + failed = true + } + + if got := sub_int8_0_ssa(127); got != 127 { + fmt.Printf("sub_int8 127-0 = %d, wanted 127\n", got) + failed = true + } + + if got := sub_1_int8_ssa(-128); got != -127 { + fmt.Printf("sub_int8 1--128 = %d, wanted -127\n", got) + failed = true + } + + if got := sub_int8_1_ssa(-128); got != 127 { + fmt.Printf("sub_int8 -128-1 = %d, wanted 127\n", got) + failed = true + } + + if got := sub_1_int8_ssa(-127); got != -128 { + fmt.Printf("sub_int8 1--127 = %d, wanted -128\n", got) + failed = true + } + + if got := sub_int8_1_ssa(-127); got != -128 { + fmt.Printf("sub_int8 -127-1 = %d, wanted -128\n", got) + failed = true + } + + if got := sub_1_int8_ssa(-1); got != 2 { + fmt.Printf("sub_int8 1--1 = %d, wanted 2\n", got) + failed = true + } + + if got := sub_int8_1_ssa(-1); got != -2 { + fmt.Printf("sub_int8 -1-1 = %d, wanted -2\n", got) + failed = true + } + + if got := sub_1_int8_ssa(0); got != 1 { + fmt.Printf("sub_int8 1-0 = %d, wanted 1\n", got) + failed = true + } + + if got := sub_int8_1_ssa(0); got != -1 { + fmt.Printf("sub_int8 0-1 = %d, wanted -1\n", got) + failed = true + } + + if got := sub_1_int8_ssa(1); got != 0 { + fmt.Printf("sub_int8 1-1 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_int8_1_ssa(1); got != 0 { + fmt.Printf("sub_int8 1-1 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_1_int8_ssa(126); got != -125 { + fmt.Printf("sub_int8 1-126 = %d, wanted -125\n", got) + failed = true + } + + if got := sub_int8_1_ssa(126); got != 125 { + fmt.Printf("sub_int8 126-1 = %d, wanted 125\n", got) + failed = true + } + + if got := sub_1_int8_ssa(127); got != -126 { + fmt.Printf("sub_int8 1-127 = %d, wanted -126\n", got) + failed = true + } + + if got := sub_int8_1_ssa(127); got != 126 { + fmt.Printf("sub_int8 127-1 = %d, wanted 126\n", got) + failed = true + } + + if got := sub_126_int8_ssa(-128); got != -2 { + fmt.Printf("sub_int8 126--128 = %d, wanted -2\n", got) + failed = true + } + + if got := sub_int8_126_ssa(-128); got != 2 { + fmt.Printf("sub_int8 -128-126 = %d, wanted 2\n", got) + failed = true + } + + if got := sub_126_int8_ssa(-127); got != -3 { + fmt.Printf("sub_int8 126--127 = %d, wanted -3\n", got) + failed = true + } + + if got := sub_int8_126_ssa(-127); got != 3 { + fmt.Printf("sub_int8 -127-126 = %d, wanted 3\n", got) + failed = true + } + + if got := sub_126_int8_ssa(-1); got != 127 { + fmt.Printf("sub_int8 126--1 = %d, wanted 127\n", got) + failed = true + } + + if got := sub_int8_126_ssa(-1); got != -127 { + fmt.Printf("sub_int8 -1-126 = %d, wanted -127\n", got) + failed = true + } + + if got := sub_126_int8_ssa(0); got != 126 { + fmt.Printf("sub_int8 126-0 = %d, wanted 126\n", got) + failed = true + } + + if got := sub_int8_126_ssa(0); got != -126 { + fmt.Printf("sub_int8 0-126 = %d, wanted -126\n", got) + failed = true + } + + if got := sub_126_int8_ssa(1); got != 125 { + fmt.Printf("sub_int8 126-1 = %d, wanted 125\n", got) + failed = true + } + + if got := sub_int8_126_ssa(1); got != -125 { + fmt.Printf("sub_int8 1-126 = %d, wanted -125\n", got) + failed = true + } + + if got := sub_126_int8_ssa(126); got != 0 { + fmt.Printf("sub_int8 126-126 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_int8_126_ssa(126); got != 0 { + fmt.Printf("sub_int8 126-126 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_126_int8_ssa(127); got != -1 { + fmt.Printf("sub_int8 126-127 = %d, wanted -1\n", got) + failed = true + } + + if got := sub_int8_126_ssa(127); got != 1 { + fmt.Printf("sub_int8 127-126 = %d, wanted 1\n", got) + failed = true + } + + if got := sub_127_int8_ssa(-128); got != -1 { + fmt.Printf("sub_int8 127--128 = %d, wanted -1\n", got) + failed = true + } + + if got := sub_int8_127_ssa(-128); got != 1 { + fmt.Printf("sub_int8 -128-127 = %d, wanted 1\n", got) + failed = true + } + + if got := sub_127_int8_ssa(-127); got != -2 { + fmt.Printf("sub_int8 127--127 = %d, wanted -2\n", got) + failed = true + } + + if got := sub_int8_127_ssa(-127); got != 2 { + fmt.Printf("sub_int8 -127-127 = %d, wanted 2\n", got) + failed = true + } + + if got := sub_127_int8_ssa(-1); got != -128 { + fmt.Printf("sub_int8 127--1 = %d, wanted -128\n", got) + failed = true + } + + if got := sub_int8_127_ssa(-1); got != -128 { + fmt.Printf("sub_int8 -1-127 = %d, wanted -128\n", got) + failed = true + } + + if got := sub_127_int8_ssa(0); got != 127 { + fmt.Printf("sub_int8 127-0 = %d, wanted 127\n", got) + failed = true + } + + if got := sub_int8_127_ssa(0); got != -127 { + fmt.Printf("sub_int8 0-127 = %d, wanted -127\n", got) + failed = true + } + + if got := sub_127_int8_ssa(1); got != 126 { + fmt.Printf("sub_int8 127-1 = %d, wanted 126\n", got) + failed = true + } + + if got := sub_int8_127_ssa(1); got != -126 { + fmt.Printf("sub_int8 1-127 = %d, wanted -126\n", got) + failed = true + } + + if got := sub_127_int8_ssa(126); got != 1 { + fmt.Printf("sub_int8 127-126 = %d, wanted 1\n", got) + failed = true + } + + if got := sub_int8_127_ssa(126); got != -1 { + fmt.Printf("sub_int8 126-127 = %d, wanted -1\n", got) + failed = true + } + + if got := sub_127_int8_ssa(127); got != 0 { + fmt.Printf("sub_int8 127-127 = %d, wanted 0\n", got) + failed = true + } + + if got := sub_int8_127_ssa(127); got != 0 { + fmt.Printf("sub_int8 127-127 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg128_int8_ssa(-128); got != 1 { + fmt.Printf("div_int8 -128/-128 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int8_Neg128_ssa(-128); got != 1 { + fmt.Printf("div_int8 -128/-128 = %d, wanted 1\n", got) + failed = true + } + + if got := div_Neg128_int8_ssa(-127); got != 1 { + fmt.Printf("div_int8 -128/-127 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int8_Neg128_ssa(-127); got != 0 { + fmt.Printf("div_int8 -127/-128 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg128_int8_ssa(-1); got != -128 { + fmt.Printf("div_int8 -128/-1 = %d, wanted -128\n", got) + failed = true + } + + if got := div_int8_Neg128_ssa(-1); got != 0 { + fmt.Printf("div_int8 -1/-128 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int8_Neg128_ssa(0); got != 0 { + fmt.Printf("div_int8 0/-128 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg128_int8_ssa(1); got != -128 { + fmt.Printf("div_int8 -128/1 = %d, wanted -128\n", got) + failed = true + } + + if got := div_int8_Neg128_ssa(1); got != 0 { + fmt.Printf("div_int8 1/-128 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg128_int8_ssa(126); got != -1 { + fmt.Printf("div_int8 -128/126 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int8_Neg128_ssa(126); got != 0 { + fmt.Printf("div_int8 126/-128 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg128_int8_ssa(127); got != -1 { + fmt.Printf("div_int8 -128/127 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int8_Neg128_ssa(127); got != 0 { + fmt.Printf("div_int8 127/-128 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg127_int8_ssa(-128); got != 0 { + fmt.Printf("div_int8 -127/-128 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int8_Neg127_ssa(-128); got != 1 { + fmt.Printf("div_int8 -128/-127 = %d, wanted 1\n", got) + failed = true + } + + if got := div_Neg127_int8_ssa(-127); got != 1 { + fmt.Printf("div_int8 -127/-127 = %d, wanted 1\n", got) failed = true } - if got := div_int16_1_ssa(32766); got != 32766 { - fmt.Printf("div_int16 32766/1 = %d, wanted 32766\n", got) + if got := div_int8_Neg127_ssa(-127); got != 1 { + fmt.Printf("div_int8 -127/-127 = %d, wanted 1\n", got) failed = true } - if got := div_1_int16_ssa(32767); got != 0 { - fmt.Printf("div_int16 1/32767 = %d, wanted 0\n", got) + if got := div_Neg127_int8_ssa(-1); got != 127 { + fmt.Printf("div_int8 -127/-1 = %d, wanted 127\n", got) failed = true } - if got := div_int16_1_ssa(32767); got != 32767 { - fmt.Printf("div_int16 32767/1 = %d, wanted 32767\n", got) + if got := div_int8_Neg127_ssa(-1); got != 0 { + fmt.Printf("div_int8 -1/-127 = %d, wanted 0\n", got) failed = true } - if got := div_32766_int16_ssa(-32768); got != 0 { - fmt.Printf("div_int16 32766/-32768 = %d, wanted 0\n", got) + if got := div_int8_Neg127_ssa(0); got != 0 { + fmt.Printf("div_int8 0/-127 = %d, wanted 0\n", got) failed = true } - if got := div_int16_32766_ssa(-32768); got != -1 { - fmt.Printf("div_int16 -32768/32766 = %d, wanted -1\n", got) + if got := div_Neg127_int8_ssa(1); got != -127 { + fmt.Printf("div_int8 -127/1 = %d, wanted -127\n", got) failed = true } - if got := div_32766_int16_ssa(-32767); got != 0 { - fmt.Printf("div_int16 32766/-32767 = %d, wanted 0\n", got) + if got := div_int8_Neg127_ssa(1); got != 0 { + fmt.Printf("div_int8 1/-127 = %d, wanted 0\n", got) failed = true } - if got := div_int16_32766_ssa(-32767); got != -1 { - fmt.Printf("div_int16 -32767/32766 = %d, wanted -1\n", got) + if got := div_Neg127_int8_ssa(126); got != -1 { + fmt.Printf("div_int8 -127/126 = %d, wanted -1\n", got) failed = true } - if got := div_32766_int16_ssa(-1); got != -32766 { - fmt.Printf("div_int16 32766/-1 = %d, wanted -32766\n", got) + if got := div_int8_Neg127_ssa(126); got != 0 { + fmt.Printf("div_int8 126/-127 = %d, wanted 0\n", got) failed = true } - if got := div_int16_32766_ssa(-1); got != 0 { - fmt.Printf("div_int16 -1/32766 = %d, wanted 0\n", got) + if got := div_Neg127_int8_ssa(127); got != -1 { + fmt.Printf("div_int8 -127/127 = %d, wanted -1\n", got) failed = true } - if got := div_int16_32766_ssa(0); got != 0 { - fmt.Printf("div_int16 0/32766 = %d, wanted 0\n", got) + if got := div_int8_Neg127_ssa(127); got != -1 { + fmt.Printf("div_int8 127/-127 = %d, wanted -1\n", got) failed = true } - if got := div_32766_int16_ssa(1); got != 32766 { - fmt.Printf("div_int16 32766/1 = %d, wanted 32766\n", got) + if got := div_Neg1_int8_ssa(-128); got != 0 { + fmt.Printf("div_int8 -1/-128 = %d, wanted 0\n", got) failed = true } - if got := div_int16_32766_ssa(1); got != 0 { - fmt.Printf("div_int16 1/32766 = %d, wanted 0\n", got) + if got := div_int8_Neg1_ssa(-128); got != -128 { + fmt.Printf("div_int8 -128/-1 = %d, wanted -128\n", got) + failed = true + } + + if got := div_Neg1_int8_ssa(-127); got != 0 { + fmt.Printf("div_int8 -1/-127 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int8_Neg1_ssa(-127); got != 127 { + fmt.Printf("div_int8 -127/-1 = %d, wanted 127\n", got) + failed = true + } + + if got := div_Neg1_int8_ssa(-1); got != 1 { + fmt.Printf("div_int8 -1/-1 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int8_Neg1_ssa(-1); got != 1 { + fmt.Printf("div_int8 -1/-1 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int8_Neg1_ssa(0); got != 0 { + fmt.Printf("div_int8 0/-1 = %d, wanted 0\n", got) + failed = true + } + + if got := div_Neg1_int8_ssa(1); got != -1 { + fmt.Printf("div_int8 -1/1 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int8_Neg1_ssa(1); got != -1 { + fmt.Printf("div_int8 1/-1 = %d, wanted -1\n", got) + failed = true + } + + if got := div_Neg1_int8_ssa(126); got != 0 { + fmt.Printf("div_int8 -1/126 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int8_Neg1_ssa(126); got != -126 { + fmt.Printf("div_int8 126/-1 = %d, wanted -126\n", got) + failed = true + } + + if got := div_Neg1_int8_ssa(127); got != 0 { + fmt.Printf("div_int8 -1/127 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int8_Neg1_ssa(127); got != -127 { + fmt.Printf("div_int8 127/-1 = %d, wanted -127\n", got) + failed = true + } + + if got := div_0_int8_ssa(-128); got != 0 { + fmt.Printf("div_int8 0/-128 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_int8_ssa(-127); got != 0 { + fmt.Printf("div_int8 0/-127 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_int8_ssa(-1); got != 0 { + fmt.Printf("div_int8 0/-1 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_int8_ssa(1); got != 0 { + fmt.Printf("div_int8 0/1 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_int8_ssa(126); got != 0 { + fmt.Printf("div_int8 0/126 = %d, wanted 0\n", got) + failed = true + } + + if got := div_0_int8_ssa(127); got != 0 { + fmt.Printf("div_int8 0/127 = %d, wanted 0\n", got) + failed = true + } + + if got := div_1_int8_ssa(-128); got != 0 { + fmt.Printf("div_int8 1/-128 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int8_1_ssa(-128); got != -128 { + fmt.Printf("div_int8 -128/1 = %d, wanted -128\n", got) + failed = true + } + + if got := div_1_int8_ssa(-127); got != 0 { + fmt.Printf("div_int8 1/-127 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int8_1_ssa(-127); got != -127 { + fmt.Printf("div_int8 -127/1 = %d, wanted -127\n", got) + failed = true + } + + if got := div_1_int8_ssa(-1); got != -1 { + fmt.Printf("div_int8 1/-1 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int8_1_ssa(-1); got != -1 { + fmt.Printf("div_int8 -1/1 = %d, wanted -1\n", got) + failed = true + } + + if got := div_int8_1_ssa(0); got != 0 { + fmt.Printf("div_int8 0/1 = %d, wanted 0\n", got) + failed = true + } + + if got := div_1_int8_ssa(1); got != 1 { + fmt.Printf("div_int8 1/1 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int8_1_ssa(1); got != 1 { + fmt.Printf("div_int8 1/1 = %d, wanted 1\n", got) + failed = true + } + + if got := div_1_int8_ssa(126); got != 0 { + fmt.Printf("div_int8 1/126 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int8_1_ssa(126); got != 126 { + fmt.Printf("div_int8 126/1 = %d, wanted 126\n", got) + failed = true + } + + if got := div_1_int8_ssa(127); got != 0 { + fmt.Printf("div_int8 1/127 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int8_1_ssa(127); got != 127 { + fmt.Printf("div_int8 127/1 = %d, wanted 127\n", got) + failed = true + } + + if got := div_126_int8_ssa(-128); got != 0 { + fmt.Printf("div_int8 126/-128 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int8_126_ssa(-128); got != -1 { + fmt.Printf("div_int8 -128/126 = %d, wanted -1\n", got) + failed = true + } + + if got := div_126_int8_ssa(-127); got != 0 { + fmt.Printf("div_int8 126/-127 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int8_126_ssa(-127); got != -1 { + fmt.Printf("div_int8 -127/126 = %d, wanted -1\n", got) + failed = true + } + + if got := div_126_int8_ssa(-1); got != -126 { + fmt.Printf("div_int8 126/-1 = %d, wanted -126\n", got) + failed = true + } + + if got := div_int8_126_ssa(-1); got != 0 { + fmt.Printf("div_int8 -1/126 = %d, wanted 0\n", got) + failed = true + } + + if got := div_int8_126_ssa(0); got != 0 { + fmt.Printf("div_int8 0/126 = %d, wanted 0\n", got) + failed = true + } + + if got := div_126_int8_ssa(1); got != 126 { + fmt.Printf("div_int8 126/1 = %d, wanted 126\n", got) + failed = true + } + + if got := div_int8_126_ssa(1); got != 0 { + fmt.Printf("div_int8 1/126 = %d, wanted 0\n", got) + failed = true + } + + if got := div_126_int8_ssa(126); got != 1 { + fmt.Printf("div_int8 126/126 = %d, wanted 1\n", got) + failed = true + } + + if got := div_int8_126_ssa(126); got != 1 { + fmt.Printf("div_int8 126/126 = %d, wanted 1\n", got) failed = true } - if got := div_32766_int16_ssa(32766); got != 1 { - fmt.Printf("div_int16 32766/32766 = %d, wanted 1\n", got) + if got := div_126_int8_ssa(127); got != 0 { + fmt.Printf("div_int8 126/127 = %d, wanted 0\n", got) failed = true } - if got := div_int16_32766_ssa(32766); got != 1 { - fmt.Printf("div_int16 32766/32766 = %d, wanted 1\n", got) + if got := div_int8_126_ssa(127); got != 1 { + fmt.Printf("div_int8 127/126 = %d, wanted 1\n", got) failed = true } - if got := div_32766_int16_ssa(32767); got != 0 { - fmt.Printf("div_int16 32766/32767 = %d, wanted 0\n", got) + if got := div_127_int8_ssa(-128); got != 0 { + fmt.Printf("div_int8 127/-128 = %d, wanted 0\n", got) failed = true } - if got := div_int16_32766_ssa(32767); got != 1 { - fmt.Printf("div_int16 32767/32766 = %d, wanted 1\n", got) + if got := div_int8_127_ssa(-128); got != -1 { + fmt.Printf("div_int8 -128/127 = %d, wanted -1\n", got) failed = true } - if got := div_32767_int16_ssa(-32768); got != 0 { - fmt.Printf("div_int16 32767/-32768 = %d, wanted 0\n", got) + if got := div_127_int8_ssa(-127); got != -1 { + fmt.Printf("div_int8 127/-127 = %d, wanted -1\n", got) failed = true } - if got := div_int16_32767_ssa(-32768); got != -1 { - fmt.Printf("div_int16 -32768/32767 = %d, wanted -1\n", got) + if got := div_int8_127_ssa(-127); got != -1 { + fmt.Printf("div_int8 -127/127 = %d, wanted -1\n", got) failed = true } - if got := div_32767_int16_ssa(-32767); got != -1 { - fmt.Printf("div_int16 32767/-32767 = %d, wanted -1\n", got) + if got := div_127_int8_ssa(-1); got != -127 { + fmt.Printf("div_int8 127/-1 = %d, wanted -127\n", got) failed = true } - if got := div_int16_32767_ssa(-32767); got != -1 { - fmt.Printf("div_int16 -32767/32767 = %d, wanted -1\n", got) + if got := div_int8_127_ssa(-1); got != 0 { + fmt.Printf("div_int8 -1/127 = %d, wanted 0\n", got) failed = true } - if got := div_32767_int16_ssa(-1); got != -32767 { - fmt.Printf("div_int16 32767/-1 = %d, wanted -32767\n", got) + if got := div_int8_127_ssa(0); got != 0 { + fmt.Printf("div_int8 0/127 = %d, wanted 0\n", got) failed = true } - if got := div_int16_32767_ssa(-1); got != 0 { - fmt.Printf("div_int16 -1/32767 = %d, wanted 0\n", got) + if got := div_127_int8_ssa(1); got != 127 { + fmt.Printf("div_int8 127/1 = %d, wanted 127\n", got) failed = true } - if got := div_int16_32767_ssa(0); got != 0 { - fmt.Printf("div_int16 0/32767 = %d, wanted 0\n", got) + if got := div_int8_127_ssa(1); got != 0 { + fmt.Printf("div_int8 1/127 = %d, wanted 0\n", got) failed = true } - if got := div_32767_int16_ssa(1); got != 32767 { - fmt.Printf("div_int16 32767/1 = %d, wanted 32767\n", got) + if got := div_127_int8_ssa(126); got != 1 { + fmt.Printf("div_int8 127/126 = %d, wanted 1\n", got) failed = true } - if got := div_int16_32767_ssa(1); got != 0 { - fmt.Printf("div_int16 1/32767 = %d, wanted 0\n", got) + if got := div_int8_127_ssa(126); got != 0 { + fmt.Printf("div_int8 126/127 = %d, wanted 0\n", got) failed = true } - if got := div_32767_int16_ssa(32766); got != 1 { - fmt.Printf("div_int16 32767/32766 = %d, wanted 1\n", got) + if got := div_127_int8_ssa(127); got != 1 { + fmt.Printf("div_int8 127/127 = %d, wanted 1\n", got) failed = true } - if got := div_int16_32767_ssa(32766); got != 0 { - fmt.Printf("div_int16 32766/32767 = %d, wanted 0\n", got) + if got := div_int8_127_ssa(127); got != 1 { + fmt.Printf("div_int8 127/127 = %d, wanted 1\n", got) failed = true } - if got := div_32767_int16_ssa(32767); got != 1 { - fmt.Printf("div_int16 32767/32767 = %d, wanted 1\n", got) + if got := mul_Neg128_int8_ssa(-128); got != 0 { + fmt.Printf("mul_int8 -128*-128 = %d, wanted 0\n", got) failed = true } - if got := div_int16_32767_ssa(32767); got != 1 { - fmt.Printf("div_int16 32767/32767 = %d, wanted 1\n", got) + if got := mul_int8_Neg128_ssa(-128); got != 0 { + fmt.Printf("mul_int8 -128*-128 = %d, wanted 0\n", got) failed = true } - if got := div_0_uint8_ssa(1); got != 0 { - fmt.Printf("div_uint8 0/1 = %d, wanted 0\n", got) + if got := mul_Neg128_int8_ssa(-127); got != -128 { + fmt.Printf("mul_int8 -128*-127 = %d, wanted -128\n", got) failed = true } - if got := div_0_uint8_ssa(255); got != 0 { - fmt.Printf("div_uint8 0/255 = %d, wanted 0\n", got) + if got := mul_int8_Neg128_ssa(-127); got != -128 { + fmt.Printf("mul_int8 -127*-128 = %d, wanted -128\n", got) failed = true } - if got := div_uint8_1_ssa(0); got != 0 { - fmt.Printf("div_uint8 0/1 = %d, wanted 0\n", got) + if got := mul_Neg128_int8_ssa(-1); got != -128 { + fmt.Printf("mul_int8 -128*-1 = %d, wanted -128\n", got) failed = true } - if got := div_1_uint8_ssa(1); got != 1 { - fmt.Printf("div_uint8 1/1 = %d, wanted 1\n", got) + if got := mul_int8_Neg128_ssa(-1); got != -128 { + fmt.Printf("mul_int8 -1*-128 = %d, wanted -128\n", got) failed = true } - if got := div_uint8_1_ssa(1); got != 1 { - fmt.Printf("div_uint8 1/1 = %d, wanted 1\n", got) + if got := mul_Neg128_int8_ssa(0); got != 0 { + fmt.Printf("mul_int8 -128*0 = %d, wanted 0\n", got) failed = true } - if got := div_1_uint8_ssa(255); got != 0 { - fmt.Printf("adiv_uint8 1/255 = %d, wanted 0\n", got) + if got := mul_int8_Neg128_ssa(0); got != 0 { + fmt.Printf("mul_int8 0*-128 = %d, wanted 0\n", got) failed = true } - if got := div_uint8_1_ssa(255); got != 255 { - fmt.Printf("div_uint8 255/1 = %d, wanted 255\n", got) + if got := mul_Neg128_int8_ssa(1); got != -128 { + fmt.Printf("mul_int8 -128*1 = %d, wanted -128\n", got) failed = true } - if got := div_uint8_255_ssa(0); got != 0 { - fmt.Printf("div_uint8 0/255 = %d, wanted 0\n", got) + if got := mul_int8_Neg128_ssa(1); got != -128 { + fmt.Printf("mul_int8 1*-128 = %d, wanted -128\n", got) failed = true } - if got := div_255_uint8_ssa(1); got != 255 { - fmt.Printf("div_uint8 255/1 = %d, wanted 255\n", got) + if got := mul_Neg128_int8_ssa(126); got != 0 { + fmt.Printf("mul_int8 -128*126 = %d, wanted 0\n", got) failed = true } - if got := div_uint8_255_ssa(1); got != 0 { - fmt.Printf("bdiv_uint8 1/255 = %d, wanted 0\n", got) + if got := mul_int8_Neg128_ssa(126); got != 0 { + fmt.Printf("mul_int8 126*-128 = %d, wanted 0\n", got) failed = true } - if got := div_255_uint8_ssa(255); got != 1 { - fmt.Printf("div_uint8 255/255 = %d, wanted 1\n", got) + if got := mul_Neg128_int8_ssa(127); got != -128 { + fmt.Printf("mul_int8 -128*127 = %d, wanted -128\n", got) failed = true } - if got := div_uint8_255_ssa(255); got != 1 { - fmt.Printf("div_uint8 255/255 = %d, wanted 1\n", got) + if got := mul_int8_Neg128_ssa(127); got != -128 { + fmt.Printf("mul_int8 127*-128 = %d, wanted -128\n", got) failed = true } - if got := div_Neg128_int8_ssa(-128); got != 1 { - fmt.Printf("div_int8 -128/-128 = %d, wanted 1\n", got) + if got := mul_Neg127_int8_ssa(-128); got != -128 { + fmt.Printf("mul_int8 -127*-128 = %d, wanted -128\n", got) failed = true } - if got := div_int8_Neg128_ssa(-128); got != 1 { - fmt.Printf("div_int8 -128/-128 = %d, wanted 1\n", got) + if got := mul_int8_Neg127_ssa(-128); got != -128 { + fmt.Printf("mul_int8 -128*-127 = %d, wanted -128\n", got) failed = true } - if got := div_Neg128_int8_ssa(-127); got != 1 { - fmt.Printf("div_int8 -128/-127 = %d, wanted 1\n", got) + if got := mul_Neg127_int8_ssa(-127); got != 1 { + fmt.Printf("mul_int8 -127*-127 = %d, wanted 1\n", got) failed = true } - if got := div_int8_Neg128_ssa(-127); got != 0 { - fmt.Printf("div_int8 -127/-128 = %d, wanted 0\n", got) + if got := mul_int8_Neg127_ssa(-127); got != 1 { + fmt.Printf("mul_int8 -127*-127 = %d, wanted 1\n", got) failed = true } - if got := div_Neg128_int8_ssa(-1); got != -128 { - fmt.Printf("div_int8 -128/-1 = %d, wanted -128\n", got) + if got := mul_Neg127_int8_ssa(-1); got != 127 { + fmt.Printf("mul_int8 -127*-1 = %d, wanted 127\n", got) failed = true } - if got := div_int8_Neg128_ssa(-1); got != 0 { - fmt.Printf("div_int8 -1/-128 = %d, wanted 0\n", got) + if got := mul_int8_Neg127_ssa(-1); got != 127 { + fmt.Printf("mul_int8 -1*-127 = %d, wanted 127\n", got) failed = true } - if got := div_int8_Neg128_ssa(0); got != 0 { - fmt.Printf("div_int8 0/-128 = %d, wanted 0\n", got) + if got := mul_Neg127_int8_ssa(0); got != 0 { + fmt.Printf("mul_int8 -127*0 = %d, wanted 0\n", got) failed = true } - if got := div_Neg128_int8_ssa(1); got != -128 { - fmt.Printf("div_int8 -128/1 = %d, wanted -128\n", got) + if got := mul_int8_Neg127_ssa(0); got != 0 { + fmt.Printf("mul_int8 0*-127 = %d, wanted 0\n", got) failed = true } - if got := div_int8_Neg128_ssa(1); got != 0 { - fmt.Printf("div_int8 1/-128 = %d, wanted 0\n", got) + if got := mul_Neg127_int8_ssa(1); got != -127 { + fmt.Printf("mul_int8 -127*1 = %d, wanted -127\n", got) failed = true } - if got := div_Neg128_int8_ssa(126); got != -1 { - fmt.Printf("div_int8 -128/126 = %d, wanted -1\n", got) + if got := mul_int8_Neg127_ssa(1); got != -127 { + fmt.Printf("mul_int8 1*-127 = %d, wanted -127\n", got) failed = true } - if got := div_int8_Neg128_ssa(126); got != 0 { - fmt.Printf("div_int8 126/-128 = %d, wanted 0\n", got) + if got := mul_Neg127_int8_ssa(126); got != 126 { + fmt.Printf("mul_int8 -127*126 = %d, wanted 126\n", got) failed = true } - if got := div_Neg128_int8_ssa(127); got != -1 { - fmt.Printf("div_int8 -128/127 = %d, wanted -1\n", got) + if got := mul_int8_Neg127_ssa(126); got != 126 { + fmt.Printf("mul_int8 126*-127 = %d, wanted 126\n", got) failed = true } - if got := div_int8_Neg128_ssa(127); got != 0 { - fmt.Printf("div_int8 127/-128 = %d, wanted 0\n", got) + if got := mul_Neg127_int8_ssa(127); got != -1 { + fmt.Printf("mul_int8 -127*127 = %d, wanted -1\n", got) failed = true } - if got := div_Neg127_int8_ssa(-128); got != 0 { - fmt.Printf("div_int8 -127/-128 = %d, wanted 0\n", got) + if got := mul_int8_Neg127_ssa(127); got != -1 { + fmt.Printf("mul_int8 127*-127 = %d, wanted -1\n", got) failed = true } - if got := div_int8_Neg127_ssa(-128); got != 1 { - fmt.Printf("div_int8 -128/-127 = %d, wanted 1\n", got) + if got := mul_Neg1_int8_ssa(-128); got != -128 { + fmt.Printf("mul_int8 -1*-128 = %d, wanted -128\n", got) failed = true } - if got := div_Neg127_int8_ssa(-127); got != 1 { - fmt.Printf("div_int8 -127/-127 = %d, wanted 1\n", got) + if got := mul_int8_Neg1_ssa(-128); got != -128 { + fmt.Printf("mul_int8 -128*-1 = %d, wanted -128\n", got) failed = true } - if got := div_int8_Neg127_ssa(-127); got != 1 { - fmt.Printf("div_int8 -127/-127 = %d, wanted 1\n", got) + if got := mul_Neg1_int8_ssa(-127); got != 127 { + fmt.Printf("mul_int8 -1*-127 = %d, wanted 127\n", got) failed = true } - if got := div_Neg127_int8_ssa(-1); got != 127 { - fmt.Printf("div_int8 -127/-1 = %d, wanted 127\n", got) + if got := mul_int8_Neg1_ssa(-127); got != 127 { + fmt.Printf("mul_int8 -127*-1 = %d, wanted 127\n", got) failed = true } - if got := div_int8_Neg127_ssa(-1); got != 0 { - fmt.Printf("div_int8 -1/-127 = %d, wanted 0\n", got) + if got := mul_Neg1_int8_ssa(-1); got != 1 { + fmt.Printf("mul_int8 -1*-1 = %d, wanted 1\n", got) failed = true } - if got := div_int8_Neg127_ssa(0); got != 0 { - fmt.Printf("div_int8 0/-127 = %d, wanted 0\n", got) + if got := mul_int8_Neg1_ssa(-1); got != 1 { + fmt.Printf("mul_int8 -1*-1 = %d, wanted 1\n", got) failed = true } - if got := div_Neg127_int8_ssa(1); got != -127 { - fmt.Printf("div_int8 -127/1 = %d, wanted -127\n", got) + if got := mul_Neg1_int8_ssa(0); got != 0 { + fmt.Printf("mul_int8 -1*0 = %d, wanted 0\n", got) failed = true } - if got := div_int8_Neg127_ssa(1); got != 0 { - fmt.Printf("div_int8 1/-127 = %d, wanted 0\n", got) + if got := mul_int8_Neg1_ssa(0); got != 0 { + fmt.Printf("mul_int8 0*-1 = %d, wanted 0\n", got) failed = true } - if got := div_Neg127_int8_ssa(126); got != -1 { - fmt.Printf("div_int8 -127/126 = %d, wanted -1\n", got) + if got := mul_Neg1_int8_ssa(1); got != -1 { + fmt.Printf("mul_int8 -1*1 = %d, wanted -1\n", got) failed = true } - if got := div_int8_Neg127_ssa(126); got != 0 { - fmt.Printf("div_int8 126/-127 = %d, wanted 0\n", got) + if got := mul_int8_Neg1_ssa(1); got != -1 { + fmt.Printf("mul_int8 1*-1 = %d, wanted -1\n", got) failed = true } - if got := div_Neg127_int8_ssa(127); got != -1 { - fmt.Printf("div_int8 -127/127 = %d, wanted -1\n", got) + if got := mul_Neg1_int8_ssa(126); got != -126 { + fmt.Printf("mul_int8 -1*126 = %d, wanted -126\n", got) failed = true } - if got := div_int8_Neg127_ssa(127); got != -1 { - fmt.Printf("div_int8 127/-127 = %d, wanted -1\n", got) + if got := mul_int8_Neg1_ssa(126); got != -126 { + fmt.Printf("mul_int8 126*-1 = %d, wanted -126\n", got) failed = true } - if got := div_Neg1_int8_ssa(-128); got != 0 { - fmt.Printf("div_int8 -1/-128 = %d, wanted 0\n", got) + if got := mul_Neg1_int8_ssa(127); got != -127 { + fmt.Printf("mul_int8 -1*127 = %d, wanted -127\n", got) failed = true } - if got := div_int8_Neg1_ssa(-128); got != -128 { - fmt.Printf("div_int8 -128/-1 = %d, wanted -128\n", got) + if got := mul_int8_Neg1_ssa(127); got != -127 { + fmt.Printf("mul_int8 127*-1 = %d, wanted -127\n", got) failed = true } - if got := div_Neg1_int8_ssa(-127); got != 0 { - fmt.Printf("div_int8 -1/-127 = %d, wanted 0\n", got) + if got := mul_0_int8_ssa(-128); got != 0 { + fmt.Printf("mul_int8 0*-128 = %d, wanted 0\n", got) failed = true } - if got := div_int8_Neg1_ssa(-127); got != 127 { - fmt.Printf("div_int8 -127/-1 = %d, wanted 127\n", got) + if got := mul_int8_0_ssa(-128); got != 0 { + fmt.Printf("mul_int8 -128*0 = %d, wanted 0\n", got) failed = true } - if got := div_Neg1_int8_ssa(-1); got != 1 { - fmt.Printf("div_int8 -1/-1 = %d, wanted 1\n", got) + if got := mul_0_int8_ssa(-127); got != 0 { + fmt.Printf("mul_int8 0*-127 = %d, wanted 0\n", got) failed = true } - if got := div_int8_Neg1_ssa(-1); got != 1 { - fmt.Printf("div_int8 -1/-1 = %d, wanted 1\n", got) + if got := mul_int8_0_ssa(-127); got != 0 { + fmt.Printf("mul_int8 -127*0 = %d, wanted 0\n", got) failed = true } - if got := div_int8_Neg1_ssa(0); got != 0 { - fmt.Printf("div_int8 0/-1 = %d, wanted 0\n", got) + if got := mul_0_int8_ssa(-1); got != 0 { + fmt.Printf("mul_int8 0*-1 = %d, wanted 0\n", got) failed = true } - if got := div_Neg1_int8_ssa(1); got != -1 { - fmt.Printf("div_int8 -1/1 = %d, wanted -1\n", got) + if got := mul_int8_0_ssa(-1); got != 0 { + fmt.Printf("mul_int8 -1*0 = %d, wanted 0\n", got) failed = true } - if got := div_int8_Neg1_ssa(1); got != -1 { - fmt.Printf("div_int8 1/-1 = %d, wanted -1\n", got) + if got := mul_0_int8_ssa(0); got != 0 { + fmt.Printf("mul_int8 0*0 = %d, wanted 0\n", got) failed = true } - if got := div_Neg1_int8_ssa(126); got != 0 { - fmt.Printf("div_int8 -1/126 = %d, wanted 0\n", got) + if got := mul_int8_0_ssa(0); got != 0 { + fmt.Printf("mul_int8 0*0 = %d, wanted 0\n", got) failed = true } - if got := div_int8_Neg1_ssa(126); got != -126 { - fmt.Printf("div_int8 126/-1 = %d, wanted -126\n", got) + if got := mul_0_int8_ssa(1); got != 0 { + fmt.Printf("mul_int8 0*1 = %d, wanted 0\n", got) failed = true } - if got := div_Neg1_int8_ssa(127); got != 0 { - fmt.Printf("div_int8 -1/127 = %d, wanted 0\n", got) + if got := mul_int8_0_ssa(1); got != 0 { + fmt.Printf("mul_int8 1*0 = %d, wanted 0\n", got) failed = true } - if got := div_int8_Neg1_ssa(127); got != -127 { - fmt.Printf("div_int8 127/-1 = %d, wanted -127\n", got) + if got := mul_0_int8_ssa(126); got != 0 { + fmt.Printf("mul_int8 0*126 = %d, wanted 0\n", got) failed = true } - if got := div_0_int8_ssa(-128); got != 0 { - fmt.Printf("div_int8 0/-128 = %d, wanted 0\n", got) + if got := mul_int8_0_ssa(126); got != 0 { + fmt.Printf("mul_int8 126*0 = %d, wanted 0\n", got) failed = true } - if got := div_0_int8_ssa(-127); got != 0 { - fmt.Printf("div_int8 0/-127 = %d, wanted 0\n", got) + if got := mul_0_int8_ssa(127); got != 0 { + fmt.Printf("mul_int8 0*127 = %d, wanted 0\n", got) failed = true } - if got := div_0_int8_ssa(-1); got != 0 { - fmt.Printf("div_int8 0/-1 = %d, wanted 0\n", got) + if got := mul_int8_0_ssa(127); got != 0 { + fmt.Printf("mul_int8 127*0 = %d, wanted 0\n", got) failed = true } - if got := div_0_int8_ssa(1); got != 0 { - fmt.Printf("div_int8 0/1 = %d, wanted 0\n", got) + if got := mul_1_int8_ssa(-128); got != -128 { + fmt.Printf("mul_int8 1*-128 = %d, wanted -128\n", got) failed = true } - if got := div_0_int8_ssa(126); got != 0 { - fmt.Printf("div_int8 0/126 = %d, wanted 0\n", got) + if got := mul_int8_1_ssa(-128); got != -128 { + fmt.Printf("mul_int8 -128*1 = %d, wanted -128\n", got) failed = true } - if got := div_0_int8_ssa(127); got != 0 { - fmt.Printf("div_int8 0/127 = %d, wanted 0\n", got) + if got := mul_1_int8_ssa(-127); got != -127 { + fmt.Printf("mul_int8 1*-127 = %d, wanted -127\n", got) failed = true } - if got := div_1_int8_ssa(-128); got != 0 { - fmt.Printf("div_int8 1/-128 = %d, wanted 0\n", got) + if got := mul_int8_1_ssa(-127); got != -127 { + fmt.Printf("mul_int8 -127*1 = %d, wanted -127\n", got) failed = true } - if got := div_int8_1_ssa(-128); got != -128 { - fmt.Printf("div_int8 -128/1 = %d, wanted -128\n", got) + if got := mul_1_int8_ssa(-1); got != -1 { + fmt.Printf("mul_int8 1*-1 = %d, wanted -1\n", got) failed = true } - if got := div_1_int8_ssa(-127); got != 0 { - fmt.Printf("div_int8 1/-127 = %d, wanted 0\n", got) + if got := mul_int8_1_ssa(-1); got != -1 { + fmt.Printf("mul_int8 -1*1 = %d, wanted -1\n", got) failed = true } - if got := div_int8_1_ssa(-127); got != -127 { - fmt.Printf("div_int8 -127/1 = %d, wanted -127\n", got) + if got := mul_1_int8_ssa(0); got != 0 { + fmt.Printf("mul_int8 1*0 = %d, wanted 0\n", got) failed = true } - if got := div_1_int8_ssa(-1); got != -1 { - fmt.Printf("div_int8 1/-1 = %d, wanted -1\n", got) + if got := mul_int8_1_ssa(0); got != 0 { + fmt.Printf("mul_int8 0*1 = %d, wanted 0\n", got) failed = true } - if got := div_int8_1_ssa(-1); got != -1 { - fmt.Printf("div_int8 -1/1 = %d, wanted -1\n", got) + if got := mul_1_int8_ssa(1); got != 1 { + fmt.Printf("mul_int8 1*1 = %d, wanted 1\n", got) failed = true } - if got := div_int8_1_ssa(0); got != 0 { - fmt.Printf("div_int8 0/1 = %d, wanted 0\n", got) + if got := mul_int8_1_ssa(1); got != 1 { + fmt.Printf("mul_int8 1*1 = %d, wanted 1\n", got) failed = true } - if got := div_1_int8_ssa(1); got != 1 { - fmt.Printf("div_int8 1/1 = %d, wanted 1\n", got) + if got := mul_1_int8_ssa(126); got != 126 { + fmt.Printf("mul_int8 1*126 = %d, wanted 126\n", got) failed = true } - if got := div_int8_1_ssa(1); got != 1 { - fmt.Printf("div_int8 1/1 = %d, wanted 1\n", got) + if got := mul_int8_1_ssa(126); got != 126 { + fmt.Printf("mul_int8 126*1 = %d, wanted 126\n", got) failed = true } - if got := div_1_int8_ssa(126); got != 0 { - fmt.Printf("div_int8 1/126 = %d, wanted 0\n", got) + if got := mul_1_int8_ssa(127); got != 127 { + fmt.Printf("mul_int8 1*127 = %d, wanted 127\n", got) failed = true } - if got := div_int8_1_ssa(126); got != 126 { - fmt.Printf("div_int8 126/1 = %d, wanted 126\n", got) + if got := mul_int8_1_ssa(127); got != 127 { + fmt.Printf("mul_int8 127*1 = %d, wanted 127\n", got) failed = true } - if got := div_1_int8_ssa(127); got != 0 { - fmt.Printf("div_int8 1/127 = %d, wanted 0\n", got) + if got := mul_126_int8_ssa(-128); got != 0 { + fmt.Printf("mul_int8 126*-128 = %d, wanted 0\n", got) failed = true } - if got := div_int8_1_ssa(127); got != 127 { - fmt.Printf("div_int8 127/1 = %d, wanted 127\n", got) + if got := mul_int8_126_ssa(-128); got != 0 { + fmt.Printf("mul_int8 -128*126 = %d, wanted 0\n", got) failed = true } - if got := div_126_int8_ssa(-128); got != 0 { - fmt.Printf("div_int8 126/-128 = %d, wanted 0\n", got) + if got := mul_126_int8_ssa(-127); got != 126 { + fmt.Printf("mul_int8 126*-127 = %d, wanted 126\n", got) failed = true } - if got := div_int8_126_ssa(-128); got != -1 { - fmt.Printf("div_int8 -128/126 = %d, wanted -1\n", got) + if got := mul_int8_126_ssa(-127); got != 126 { + fmt.Printf("mul_int8 -127*126 = %d, wanted 126\n", got) failed = true } - if got := div_126_int8_ssa(-127); got != 0 { - fmt.Printf("div_int8 126/-127 = %d, wanted 0\n", got) + if got := mul_126_int8_ssa(-1); got != -126 { + fmt.Printf("mul_int8 126*-1 = %d, wanted -126\n", got) failed = true } - if got := div_int8_126_ssa(-127); got != -1 { - fmt.Printf("div_int8 -127/126 = %d, wanted -1\n", got) + if got := mul_int8_126_ssa(-1); got != -126 { + fmt.Printf("mul_int8 -1*126 = %d, wanted -126\n", got) failed = true } - if got := div_126_int8_ssa(-1); got != -126 { - fmt.Printf("div_int8 126/-1 = %d, wanted -126\n", got) + if got := mul_126_int8_ssa(0); got != 0 { + fmt.Printf("mul_int8 126*0 = %d, wanted 0\n", got) failed = true } - if got := div_int8_126_ssa(-1); got != 0 { - fmt.Printf("div_int8 -1/126 = %d, wanted 0\n", got) + if got := mul_int8_126_ssa(0); got != 0 { + fmt.Printf("mul_int8 0*126 = %d, wanted 0\n", got) failed = true } - if got := div_int8_126_ssa(0); got != 0 { - fmt.Printf("div_int8 0/126 = %d, wanted 0\n", got) + if got := mul_126_int8_ssa(1); got != 126 { + fmt.Printf("mul_int8 126*1 = %d, wanted 126\n", got) failed = true } - if got := div_126_int8_ssa(1); got != 126 { - fmt.Printf("div_int8 126/1 = %d, wanted 126\n", got) + if got := mul_int8_126_ssa(1); got != 126 { + fmt.Printf("mul_int8 1*126 = %d, wanted 126\n", got) failed = true } - if got := div_int8_126_ssa(1); got != 0 { - fmt.Printf("div_int8 1/126 = %d, wanted 0\n", got) + if got := mul_126_int8_ssa(126); got != 4 { + fmt.Printf("mul_int8 126*126 = %d, wanted 4\n", got) failed = true } - if got := div_126_int8_ssa(126); got != 1 { - fmt.Printf("div_int8 126/126 = %d, wanted 1\n", got) + if got := mul_int8_126_ssa(126); got != 4 { + fmt.Printf("mul_int8 126*126 = %d, wanted 4\n", got) failed = true } - if got := div_int8_126_ssa(126); got != 1 { - fmt.Printf("div_int8 126/126 = %d, wanted 1\n", got) + if got := mul_126_int8_ssa(127); got != -126 { + fmt.Printf("mul_int8 126*127 = %d, wanted -126\n", got) failed = true } - if got := div_126_int8_ssa(127); got != 0 { - fmt.Printf("div_int8 126/127 = %d, wanted 0\n", got) + if got := mul_int8_126_ssa(127); got != -126 { + fmt.Printf("mul_int8 127*126 = %d, wanted -126\n", got) failed = true } - if got := div_int8_126_ssa(127); got != 1 { - fmt.Printf("div_int8 127/126 = %d, wanted 1\n", got) + if got := mul_127_int8_ssa(-128); got != -128 { + fmt.Printf("mul_int8 127*-128 = %d, wanted -128\n", got) failed = true } - if got := div_127_int8_ssa(-128); got != 0 { - fmt.Printf("div_int8 127/-128 = %d, wanted 0\n", got) + if got := mul_int8_127_ssa(-128); got != -128 { + fmt.Printf("mul_int8 -128*127 = %d, wanted -128\n", got) failed = true } - if got := div_int8_127_ssa(-128); got != -1 { - fmt.Printf("div_int8 -128/127 = %d, wanted -1\n", got) + if got := mul_127_int8_ssa(-127); got != -1 { + fmt.Printf("mul_int8 127*-127 = %d, wanted -1\n", got) failed = true } - if got := div_127_int8_ssa(-127); got != -1 { - fmt.Printf("div_int8 127/-127 = %d, wanted -1\n", got) + if got := mul_int8_127_ssa(-127); got != -1 { + fmt.Printf("mul_int8 -127*127 = %d, wanted -1\n", got) failed = true } - if got := div_int8_127_ssa(-127); got != -1 { - fmt.Printf("div_int8 -127/127 = %d, wanted -1\n", got) + if got := mul_127_int8_ssa(-1); got != -127 { + fmt.Printf("mul_int8 127*-1 = %d, wanted -127\n", got) failed = true } - if got := div_127_int8_ssa(-1); got != -127 { - fmt.Printf("div_int8 127/-1 = %d, wanted -127\n", got) + if got := mul_int8_127_ssa(-1); got != -127 { + fmt.Printf("mul_int8 -1*127 = %d, wanted -127\n", got) failed = true } - if got := div_int8_127_ssa(-1); got != 0 { - fmt.Printf("div_int8 -1/127 = %d, wanted 0\n", got) + if got := mul_127_int8_ssa(0); got != 0 { + fmt.Printf("mul_int8 127*0 = %d, wanted 0\n", got) failed = true } - if got := div_int8_127_ssa(0); got != 0 { - fmt.Printf("div_int8 0/127 = %d, wanted 0\n", got) + if got := mul_int8_127_ssa(0); got != 0 { + fmt.Printf("mul_int8 0*127 = %d, wanted 0\n", got) failed = true } - if got := div_127_int8_ssa(1); got != 127 { - fmt.Printf("div_int8 127/1 = %d, wanted 127\n", got) + if got := mul_127_int8_ssa(1); got != 127 { + fmt.Printf("mul_int8 127*1 = %d, wanted 127\n", got) failed = true } - if got := div_int8_127_ssa(1); got != 0 { - fmt.Printf("div_int8 1/127 = %d, wanted 0\n", got) + if got := mul_int8_127_ssa(1); got != 127 { + fmt.Printf("mul_int8 1*127 = %d, wanted 127\n", got) failed = true } - if got := div_127_int8_ssa(126); got != 1 { - fmt.Printf("div_int8 127/126 = %d, wanted 1\n", got) + if got := mul_127_int8_ssa(126); got != -126 { + fmt.Printf("mul_int8 127*126 = %d, wanted -126\n", got) failed = true } - if got := div_int8_127_ssa(126); got != 0 { - fmt.Printf("div_int8 126/127 = %d, wanted 0\n", got) + if got := mul_int8_127_ssa(126); got != -126 { + fmt.Printf("mul_int8 126*127 = %d, wanted -126\n", got) failed = true } - if got := div_127_int8_ssa(127); got != 1 { - fmt.Printf("div_int8 127/127 = %d, wanted 1\n", got) + if got := mul_127_int8_ssa(127); got != 1 { + fmt.Printf("mul_int8 127*127 = %d, wanted 1\n", got) failed = true } - if got := div_int8_127_ssa(127); got != 1 { - fmt.Printf("div_int8 127/127 = %d, wanted 1\n", got) + if got := mul_int8_127_ssa(127); got != 1 { + fmt.Printf("mul_int8 127*127 = %d, wanted 1\n", got) failed = true } if failed { diff --git a/src/cmd/compile/internal/gc/testdata/arith_ssa.go b/src/cmd/compile/internal/gc/testdata/arith_ssa.go index af31245505..22a78105e0 100644 --- a/src/cmd/compile/internal/gc/testdata/arith_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/arith_ssa.go @@ -8,6 +8,102 @@ package main +import "fmt" + +// testArithRshConst ensures that "const >> const" right shifts correctly perform +// sign extension on the lhs constant +func testArithRshConst() { + wantu := uint64(0x4000000000000000) + if got := arithRshuConst_ssa(); got != wantu { + println("arithRshuConst failed, wanted", wantu, "got", got) + failed = true + } + + wants := int64(-0x4000000000000000) + if got := arithRshConst_ssa(); got != wants { + println("arithRshuConst failed, wanted", wants, "got", got) + failed = true + } +} + +//go:noinline +func arithRshuConst_ssa() uint64 { + y := uint64(0x8000000000000001) + z := uint64(1) + return uint64(y >> z) +} + +//go:noinline +func arithRshConst_ssa() int64 { + y := int64(-0x8000000000000000) + z := uint64(1) + return int64(y >> z) +} + +//go:noinline +func arithConstShift_ssa(x int64) int64 { + return x >> 100 +} + +// testArithConstShift tests that right shift by large constants preserve +// the sign of the input. +func testArithConstShift() { + want := int64(-1) + if got := arithConstShift_ssa(-1); want != got { + println("arithConstShift_ssa(-1) failed, wanted", want, "got", got) + failed = true + } + want = 0 + if got := arithConstShift_ssa(1); want != got { + println("arithConstShift_ssa(1) failed, wanted", want, "got", got) + failed = true + } +} + +// overflowConstShift_ssa verifes that constant folding for shift +// doesn't wrap (i.e. x << MAX_INT << 1 doesn't get folded to x << 0). +//go:noinline +func overflowConstShift64_ssa(x int64) int64 { + return x << uint64(0xffffffffffffffff) << uint64(1) +} + +//go:noinline +func overflowConstShift32_ssa(x int64) int32 { + return int32(x) << uint32(0xffffffff) << uint32(1) +} + +//go:noinline +func overflowConstShift16_ssa(x int64) int16 { + return int16(x) << uint16(0xffff) << uint16(1) +} + +//go:noinline +func overflowConstShift8_ssa(x int64) int8 { + return int8(x) << uint8(0xff) << uint8(1) +} + +func testOverflowConstShift() { + want := int64(0) + for x := int64(-127); x < int64(127); x++ { + got := overflowConstShift64_ssa(x) + if want != got { + fmt.Printf("overflowShift64 failed, wanted %d got %d\n", want, got) + } + got = int64(overflowConstShift32_ssa(x)) + if want != got { + fmt.Printf("overflowShift32 failed, wanted %d got %d\n", want, got) + } + got = int64(overflowConstShift16_ssa(x)) + if want != got { + fmt.Printf("overflowShift16 failed, wanted %d got %d\n", want, got) + } + got = int64(overflowConstShift8_ssa(x)) + if want != got { + fmt.Printf("overflowShift8 failed, wanted %d got %d\n", want, got) + } + } +} + // test64BitConstMult tests that rewrite rules don't fold 64 bit constants // into multiply instructions. func test64BitConstMult() { @@ -275,6 +371,9 @@ func main() { testLrot() testShiftCX() testSubConst() + testOverflowConstShift() + testArithConstShift() + testArithRshConst() if failed { panic("failed") diff --git a/src/cmd/compile/internal/gc/testdata/gen/arithConstGen.go b/src/cmd/compile/internal/gc/testdata/gen/arithConstGen.go new file mode 100644 index 0000000000..34e54ad08a --- /dev/null +++ b/src/cmd/compile/internal/gc/testdata/gen/arithConstGen.go @@ -0,0 +1,294 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This program generates a test to verify that the standard arithmetic +// operators properly handle const cases. The test file should be +// generated with a known working version of go. +// launch with `go run arithConstGen.go` a file called arithConst_ssa.go +// will be written into the parent directory containing the tests + +package main + +import ( + "bytes" + "fmt" + "go/format" + "io/ioutil" + "log" + "strings" + "text/template" +) + +type op struct { + name, symbol string +} +type szD struct { + name string + sn string + u []uint64 + i []int64 +} + +var szs []szD = []szD{ + szD{name: "uint64", sn: "64", u: []uint64{0, 1, 4294967296, 0xffffFFFFffffFFFF}}, + szD{name: "int64", sn: "64", i: []int64{-0x8000000000000000, -0x7FFFFFFFFFFFFFFF, + -4294967296, -1, 0, 1, 4294967296, 0x7FFFFFFFFFFFFFFE, 0x7FFFFFFFFFFFFFFF}}, + + szD{name: "uint32", sn: "32", u: []uint64{0, 1, 4294967295}}, + szD{name: "int32", sn: "32", i: []int64{-0x80000000, -0x7FFFFFFF, -1, 0, + 1, 0x7FFFFFFF}}, + + szD{name: "uint16", sn: "16", u: []uint64{0, 1, 65535}}, + szD{name: "int16", sn: "16", i: []int64{-32768, -32767, -1, 0, 1, 32766, 32767}}, + + szD{name: "uint8", sn: "8", u: []uint64{0, 1, 255}}, + szD{name: "int8", sn: "8", i: []int64{-128, -127, -1, 0, 1, 126, 127}}, +} + +var ops []op = []op{op{"add", "+"}, op{"sub", "-"}, op{"div", "/"}, op{"mul", "*"}, + op{"lsh", "<<"}, op{"rsh", ">>"}} + +// compute the result of i op j, cast as type t. +func ansU(i, j uint64, t, op string) string { + var ans uint64 + switch op { + case "+": + ans = i + j + case "-": + ans = i - j + case "*": + ans = i * j + case "/": + if j != 0 { + ans = i / j + } + case "<<": + ans = i << j + case ">>": + ans = i >> j + } + switch t { + case "uint32": + ans = uint64(uint32(ans)) + case "uint16": + ans = uint64(uint16(ans)) + case "uint8": + ans = uint64(uint8(ans)) + } + return fmt.Sprintf("%d", ans) +} + +// compute the result of i op j, cast as type t. +func ansS(i, j int64, t, op string) string { + var ans int64 + switch op { + case "+": + ans = i + j + case "-": + ans = i - j + case "*": + ans = i * j + case "/": + if j != 0 { + ans = i / j + } + case "<<": + ans = i << uint64(j) + case ">>": + ans = i >> uint64(j) + } + switch t { + case "int32": + ans = int64(int32(ans)) + case "int16": + ans = int64(int16(ans)) + case "int8": + ans = int64(int8(ans)) + } + return fmt.Sprintf("%d", ans) +} + +func main() { + + w := new(bytes.Buffer) + + fmt.Fprintf(w, "package main;\n") + fmt.Fprintf(w, "import \"fmt\"\n") + + fncCnst1, err := template.New("fnc").Parse( + `//go:noinline + func {{.Name}}_{{.Type_}}_{{.FNumber}}_ssa(a {{.Type_}}) {{.Type_}} { + return a {{.Symbol}} {{.Number}} +} +`) + if err != nil { + panic(err) + } + fncCnst2, err := template.New("fnc").Parse( + `//go:noinline + func {{.Name}}_{{.FNumber}}_{{.Type_}}_ssa(a {{.Type_}}) {{.Type_}} { + return {{.Number}} {{.Symbol}} a +} + +`) + if err != nil { + panic(err) + } + + type fncData struct { + Name, Type_, Symbol, FNumber, Number string + } + + for _, s := range szs { + for _, o := range ops { + fd := fncData{o.name, s.name, o.symbol, "", ""} + + // unsigned test cases + if len(s.u) > 0 { + for _, i := range s.u { + fd.Number = fmt.Sprintf("%d", i) + fd.FNumber = strings.Replace(fd.Number, "-", "Neg", -1) + + // avoid division by zero + if o.name != "div" || i != 0 { + fncCnst1.Execute(w, fd) + } + + fncCnst2.Execute(w, fd) + } + } + + // signed test cases + if len(s.i) > 0 { + // don't generate tests for shifts by signed integers + if o.name == "lsh" || o.name == "rsh" { + continue + } + for _, i := range s.i { + fd.Number = fmt.Sprintf("%d", i) + fd.FNumber = strings.Replace(fd.Number, "-", "Neg", -1) + + // avoid division by zero + if o.name != "div" || i != 0 { + fncCnst1.Execute(w, fd) + } + fncCnst2.Execute(w, fd) + } + } + } + } + + fmt.Fprintf(w, "var failed bool\n\n") + fmt.Fprintf(w, "func main() {\n\n") + + vrf1, _ := template.New("vrf1").Parse(` + if got := {{.Name}}_{{.FNumber}}_{{.Type_}}_ssa({{.Input}}); got != {{.Ans}} { + fmt.Printf("{{.Name}}_{{.Type_}} {{.Number}}{{.Symbol}}{{.Input}} = %d, wanted {{.Ans}}\n",got) + failed = true + } +`) + + vrf2, _ := template.New("vrf2").Parse(` + if got := {{.Name}}_{{.Type_}}_{{.FNumber}}_ssa({{.Input}}); got != {{.Ans}} { + fmt.Printf("{{.Name}}_{{.Type_}} {{.Input}}{{.Symbol}}{{.Number}} = %d, wanted {{.Ans}}\n",got) + failed = true + } +`) + + type cfncData struct { + Name, Type_, Symbol, FNumber, Number string + Ans, Input string + } + for _, s := range szs { + if len(s.u) > 0 { + for _, o := range ops { + fd := cfncData{o.name, s.name, o.symbol, "", "", "", ""} + for _, i := range s.u { + fd.Number = fmt.Sprintf("%d", i) + fd.FNumber = strings.Replace(fd.Number, "-", "Neg", -1) + + // unsigned + for _, j := range s.u { + + if o.name != "div" || j != 0 { + fd.Ans = ansU(i, j, s.name, o.symbol) + fd.Input = fmt.Sprintf("%d", j) + err = vrf1.Execute(w, fd) + if err != nil { + panic(err) + } + } + + if o.name != "div" || i != 0 { + fd.Ans = ansU(j, i, s.name, o.symbol) + fd.Input = fmt.Sprintf("%d", j) + err = vrf2.Execute(w, fd) + if err != nil { + panic(err) + } + } + + } + } + + } + } + + // signed + if len(s.i) > 0 { + for _, o := range ops { + // don't generate tests for shifts by signed integers + if o.name == "lsh" || o.name == "rsh" { + continue + } + fd := cfncData{o.name, s.name, o.symbol, "", "", "", ""} + for _, i := range s.i { + fd.Number = fmt.Sprintf("%d", i) + fd.FNumber = strings.Replace(fd.Number, "-", "Neg", -1) + for _, j := range s.i { + if o.name != "div" || j != 0 { + fd.Ans = ansS(i, j, s.name, o.symbol) + fd.Input = fmt.Sprintf("%d", j) + err = vrf1.Execute(w, fd) + if err != nil { + panic(err) + } + } + + if o.name != "div" || i != 0 { + fd.Ans = ansS(j, i, s.name, o.symbol) + fd.Input = fmt.Sprintf("%d", j) + err = vrf2.Execute(w, fd) + if err != nil { + panic(err) + } + } + + } + } + + } + } + } + + fmt.Fprintf(w, `if failed { + panic("tests failed") + } +`) + fmt.Fprintf(w, "}\n") + + // gofmt result + b := w.Bytes() + src, err := format.Source(b) + if err != nil { + fmt.Printf("%s\n", b) + panic(err) + } + + // write to file + err = ioutil.WriteFile("../arithConst_ssa.go", src, 0666) + if err != nil { + log.Fatalf("can't write output: %v\n", err) + } +} diff --git a/src/cmd/compile/internal/ssa/gen/generic.rules b/src/cmd/compile/internal/ssa/gen/generic.rules index 658d78ca32..28fe9ff878 100644 --- a/src/cmd/compile/internal/ssa/gen/generic.rules +++ b/src/cmd/compile/internal/ssa/gen/generic.rules @@ -35,6 +35,19 @@ (Mul32 (Const32 [c]) (Const32 [d])) -> (Const32 [c*d]) (Mul64 (Const64 [c]) (Const64 [d])) -> (Const64 [c*d]) +(Lsh64x64 (Const64 [c]) (Const64 [d])) -> (Const64 [c << uint64(d)]) +(Rsh64x64 (Const64 [c]) (Const64 [d])) -> (Const64 [c >> uint64(d)]) +(Rsh64Ux64 (Const64 [c]) (Const64 [d])) -> (Const64 [int64(uint64(c) >> uint64(d))]) +(Lsh32x64 (Const32 [c]) (Const64 [d])) -> (Const32 [int64(int32(c) << uint64(d))]) +(Rsh32x64 (Const32 [c]) (Const64 [d])) -> (Const32 [int64(int32(c) >> uint64(d))]) +(Rsh32Ux64 (Const32 [c]) (Const64 [d])) -> (Const32 [int64(uint32(c) >> uint64(d))]) +(Lsh16x64 (Const16 [c]) (Const64 [d])) -> (Const16 [int64(int16(c) << uint64(d))]) +(Rsh16x64 (Const16 [c]) (Const64 [d])) -> (Const16 [int64(int16(c) >> uint64(d))]) +(Rsh16Ux64 (Const16 [c]) (Const64 [d])) -> (Const16 [int64(uint16(c) >> uint64(d))]) +(Lsh8x64 (Const8 [c]) (Const64 [d])) -> (Const8 [int64(int8(c) << uint64(d))]) +(Rsh8x64 (Const8 [c]) (Const64 [d])) -> (Const8 [int64(int8(c) >> uint64(d))]) +(Rsh8Ux64 (Const8 [c]) (Const64 [d])) -> (Const8 [int64(uint8(c) >> uint64(d))]) + (IsInBounds (Const32 [c]) (Const32 [d])) -> (ConstBool [b2i(inBounds32(c,d))]) (IsInBounds (Const64 [c]) (Const64 [d])) -> (ConstBool [b2i(inBounds64(c,d))]) (IsSliceInBounds (Const32 [c]) (Const32 [d])) -> (ConstBool [b2i(sliceInBounds32(c,d))]) @@ -79,6 +92,89 @@ (Sub16 x (Const16 [c])) && x.Op != OpConst16 -> (Add16 (Const16 [-c]) x) (Sub8 x (Const8 [c])) && x.Op != OpConst8 -> (Add8 (Const8 [-c]) x) +// rewrite shifts of 8/16/32 bit consts into 64 bit consts to reduce +// the number of the other rewrite rules for const shifts +(Lsh64x32 x (Const32 [c])) -> (Lsh64x64 x (Const64 [int64(uint32(c))])) +(Lsh64x16 x (Const16 [c])) -> (Lsh64x64 x (Const64 [int64(uint16(c))])) +(Lsh64x8 x (Const8 [c])) -> (Lsh64x64 x (Const64 [int64(uint8(c))])) +(Rsh64x32 x (Const32 [c])) -> (Rsh64x64 x (Const64 [int64(uint32(c))])) +(Rsh64x16 x (Const16 [c])) -> (Rsh64x64 x (Const64 [int64(uint16(c))])) +(Rsh64x8 x (Const8 [c])) -> (Rsh64x64 x (Const64 [int64(uint8(c))])) +(Rsh64Ux32 x (Const32 [c])) -> (Rsh64Ux64 x (Const64 [int64(uint32(c))])) +(Rsh64Ux16 x (Const16 [c])) -> (Rsh64Ux64 x (Const64 [int64(uint16(c))])) +(Rsh64Ux8 x (Const8 [c])) -> (Rsh64Ux64 x (Const64 [int64(uint8(c))])) + +(Lsh32x32 x (Const32 [c])) -> (Lsh32x64 x (Const64 [int64(uint32(c))])) +(Lsh32x16 x (Const16 [c])) -> (Lsh32x64 x (Const64 [int64(uint16(c))])) +(Lsh32x8 x (Const8 [c])) -> (Lsh32x64 x (Const64 [int64(uint8(c))])) +(Rsh32x32 x (Const32 [c])) -> (Rsh32x64 x (Const64 [int64(uint32(c))])) +(Rsh32x16 x (Const16 [c])) -> (Rsh32x64 x (Const64 [int64(uint16(c))])) +(Rsh32x8 x (Const8 [c])) -> (Rsh32x64 x (Const64 [int64(uint8(c))])) +(Rsh32Ux32 x (Const32 [c])) -> (Rsh32Ux64 x (Const64 [int64(uint32(c))])) +(Rsh32Ux16 x (Const16 [c])) -> (Rsh32Ux64 x (Const64 [int64(uint16(c))])) +(Rsh32Ux8 x (Const8 [c])) -> (Rsh32Ux64 x (Const64 [int64(uint8(c))])) + +(Lsh16x32 x (Const32 [c])) -> (Lsh16x64 x (Const64 [int64(uint32(c))])) +(Lsh16x16 x (Const16 [c])) -> (Lsh16x64 x (Const64 [int64(uint16(c))])) +(Lsh16x8 x (Const8 [c])) -> (Lsh16x64 x (Const64 [int64(uint8(c))])) +(Rsh16x32 x (Const32 [c])) -> (Rsh16x64 x (Const64 [int64(uint32(c))])) +(Rsh16x16 x (Const16 [c])) -> (Rsh16x64 x (Const64 [int64(uint16(c))])) +(Rsh16x8 x (Const8 [c])) -> (Rsh16x64 x (Const64 [int64(uint8(c))])) +(Rsh16Ux32 x (Const32 [c])) -> (Rsh16Ux64 x (Const64 [int64(uint32(c))])) +(Rsh16Ux16 x (Const16 [c])) -> (Rsh16Ux64 x (Const64 [int64(uint16(c))])) +(Rsh16Ux8 x (Const8 [c])) -> (Rsh16Ux64 x (Const64 [int64(uint8(c))])) + +(Lsh8x32 x (Const32 [c])) -> (Lsh8x64 x (Const64 [int64(uint32(c))])) +(Lsh8x16 x (Const16 [c])) -> (Lsh8x64 x (Const64 [int64(uint16(c))])) +(Lsh8x8 x (Const8 [c])) -> (Lsh8x64 x (Const64 [int64(uint8(c))])) +(Rsh8x32 x (Const32 [c])) -> (Rsh8x64 x (Const64 [int64(uint32(c))])) +(Rsh8x16 x (Const16 [c])) -> (Rsh8x64 x (Const64 [int64(uint16(c))])) +(Rsh8x8 x (Const8 [c])) -> (Rsh8x64 x (Const64 [int64(uint8(c))])) +(Rsh8Ux32 x (Const32 [c])) -> (Rsh8Ux64 x (Const64 [int64(uint32(c))])) +(Rsh8Ux16 x (Const16 [c])) -> (Rsh8Ux64 x (Const64 [int64(uint16(c))])) +(Rsh8Ux8 x (Const8 [c])) -> (Rsh8Ux64 x (Const64 [int64(uint8(c))])) + +// shifts by zero +(Lsh64x64 x (Const64 [0])) -> x +(Rsh64x64 x (Const64 [0])) -> x +(Rsh64Ux64 x (Const64 [0])) -> x +(Lsh32x64 x (Const64 [0])) -> x +(Rsh32x64 x (Const64 [0])) -> x +(Rsh32Ux64 x (Const64 [0])) -> x +(Lsh16x64 x (Const64 [0])) -> x +(Rsh16x64 x (Const64 [0])) -> x +(Rsh16Ux64 x (Const64 [0])) -> x +(Lsh8x64 x (Const64 [0])) -> x +(Rsh8x64 x (Const64 [0])) -> x +(Rsh8Ux64 x (Const64 [0])) -> x + +// large left shifts of all values, and right shifts of unsigned values +(Lsh64x64 _ (Const64 [c])) && uint64(c) >= 64 -> (Const64 [0]) +(Rsh64Ux64 _ (Const64 [c])) && uint64(c) >= 64 -> (Const64 [0]) +(Lsh32x64 _ (Const64 [c])) && uint64(c) >= 32 -> (Const64 [0]) +(Rsh32Ux64 _ (Const64 [c])) && uint64(c) >= 32 -> (Const64 [0]) +(Lsh16x64 _ (Const64 [c])) && uint64(c) >= 16 -> (Const64 [0]) +(Rsh16Ux64 _ (Const64 [c])) && uint64(c) >= 16 -> (Const64 [0]) +(Lsh8x64 _ (Const64 [c])) && uint64(c) >= 8 -> (Const64 [0]) +(Rsh8Ux64 _ (Const64 [c])) && uint64(c) >= 8 -> (Const64 [0]) + + +// combine const shifts +(Lsh64x64 (Lsh64x64 x (Const64 [c])) (Const64 [d])) && !uaddOvf(c,d) -> (Lsh64x64 x (Const64 [c+d])) +(Lsh32x64 (Lsh32x64 x (Const64 [c])) (Const64 [d])) && !uaddOvf(c,d) -> (Lsh32x64 x (Const64 [c+d])) +(Lsh16x64 (Lsh16x64 x (Const64 [c])) (Const64 [d])) && !uaddOvf(c,d) -> (Lsh16x64 x (Const64 [c+d])) +(Lsh8x64 (Lsh8x64 x (Const64 [c])) (Const64 [d])) && !uaddOvf(c,d) -> (Lsh8x64 x (Const64 [c+d])) + +(Rsh64x64 (Rsh64x64 x (Const64 [c])) (Const64 [d])) && !uaddOvf(c,d) -> (Rsh64x64 x (Const64 [c+d])) +(Rsh32x64 (Rsh32x64 x (Const64 [c])) (Const64 [d])) && !uaddOvf(c,d) -> (Rsh32x64 x (Const64 [c+d])) +(Rsh16x64 (Rsh16x64 x (Const64 [c])) (Const64 [d])) && !uaddOvf(c,d) -> (Rsh16x64 x (Const64 [c+d])) +(Rsh8x64 (Rsh8x64 x (Const64 [c])) (Const64 [d])) && !uaddOvf(c,d) -> (Rsh8x64 x (Const64 [c+d])) + +(Rsh64Ux64 (Rsh64Ux64 x (Const64 [c])) (Const64 [d])) && !uaddOvf(c,d) -> (Rsh64Ux64 x (Const64 [c+d])) +(Rsh32Ux64 (Rsh32Ux64 x (Const64 [c])) (Const64 [d])) && !uaddOvf(c,d) -> (Rsh32Ux64 x (Const64 [c+d])) +(Rsh16Ux64 (Rsh16Ux64 x (Const64 [c])) (Const64 [d])) && !uaddOvf(c,d) -> (Rsh16Ux64 x (Const64 [c+d])) +(Rsh8Ux64 (Rsh8Ux64 x (Const64 [c])) (Const64 [d])) && !uaddOvf(c,d) -> (Rsh8Ux64 x (Const64 [c+d])) + // constant comparisons (Eq64 (Const64 [c]) (Const64 [d])) -> (ConstBool [b2i(int64(c) == int64(d))]) (Eq32 (Const32 [c]) (Const32 [d])) -> (ConstBool [b2i(int32(c) == int32(d))]) diff --git a/src/cmd/compile/internal/ssa/rewrite.go b/src/cmd/compile/internal/ssa/rewrite.go index f7da347263..7dd0d2e5d5 100644 --- a/src/cmd/compile/internal/ssa/rewrite.go +++ b/src/cmd/compile/internal/ssa/rewrite.go @@ -181,6 +181,11 @@ func f2i(f float64) int64 { return int64(math.Float64bits(f)) } +// uaddOvf returns true if unsigned a+b would overflow. +func uaddOvf(a, b int64) bool { + return uint64(a)+uint64(b) < uint64(a) +} + // DUFFZERO consists of repeated blocks of 4 MOVUPSs + ADD, // See runtime/mkduff.go. const ( diff --git a/src/cmd/compile/internal/ssa/rewritegeneric.go b/src/cmd/compile/internal/ssa/rewritegeneric.go index b9e4d186e9..67f07e65dc 100644 --- a/src/cmd/compile/internal/ssa/rewritegeneric.go +++ b/src/cmd/compile/internal/ssa/rewritegeneric.go @@ -135,6 +135,38 @@ func rewriteValuegeneric(v *Value, config *Config) bool { return rewriteValuegeneric_OpLess8U(v, config) case OpLoad: return rewriteValuegeneric_OpLoad(v, config) + case OpLsh16x16: + return rewriteValuegeneric_OpLsh16x16(v, config) + case OpLsh16x32: + return rewriteValuegeneric_OpLsh16x32(v, config) + case OpLsh16x64: + return rewriteValuegeneric_OpLsh16x64(v, config) + case OpLsh16x8: + return rewriteValuegeneric_OpLsh16x8(v, config) + case OpLsh32x16: + return rewriteValuegeneric_OpLsh32x16(v, config) + case OpLsh32x32: + return rewriteValuegeneric_OpLsh32x32(v, config) + case OpLsh32x64: + return rewriteValuegeneric_OpLsh32x64(v, config) + case OpLsh32x8: + return rewriteValuegeneric_OpLsh32x8(v, config) + case OpLsh64x16: + return rewriteValuegeneric_OpLsh64x16(v, config) + case OpLsh64x32: + return rewriteValuegeneric_OpLsh64x32(v, config) + case OpLsh64x64: + return rewriteValuegeneric_OpLsh64x64(v, config) + case OpLsh64x8: + return rewriteValuegeneric_OpLsh64x8(v, config) + case OpLsh8x16: + return rewriteValuegeneric_OpLsh8x16(v, config) + case OpLsh8x32: + return rewriteValuegeneric_OpLsh8x32(v, config) + case OpLsh8x64: + return rewriteValuegeneric_OpLsh8x64(v, config) + case OpLsh8x8: + return rewriteValuegeneric_OpLsh8x8(v, config) case OpMul16: return rewriteValuegeneric_OpMul16(v, config) case OpMul32: @@ -167,6 +199,70 @@ func rewriteValuegeneric(v *Value, config *Config) bool { return rewriteValuegeneric_OpOr8(v, config) case OpPtrIndex: return rewriteValuegeneric_OpPtrIndex(v, config) + case OpRsh16Ux16: + return rewriteValuegeneric_OpRsh16Ux16(v, config) + case OpRsh16Ux32: + return rewriteValuegeneric_OpRsh16Ux32(v, config) + case OpRsh16Ux64: + return rewriteValuegeneric_OpRsh16Ux64(v, config) + case OpRsh16Ux8: + return rewriteValuegeneric_OpRsh16Ux8(v, config) + case OpRsh16x16: + return rewriteValuegeneric_OpRsh16x16(v, config) + case OpRsh16x32: + return rewriteValuegeneric_OpRsh16x32(v, config) + case OpRsh16x64: + return rewriteValuegeneric_OpRsh16x64(v, config) + case OpRsh16x8: + return rewriteValuegeneric_OpRsh16x8(v, config) + case OpRsh32Ux16: + return rewriteValuegeneric_OpRsh32Ux16(v, config) + case OpRsh32Ux32: + return rewriteValuegeneric_OpRsh32Ux32(v, config) + case OpRsh32Ux64: + return rewriteValuegeneric_OpRsh32Ux64(v, config) + case OpRsh32Ux8: + return rewriteValuegeneric_OpRsh32Ux8(v, config) + case OpRsh32x16: + return rewriteValuegeneric_OpRsh32x16(v, config) + case OpRsh32x32: + return rewriteValuegeneric_OpRsh32x32(v, config) + case OpRsh32x64: + return rewriteValuegeneric_OpRsh32x64(v, config) + case OpRsh32x8: + return rewriteValuegeneric_OpRsh32x8(v, config) + case OpRsh64Ux16: + return rewriteValuegeneric_OpRsh64Ux16(v, config) + case OpRsh64Ux32: + return rewriteValuegeneric_OpRsh64Ux32(v, config) + case OpRsh64Ux64: + return rewriteValuegeneric_OpRsh64Ux64(v, config) + case OpRsh64Ux8: + return rewriteValuegeneric_OpRsh64Ux8(v, config) + case OpRsh64x16: + return rewriteValuegeneric_OpRsh64x16(v, config) + case OpRsh64x32: + return rewriteValuegeneric_OpRsh64x32(v, config) + case OpRsh64x64: + return rewriteValuegeneric_OpRsh64x64(v, config) + case OpRsh64x8: + return rewriteValuegeneric_OpRsh64x8(v, config) + case OpRsh8Ux16: + return rewriteValuegeneric_OpRsh8Ux16(v, config) + case OpRsh8Ux32: + return rewriteValuegeneric_OpRsh8Ux32(v, config) + case OpRsh8Ux64: + return rewriteValuegeneric_OpRsh8Ux64(v, config) + case OpRsh8Ux8: + return rewriteValuegeneric_OpRsh8Ux8(v, config) + case OpRsh8x16: + return rewriteValuegeneric_OpRsh8x16(v, config) + case OpRsh8x32: + return rewriteValuegeneric_OpRsh8x32(v, config) + case OpRsh8x64: + return rewriteValuegeneric_OpRsh8x64(v, config) + case OpRsh8x8: + return rewriteValuegeneric_OpRsh8x8(v, config) case OpSliceCap: return rewriteValuegeneric_OpSliceCap(v, config) case OpSliceLen: @@ -242,8 +338,7 @@ end359c546ef662b7990116329cb30d6892: v.AuxInt = 0 v.Aux = nil v.resetArgs() - v0 := b.NewValue0(v.Line, OpConst16, TypeInvalid) - v0.Type = t + v0 := b.NewValue0(v.Line, OpConst16, t) v0.AuxInt = c v.AddArg(v0) v.AddArg(x) @@ -296,8 +391,7 @@ enda3edaa9a512bd1d7a95f002c890bfb88: v.AuxInt = 0 v.Aux = nil v.resetArgs() - v0 := b.NewValue0(v.Line, OpConst32, TypeInvalid) - v0.Type = t + v0 := b.NewValue0(v.Line, OpConst32, t) v0.AuxInt = c v.AddArg(v0) v.AddArg(x) @@ -350,8 +444,7 @@ end8c46df6f85a11cb1d594076b0e467908: v.AuxInt = 0 v.Aux = nil v.resetArgs() - v0 := b.NewValue0(v.Line, OpConst64, TypeInvalid) - v0.Type = t + v0 := b.NewValue0(v.Line, OpConst64, t) v0.AuxInt = c v.AddArg(v0) v.AddArg(x) @@ -404,8 +497,7 @@ end60c66721511a442aade8e4da2fb326bd: v.AuxInt = 0 v.Aux = nil v.resetArgs() - v0 := b.NewValue0(v.Line, OpConst8, TypeInvalid) - v0.Type = t + v0 := b.NewValue0(v.Line, OpConst8, t) v0.AuxInt = c v.AddArg(v0) v.AddArg(x) @@ -1234,8 +1326,7 @@ end0c0fe5fdfba3821add3448fd3f1fc6b7: v.AuxInt = 0 v.Aux = nil v.resetArgs() - v0 := b.NewValue0(v.Line, OpConst16, TypeInvalid) - v0.Type = t + v0 := b.NewValue0(v.Line, OpConst16, t) v0.AuxInt = c - d v.AddArg(v0) v.AddArg(x) @@ -1261,8 +1352,7 @@ end79c830afa265161fc0f0532c4c4e7f50: v.AuxInt = 0 v.Aux = nil v.resetArgs() - v0 := b.NewValue0(v.Line, OpConst16, TypeInvalid) - v0.Type = t + v0 := b.NewValue0(v.Line, OpConst16, t) v0.AuxInt = c v.AddArg(v0) v.AddArg(x) @@ -1340,8 +1430,7 @@ end6da547ec4ee93d787434f3bda873e4a0: v.AuxInt = 0 v.Aux = nil v.resetArgs() - v0 := b.NewValue0(v.Line, OpConst32, TypeInvalid) - v0.Type = t + v0 := b.NewValue0(v.Line, OpConst32, t) v0.AuxInt = c - d v.AddArg(v0) v.AddArg(x) @@ -1367,8 +1456,7 @@ end1a69730a32c6e432784dcdf643320ecd: v.AuxInt = 0 v.Aux = nil v.resetArgs() - v0 := b.NewValue0(v.Line, OpConst32, TypeInvalid) - v0.Type = t + v0 := b.NewValue0(v.Line, OpConst32, t) v0.AuxInt = c v.AddArg(v0) v.AddArg(x) @@ -1446,8 +1534,7 @@ endb1d471cc503ba8bb05440f01dbf33d81: v.AuxInt = 0 v.Aux = nil v.resetArgs() - v0 := b.NewValue0(v.Line, OpConst64, TypeInvalid) - v0.Type = t + v0 := b.NewValue0(v.Line, OpConst64, t) v0.AuxInt = c - d v.AddArg(v0) v.AddArg(x) @@ -1473,8 +1560,7 @@ endffd67f3b83f6972cd459153d318f714d: v.AuxInt = 0 v.Aux = nil v.resetArgs() - v0 := b.NewValue0(v.Line, OpConst64, TypeInvalid) - v0.Type = t + v0 := b.NewValue0(v.Line, OpConst64, t) v0.AuxInt = c v.AddArg(v0) v.AddArg(x) @@ -1552,8 +1638,7 @@ enda66da0d3e7e51624ee46527727c48a9a: v.AuxInt = 0 v.Aux = nil v.resetArgs() - v0 := b.NewValue0(v.Line, OpConst8, TypeInvalid) - v0.Type = t + v0 := b.NewValue0(v.Line, OpConst8, t) v0.AuxInt = c - d v.AddArg(v0) v.AddArg(x) @@ -1579,8 +1664,7 @@ end6912961350bb485f56ef176522aa683b: v.AuxInt = 0 v.Aux = nil v.resetArgs() - v0 := b.NewValue0(v.Line, OpConst8, TypeInvalid) - v0.Type = t + v0 := b.NewValue0(v.Line, OpConst8, t) v0.AuxInt = c v.AddArg(v0) v.AddArg(x) @@ -3033,713 +3117,2861 @@ end12671c83ebe3ccbc8e53383765ee7675: ; return false } -func rewriteValuegeneric_OpMul16(v *Value, config *Config) bool { +func rewriteValuegeneric_OpLsh16x16(v *Value, config *Config) bool { b := v.Block _ = b - // match: (Mul16 (Const16 [c]) (Const16 [d])) + // match: (Lsh16x16 x (Const16 [c])) // cond: - // result: (Const16 [c*d]) + // result: (Lsh16x64 x (Const64 [int64(uint16(c))])) { - if v.Args[0].Op != OpConst16 { - goto ende8dd468add3015aea24531cf3c89ccb7 - } - c := v.Args[0].AuxInt + t := v.Type + x := v.Args[0] if v.Args[1].Op != OpConst16 { - goto ende8dd468add3015aea24531cf3c89ccb7 + goto end2f5aa78b30ebd2471e8d03a307923b06 } - d := v.Args[1].AuxInt - v.Op = OpConst16 + c := v.Args[1].AuxInt + v.Op = OpLsh16x64 v.AuxInt = 0 v.Aux = nil v.resetArgs() - v.AuxInt = c * d + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpConst64, t) + v0.AuxInt = int64(uint16(c)) + v.AddArg(v0) return true } - goto ende8dd468add3015aea24531cf3c89ccb7 -ende8dd468add3015aea24531cf3c89ccb7: + goto end2f5aa78b30ebd2471e8d03a307923b06 +end2f5aa78b30ebd2471e8d03a307923b06: ; return false } -func rewriteValuegeneric_OpMul32(v *Value, config *Config) bool { +func rewriteValuegeneric_OpLsh16x32(v *Value, config *Config) bool { b := v.Block _ = b - // match: (Mul32 (Const32 [c]) (Const32 [d])) + // match: (Lsh16x32 x (Const32 [c])) // cond: - // result: (Const32 [c*d]) + // result: (Lsh16x64 x (Const64 [int64(uint32(c))])) { - if v.Args[0].Op != OpConst32 { - goto end60b4523099fa7b55e2e872e05bd497a7 - } - c := v.Args[0].AuxInt + t := v.Type + x := v.Args[0] if v.Args[1].Op != OpConst32 { - goto end60b4523099fa7b55e2e872e05bd497a7 + goto endedeb000c8c97090261a47f08a2ff17e4 } - d := v.Args[1].AuxInt - v.Op = OpConst32 + c := v.Args[1].AuxInt + v.Op = OpLsh16x64 v.AuxInt = 0 v.Aux = nil v.resetArgs() - v.AuxInt = c * d + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpConst64, t) + v0.AuxInt = int64(uint32(c)) + v.AddArg(v0) return true } - goto end60b4523099fa7b55e2e872e05bd497a7 -end60b4523099fa7b55e2e872e05bd497a7: + goto endedeb000c8c97090261a47f08a2ff17e4 +endedeb000c8c97090261a47f08a2ff17e4: ; return false } -func rewriteValuegeneric_OpMul64(v *Value, config *Config) bool { +func rewriteValuegeneric_OpLsh16x64(v *Value, config *Config) bool { b := v.Block _ = b - // match: (Mul64 (Const64 [c]) (Const64 [d])) + // match: (Lsh16x64 (Const16 [c]) (Const64 [d])) // cond: - // result: (Const64 [c*d]) + // result: (Const16 [int64(int16(c) << uint64(d))]) { - if v.Args[0].Op != OpConst64 { - goto end7aea1048b5d1230974b97f17238380ae + if v.Args[0].Op != OpConst16 { + goto endc9f0d91f3da4bdd46a634a62549810e0 } c := v.Args[0].AuxInt if v.Args[1].Op != OpConst64 { - goto end7aea1048b5d1230974b97f17238380ae + goto endc9f0d91f3da4bdd46a634a62549810e0 } d := v.Args[1].AuxInt - v.Op = OpConst64 + v.Op = OpConst16 v.AuxInt = 0 v.Aux = nil v.resetArgs() - v.AuxInt = c * d + v.AuxInt = int64(int16(c) << uint64(d)) return true } - goto end7aea1048b5d1230974b97f17238380ae -end7aea1048b5d1230974b97f17238380ae: + goto endc9f0d91f3da4bdd46a634a62549810e0 +endc9f0d91f3da4bdd46a634a62549810e0: ; - return false -} -func rewriteValuegeneric_OpMul8(v *Value, config *Config) bool { - b := v.Block - _ = b - // match: (Mul8 (Const8 [c]) (Const8 [d])) + // match: (Lsh16x64 x (Const64 [0])) // cond: - // result: (Const8 [c*d]) + // result: x { - if v.Args[0].Op != OpConst8 { - goto end2f1952fd654c4a62ff00511041728809 + x := v.Args[0] + if v.Args[1].Op != OpConst64 { + goto end7ecc343739fab9b50a0bdff6e9d121e6 } - c := v.Args[0].AuxInt - if v.Args[1].Op != OpConst8 { - goto end2f1952fd654c4a62ff00511041728809 + if v.Args[1].AuxInt != 0 { + goto end7ecc343739fab9b50a0bdff6e9d121e6 } - d := v.Args[1].AuxInt - v.Op = OpConst8 + v.Op = OpCopy v.AuxInt = 0 v.Aux = nil v.resetArgs() - v.AuxInt = c * d + v.Type = x.Type + v.AddArg(x) return true } - goto end2f1952fd654c4a62ff00511041728809 -end2f1952fd654c4a62ff00511041728809: + goto end7ecc343739fab9b50a0bdff6e9d121e6 +end7ecc343739fab9b50a0bdff6e9d121e6: ; - return false -} -func rewriteValuegeneric_OpNeq16(v *Value, config *Config) bool { - b := v.Block - _ = b - // match: (Neq16 x x) - // cond: - // result: (ConstBool [0]) + // match: (Lsh16x64 _ (Const64 [c])) + // cond: uint64(c) >= 16 + // result: (Const64 [0]) { - x := v.Args[0] - if v.Args[1] != x { - goto ende76a50b524aeb16c7aeccf5f5cc60c06 + if v.Args[1].Op != OpConst64 { + goto end1d2c74d359df9d89b16c4f658a231dfe } - v.Op = OpConstBool + c := v.Args[1].AuxInt + if !(uint64(c) >= 16) { + goto end1d2c74d359df9d89b16c4f658a231dfe + } + v.Op = OpConst64 v.AuxInt = 0 v.Aux = nil v.resetArgs() v.AuxInt = 0 return true } - goto ende76a50b524aeb16c7aeccf5f5cc60c06 -ende76a50b524aeb16c7aeccf5f5cc60c06: + goto end1d2c74d359df9d89b16c4f658a231dfe +end1d2c74d359df9d89b16c4f658a231dfe: ; - // match: (Neq16 (Const16 [c]) (Add16 (Const16 [d]) x)) - // cond: - // result: (Neq16 (Const16 [c-d]) x) + // match: (Lsh16x64 (Lsh16x64 x (Const64 [c])) (Const64 [d])) + // cond: !uaddOvf(c,d) + // result: (Lsh16x64 x (Const64 [c+d])) { - if v.Args[0].Op != OpConst16 { - goto end552011bd97e6f92ebc2672aa1843eadd + t := v.Type + if v.Args[0].Op != OpLsh16x64 { + goto end26a91e42735a02a30e94a998f54372dd } - t := v.Args[0].Type - c := v.Args[0].AuxInt - if v.Args[1].Op != OpAdd16 { - goto end552011bd97e6f92ebc2672aa1843eadd + x := v.Args[0].Args[0] + if v.Args[0].Args[1].Op != OpConst64 { + goto end26a91e42735a02a30e94a998f54372dd } - if v.Args[1].Args[0].Op != OpConst16 { - goto end552011bd97e6f92ebc2672aa1843eadd + c := v.Args[0].Args[1].AuxInt + if v.Args[1].Op != OpConst64 { + goto end26a91e42735a02a30e94a998f54372dd } - if v.Args[1].Args[0].Type != v.Args[0].Type { - goto end552011bd97e6f92ebc2672aa1843eadd + d := v.Args[1].AuxInt + if !(!uaddOvf(c, d)) { + goto end26a91e42735a02a30e94a998f54372dd } - d := v.Args[1].Args[0].AuxInt - x := v.Args[1].Args[1] - v.Op = OpNeq16 + v.Op = OpLsh16x64 v.AuxInt = 0 v.Aux = nil v.resetArgs() - v0 := b.NewValue0(v.Line, OpConst16, TypeInvalid) - v0.Type = t - v0.AuxInt = c - d - v.AddArg(v0) v.AddArg(x) + v0 := b.NewValue0(v.Line, OpConst64, t) + v0.AuxInt = c + d + v.AddArg(v0) return true } - goto end552011bd97e6f92ebc2672aa1843eadd -end552011bd97e6f92ebc2672aa1843eadd: + goto end26a91e42735a02a30e94a998f54372dd +end26a91e42735a02a30e94a998f54372dd: ; - // match: (Neq16 x (Const16 [c])) - // cond: x.Op != OpConst16 - // result: (Neq16 (Const16 [c]) x) + return false +} +func rewriteValuegeneric_OpLsh16x8(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Lsh16x8 x (Const8 [c])) + // cond: + // result: (Lsh16x64 x (Const64 [int64(uint8(c))])) { + t := v.Type x := v.Args[0] - if v.Args[1].Op != OpConst16 { - goto end0e45958f29e87997f632248aa9ee97e0 + if v.Args[1].Op != OpConst8 { + goto endce2401b8a6c6190fe81d77e2d562a10c } - t := v.Args[1].Type c := v.Args[1].AuxInt - if !(x.Op != OpConst16) { - goto end0e45958f29e87997f632248aa9ee97e0 - } - v.Op = OpNeq16 + v.Op = OpLsh16x64 v.AuxInt = 0 v.Aux = nil v.resetArgs() - v0 := b.NewValue0(v.Line, OpConst16, TypeInvalid) - v0.Type = t - v0.AuxInt = c - v.AddArg(v0) v.AddArg(x) + v0 := b.NewValue0(v.Line, OpConst64, t) + v0.AuxInt = int64(uint8(c)) + v.AddArg(v0) return true } - goto end0e45958f29e87997f632248aa9ee97e0 -end0e45958f29e87997f632248aa9ee97e0: + goto endce2401b8a6c6190fe81d77e2d562a10c +endce2401b8a6c6190fe81d77e2d562a10c: ; - // match: (Neq16 (Const16 [c]) (Const16 [d])) + return false +} +func rewriteValuegeneric_OpLsh32x16(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Lsh32x16 x (Const16 [c])) // cond: - // result: (ConstBool [b2i(int16(c) != int16(d))]) + // result: (Lsh32x64 x (Const64 [int64(uint16(c))])) { - if v.Args[0].Op != OpConst16 { - goto end6302c9b645bb191982d28c2f846904d6 - } - c := v.Args[0].AuxInt + t := v.Type + x := v.Args[0] if v.Args[1].Op != OpConst16 { - goto end6302c9b645bb191982d28c2f846904d6 + goto end7205eb3e315971143ac5584d07045570 } - d := v.Args[1].AuxInt - v.Op = OpConstBool + c := v.Args[1].AuxInt + v.Op = OpLsh32x64 v.AuxInt = 0 v.Aux = nil v.resetArgs() - v.AuxInt = b2i(int16(c) != int16(d)) + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpConst64, t) + v0.AuxInt = int64(uint16(c)) + v.AddArg(v0) return true } - goto end6302c9b645bb191982d28c2f846904d6 -end6302c9b645bb191982d28c2f846904d6: + goto end7205eb3e315971143ac5584d07045570 +end7205eb3e315971143ac5584d07045570: ; return false } -func rewriteValuegeneric_OpNeq32(v *Value, config *Config) bool { +func rewriteValuegeneric_OpLsh32x32(v *Value, config *Config) bool { b := v.Block _ = b - // match: (Neq32 x x) + // match: (Lsh32x32 x (Const32 [c])) // cond: - // result: (ConstBool [0]) + // result: (Lsh32x64 x (Const64 [int64(uint32(c))])) { + t := v.Type x := v.Args[0] - if v.Args[1] != x { - goto end3713a608cffd29b40ff7c3b3f2585cbb + if v.Args[1].Op != OpConst32 { + goto endc1a330b287199c80228e665a53881298 } - v.Op = OpConstBool + c := v.Args[1].AuxInt + v.Op = OpLsh32x64 v.AuxInt = 0 v.Aux = nil v.resetArgs() - v.AuxInt = 0 + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpConst64, t) + v0.AuxInt = int64(uint32(c)) + v.AddArg(v0) return true } - goto end3713a608cffd29b40ff7c3b3f2585cbb -end3713a608cffd29b40ff7c3b3f2585cbb: + goto endc1a330b287199c80228e665a53881298 +endc1a330b287199c80228e665a53881298: ; - // match: (Neq32 (Const32 [c]) (Add32 (Const32 [d]) x)) + return false +} +func rewriteValuegeneric_OpLsh32x64(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Lsh32x64 (Const32 [c]) (Const64 [d])) // cond: - // result: (Neq32 (Const32 [c-d]) x) + // result: (Const32 [int64(int32(c) << uint64(d))]) { if v.Args[0].Op != OpConst32 { - goto end93fc3b4a3639b965b414891111b16245 + goto end5896bd9a3fe78f1e1712563642d33254 } - t := v.Args[0].Type c := v.Args[0].AuxInt - if v.Args[1].Op != OpAdd32 { - goto end93fc3b4a3639b965b414891111b16245 + if v.Args[1].Op != OpConst64 { + goto end5896bd9a3fe78f1e1712563642d33254 } - if v.Args[1].Args[0].Op != OpConst32 { - goto end93fc3b4a3639b965b414891111b16245 + d := v.Args[1].AuxInt + v.Op = OpConst32 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = int64(int32(c) << uint64(d)) + return true + } + goto end5896bd9a3fe78f1e1712563642d33254 +end5896bd9a3fe78f1e1712563642d33254: + ; + // match: (Lsh32x64 x (Const64 [0])) + // cond: + // result: x + { + x := v.Args[0] + if v.Args[1].Op != OpConst64 { + goto endd9ce9639a91b11e601823be3d4d6c209 } - if v.Args[1].Args[0].Type != v.Args[0].Type { - goto end93fc3b4a3639b965b414891111b16245 + if v.Args[1].AuxInt != 0 { + goto endd9ce9639a91b11e601823be3d4d6c209 } - d := v.Args[1].Args[0].AuxInt - x := v.Args[1].Args[1] - v.Op = OpNeq32 + v.Op = OpCopy v.AuxInt = 0 v.Aux = nil v.resetArgs() - v0 := b.NewValue0(v.Line, OpConst32, TypeInvalid) - v0.Type = t - v0.AuxInt = c - d - v.AddArg(v0) + v.Type = x.Type v.AddArg(x) return true } - goto end93fc3b4a3639b965b414891111b16245 -end93fc3b4a3639b965b414891111b16245: + goto endd9ce9639a91b11e601823be3d4d6c209 +endd9ce9639a91b11e601823be3d4d6c209: ; - // match: (Neq32 x (Const32 [c])) - // cond: x.Op != OpConst32 - // result: (Neq32 (Const32 [c]) x) + // match: (Lsh32x64 _ (Const64 [c])) + // cond: uint64(c) >= 32 + // result: (Const64 [0]) { - x := v.Args[0] - if v.Args[1].Op != OpConst32 { - goto end5376f9ab90e282450f49011d0e0ce236 + if v.Args[1].Op != OpConst64 { + goto end81247a2423f489be15859d3930738fdf } - t := v.Args[1].Type c := v.Args[1].AuxInt - if !(x.Op != OpConst32) { - goto end5376f9ab90e282450f49011d0e0ce236 + if !(uint64(c) >= 32) { + goto end81247a2423f489be15859d3930738fdf } - v.Op = OpNeq32 + v.Op = OpConst64 v.AuxInt = 0 v.Aux = nil v.resetArgs() - v0 := b.NewValue0(v.Line, OpConst32, TypeInvalid) - v0.Type = t - v0.AuxInt = c - v.AddArg(v0) - v.AddArg(x) + v.AuxInt = 0 return true } - goto end5376f9ab90e282450f49011d0e0ce236 -end5376f9ab90e282450f49011d0e0ce236: + goto end81247a2423f489be15859d3930738fdf +end81247a2423f489be15859d3930738fdf: ; - // match: (Neq32 (Const32 [c]) (Const32 [d])) - // cond: - // result: (ConstBool [b2i(int32(c) != int32(d))]) + // match: (Lsh32x64 (Lsh32x64 x (Const64 [c])) (Const64 [d])) + // cond: !uaddOvf(c,d) + // result: (Lsh32x64 x (Const64 [c+d])) { - if v.Args[0].Op != OpConst32 { - goto endf9f3d0814854d2d0879d331e9bdfcae2 + t := v.Type + if v.Args[0].Op != OpLsh32x64 { + goto endf96a7c9571797fe61a5b63a4923d7e6e } - c := v.Args[0].AuxInt - if v.Args[1].Op != OpConst32 { - goto endf9f3d0814854d2d0879d331e9bdfcae2 + x := v.Args[0].Args[0] + if v.Args[0].Args[1].Op != OpConst64 { + goto endf96a7c9571797fe61a5b63a4923d7e6e + } + c := v.Args[0].Args[1].AuxInt + if v.Args[1].Op != OpConst64 { + goto endf96a7c9571797fe61a5b63a4923d7e6e } d := v.Args[1].AuxInt - v.Op = OpConstBool + if !(!uaddOvf(c, d)) { + goto endf96a7c9571797fe61a5b63a4923d7e6e + } + v.Op = OpLsh32x64 v.AuxInt = 0 v.Aux = nil v.resetArgs() - v.AuxInt = b2i(int32(c) != int32(d)) + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpConst64, t) + v0.AuxInt = c + d + v.AddArg(v0) return true } - goto endf9f3d0814854d2d0879d331e9bdfcae2 -endf9f3d0814854d2d0879d331e9bdfcae2: + goto endf96a7c9571797fe61a5b63a4923d7e6e +endf96a7c9571797fe61a5b63a4923d7e6e: ; return false } -func rewriteValuegeneric_OpNeq64(v *Value, config *Config) bool { +func rewriteValuegeneric_OpLsh32x8(v *Value, config *Config) bool { b := v.Block _ = b - // match: (Neq64 x x) + // match: (Lsh32x8 x (Const8 [c])) // cond: - // result: (ConstBool [0]) + // result: (Lsh32x64 x (Const64 [int64(uint8(c))])) { + t := v.Type x := v.Args[0] - if v.Args[1] != x { - goto end3601ad382705ea12b79d2008c1e5725c + if v.Args[1].Op != OpConst8 { + goto end1759d7c25a5bcda288e34d1d197c0b8f } - v.Op = OpConstBool + c := v.Args[1].AuxInt + v.Op = OpLsh32x64 v.AuxInt = 0 v.Aux = nil v.resetArgs() + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpConst64, t) + v0.AuxInt = int64(uint8(c)) + v.AddArg(v0) + return true + } + goto end1759d7c25a5bcda288e34d1d197c0b8f +end1759d7c25a5bcda288e34d1d197c0b8f: + ; + return false +} +func rewriteValuegeneric_OpLsh64x16(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Lsh64x16 x (Const16 [c])) + // cond: + // result: (Lsh64x64 x (Const64 [int64(uint16(c))])) + { + t := v.Type + x := v.Args[0] + if v.Args[1].Op != OpConst16 { + goto enda649fbb5e14490c9eea9616550a76b5c + } + c := v.Args[1].AuxInt + v.Op = OpLsh64x64 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpConst64, t) + v0.AuxInt = int64(uint16(c)) + v.AddArg(v0) + return true + } + goto enda649fbb5e14490c9eea9616550a76b5c +enda649fbb5e14490c9eea9616550a76b5c: + ; + return false +} +func rewriteValuegeneric_OpLsh64x32(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Lsh64x32 x (Const32 [c])) + // cond: + // result: (Lsh64x64 x (Const64 [int64(uint32(c))])) + { + t := v.Type + x := v.Args[0] + if v.Args[1].Op != OpConst32 { + goto end40069675cde851a63cce81b1b02751f9 + } + c := v.Args[1].AuxInt + v.Op = OpLsh64x64 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpConst64, t) + v0.AuxInt = int64(uint32(c)) + v.AddArg(v0) + return true + } + goto end40069675cde851a63cce81b1b02751f9 +end40069675cde851a63cce81b1b02751f9: + ; + return false +} +func rewriteValuegeneric_OpLsh64x64(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Lsh64x64 (Const64 [c]) (Const64 [d])) + // cond: + // result: (Const64 [c << uint64(d)]) + { + if v.Args[0].Op != OpConst64 { + goto end9c157a23e021f659f1568566435ed57b + } + c := v.Args[0].AuxInt + if v.Args[1].Op != OpConst64 { + goto end9c157a23e021f659f1568566435ed57b + } + d := v.Args[1].AuxInt + v.Op = OpConst64 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c << uint64(d) + return true + } + goto end9c157a23e021f659f1568566435ed57b +end9c157a23e021f659f1568566435ed57b: + ; + // match: (Lsh64x64 x (Const64 [0])) + // cond: + // result: x + { + x := v.Args[0] + if v.Args[1].Op != OpConst64 { + goto end9f18ca0556dbb4b50fe888273fab20ca + } + if v.Args[1].AuxInt != 0 { + goto end9f18ca0556dbb4b50fe888273fab20ca + } + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = x.Type + v.AddArg(x) + return true + } + goto end9f18ca0556dbb4b50fe888273fab20ca +end9f18ca0556dbb4b50fe888273fab20ca: + ; + // match: (Lsh64x64 _ (Const64 [c])) + // cond: uint64(c) >= 64 + // result: (Const64 [0]) + { + if v.Args[1].Op != OpConst64 { + goto end33da2e0ce5ca3e0554564477ef422402 + } + c := v.Args[1].AuxInt + if !(uint64(c) >= 64) { + goto end33da2e0ce5ca3e0554564477ef422402 + } + v.Op = OpConst64 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = 0 + return true + } + goto end33da2e0ce5ca3e0554564477ef422402 +end33da2e0ce5ca3e0554564477ef422402: + ; + // match: (Lsh64x64 (Lsh64x64 x (Const64 [c])) (Const64 [d])) + // cond: !uaddOvf(c,d) + // result: (Lsh64x64 x (Const64 [c+d])) + { + t := v.Type + if v.Args[0].Op != OpLsh64x64 { + goto end001c62ee580a700ec7b07ccaa3740ac2 + } + x := v.Args[0].Args[0] + if v.Args[0].Args[1].Op != OpConst64 { + goto end001c62ee580a700ec7b07ccaa3740ac2 + } + c := v.Args[0].Args[1].AuxInt + if v.Args[1].Op != OpConst64 { + goto end001c62ee580a700ec7b07ccaa3740ac2 + } + d := v.Args[1].AuxInt + if !(!uaddOvf(c, d)) { + goto end001c62ee580a700ec7b07ccaa3740ac2 + } + v.Op = OpLsh64x64 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpConst64, t) + v0.AuxInt = c + d + v.AddArg(v0) + return true + } + goto end001c62ee580a700ec7b07ccaa3740ac2 +end001c62ee580a700ec7b07ccaa3740ac2: + ; + return false +} +func rewriteValuegeneric_OpLsh64x8(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Lsh64x8 x (Const8 [c])) + // cond: + // result: (Lsh64x64 x (Const64 [int64(uint8(c))])) + { + t := v.Type + x := v.Args[0] + if v.Args[1].Op != OpConst8 { + goto end4d9224069abdade8e405df343938d932 + } + c := v.Args[1].AuxInt + v.Op = OpLsh64x64 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpConst64, t) + v0.AuxInt = int64(uint8(c)) + v.AddArg(v0) + return true + } + goto end4d9224069abdade8e405df343938d932 +end4d9224069abdade8e405df343938d932: + ; + return false +} +func rewriteValuegeneric_OpLsh8x16(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Lsh8x16 x (Const16 [c])) + // cond: + // result: (Lsh8x64 x (Const64 [int64(uint16(c))])) + { + t := v.Type + x := v.Args[0] + if v.Args[1].Op != OpConst16 { + goto end0ad4a82e2eb4c7ca7407d79ec3aa5142 + } + c := v.Args[1].AuxInt + v.Op = OpLsh8x64 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpConst64, t) + v0.AuxInt = int64(uint16(c)) + v.AddArg(v0) + return true + } + goto end0ad4a82e2eb4c7ca7407d79ec3aa5142 +end0ad4a82e2eb4c7ca7407d79ec3aa5142: + ; + return false +} +func rewriteValuegeneric_OpLsh8x32(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Lsh8x32 x (Const32 [c])) + // cond: + // result: (Lsh8x64 x (Const64 [int64(uint32(c))])) + { + t := v.Type + x := v.Args[0] + if v.Args[1].Op != OpConst32 { + goto enddaacda113ecc79fe0621fd22ebc548dd + } + c := v.Args[1].AuxInt + v.Op = OpLsh8x64 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpConst64, t) + v0.AuxInt = int64(uint32(c)) + v.AddArg(v0) + return true + } + goto enddaacda113ecc79fe0621fd22ebc548dd +enddaacda113ecc79fe0621fd22ebc548dd: + ; + return false +} +func rewriteValuegeneric_OpLsh8x64(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Lsh8x64 (Const8 [c]) (Const64 [d])) + // cond: + // result: (Const8 [int64(int8(c) << uint64(d))]) + { + if v.Args[0].Op != OpConst8 { + goto endbc3297ea9642b97eb71f0a9735048d7b + } + c := v.Args[0].AuxInt + if v.Args[1].Op != OpConst64 { + goto endbc3297ea9642b97eb71f0a9735048d7b + } + d := v.Args[1].AuxInt + v.Op = OpConst8 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = int64(int8(c) << uint64(d)) + return true + } + goto endbc3297ea9642b97eb71f0a9735048d7b +endbc3297ea9642b97eb71f0a9735048d7b: + ; + // match: (Lsh8x64 x (Const64 [0])) + // cond: + // result: x + { + x := v.Args[0] + if v.Args[1].Op != OpConst64 { + goto end715f3db41cccf963e25a20c33f618a04 + } + if v.Args[1].AuxInt != 0 { + goto end715f3db41cccf963e25a20c33f618a04 + } + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = x.Type + v.AddArg(x) + return true + } + goto end715f3db41cccf963e25a20c33f618a04 +end715f3db41cccf963e25a20c33f618a04: + ; + // match: (Lsh8x64 _ (Const64 [c])) + // cond: uint64(c) >= 8 + // result: (Const64 [0]) + { + if v.Args[1].Op != OpConst64 { + goto endb6749df4d0cdc0cd9acc627187d73488 + } + c := v.Args[1].AuxInt + if !(uint64(c) >= 8) { + goto endb6749df4d0cdc0cd9acc627187d73488 + } + v.Op = OpConst64 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = 0 + return true + } + goto endb6749df4d0cdc0cd9acc627187d73488 +endb6749df4d0cdc0cd9acc627187d73488: + ; + // match: (Lsh8x64 (Lsh8x64 x (Const64 [c])) (Const64 [d])) + // cond: !uaddOvf(c,d) + // result: (Lsh8x64 x (Const64 [c+d])) + { + t := v.Type + if v.Args[0].Op != OpLsh8x64 { + goto end73a4878b6bbd21c9e22fb99226ef947e + } + x := v.Args[0].Args[0] + if v.Args[0].Args[1].Op != OpConst64 { + goto end73a4878b6bbd21c9e22fb99226ef947e + } + c := v.Args[0].Args[1].AuxInt + if v.Args[1].Op != OpConst64 { + goto end73a4878b6bbd21c9e22fb99226ef947e + } + d := v.Args[1].AuxInt + if !(!uaddOvf(c, d)) { + goto end73a4878b6bbd21c9e22fb99226ef947e + } + v.Op = OpLsh8x64 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpConst64, t) + v0.AuxInt = c + d + v.AddArg(v0) + return true + } + goto end73a4878b6bbd21c9e22fb99226ef947e +end73a4878b6bbd21c9e22fb99226ef947e: + ; + return false +} +func rewriteValuegeneric_OpLsh8x8(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Lsh8x8 x (Const8 [c])) + // cond: + // result: (Lsh8x64 x (Const64 [int64(uint8(c))])) + { + t := v.Type + x := v.Args[0] + if v.Args[1].Op != OpConst8 { + goto end8b770597435467b0c96014624d522b33 + } + c := v.Args[1].AuxInt + v.Op = OpLsh8x64 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpConst64, t) + v0.AuxInt = int64(uint8(c)) + v.AddArg(v0) + return true + } + goto end8b770597435467b0c96014624d522b33 +end8b770597435467b0c96014624d522b33: + ; + return false +} +func rewriteValuegeneric_OpMul16(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Mul16 (Const16 [c]) (Const16 [d])) + // cond: + // result: (Const16 [c*d]) + { + if v.Args[0].Op != OpConst16 { + goto ende8dd468add3015aea24531cf3c89ccb7 + } + c := v.Args[0].AuxInt + if v.Args[1].Op != OpConst16 { + goto ende8dd468add3015aea24531cf3c89ccb7 + } + d := v.Args[1].AuxInt + v.Op = OpConst16 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c * d + return true + } + goto ende8dd468add3015aea24531cf3c89ccb7 +ende8dd468add3015aea24531cf3c89ccb7: + ; + return false +} +func rewriteValuegeneric_OpMul32(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Mul32 (Const32 [c]) (Const32 [d])) + // cond: + // result: (Const32 [c*d]) + { + if v.Args[0].Op != OpConst32 { + goto end60b4523099fa7b55e2e872e05bd497a7 + } + c := v.Args[0].AuxInt + if v.Args[1].Op != OpConst32 { + goto end60b4523099fa7b55e2e872e05bd497a7 + } + d := v.Args[1].AuxInt + v.Op = OpConst32 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c * d + return true + } + goto end60b4523099fa7b55e2e872e05bd497a7 +end60b4523099fa7b55e2e872e05bd497a7: + ; + return false +} +func rewriteValuegeneric_OpMul64(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Mul64 (Const64 [c]) (Const64 [d])) + // cond: + // result: (Const64 [c*d]) + { + if v.Args[0].Op != OpConst64 { + goto end7aea1048b5d1230974b97f17238380ae + } + c := v.Args[0].AuxInt + if v.Args[1].Op != OpConst64 { + goto end7aea1048b5d1230974b97f17238380ae + } + d := v.Args[1].AuxInt + v.Op = OpConst64 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c * d + return true + } + goto end7aea1048b5d1230974b97f17238380ae +end7aea1048b5d1230974b97f17238380ae: + ; + return false +} +func rewriteValuegeneric_OpMul8(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Mul8 (Const8 [c]) (Const8 [d])) + // cond: + // result: (Const8 [c*d]) + { + if v.Args[0].Op != OpConst8 { + goto end2f1952fd654c4a62ff00511041728809 + } + c := v.Args[0].AuxInt + if v.Args[1].Op != OpConst8 { + goto end2f1952fd654c4a62ff00511041728809 + } + d := v.Args[1].AuxInt + v.Op = OpConst8 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c * d + return true + } + goto end2f1952fd654c4a62ff00511041728809 +end2f1952fd654c4a62ff00511041728809: + ; + return false +} +func rewriteValuegeneric_OpNeq16(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Neq16 x x) + // cond: + // result: (ConstBool [0]) + { + x := v.Args[0] + if v.Args[1] != x { + goto ende76a50b524aeb16c7aeccf5f5cc60c06 + } + v.Op = OpConstBool + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = 0 + return true + } + goto ende76a50b524aeb16c7aeccf5f5cc60c06 +ende76a50b524aeb16c7aeccf5f5cc60c06: + ; + // match: (Neq16 (Const16 [c]) (Add16 (Const16 [d]) x)) + // cond: + // result: (Neq16 (Const16 [c-d]) x) + { + if v.Args[0].Op != OpConst16 { + goto end552011bd97e6f92ebc2672aa1843eadd + } + t := v.Args[0].Type + c := v.Args[0].AuxInt + if v.Args[1].Op != OpAdd16 { + goto end552011bd97e6f92ebc2672aa1843eadd + } + if v.Args[1].Args[0].Op != OpConst16 { + goto end552011bd97e6f92ebc2672aa1843eadd + } + if v.Args[1].Args[0].Type != v.Args[0].Type { + goto end552011bd97e6f92ebc2672aa1843eadd + } + d := v.Args[1].Args[0].AuxInt + x := v.Args[1].Args[1] + v.Op = OpNeq16 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpConst16, t) + v0.AuxInt = c - d + v.AddArg(v0) + v.AddArg(x) + return true + } + goto end552011bd97e6f92ebc2672aa1843eadd +end552011bd97e6f92ebc2672aa1843eadd: + ; + // match: (Neq16 x (Const16 [c])) + // cond: x.Op != OpConst16 + // result: (Neq16 (Const16 [c]) x) + { + x := v.Args[0] + if v.Args[1].Op != OpConst16 { + goto end0e45958f29e87997f632248aa9ee97e0 + } + t := v.Args[1].Type + c := v.Args[1].AuxInt + if !(x.Op != OpConst16) { + goto end0e45958f29e87997f632248aa9ee97e0 + } + v.Op = OpNeq16 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpConst16, t) + v0.AuxInt = c + v.AddArg(v0) + v.AddArg(x) + return true + } + goto end0e45958f29e87997f632248aa9ee97e0 +end0e45958f29e87997f632248aa9ee97e0: + ; + // match: (Neq16 (Const16 [c]) (Const16 [d])) + // cond: + // result: (ConstBool [b2i(int16(c) != int16(d))]) + { + if v.Args[0].Op != OpConst16 { + goto end6302c9b645bb191982d28c2f846904d6 + } + c := v.Args[0].AuxInt + if v.Args[1].Op != OpConst16 { + goto end6302c9b645bb191982d28c2f846904d6 + } + d := v.Args[1].AuxInt + v.Op = OpConstBool + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = b2i(int16(c) != int16(d)) + return true + } + goto end6302c9b645bb191982d28c2f846904d6 +end6302c9b645bb191982d28c2f846904d6: + ; + return false +} +func rewriteValuegeneric_OpNeq32(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Neq32 x x) + // cond: + // result: (ConstBool [0]) + { + x := v.Args[0] + if v.Args[1] != x { + goto end3713a608cffd29b40ff7c3b3f2585cbb + } + v.Op = OpConstBool + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = 0 + return true + } + goto end3713a608cffd29b40ff7c3b3f2585cbb +end3713a608cffd29b40ff7c3b3f2585cbb: + ; + // match: (Neq32 (Const32 [c]) (Add32 (Const32 [d]) x)) + // cond: + // result: (Neq32 (Const32 [c-d]) x) + { + if v.Args[0].Op != OpConst32 { + goto end93fc3b4a3639b965b414891111b16245 + } + t := v.Args[0].Type + c := v.Args[0].AuxInt + if v.Args[1].Op != OpAdd32 { + goto end93fc3b4a3639b965b414891111b16245 + } + if v.Args[1].Args[0].Op != OpConst32 { + goto end93fc3b4a3639b965b414891111b16245 + } + if v.Args[1].Args[0].Type != v.Args[0].Type { + goto end93fc3b4a3639b965b414891111b16245 + } + d := v.Args[1].Args[0].AuxInt + x := v.Args[1].Args[1] + v.Op = OpNeq32 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpConst32, t) + v0.AuxInt = c - d + v.AddArg(v0) + v.AddArg(x) + return true + } + goto end93fc3b4a3639b965b414891111b16245 +end93fc3b4a3639b965b414891111b16245: + ; + // match: (Neq32 x (Const32 [c])) + // cond: x.Op != OpConst32 + // result: (Neq32 (Const32 [c]) x) + { + x := v.Args[0] + if v.Args[1].Op != OpConst32 { + goto end5376f9ab90e282450f49011d0e0ce236 + } + t := v.Args[1].Type + c := v.Args[1].AuxInt + if !(x.Op != OpConst32) { + goto end5376f9ab90e282450f49011d0e0ce236 + } + v.Op = OpNeq32 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpConst32, t) + v0.AuxInt = c + v.AddArg(v0) + v.AddArg(x) + return true + } + goto end5376f9ab90e282450f49011d0e0ce236 +end5376f9ab90e282450f49011d0e0ce236: + ; + // match: (Neq32 (Const32 [c]) (Const32 [d])) + // cond: + // result: (ConstBool [b2i(int32(c) != int32(d))]) + { + if v.Args[0].Op != OpConst32 { + goto endf9f3d0814854d2d0879d331e9bdfcae2 + } + c := v.Args[0].AuxInt + if v.Args[1].Op != OpConst32 { + goto endf9f3d0814854d2d0879d331e9bdfcae2 + } + d := v.Args[1].AuxInt + v.Op = OpConstBool + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = b2i(int32(c) != int32(d)) + return true + } + goto endf9f3d0814854d2d0879d331e9bdfcae2 +endf9f3d0814854d2d0879d331e9bdfcae2: + ; + return false +} +func rewriteValuegeneric_OpNeq64(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Neq64 x x) + // cond: + // result: (ConstBool [0]) + { + x := v.Args[0] + if v.Args[1] != x { + goto end3601ad382705ea12b79d2008c1e5725c + } + v.Op = OpConstBool + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = 0 + return true + } + goto end3601ad382705ea12b79d2008c1e5725c +end3601ad382705ea12b79d2008c1e5725c: + ; + // match: (Neq64 (Const64 [c]) (Add64 (Const64 [d]) x)) + // cond: + // result: (Neq64 (Const64 [c-d]) x) + { + if v.Args[0].Op != OpConst64 { + goto enda3d39cad13a557a2aa6d086f43596c1b + } + t := v.Args[0].Type + c := v.Args[0].AuxInt + if v.Args[1].Op != OpAdd64 { + goto enda3d39cad13a557a2aa6d086f43596c1b + } + if v.Args[1].Args[0].Op != OpConst64 { + goto enda3d39cad13a557a2aa6d086f43596c1b + } + if v.Args[1].Args[0].Type != v.Args[0].Type { + goto enda3d39cad13a557a2aa6d086f43596c1b + } + d := v.Args[1].Args[0].AuxInt + x := v.Args[1].Args[1] + v.Op = OpNeq64 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpConst64, t) + v0.AuxInt = c - d + v.AddArg(v0) + v.AddArg(x) + return true + } + goto enda3d39cad13a557a2aa6d086f43596c1b +enda3d39cad13a557a2aa6d086f43596c1b: + ; + // match: (Neq64 x (Const64 [c])) + // cond: x.Op != OpConst64 + // result: (Neq64 (Const64 [c]) x) + { + x := v.Args[0] + if v.Args[1].Op != OpConst64 { + goto end0936a57de20373ca6cacb9506ddde708 + } + t := v.Args[1].Type + c := v.Args[1].AuxInt + if !(x.Op != OpConst64) { + goto end0936a57de20373ca6cacb9506ddde708 + } + v.Op = OpNeq64 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpConst64, t) + v0.AuxInt = c + v.AddArg(v0) + v.AddArg(x) + return true + } + goto end0936a57de20373ca6cacb9506ddde708 +end0936a57de20373ca6cacb9506ddde708: + ; + // match: (Neq64 (Const64 [c]) (Const64 [d])) + // cond: + // result: (ConstBool [b2i(int64(c) != int64(d))]) + { + if v.Args[0].Op != OpConst64 { + goto endf07433ecd3c150b1b75e943aa44a7203 + } + c := v.Args[0].AuxInt + if v.Args[1].Op != OpConst64 { + goto endf07433ecd3c150b1b75e943aa44a7203 + } + d := v.Args[1].AuxInt + v.Op = OpConstBool + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = b2i(int64(c) != int64(d)) + return true + } + goto endf07433ecd3c150b1b75e943aa44a7203 +endf07433ecd3c150b1b75e943aa44a7203: + ; + return false +} +func rewriteValuegeneric_OpNeq8(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Neq8 x x) + // cond: + // result: (ConstBool [0]) + { + x := v.Args[0] + if v.Args[1] != x { + goto end09a0deaf3c42627d0d2d3efa96e30745 + } + v.Op = OpConstBool + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = 0 + return true + } + goto end09a0deaf3c42627d0d2d3efa96e30745 +end09a0deaf3c42627d0d2d3efa96e30745: + ; + // match: (Neq8 (Const8 [c]) (Add8 (Const8 [d]) x)) + // cond: + // result: (Neq8 (Const8 [c-d]) x) + { + if v.Args[0].Op != OpConst8 { + goto endc8f853c610c460c887cbfdca958e3691 + } + t := v.Args[0].Type + c := v.Args[0].AuxInt + if v.Args[1].Op != OpAdd8 { + goto endc8f853c610c460c887cbfdca958e3691 + } + if v.Args[1].Args[0].Op != OpConst8 { + goto endc8f853c610c460c887cbfdca958e3691 + } + if v.Args[1].Args[0].Type != v.Args[0].Type { + goto endc8f853c610c460c887cbfdca958e3691 + } + d := v.Args[1].Args[0].AuxInt + x := v.Args[1].Args[1] + v.Op = OpNeq8 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpConst8, t) + v0.AuxInt = c - d + v.AddArg(v0) + v.AddArg(x) + return true + } + goto endc8f853c610c460c887cbfdca958e3691 +endc8f853c610c460c887cbfdca958e3691: + ; + // match: (Neq8 x (Const8 [c])) + // cond: x.Op != OpConst8 + // result: (Neq8 (Const8 [c]) x) + { + x := v.Args[0] + if v.Args[1].Op != OpConst8 { + goto end04dc0ae2b08cf0447b50e5b8ef469252 + } + t := v.Args[1].Type + c := v.Args[1].AuxInt + if !(x.Op != OpConst8) { + goto end04dc0ae2b08cf0447b50e5b8ef469252 + } + v.Op = OpNeq8 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpConst8, t) + v0.AuxInt = c + v.AddArg(v0) + v.AddArg(x) + return true + } + goto end04dc0ae2b08cf0447b50e5b8ef469252 +end04dc0ae2b08cf0447b50e5b8ef469252: + ; + // match: (Neq8 (Const8 [c]) (Const8 [d])) + // cond: + // result: (ConstBool [b2i(int8(c) != int8(d))]) + { + if v.Args[0].Op != OpConst8 { + goto end72ebdaf2de9b3aa57cf0cb8e068b5f9c + } + c := v.Args[0].AuxInt + if v.Args[1].Op != OpConst8 { + goto end72ebdaf2de9b3aa57cf0cb8e068b5f9c + } + d := v.Args[1].AuxInt + v.Op = OpConstBool + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = b2i(int8(c) != int8(d)) + return true + } + goto end72ebdaf2de9b3aa57cf0cb8e068b5f9c +end72ebdaf2de9b3aa57cf0cb8e068b5f9c: + ; + return false +} +func rewriteValuegeneric_OpNeqInter(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (NeqInter x y) + // cond: + // result: (NeqPtr (ITab x) (ITab y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpNeqPtr + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpITab, config.fe.TypeBytePtr()) + v0.AddArg(x) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpITab, config.fe.TypeBytePtr()) + v1.AddArg(y) + v.AddArg(v1) + return true + } + goto end17b2333bf57e9fe81a671be02f9c4c14 +end17b2333bf57e9fe81a671be02f9c4c14: + ; + return false +} +func rewriteValuegeneric_OpNeqPtr(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (NeqPtr p (ConstNil)) + // cond: + // result: (IsNonNil p) + { + p := v.Args[0] + if v.Args[1].Op != OpConstNil { + goto endba798520b4d41172b110347158c44791 + } + v.Op = OpIsNonNil + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(p) + return true + } + goto endba798520b4d41172b110347158c44791 +endba798520b4d41172b110347158c44791: + ; + // match: (NeqPtr (ConstNil) p) + // cond: + // result: (IsNonNil p) + { + if v.Args[0].Op != OpConstNil { + goto enddd95e9c3606d9fd48034f1a703561e45 + } + p := v.Args[1] + v.Op = OpIsNonNil + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(p) + return true + } + goto enddd95e9c3606d9fd48034f1a703561e45 +enddd95e9c3606d9fd48034f1a703561e45: + ; + return false +} +func rewriteValuegeneric_OpNeqSlice(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (NeqSlice x y) + // cond: + // result: (NeqPtr (SlicePtr x) (SlicePtr y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpNeqPtr + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpSlicePtr, config.fe.TypeBytePtr()) + v0.AddArg(x) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpSlicePtr, config.fe.TypeBytePtr()) + v1.AddArg(y) + v.AddArg(v1) + return true + } + goto endc6bc83c506e491236ca66ea1081231a2 +endc6bc83c506e491236ca66ea1081231a2: + ; + return false +} +func rewriteValuegeneric_OpOr16(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Or16 x x) + // cond: + // result: x + { + x := v.Args[0] + if v.Args[1] != x { + goto end47a2f25fd31a76807aced3e2b126acdc + } + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = x.Type + v.AddArg(x) + return true + } + goto end47a2f25fd31a76807aced3e2b126acdc +end47a2f25fd31a76807aced3e2b126acdc: + ; + return false +} +func rewriteValuegeneric_OpOr32(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Or32 x x) + // cond: + // result: x + { + x := v.Args[0] + if v.Args[1] != x { + goto end231e283e568e90bd9a3e6a4fa328c8a4 + } + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = x.Type + v.AddArg(x) + return true + } + goto end231e283e568e90bd9a3e6a4fa328c8a4 +end231e283e568e90bd9a3e6a4fa328c8a4: + ; + return false +} +func rewriteValuegeneric_OpOr64(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Or64 x x) + // cond: + // result: x + { + x := v.Args[0] + if v.Args[1] != x { + goto end6b0efc212016dc97d0e3939db04c81d9 + } + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = x.Type + v.AddArg(x) + return true + } + goto end6b0efc212016dc97d0e3939db04c81d9 +end6b0efc212016dc97d0e3939db04c81d9: + ; + return false +} +func rewriteValuegeneric_OpOr8(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Or8 x x) + // cond: + // result: x + { + x := v.Args[0] + if v.Args[1] != x { + goto end05295dbfafd6869af79b4daee9fda000 + } + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = x.Type + v.AddArg(x) + return true + } + goto end05295dbfafd6869af79b4daee9fda000 +end05295dbfafd6869af79b4daee9fda000: + ; + return false +} +func rewriteValuegeneric_OpPtrIndex(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (PtrIndex ptr idx) + // cond: config.PtrSize == 4 + // result: (AddPtr ptr (Mul32 idx (Const32 [t.Elem().Size()]))) + { + t := v.Type + ptr := v.Args[0] + idx := v.Args[1] + if !(config.PtrSize == 4) { + goto endd902622aaa1e7545b5a2a0c08b47d287 + } + v.Op = OpAddPtr + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(ptr) + v0 := b.NewValue0(v.Line, OpMul32, config.fe.TypeInt()) + v0.AddArg(idx) + v1 := b.NewValue0(v.Line, OpConst32, config.fe.TypeInt()) + v1.AuxInt = t.Elem().Size() + v0.AddArg(v1) + v.AddArg(v0) + return true + } + goto endd902622aaa1e7545b5a2a0c08b47d287 +endd902622aaa1e7545b5a2a0c08b47d287: + ; + // match: (PtrIndex ptr idx) + // cond: config.PtrSize == 8 + // result: (AddPtr ptr (Mul64 idx (Const64 [t.Elem().Size()]))) + { + t := v.Type + ptr := v.Args[0] + idx := v.Args[1] + if !(config.PtrSize == 8) { + goto end47a5f1d1b158914fa383de024bbe3b08 + } + v.Op = OpAddPtr + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(ptr) + v0 := b.NewValue0(v.Line, OpMul64, config.fe.TypeInt()) + v0.AddArg(idx) + v1 := b.NewValue0(v.Line, OpConst64, config.fe.TypeInt()) + v1.AuxInt = t.Elem().Size() + v0.AddArg(v1) + v.AddArg(v0) + return true + } + goto end47a5f1d1b158914fa383de024bbe3b08 +end47a5f1d1b158914fa383de024bbe3b08: + ; + return false +} +func rewriteValuegeneric_OpRsh16Ux16(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Rsh16Ux16 x (Const16 [c])) + // cond: + // result: (Rsh16Ux64 x (Const64 [int64(uint16(c))])) + { + t := v.Type + x := v.Args[0] + if v.Args[1].Op != OpConst16 { + goto endd981df40f353104ef828d13ad4ccdf02 + } + c := v.Args[1].AuxInt + v.Op = OpRsh16Ux64 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpConst64, t) + v0.AuxInt = int64(uint16(c)) + v.AddArg(v0) + return true + } + goto endd981df40f353104ef828d13ad4ccdf02 +endd981df40f353104ef828d13ad4ccdf02: + ; + return false +} +func rewriteValuegeneric_OpRsh16Ux32(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Rsh16Ux32 x (Const32 [c])) + // cond: + // result: (Rsh16Ux64 x (Const64 [int64(uint32(c))])) + { + t := v.Type + x := v.Args[0] + if v.Args[1].Op != OpConst32 { + goto ende0be9ee562725206dcf96d3e5750b5ea + } + c := v.Args[1].AuxInt + v.Op = OpRsh16Ux64 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpConst64, t) + v0.AuxInt = int64(uint32(c)) + v.AddArg(v0) + return true + } + goto ende0be9ee562725206dcf96d3e5750b5ea +ende0be9ee562725206dcf96d3e5750b5ea: + ; + return false +} +func rewriteValuegeneric_OpRsh16Ux64(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Rsh16Ux64 (Const16 [c]) (Const64 [d])) + // cond: + // result: (Const16 [int64(uint16(c) >> uint64(d))]) + { + if v.Args[0].Op != OpConst16 { + goto ended17f40375fb44bcbaf2d87161c5ed3c + } + c := v.Args[0].AuxInt + if v.Args[1].Op != OpConst64 { + goto ended17f40375fb44bcbaf2d87161c5ed3c + } + d := v.Args[1].AuxInt + v.Op = OpConst16 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = int64(uint16(c) >> uint64(d)) + return true + } + goto ended17f40375fb44bcbaf2d87161c5ed3c +ended17f40375fb44bcbaf2d87161c5ed3c: + ; + // match: (Rsh16Ux64 x (Const64 [0])) + // cond: + // result: x + { + x := v.Args[0] + if v.Args[1].Op != OpConst64 { + goto end752d1b5a60f87afa7e40febbf1bce309 + } + if v.Args[1].AuxInt != 0 { + goto end752d1b5a60f87afa7e40febbf1bce309 + } + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = x.Type + v.AddArg(x) + return true + } + goto end752d1b5a60f87afa7e40febbf1bce309 +end752d1b5a60f87afa7e40febbf1bce309: + ; + // match: (Rsh16Ux64 _ (Const64 [c])) + // cond: uint64(c) >= 16 + // result: (Const64 [0]) + { + if v.Args[1].Op != OpConst64 { + goto endca5c7ae2e51f2ae32486c2b1a3033b77 + } + c := v.Args[1].AuxInt + if !(uint64(c) >= 16) { + goto endca5c7ae2e51f2ae32486c2b1a3033b77 + } + v.Op = OpConst64 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = 0 + return true + } + goto endca5c7ae2e51f2ae32486c2b1a3033b77 +endca5c7ae2e51f2ae32486c2b1a3033b77: + ; + // match: (Rsh16Ux64 (Rsh16Ux64 x (Const64 [c])) (Const64 [d])) + // cond: !uaddOvf(c,d) + // result: (Rsh16Ux64 x (Const64 [c+d])) + { + t := v.Type + if v.Args[0].Op != OpRsh16Ux64 { + goto end56f2c0034c9fbe651abb36fb640af465 + } + x := v.Args[0].Args[0] + if v.Args[0].Args[1].Op != OpConst64 { + goto end56f2c0034c9fbe651abb36fb640af465 + } + c := v.Args[0].Args[1].AuxInt + if v.Args[1].Op != OpConst64 { + goto end56f2c0034c9fbe651abb36fb640af465 + } + d := v.Args[1].AuxInt + if !(!uaddOvf(c, d)) { + goto end56f2c0034c9fbe651abb36fb640af465 + } + v.Op = OpRsh16Ux64 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpConst64, t) + v0.AuxInt = c + d + v.AddArg(v0) + return true + } + goto end56f2c0034c9fbe651abb36fb640af465 +end56f2c0034c9fbe651abb36fb640af465: + ; + return false +} +func rewriteValuegeneric_OpRsh16Ux8(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Rsh16Ux8 x (Const8 [c])) + // cond: + // result: (Rsh16Ux64 x (Const64 [int64(uint8(c))])) + { + t := v.Type + x := v.Args[0] + if v.Args[1].Op != OpConst8 { + goto end20d4667094c32c71bac4e0805dab85c9 + } + c := v.Args[1].AuxInt + v.Op = OpRsh16Ux64 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpConst64, t) + v0.AuxInt = int64(uint8(c)) + v.AddArg(v0) + return true + } + goto end20d4667094c32c71bac4e0805dab85c9 +end20d4667094c32c71bac4e0805dab85c9: + ; + return false +} +func rewriteValuegeneric_OpRsh16x16(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Rsh16x16 x (Const16 [c])) + // cond: + // result: (Rsh16x64 x (Const64 [int64(uint16(c))])) + { + t := v.Type + x := v.Args[0] + if v.Args[1].Op != OpConst16 { + goto end1b501c7ae2fe58ad3a88b467f2d95389 + } + c := v.Args[1].AuxInt + v.Op = OpRsh16x64 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpConst64, t) + v0.AuxInt = int64(uint16(c)) + v.AddArg(v0) + return true + } + goto end1b501c7ae2fe58ad3a88b467f2d95389 +end1b501c7ae2fe58ad3a88b467f2d95389: + ; + return false +} +func rewriteValuegeneric_OpRsh16x32(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Rsh16x32 x (Const32 [c])) + // cond: + // result: (Rsh16x64 x (Const64 [int64(uint32(c))])) + { + t := v.Type + x := v.Args[0] + if v.Args[1].Op != OpConst32 { + goto end4d3a41113d2d0b09924bf5759ca49cab + } + c := v.Args[1].AuxInt + v.Op = OpRsh16x64 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpConst64, t) + v0.AuxInt = int64(uint32(c)) + v.AddArg(v0) + return true + } + goto end4d3a41113d2d0b09924bf5759ca49cab +end4d3a41113d2d0b09924bf5759ca49cab: + ; + return false +} +func rewriteValuegeneric_OpRsh16x64(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Rsh16x64 (Const16 [c]) (Const64 [d])) + // cond: + // result: (Const16 [int64(int16(c) >> uint64(d))]) + { + if v.Args[0].Op != OpConst16 { + goto end8f05fede35a3d2f687fcd4a5829a25ad + } + c := v.Args[0].AuxInt + if v.Args[1].Op != OpConst64 { + goto end8f05fede35a3d2f687fcd4a5829a25ad + } + d := v.Args[1].AuxInt + v.Op = OpConst16 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = int64(int16(c) >> uint64(d)) + return true + } + goto end8f05fede35a3d2f687fcd4a5829a25ad +end8f05fede35a3d2f687fcd4a5829a25ad: + ; + // match: (Rsh16x64 x (Const64 [0])) + // cond: + // result: x + { + x := v.Args[0] + if v.Args[1].Op != OpConst64 { + goto end750fafe01fcc689d953101d53efc19ab + } + if v.Args[1].AuxInt != 0 { + goto end750fafe01fcc689d953101d53efc19ab + } + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = x.Type + v.AddArg(x) + return true + } + goto end750fafe01fcc689d953101d53efc19ab +end750fafe01fcc689d953101d53efc19ab: + ; + // match: (Rsh16x64 (Rsh16x64 x (Const64 [c])) (Const64 [d])) + // cond: !uaddOvf(c,d) + // result: (Rsh16x64 x (Const64 [c+d])) + { + t := v.Type + if v.Args[0].Op != OpRsh16x64 { + goto endf425eff9e05aad27194af957e3383c76 + } + x := v.Args[0].Args[0] + if v.Args[0].Args[1].Op != OpConst64 { + goto endf425eff9e05aad27194af957e3383c76 + } + c := v.Args[0].Args[1].AuxInt + if v.Args[1].Op != OpConst64 { + goto endf425eff9e05aad27194af957e3383c76 + } + d := v.Args[1].AuxInt + if !(!uaddOvf(c, d)) { + goto endf425eff9e05aad27194af957e3383c76 + } + v.Op = OpRsh16x64 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpConst64, t) + v0.AuxInt = c + d + v.AddArg(v0) + return true + } + goto endf425eff9e05aad27194af957e3383c76 +endf425eff9e05aad27194af957e3383c76: + ; + return false +} +func rewriteValuegeneric_OpRsh16x8(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Rsh16x8 x (Const8 [c])) + // cond: + // result: (Rsh16x64 x (Const64 [int64(uint8(c))])) + { + t := v.Type + x := v.Args[0] + if v.Args[1].Op != OpConst8 { + goto end0b5e274d62a3ae8df9f4089756c6a9d4 + } + c := v.Args[1].AuxInt + v.Op = OpRsh16x64 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpConst64, t) + v0.AuxInt = int64(uint8(c)) + v.AddArg(v0) + return true + } + goto end0b5e274d62a3ae8df9f4089756c6a9d4 +end0b5e274d62a3ae8df9f4089756c6a9d4: + ; + return false +} +func rewriteValuegeneric_OpRsh32Ux16(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Rsh32Ux16 x (Const16 [c])) + // cond: + // result: (Rsh32Ux64 x (Const64 [int64(uint16(c))])) + { + t := v.Type + x := v.Args[0] + if v.Args[1].Op != OpConst16 { + goto end8d8f9f3e2e1f7a5e9a186fb792fc40a8 + } + c := v.Args[1].AuxInt + v.Op = OpRsh32Ux64 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpConst64, t) + v0.AuxInt = int64(uint16(c)) + v.AddArg(v0) + return true + } + goto end8d8f9f3e2e1f7a5e9a186fb792fc40a8 +end8d8f9f3e2e1f7a5e9a186fb792fc40a8: + ; + return false +} +func rewriteValuegeneric_OpRsh32Ux32(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Rsh32Ux32 x (Const32 [c])) + // cond: + // result: (Rsh32Ux64 x (Const64 [int64(uint32(c))])) + { + t := v.Type + x := v.Args[0] + if v.Args[1].Op != OpConst32 { + goto endd23d060f74e00f34cc967b6fb9a4d320 + } + c := v.Args[1].AuxInt + v.Op = OpRsh32Ux64 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpConst64, t) + v0.AuxInt = int64(uint32(c)) + v.AddArg(v0) + return true + } + goto endd23d060f74e00f34cc967b6fb9a4d320 +endd23d060f74e00f34cc967b6fb9a4d320: + ; + return false +} +func rewriteValuegeneric_OpRsh32Ux64(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Rsh32Ux64 (Const32 [c]) (Const64 [d])) + // cond: + // result: (Const32 [int64(uint32(c) >> uint64(d))]) + { + if v.Args[0].Op != OpConst32 { + goto enda101e6b765d7ecffd9b7410c9dc3be82 + } + c := v.Args[0].AuxInt + if v.Args[1].Op != OpConst64 { + goto enda101e6b765d7ecffd9b7410c9dc3be82 + } + d := v.Args[1].AuxInt + v.Op = OpConst32 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = int64(uint32(c) >> uint64(d)) + return true + } + goto enda101e6b765d7ecffd9b7410c9dc3be82 +enda101e6b765d7ecffd9b7410c9dc3be82: + ; + // match: (Rsh32Ux64 x (Const64 [0])) + // cond: + // result: x + { + x := v.Args[0] + if v.Args[1].Op != OpConst64 { + goto end162e4e182a665d4e6f0d85fe131e7288 + } + if v.Args[1].AuxInt != 0 { + goto end162e4e182a665d4e6f0d85fe131e7288 + } + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = x.Type + v.AddArg(x) + return true + } + goto end162e4e182a665d4e6f0d85fe131e7288 +end162e4e182a665d4e6f0d85fe131e7288: + ; + // match: (Rsh32Ux64 _ (Const64 [c])) + // cond: uint64(c) >= 32 + // result: (Const64 [0]) + { + if v.Args[1].Op != OpConst64 { + goto endca322c370839b4264b219ee042a6ab33 + } + c := v.Args[1].AuxInt + if !(uint64(c) >= 32) { + goto endca322c370839b4264b219ee042a6ab33 + } + v.Op = OpConst64 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = 0 + return true + } + goto endca322c370839b4264b219ee042a6ab33 +endca322c370839b4264b219ee042a6ab33: + ; + // match: (Rsh32Ux64 (Rsh32Ux64 x (Const64 [c])) (Const64 [d])) + // cond: !uaddOvf(c,d) + // result: (Rsh32Ux64 x (Const64 [c+d])) + { + t := v.Type + if v.Args[0].Op != OpRsh32Ux64 { + goto end2e502d68a32663142684194adbe6c297 + } + x := v.Args[0].Args[0] + if v.Args[0].Args[1].Op != OpConst64 { + goto end2e502d68a32663142684194adbe6c297 + } + c := v.Args[0].Args[1].AuxInt + if v.Args[1].Op != OpConst64 { + goto end2e502d68a32663142684194adbe6c297 + } + d := v.Args[1].AuxInt + if !(!uaddOvf(c, d)) { + goto end2e502d68a32663142684194adbe6c297 + } + v.Op = OpRsh32Ux64 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpConst64, t) + v0.AuxInt = c + d + v.AddArg(v0) + return true + } + goto end2e502d68a32663142684194adbe6c297 +end2e502d68a32663142684194adbe6c297: + ; + return false +} +func rewriteValuegeneric_OpRsh32Ux8(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Rsh32Ux8 x (Const8 [c])) + // cond: + // result: (Rsh32Ux64 x (Const64 [int64(uint8(c))])) + { + t := v.Type + x := v.Args[0] + if v.Args[1].Op != OpConst8 { + goto end967cea80158afaffb783f6da7aa898ca + } + c := v.Args[1].AuxInt + v.Op = OpRsh32Ux64 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpConst64, t) + v0.AuxInt = int64(uint8(c)) + v.AddArg(v0) + return true + } + goto end967cea80158afaffb783f6da7aa898ca +end967cea80158afaffb783f6da7aa898ca: + ; + return false +} +func rewriteValuegeneric_OpRsh32x16(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Rsh32x16 x (Const16 [c])) + // cond: + // result: (Rsh32x64 x (Const64 [int64(uint16(c))])) + { + t := v.Type + x := v.Args[0] + if v.Args[1].Op != OpConst16 { + goto end6a62ebdcc98ea2e3214559214708d26a + } + c := v.Args[1].AuxInt + v.Op = OpRsh32x64 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpConst64, t) + v0.AuxInt = int64(uint16(c)) + v.AddArg(v0) + return true + } + goto end6a62ebdcc98ea2e3214559214708d26a +end6a62ebdcc98ea2e3214559214708d26a: + ; + return false +} +func rewriteValuegeneric_OpRsh32x32(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Rsh32x32 x (Const32 [c])) + // cond: + // result: (Rsh32x64 x (Const64 [int64(uint32(c))])) + { + t := v.Type + x := v.Args[0] + if v.Args[1].Op != OpConst32 { + goto end6e3b467acdca74f58e9177fb42a1968b + } + c := v.Args[1].AuxInt + v.Op = OpRsh32x64 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpConst64, t) + v0.AuxInt = int64(uint32(c)) + v.AddArg(v0) + return true + } + goto end6e3b467acdca74f58e9177fb42a1968b +end6e3b467acdca74f58e9177fb42a1968b: + ; + return false +} +func rewriteValuegeneric_OpRsh32x64(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Rsh32x64 (Const32 [c]) (Const64 [d])) + // cond: + // result: (Const32 [int64(int32(c) >> uint64(d))]) + { + if v.Args[0].Op != OpConst32 { + goto end7e4b8c499cffe1fef73a16e6be54d4d2 + } + c := v.Args[0].AuxInt + if v.Args[1].Op != OpConst64 { + goto end7e4b8c499cffe1fef73a16e6be54d4d2 + } + d := v.Args[1].AuxInt + v.Op = OpConst32 v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = int64(int32(c) >> uint64(d)) return true } - goto end3601ad382705ea12b79d2008c1e5725c -end3601ad382705ea12b79d2008c1e5725c: + goto end7e4b8c499cffe1fef73a16e6be54d4d2 +end7e4b8c499cffe1fef73a16e6be54d4d2: ; - // match: (Neq64 (Const64 [c]) (Add64 (Const64 [d]) x)) + // match: (Rsh32x64 x (Const64 [0])) // cond: - // result: (Neq64 (Const64 [c-d]) x) + // result: x { - if v.Args[0].Op != OpConst64 { - goto enda3d39cad13a557a2aa6d086f43596c1b + x := v.Args[0] + if v.Args[1].Op != OpConst64 { + goto end72da2611eaaffe407efa1cc45c23ade3 } - t := v.Args[0].Type - c := v.Args[0].AuxInt - if v.Args[1].Op != OpAdd64 { - goto enda3d39cad13a557a2aa6d086f43596c1b + if v.Args[1].AuxInt != 0 { + goto end72da2611eaaffe407efa1cc45c23ade3 } - if v.Args[1].Args[0].Op != OpConst64 { - goto enda3d39cad13a557a2aa6d086f43596c1b + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = x.Type + v.AddArg(x) + return true + } + goto end72da2611eaaffe407efa1cc45c23ade3 +end72da2611eaaffe407efa1cc45c23ade3: + ; + // match: (Rsh32x64 (Rsh32x64 x (Const64 [c])) (Const64 [d])) + // cond: !uaddOvf(c,d) + // result: (Rsh32x64 x (Const64 [c+d])) + { + t := v.Type + if v.Args[0].Op != OpRsh32x64 { + goto endadb415be78ee46a8a4135ec50df772b0 } - if v.Args[1].Args[0].Type != v.Args[0].Type { - goto enda3d39cad13a557a2aa6d086f43596c1b + x := v.Args[0].Args[0] + if v.Args[0].Args[1].Op != OpConst64 { + goto endadb415be78ee46a8a4135ec50df772b0 } - d := v.Args[1].Args[0].AuxInt - x := v.Args[1].Args[1] - v.Op = OpNeq64 + c := v.Args[0].Args[1].AuxInt + if v.Args[1].Op != OpConst64 { + goto endadb415be78ee46a8a4135ec50df772b0 + } + d := v.Args[1].AuxInt + if !(!uaddOvf(c, d)) { + goto endadb415be78ee46a8a4135ec50df772b0 + } + v.Op = OpRsh32x64 v.AuxInt = 0 v.Aux = nil v.resetArgs() - v0 := b.NewValue0(v.Line, OpConst64, TypeInvalid) - v0.Type = t - v0.AuxInt = c - d - v.AddArg(v0) v.AddArg(x) + v0 := b.NewValue0(v.Line, OpConst64, t) + v0.AuxInt = c + d + v.AddArg(v0) return true } - goto enda3d39cad13a557a2aa6d086f43596c1b -enda3d39cad13a557a2aa6d086f43596c1b: + goto endadb415be78ee46a8a4135ec50df772b0 +endadb415be78ee46a8a4135ec50df772b0: ; - // match: (Neq64 x (Const64 [c])) - // cond: x.Op != OpConst64 - // result: (Neq64 (Const64 [c]) x) + return false +} +func rewriteValuegeneric_OpRsh32x8(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Rsh32x8 x (Const8 [c])) + // cond: + // result: (Rsh32x64 x (Const64 [int64(uint8(c))])) { + t := v.Type x := v.Args[0] - if v.Args[1].Op != OpConst64 { - goto end0936a57de20373ca6cacb9506ddde708 + if v.Args[1].Op != OpConst8 { + goto end7b59b42c5c68a2d55be469a0c086dd8b } - t := v.Args[1].Type c := v.Args[1].AuxInt - if !(x.Op != OpConst64) { - goto end0936a57de20373ca6cacb9506ddde708 + v.Op = OpRsh32x64 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpConst64, t) + v0.AuxInt = int64(uint8(c)) + v.AddArg(v0) + return true + } + goto end7b59b42c5c68a2d55be469a0c086dd8b +end7b59b42c5c68a2d55be469a0c086dd8b: + ; + return false +} +func rewriteValuegeneric_OpRsh64Ux16(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Rsh64Ux16 x (Const16 [c])) + // cond: + // result: (Rsh64Ux64 x (Const64 [int64(uint16(c))])) + { + t := v.Type + x := v.Args[0] + if v.Args[1].Op != OpConst16 { + goto end733d85a7b599bcba969ca1cb4bdb9e48 } - v.Op = OpNeq64 + c := v.Args[1].AuxInt + v.Op = OpRsh64Ux64 v.AuxInt = 0 v.Aux = nil v.resetArgs() - v0 := b.NewValue0(v.Line, OpConst64, TypeInvalid) - v0.Type = t - v0.AuxInt = c + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpConst64, t) + v0.AuxInt = int64(uint16(c)) v.AddArg(v0) + return true + } + goto end733d85a7b599bcba969ca1cb4bdb9e48 +end733d85a7b599bcba969ca1cb4bdb9e48: + ; + return false +} +func rewriteValuegeneric_OpRsh64Ux32(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Rsh64Ux32 x (Const32 [c])) + // cond: + // result: (Rsh64Ux64 x (Const64 [int64(uint32(c))])) + { + t := v.Type + x := v.Args[0] + if v.Args[1].Op != OpConst32 { + goto endeac7b34169de1fb0393b833e65b9bb19 + } + c := v.Args[1].AuxInt + v.Op = OpRsh64Ux64 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() v.AddArg(x) + v0 := b.NewValue0(v.Line, OpConst64, t) + v0.AuxInt = int64(uint32(c)) + v.AddArg(v0) return true } - goto end0936a57de20373ca6cacb9506ddde708 -end0936a57de20373ca6cacb9506ddde708: + goto endeac7b34169de1fb0393b833e65b9bb19 +endeac7b34169de1fb0393b833e65b9bb19: ; - // match: (Neq64 (Const64 [c]) (Const64 [d])) + return false +} +func rewriteValuegeneric_OpRsh64Ux64(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Rsh64Ux64 (Const64 [c]) (Const64 [d])) // cond: - // result: (ConstBool [b2i(int64(c) != int64(d))]) + // result: (Const64 [int64(uint64(c) >> uint64(d))]) { if v.Args[0].Op != OpConst64 { - goto endf07433ecd3c150b1b75e943aa44a7203 + goto end102f4cfd7979a2aa222d52c34ac6802d } c := v.Args[0].AuxInt if v.Args[1].Op != OpConst64 { - goto endf07433ecd3c150b1b75e943aa44a7203 + goto end102f4cfd7979a2aa222d52c34ac6802d } d := v.Args[1].AuxInt - v.Op = OpConstBool + v.Op = OpConst64 v.AuxInt = 0 v.Aux = nil v.resetArgs() - v.AuxInt = b2i(int64(c) != int64(d)) + v.AuxInt = int64(uint64(c) >> uint64(d)) return true } - goto endf07433ecd3c150b1b75e943aa44a7203 -endf07433ecd3c150b1b75e943aa44a7203: + goto end102f4cfd7979a2aa222d52c34ac6802d +end102f4cfd7979a2aa222d52c34ac6802d: + ; + // match: (Rsh64Ux64 x (Const64 [0])) + // cond: + // result: x + { + x := v.Args[0] + if v.Args[1].Op != OpConst64 { + goto end5ad037b910698f2847df90177c23a6ac + } + if v.Args[1].AuxInt != 0 { + goto end5ad037b910698f2847df90177c23a6ac + } + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = x.Type + v.AddArg(x) + return true + } + goto end5ad037b910698f2847df90177c23a6ac +end5ad037b910698f2847df90177c23a6ac: + ; + // match: (Rsh64Ux64 _ (Const64 [c])) + // cond: uint64(c) >= 64 + // result: (Const64 [0]) + { + if v.Args[1].Op != OpConst64 { + goto end16ea16aa61862207ea64e514369d608b + } + c := v.Args[1].AuxInt + if !(uint64(c) >= 64) { + goto end16ea16aa61862207ea64e514369d608b + } + v.Op = OpConst64 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = 0 + return true + } + goto end16ea16aa61862207ea64e514369d608b +end16ea16aa61862207ea64e514369d608b: + ; + // match: (Rsh64Ux64 (Rsh64Ux64 x (Const64 [c])) (Const64 [d])) + // cond: !uaddOvf(c,d) + // result: (Rsh64Ux64 x (Const64 [c+d])) + { + t := v.Type + if v.Args[0].Op != OpRsh64Ux64 { + goto end32bfdb1b4ccc23a5cd62fc0348ebd877 + } + x := v.Args[0].Args[0] + if v.Args[0].Args[1].Op != OpConst64 { + goto end32bfdb1b4ccc23a5cd62fc0348ebd877 + } + c := v.Args[0].Args[1].AuxInt + if v.Args[1].Op != OpConst64 { + goto end32bfdb1b4ccc23a5cd62fc0348ebd877 + } + d := v.Args[1].AuxInt + if !(!uaddOvf(c, d)) { + goto end32bfdb1b4ccc23a5cd62fc0348ebd877 + } + v.Op = OpRsh64Ux64 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpConst64, t) + v0.AuxInt = c + d + v.AddArg(v0) + return true + } + goto end32bfdb1b4ccc23a5cd62fc0348ebd877 +end32bfdb1b4ccc23a5cd62fc0348ebd877: ; return false } -func rewriteValuegeneric_OpNeq8(v *Value, config *Config) bool { +func rewriteValuegeneric_OpRsh64Ux8(v *Value, config *Config) bool { b := v.Block _ = b - // match: (Neq8 x x) + // match: (Rsh64Ux8 x (Const8 [c])) // cond: - // result: (ConstBool [0]) + // result: (Rsh64Ux64 x (Const64 [int64(uint8(c))])) { + t := v.Type x := v.Args[0] - if v.Args[1] != x { - goto end09a0deaf3c42627d0d2d3efa96e30745 + if v.Args[1].Op != OpConst8 { + goto ende3d8090a67a52dbcd24b52ee32c9d7f0 } - v.Op = OpConstBool + c := v.Args[1].AuxInt + v.Op = OpRsh64Ux64 v.AuxInt = 0 v.Aux = nil v.resetArgs() + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpConst64, t) + v0.AuxInt = int64(uint8(c)) + v.AddArg(v0) + return true + } + goto ende3d8090a67a52dbcd24b52ee32c9d7f0 +ende3d8090a67a52dbcd24b52ee32c9d7f0: + ; + return false +} +func rewriteValuegeneric_OpRsh64x16(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Rsh64x16 x (Const16 [c])) + // cond: + // result: (Rsh64x64 x (Const64 [int64(uint16(c))])) + { + t := v.Type + x := v.Args[0] + if v.Args[1].Op != OpConst16 { + goto endd5151d0bfc38c55ae6ae6836014df3bc + } + c := v.Args[1].AuxInt + v.Op = OpRsh64x64 v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpConst64, t) + v0.AuxInt = int64(uint16(c)) + v.AddArg(v0) return true } - goto end09a0deaf3c42627d0d2d3efa96e30745 -end09a0deaf3c42627d0d2d3efa96e30745: + goto endd5151d0bfc38c55ae6ae6836014df3bc +endd5151d0bfc38c55ae6ae6836014df3bc: ; - // match: (Neq8 (Const8 [c]) (Add8 (Const8 [d]) x)) + return false +} +func rewriteValuegeneric_OpRsh64x32(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Rsh64x32 x (Const32 [c])) // cond: - // result: (Neq8 (Const8 [c-d]) x) + // result: (Rsh64x64 x (Const64 [int64(uint32(c))])) { - if v.Args[0].Op != OpConst8 { - goto endc8f853c610c460c887cbfdca958e3691 + t := v.Type + x := v.Args[0] + if v.Args[1].Op != OpConst32 { + goto end0f2dbca5c7d6b100890c94a97bf0de7c + } + c := v.Args[1].AuxInt + v.Op = OpRsh64x64 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpConst64, t) + v0.AuxInt = int64(uint32(c)) + v.AddArg(v0) + return true + } + goto end0f2dbca5c7d6b100890c94a97bf0de7c +end0f2dbca5c7d6b100890c94a97bf0de7c: + ; + return false +} +func rewriteValuegeneric_OpRsh64x64(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Rsh64x64 (Const64 [c]) (Const64 [d])) + // cond: + // result: (Const64 [c >> uint64(d)]) + { + if v.Args[0].Op != OpConst64 { + goto endfa4609d6bea8a3e3d3a777b1968c97d9 } - t := v.Args[0].Type c := v.Args[0].AuxInt - if v.Args[1].Op != OpAdd8 { - goto endc8f853c610c460c887cbfdca958e3691 + if v.Args[1].Op != OpConst64 { + goto endfa4609d6bea8a3e3d3a777b1968c97d9 } - if v.Args[1].Args[0].Op != OpConst8 { - goto endc8f853c610c460c887cbfdca958e3691 + d := v.Args[1].AuxInt + v.Op = OpConst64 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c >> uint64(d) + return true + } + goto endfa4609d6bea8a3e3d3a777b1968c97d9 +endfa4609d6bea8a3e3d3a777b1968c97d9: + ; + // match: (Rsh64x64 x (Const64 [0])) + // cond: + // result: x + { + x := v.Args[0] + if v.Args[1].Op != OpConst64 { + goto ende62e0c67d3f04eb221646371a2a91d05 } - if v.Args[1].Args[0].Type != v.Args[0].Type { - goto endc8f853c610c460c887cbfdca958e3691 + if v.Args[1].AuxInt != 0 { + goto ende62e0c67d3f04eb221646371a2a91d05 + } + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = x.Type + v.AddArg(x) + return true + } + goto ende62e0c67d3f04eb221646371a2a91d05 +ende62e0c67d3f04eb221646371a2a91d05: + ; + // match: (Rsh64x64 (Rsh64x64 x (Const64 [c])) (Const64 [d])) + // cond: !uaddOvf(c,d) + // result: (Rsh64x64 x (Const64 [c+d])) + { + t := v.Type + if v.Args[0].Op != OpRsh64x64 { + goto endd3e8ea66dc3ad0bc393001d6babb7160 + } + x := v.Args[0].Args[0] + if v.Args[0].Args[1].Op != OpConst64 { + goto endd3e8ea66dc3ad0bc393001d6babb7160 + } + c := v.Args[0].Args[1].AuxInt + if v.Args[1].Op != OpConst64 { + goto endd3e8ea66dc3ad0bc393001d6babb7160 + } + d := v.Args[1].AuxInt + if !(!uaddOvf(c, d)) { + goto endd3e8ea66dc3ad0bc393001d6babb7160 } - d := v.Args[1].Args[0].AuxInt - x := v.Args[1].Args[1] - v.Op = OpNeq8 + v.Op = OpRsh64x64 v.AuxInt = 0 v.Aux = nil v.resetArgs() - v0 := b.NewValue0(v.Line, OpConst8, TypeInvalid) - v0.Type = t - v0.AuxInt = c - d - v.AddArg(v0) v.AddArg(x) + v0 := b.NewValue0(v.Line, OpConst64, t) + v0.AuxInt = c + d + v.AddArg(v0) return true } - goto endc8f853c610c460c887cbfdca958e3691 -endc8f853c610c460c887cbfdca958e3691: + goto endd3e8ea66dc3ad0bc393001d6babb7160 +endd3e8ea66dc3ad0bc393001d6babb7160: ; - // match: (Neq8 x (Const8 [c])) - // cond: x.Op != OpConst8 - // result: (Neq8 (Const8 [c]) x) + return false +} +func rewriteValuegeneric_OpRsh64x8(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Rsh64x8 x (Const8 [c])) + // cond: + // result: (Rsh64x64 x (Const64 [int64(uint8(c))])) { + t := v.Type x := v.Args[0] if v.Args[1].Op != OpConst8 { - goto end04dc0ae2b08cf0447b50e5b8ef469252 + goto end1a9e5a89849344396210da7c7ec810be } - t := v.Args[1].Type c := v.Args[1].AuxInt - if !(x.Op != OpConst8) { - goto end04dc0ae2b08cf0447b50e5b8ef469252 - } - v.Op = OpNeq8 + v.Op = OpRsh64x64 v.AuxInt = 0 v.Aux = nil v.resetArgs() - v0 := b.NewValue0(v.Line, OpConst8, TypeInvalid) - v0.Type = t - v0.AuxInt = c - v.AddArg(v0) v.AddArg(x) + v0 := b.NewValue0(v.Line, OpConst64, t) + v0.AuxInt = int64(uint8(c)) + v.AddArg(v0) return true } - goto end04dc0ae2b08cf0447b50e5b8ef469252 -end04dc0ae2b08cf0447b50e5b8ef469252: + goto end1a9e5a89849344396210da7c7ec810be +end1a9e5a89849344396210da7c7ec810be: ; - // match: (Neq8 (Const8 [c]) (Const8 [d])) + return false +} +func rewriteValuegeneric_OpRsh8Ux16(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Rsh8Ux16 x (Const16 [c])) // cond: - // result: (ConstBool [b2i(int8(c) != int8(d))]) + // result: (Rsh8Ux64 x (Const64 [int64(uint16(c))])) { - if v.Args[0].Op != OpConst8 { - goto end72ebdaf2de9b3aa57cf0cb8e068b5f9c - } - c := v.Args[0].AuxInt - if v.Args[1].Op != OpConst8 { - goto end72ebdaf2de9b3aa57cf0cb8e068b5f9c + t := v.Type + x := v.Args[0] + if v.Args[1].Op != OpConst16 { + goto end7acc015610273092e9efcce2949ee0f9 } - d := v.Args[1].AuxInt - v.Op = OpConstBool + c := v.Args[1].AuxInt + v.Op = OpRsh8Ux64 v.AuxInt = 0 v.Aux = nil v.resetArgs() - v.AuxInt = b2i(int8(c) != int8(d)) + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpConst64, t) + v0.AuxInt = int64(uint16(c)) + v.AddArg(v0) return true } - goto end72ebdaf2de9b3aa57cf0cb8e068b5f9c -end72ebdaf2de9b3aa57cf0cb8e068b5f9c: + goto end7acc015610273092e9efcce2949ee0f9 +end7acc015610273092e9efcce2949ee0f9: ; return false } -func rewriteValuegeneric_OpNeqInter(v *Value, config *Config) bool { +func rewriteValuegeneric_OpRsh8Ux32(v *Value, config *Config) bool { b := v.Block _ = b - // match: (NeqInter x y) + // match: (Rsh8Ux32 x (Const32 [c])) // cond: - // result: (NeqPtr (ITab x) (ITab y)) + // result: (Rsh8Ux64 x (Const64 [int64(uint32(c))])) { + t := v.Type x := v.Args[0] - y := v.Args[1] - v.Op = OpNeqPtr + if v.Args[1].Op != OpConst32 { + goto end27e9b4472e085b653a105b1d67554ce8 + } + c := v.Args[1].AuxInt + v.Op = OpRsh8Ux64 v.AuxInt = 0 v.Aux = nil v.resetArgs() - v0 := b.NewValue0(v.Line, OpITab, config.fe.TypeBytePtr()) - v0.AddArg(x) + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpConst64, t) + v0.AuxInt = int64(uint32(c)) v.AddArg(v0) - v1 := b.NewValue0(v.Line, OpITab, config.fe.TypeBytePtr()) - v1.AddArg(y) - v.AddArg(v1) return true } - goto end17b2333bf57e9fe81a671be02f9c4c14 -end17b2333bf57e9fe81a671be02f9c4c14: + goto end27e9b4472e085b653a105b1d67554ce8 +end27e9b4472e085b653a105b1d67554ce8: ; return false } -func rewriteValuegeneric_OpNeqPtr(v *Value, config *Config) bool { +func rewriteValuegeneric_OpRsh8Ux64(v *Value, config *Config) bool { b := v.Block _ = b - // match: (NeqPtr p (ConstNil)) + // match: (Rsh8Ux64 (Const8 [c]) (Const64 [d])) // cond: - // result: (IsNonNil p) + // result: (Const8 [int64(uint8(c) >> uint64(d))]) { - p := v.Args[0] - if v.Args[1].Op != OpConstNil { - goto endba798520b4d41172b110347158c44791 + if v.Args[0].Op != OpConst8 { + goto enddd166e450d81ba7b466d61d2fbec178c } - v.Op = OpIsNonNil + c := v.Args[0].AuxInt + if v.Args[1].Op != OpConst64 { + goto enddd166e450d81ba7b466d61d2fbec178c + } + d := v.Args[1].AuxInt + v.Op = OpConst8 v.AuxInt = 0 v.Aux = nil v.resetArgs() - v.AddArg(p) + v.AuxInt = int64(uint8(c) >> uint64(d)) return true } - goto endba798520b4d41172b110347158c44791 -endba798520b4d41172b110347158c44791: + goto enddd166e450d81ba7b466d61d2fbec178c +enddd166e450d81ba7b466d61d2fbec178c: ; - // match: (NeqPtr (ConstNil) p) + // match: (Rsh8Ux64 x (Const64 [0])) // cond: - // result: (IsNonNil p) + // result: x { - if v.Args[0].Op != OpConstNil { - goto enddd95e9c3606d9fd48034f1a703561e45 + x := v.Args[0] + if v.Args[1].Op != OpConst64 { + goto end570cb1d9db3c7bebd85e485eeb2c0969 } - p := v.Args[1] - v.Op = OpIsNonNil + if v.Args[1].AuxInt != 0 { + goto end570cb1d9db3c7bebd85e485eeb2c0969 + } + v.Op = OpCopy v.AuxInt = 0 v.Aux = nil v.resetArgs() - v.AddArg(p) + v.Type = x.Type + v.AddArg(x) return true } - goto enddd95e9c3606d9fd48034f1a703561e45 -enddd95e9c3606d9fd48034f1a703561e45: + goto end570cb1d9db3c7bebd85e485eeb2c0969 +end570cb1d9db3c7bebd85e485eeb2c0969: ; - return false -} -func rewriteValuegeneric_OpNeqSlice(v *Value, config *Config) bool { - b := v.Block - _ = b - // match: (NeqSlice x y) - // cond: - // result: (NeqPtr (SlicePtr x) (SlicePtr y)) + // match: (Rsh8Ux64 _ (Const64 [c])) + // cond: uint64(c) >= 8 + // result: (Const64 [0]) { - x := v.Args[0] - y := v.Args[1] - v.Op = OpNeqPtr + if v.Args[1].Op != OpConst64 { + goto endb63e1a7d1d91716ca0d9d74215361323 + } + c := v.Args[1].AuxInt + if !(uint64(c) >= 8) { + goto endb63e1a7d1d91716ca0d9d74215361323 + } + v.Op = OpConst64 v.AuxInt = 0 v.Aux = nil v.resetArgs() - v0 := b.NewValue0(v.Line, OpSlicePtr, config.fe.TypeBytePtr()) - v0.AddArg(x) + v.AuxInt = 0 + return true + } + goto endb63e1a7d1d91716ca0d9d74215361323 +endb63e1a7d1d91716ca0d9d74215361323: + ; + // match: (Rsh8Ux64 (Rsh8Ux64 x (Const64 [c])) (Const64 [d])) + // cond: !uaddOvf(c,d) + // result: (Rsh8Ux64 x (Const64 [c+d])) + { + t := v.Type + if v.Args[0].Op != OpRsh8Ux64 { + goto endee8824b7071ed1a6dba4fcbaab98229e + } + x := v.Args[0].Args[0] + if v.Args[0].Args[1].Op != OpConst64 { + goto endee8824b7071ed1a6dba4fcbaab98229e + } + c := v.Args[0].Args[1].AuxInt + if v.Args[1].Op != OpConst64 { + goto endee8824b7071ed1a6dba4fcbaab98229e + } + d := v.Args[1].AuxInt + if !(!uaddOvf(c, d)) { + goto endee8824b7071ed1a6dba4fcbaab98229e + } + v.Op = OpRsh8Ux64 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpConst64, t) + v0.AuxInt = c + d v.AddArg(v0) - v1 := b.NewValue0(v.Line, OpSlicePtr, config.fe.TypeBytePtr()) - v1.AddArg(y) - v.AddArg(v1) return true } - goto endc6bc83c506e491236ca66ea1081231a2 -endc6bc83c506e491236ca66ea1081231a2: + goto endee8824b7071ed1a6dba4fcbaab98229e +endee8824b7071ed1a6dba4fcbaab98229e: ; return false } -func rewriteValuegeneric_OpOr16(v *Value, config *Config) bool { +func rewriteValuegeneric_OpRsh8Ux8(v *Value, config *Config) bool { b := v.Block _ = b - // match: (Or16 x x) + // match: (Rsh8Ux8 x (Const8 [c])) // cond: - // result: x + // result: (Rsh8Ux64 x (Const64 [int64(uint8(c))])) { + t := v.Type x := v.Args[0] - if v.Args[1] != x { - goto end47a2f25fd31a76807aced3e2b126acdc + if v.Args[1].Op != OpConst8 { + goto ended7e4f4d9ab89dc26e6649d466577930 } - v.Op = OpCopy + c := v.Args[1].AuxInt + v.Op = OpRsh8Ux64 v.AuxInt = 0 v.Aux = nil v.resetArgs() - v.Type = x.Type v.AddArg(x) + v0 := b.NewValue0(v.Line, OpConst64, t) + v0.AuxInt = int64(uint8(c)) + v.AddArg(v0) return true } - goto end47a2f25fd31a76807aced3e2b126acdc -end47a2f25fd31a76807aced3e2b126acdc: + goto ended7e4f4d9ab89dc26e6649d466577930 +ended7e4f4d9ab89dc26e6649d466577930: ; return false } -func rewriteValuegeneric_OpOr32(v *Value, config *Config) bool { +func rewriteValuegeneric_OpRsh8x16(v *Value, config *Config) bool { b := v.Block _ = b - // match: (Or32 x x) + // match: (Rsh8x16 x (Const16 [c])) // cond: - // result: x + // result: (Rsh8x64 x (Const64 [int64(uint16(c))])) { + t := v.Type x := v.Args[0] - if v.Args[1] != x { - goto end231e283e568e90bd9a3e6a4fa328c8a4 + if v.Args[1].Op != OpConst16 { + goto end136bef6f60180bc8b4befbfc370af7ef } - v.Op = OpCopy + c := v.Args[1].AuxInt + v.Op = OpRsh8x64 v.AuxInt = 0 v.Aux = nil v.resetArgs() - v.Type = x.Type v.AddArg(x) + v0 := b.NewValue0(v.Line, OpConst64, t) + v0.AuxInt = int64(uint16(c)) + v.AddArg(v0) return true } - goto end231e283e568e90bd9a3e6a4fa328c8a4 -end231e283e568e90bd9a3e6a4fa328c8a4: + goto end136bef6f60180bc8b4befbfc370af7ef +end136bef6f60180bc8b4befbfc370af7ef: ; return false } -func rewriteValuegeneric_OpOr64(v *Value, config *Config) bool { +func rewriteValuegeneric_OpRsh8x32(v *Value, config *Config) bool { b := v.Block _ = b - // match: (Or64 x x) + // match: (Rsh8x32 x (Const32 [c])) // cond: - // result: x + // result: (Rsh8x64 x (Const64 [int64(uint32(c))])) { + t := v.Type x := v.Args[0] - if v.Args[1] != x { - goto end6b0efc212016dc97d0e3939db04c81d9 + if v.Args[1].Op != OpConst32 { + goto end2ef95c222a7c552fa9cc86e36196644e } - v.Op = OpCopy + c := v.Args[1].AuxInt + v.Op = OpRsh8x64 v.AuxInt = 0 v.Aux = nil v.resetArgs() - v.Type = x.Type v.AddArg(x) + v0 := b.NewValue0(v.Line, OpConst64, t) + v0.AuxInt = int64(uint32(c)) + v.AddArg(v0) return true } - goto end6b0efc212016dc97d0e3939db04c81d9 -end6b0efc212016dc97d0e3939db04c81d9: + goto end2ef95c222a7c552fa9cc86e36196644e +end2ef95c222a7c552fa9cc86e36196644e: ; return false } -func rewriteValuegeneric_OpOr8(v *Value, config *Config) bool { +func rewriteValuegeneric_OpRsh8x64(v *Value, config *Config) bool { b := v.Block _ = b - // match: (Or8 x x) + // match: (Rsh8x64 (Const8 [c]) (Const64 [d])) + // cond: + // result: (Const8 [int64(int8(c) >> uint64(d))]) + { + if v.Args[0].Op != OpConst8 { + goto end3b90206d75365466dfd1368e5b69db35 + } + c := v.Args[0].AuxInt + if v.Args[1].Op != OpConst64 { + goto end3b90206d75365466dfd1368e5b69db35 + } + d := v.Args[1].AuxInt + v.Op = OpConst8 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = int64(int8(c) >> uint64(d)) + return true + } + goto end3b90206d75365466dfd1368e5b69db35 +end3b90206d75365466dfd1368e5b69db35: + ; + // match: (Rsh8x64 x (Const64 [0])) // cond: // result: x { x := v.Args[0] - if v.Args[1] != x { - goto end05295dbfafd6869af79b4daee9fda000 + if v.Args[1].Op != OpConst64 { + goto end1e664cc720a11d1c769de8081cfa1de4 + } + if v.Args[1].AuxInt != 0 { + goto end1e664cc720a11d1c769de8081cfa1de4 } v.Op = OpCopy v.AuxInt = 0 @@ -3749,65 +5981,69 @@ func rewriteValuegeneric_OpOr8(v *Value, config *Config) bool { v.AddArg(x) return true } - goto end05295dbfafd6869af79b4daee9fda000 -end05295dbfafd6869af79b4daee9fda000: + goto end1e664cc720a11d1c769de8081cfa1de4 +end1e664cc720a11d1c769de8081cfa1de4: ; - return false -} -func rewriteValuegeneric_OpPtrIndex(v *Value, config *Config) bool { - b := v.Block - _ = b - // match: (PtrIndex ptr idx) - // cond: config.PtrSize == 4 - // result: (AddPtr ptr (Mul32 idx (Const32 [t.Elem().Size()]))) + // match: (Rsh8x64 (Rsh8x64 x (Const64 [c])) (Const64 [d])) + // cond: !uaddOvf(c,d) + // result: (Rsh8x64 x (Const64 [c+d])) { t := v.Type - ptr := v.Args[0] - idx := v.Args[1] - if !(config.PtrSize == 4) { - goto endd902622aaa1e7545b5a2a0c08b47d287 + if v.Args[0].Op != OpRsh8x64 { + goto end6408685a7276af7e76ec086f359c942c } - v.Op = OpAddPtr + x := v.Args[0].Args[0] + if v.Args[0].Args[1].Op != OpConst64 { + goto end6408685a7276af7e76ec086f359c942c + } + c := v.Args[0].Args[1].AuxInt + if v.Args[1].Op != OpConst64 { + goto end6408685a7276af7e76ec086f359c942c + } + d := v.Args[1].AuxInt + if !(!uaddOvf(c, d)) { + goto end6408685a7276af7e76ec086f359c942c + } + v.Op = OpRsh8x64 v.AuxInt = 0 v.Aux = nil v.resetArgs() - v.AddArg(ptr) - v0 := b.NewValue0(v.Line, OpMul32, config.fe.TypeInt()) - v0.AddArg(idx) - v1 := b.NewValue0(v.Line, OpConst32, config.fe.TypeInt()) - v1.AuxInt = t.Elem().Size() - v0.AddArg(v1) + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpConst64, t) + v0.AuxInt = c + d v.AddArg(v0) return true } - goto endd902622aaa1e7545b5a2a0c08b47d287 -endd902622aaa1e7545b5a2a0c08b47d287: + goto end6408685a7276af7e76ec086f359c942c +end6408685a7276af7e76ec086f359c942c: ; - // match: (PtrIndex ptr idx) - // cond: config.PtrSize == 8 - // result: (AddPtr ptr (Mul64 idx (Const64 [t.Elem().Size()]))) + return false +} +func rewriteValuegeneric_OpRsh8x8(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Rsh8x8 x (Const8 [c])) + // cond: + // result: (Rsh8x64 x (Const64 [int64(uint8(c))])) { t := v.Type - ptr := v.Args[0] - idx := v.Args[1] - if !(config.PtrSize == 8) { - goto end47a5f1d1b158914fa383de024bbe3b08 + x := v.Args[0] + if v.Args[1].Op != OpConst8 { + goto endae44f60f364cddd8903763dd921a007e } - v.Op = OpAddPtr + c := v.Args[1].AuxInt + v.Op = OpRsh8x64 v.AuxInt = 0 v.Aux = nil v.resetArgs() - v.AddArg(ptr) - v0 := b.NewValue0(v.Line, OpMul64, config.fe.TypeInt()) - v0.AddArg(idx) - v1 := b.NewValue0(v.Line, OpConst64, config.fe.TypeInt()) - v1.AuxInt = t.Elem().Size() - v0.AddArg(v1) + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpConst64, t) + v0.AuxInt = int64(uint8(c)) v.AddArg(v0) return true } - goto end47a5f1d1b158914fa383de024bbe3b08 -end47a5f1d1b158914fa383de024bbe3b08: + goto endae44f60f364cddd8903763dd921a007e +endae44f60f364cddd8903763dd921a007e: ; return false } @@ -4652,8 +6888,7 @@ end5c6fab95c9dbeff5973119096bfd4e78: v.AuxInt = 0 v.Aux = nil v.resetArgs() - v0 := b.NewValue0(v.Line, OpConst16, TypeInvalid) - v0.Type = t + v0 := b.NewValue0(v.Line, OpConst16, t) v0.AuxInt = -c v.AddArg(v0) v.AddArg(x) @@ -4770,8 +7005,7 @@ end7623799db780e1bcc42c6ea0df9c49d3: v.AuxInt = 0 v.Aux = nil v.resetArgs() - v0 := b.NewValue0(v.Line, OpConst32, TypeInvalid) - v0.Type = t + v0 := b.NewValue0(v.Line, OpConst32, t) v0.AuxInt = -c v.AddArg(v0) v.AddArg(x) @@ -4888,8 +7122,7 @@ end5a84a285ff0ff48b8ad3c64b15e3459f: v.AuxInt = 0 v.Aux = nil v.resetArgs() - v0 := b.NewValue0(v.Line, OpConst64, TypeInvalid) - v0.Type = t + v0 := b.NewValue0(v.Line, OpConst64, t) v0.AuxInt = -c v.AddArg(v0) v.AddArg(x) @@ -5006,8 +7239,7 @@ endc00ea11c7535529e211710574f5cff24: v.AuxInt = 0 v.Aux = nil v.resetArgs() - v0 := b.NewValue0(v.Line, OpConst8, TypeInvalid) - v0.Type = t + v0 := b.NewValue0(v.Line, OpConst8, t) v0.AuxInt = -c v.AddArg(v0) v.AddArg(x) -- cgit v1.3 From d0d04d2d6cdd79428f2c3b97d33b65638c1cdd71 Mon Sep 17 00:00:00 2001 From: Alexandru Moșoi Date: Tue, 9 Feb 2016 19:46:26 +0100 Subject: [dev.ssa] cmd/compile/internal/ssa: handle rewrite of Phis. * Phis can have variable number of arguments, but rulegen assumed that each operation has fixed number of arguments. * Rewriting Phis is necessary to handle the following case: func f1_ssa(a bool, x int) int { v := 0 if a { v = -1 } else { v = -1 } return x|v } Change-Id: Iff6bd411b854f3d1d6d3ce21934bf566757094f2 Reviewed-on: https://go-review.googlesource.com/19412 Reviewed-by: Keith Randall --- src/cmd/compile/internal/gc/testdata/arith_ssa.go | 20 +++++ src/cmd/compile/internal/ssa/gen/generic.rules | 6 ++ src/cmd/compile/internal/ssa/gen/genericOps.go | 4 +- src/cmd/compile/internal/ssa/gen/main.go | 1 + src/cmd/compile/internal/ssa/gen/rulegen.go | 17 ++++ src/cmd/compile/internal/ssa/rewritegeneric.go | 94 +++++++++++++++++++++++ 6 files changed, 140 insertions(+), 2 deletions(-) (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/testdata/arith_ssa.go b/src/cmd/compile/internal/gc/testdata/arith_ssa.go index 22a78105e0..821c0dd12d 100644 --- a/src/cmd/compile/internal/gc/testdata/arith_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/arith_ssa.go @@ -358,6 +358,26 @@ func testSubConst() { } } +//go:noinline +func orPhi_ssa(a bool, x int) int { + v := 0 + if a { + v = -1 + } else { + v = -1 + } + return x | v +} + +func testOrPhi() { + if want, got := -1, orPhi_ssa(true, 4); got != want { + println("orPhi_ssa(true, 4)=", got, " want ", want) + } + if want, got := -1, orPhi_ssa(false, 0); got != want { + println("orPhi_ssa(false, 0)=", got, " want ", want) + } +} + var failed = false func main() { diff --git a/src/cmd/compile/internal/ssa/gen/generic.rules b/src/cmd/compile/internal/ssa/gen/generic.rules index a3cc5654ea..29b1d42c9e 100644 --- a/src/cmd/compile/internal/ssa/gen/generic.rules +++ b/src/cmd/compile/internal/ssa/gen/generic.rules @@ -263,6 +263,12 @@ (Sub8 (Add8 x y) x) -> y (Sub8 (Add8 x y) y) -> x +// basic phi simplifications +(Phi (Const8 [c]) (Const8 [d])) && int8(c) == int8(d) -> (Const8 [c]) +(Phi (Const16 [c]) (Const16 [d])) && int16(c) == int16(d) -> (Const16 [c]) +(Phi (Const32 [c]) (Const32 [d])) && int32(c) == int32(d) -> (Const32 [c]) +(Phi (Const64 [c]) (Const64 [c])) -> (Const64 [c]) + // user nil checks (NeqPtr p (ConstNil)) -> (IsNonNil p) (NeqPtr (ConstNil) p) -> (IsNonNil p) diff --git a/src/cmd/compile/internal/ssa/gen/genericOps.go b/src/cmd/compile/internal/ssa/gen/genericOps.go index ec74859cbc..fe5169d233 100644 --- a/src/cmd/compile/internal/ssa/gen/genericOps.go +++ b/src/cmd/compile/internal/ssa/gen/genericOps.go @@ -240,8 +240,8 @@ var genericOps = []opData{ {name: "Sqrt"}, // sqrt(arg0), float64 only // Data movement - {name: "Phi"}, // select an argument based on which predecessor block we came from - {name: "Copy"}, // output = arg0 + {name: "Phi", variableLength: true}, // select an argument based on which predecessor block we came from + {name: "Copy"}, // output = arg0 // Convert converts between pointers and integers. // We have a special op for this so as to not confuse GC // (particularly stack maps). It takes a memory arg so it diff --git a/src/cmd/compile/internal/ssa/gen/main.go b/src/cmd/compile/internal/ssa/gen/main.go index f8f6c8b5f6..d739b29079 100644 --- a/src/cmd/compile/internal/ssa/gen/main.go +++ b/src/cmd/compile/internal/ssa/gen/main.go @@ -32,6 +32,7 @@ type opData struct { typ string // default result type aux string rematerializeable bool + variableLength bool // if true the operation has a variable number of arguments } type blockData struct { diff --git a/src/cmd/compile/internal/ssa/gen/rulegen.go b/src/cmd/compile/internal/ssa/gen/rulegen.go index 1a0f5d4b1e..b9aa51d165 100644 --- a/src/cmd/compile/internal/ssa/gen/rulegen.go +++ b/src/cmd/compile/internal/ssa/gen/rulegen.go @@ -395,6 +395,23 @@ func genMatch0(w io.Writer, arch arch, match, v string, m map[string]string, top argnum++ } } + + variableLength := false + for _, op := range genericOps { + if op.name == s[0] { + variableLength = op.variableLength + break + } + } + for _, op := range arch.ops { + if op.name == s[0] { + variableLength = op.variableLength + break + } + } + if variableLength { + fmt.Fprintf(w, "if len(%s.Args) != %d {\nbreak\n}\n", v, argnum) + } } func genResult(w io.Writer, arch arch, result string) { diff --git a/src/cmd/compile/internal/ssa/rewritegeneric.go b/src/cmd/compile/internal/ssa/rewritegeneric.go index a724a2d369..e0f03d2e45 100644 --- a/src/cmd/compile/internal/ssa/rewritegeneric.go +++ b/src/cmd/compile/internal/ssa/rewritegeneric.go @@ -213,6 +213,8 @@ func rewriteValuegeneric(v *Value, config *Config) bool { return rewriteValuegeneric_OpOr64(v, config) case OpOr8: return rewriteValuegeneric_OpOr8(v, config) + case OpPhi: + return rewriteValuegeneric_OpPhi(v, config) case OpPtrIndex: return rewriteValuegeneric_OpPtrIndex(v, config) case OpRsh16Ux16: @@ -3965,6 +3967,98 @@ func rewriteValuegeneric_OpOr8(v *Value, config *Config) bool { } return false } +func rewriteValuegeneric_OpPhi(v *Value, config *Config) bool { + b := v.Block + _ = b + // match: (Phi (Const8 [c]) (Const8 [d])) + // cond: int8(c) == int8(d) + // result: (Const8 [c]) + for { + if v.Args[0].Op != OpConst8 { + break + } + c := v.Args[0].AuxInt + if v.Args[1].Op != OpConst8 { + break + } + d := v.Args[1].AuxInt + if len(v.Args) != 2 { + break + } + if !(int8(c) == int8(d)) { + break + } + v.reset(OpConst8) + v.AuxInt = c + return true + } + // match: (Phi (Const16 [c]) (Const16 [d])) + // cond: int16(c) == int16(d) + // result: (Const16 [c]) + for { + if v.Args[0].Op != OpConst16 { + break + } + c := v.Args[0].AuxInt + if v.Args[1].Op != OpConst16 { + break + } + d := v.Args[1].AuxInt + if len(v.Args) != 2 { + break + } + if !(int16(c) == int16(d)) { + break + } + v.reset(OpConst16) + v.AuxInt = c + return true + } + // match: (Phi (Const32 [c]) (Const32 [d])) + // cond: int32(c) == int32(d) + // result: (Const32 [c]) + for { + if v.Args[0].Op != OpConst32 { + break + } + c := v.Args[0].AuxInt + if v.Args[1].Op != OpConst32 { + break + } + d := v.Args[1].AuxInt + if len(v.Args) != 2 { + break + } + if !(int32(c) == int32(d)) { + break + } + v.reset(OpConst32) + v.AuxInt = c + return true + } + // match: (Phi (Const64 [c]) (Const64 [c])) + // cond: + // result: (Const64 [c]) + for { + if v.Args[0].Op != OpConst64 { + break + } + c := v.Args[0].AuxInt + if v.Args[1].Op != OpConst64 { + break + } + if v.Args[1].AuxInt != v.Args[0].AuxInt { + break + } + if len(v.Args) != 2 { + break + } + v.reset(OpConst64) + v.AuxInt = c + return true + } + return false +} func rewriteValuegeneric_OpPtrIndex(v *Value, config *Config) bool { b := v.Block _ = b -- cgit v1.3 From 4827c6d0778d93afeaee658a330d97b8f1b510a6 Mon Sep 17 00:00:00 2001 From: Todd Neal Date: Sun, 21 Feb 2016 20:21:23 -0600 Subject: [dev.ssa] test: add test of pointer aliasing This adds a test case with aliased pointers to ensure modifications to dse don't remove valid stores. Change-Id: I143653250f46a403835218ec685bcd336d5087ef Reviewed-on: https://go-review.googlesource.com/19795 Reviewed-by: Keith Randall --- src/cmd/compile/internal/gc/testdata/unsafe_ssa.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/testdata/unsafe_ssa.go b/src/cmd/compile/internal/gc/testdata/unsafe_ssa.go index bc292828d5..d074eb1d5e 100644 --- a/src/cmd/compile/internal/gc/testdata/unsafe_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/unsafe_ssa.go @@ -123,7 +123,26 @@ func testg() { } } +func alias_ssa(ui64 *uint64, ui32 *uint32) uint32 { + *ui32 = 0xffffffff + *ui64 = 0 // store + ret := *ui32 // load from same address, should be zero + *ui64 = 0xffffffffffffffff // store + return ret +} +func testdse() { + x := int64(-1) + // construct two pointers that alias one another + ui64 := (*uint64)(unsafe.Pointer(&x)) + ui32 := (*uint32)(unsafe.Pointer(&x)) + if want, got := uint32(0), alias_ssa(ui64, ui32); got != want { + fmt.Printf("alias_ssa: wanted %d, got %d\n", want, got) + panic("alias_ssa") + } +} + func main() { testf() testg() + testdse() } -- cgit v1.3 From c17b6b488cbf448da374d576be0f921e655b00b1 Mon Sep 17 00:00:00 2001 From: Todd Neal Date: Fri, 19 Feb 2016 16:58:21 -0600 Subject: [dev.ssa] cmd/compile: truncate auxint when constructing Prog The upper bits of 8/16/32 bit constants are undefined. We need to truncate in order to prevent x86.oclass misidentifying the size of the constant. Fixes #14389 Change-Id: I3e5ff79cd904376572a93f489ba7e152a5cb6e60 Reviewed-on: https://go-review.googlesource.com/19740 Reviewed-by: Keith Randall --- src/cmd/compile/internal/gc/ssa.go | 39 ++++++++--------------- src/cmd/compile/internal/gc/testdata/arith_ssa.go | 37 +++++++++++++++++++++ src/cmd/compile/internal/ssa/value.go | 19 +++++++++++ 3 files changed, 70 insertions(+), 25 deletions(-) (limited to 'src/cmd/compile/internal/gc/testdata') diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 3f8fdce83b..19fda373bf 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -3990,7 +3990,7 @@ func (s *genState) genValue(v *ssa.Value) { r := regnum(v) a := regnum(v.Args[0]) if r == a { - if v.AuxInt == 1 { + if v.AuxInt2Int64() == 1 { var asm int switch v.Op { // Software optimization manual recommends add $1,reg. @@ -4009,7 +4009,7 @@ func (s *genState) genValue(v *ssa.Value) { p.To.Type = obj.TYPE_REG p.To.Reg = r return - } else if v.AuxInt == -1 { + } else if v.AuxInt2Int64() == -1 { var asm int switch v.Op { case ssa.OpAMD64ADDQconst: @@ -4026,7 +4026,7 @@ func (s *genState) genValue(v *ssa.Value) { } else { p := Prog(v.Op.Asm()) p.From.Type = obj.TYPE_CONST - p.From.Offset = v.AuxInt + p.From.Offset = v.AuxInt2Int64() p.To.Type = obj.TYPE_REG p.To.Reg = r return @@ -4044,7 +4044,7 @@ func (s *genState) genValue(v *ssa.Value) { p := Prog(asm) p.From.Type = obj.TYPE_MEM p.From.Reg = a - p.From.Offset = v.AuxInt + p.From.Offset = v.AuxInt2Int64() p.To.Type = obj.TYPE_REG p.To.Reg = r case ssa.OpAMD64MULQconst, ssa.OpAMD64MULLconst, ssa.OpAMD64MULWconst, ssa.OpAMD64MULBconst: @@ -4059,7 +4059,7 @@ func (s *genState) genValue(v *ssa.Value) { } p := Prog(v.Op.Asm()) p.From.Type = obj.TYPE_CONST - p.From.Offset = v.AuxInt + p.From.Offset = v.AuxInt2Int64() p.To.Type = obj.TYPE_REG p.To.Reg = r // TODO: Teach doasm to compile the three-address multiply imul $c, r1, r2 @@ -4074,7 +4074,7 @@ func (s *genState) genValue(v *ssa.Value) { // a = b + (- const), saves us 1 instruction. We can't fit // - (-1 << 31) into 4 bytes offset in lea. // We handle 2-address just fine below. - if v.AuxInt == -1<<31 || x == r { + if v.AuxInt2Int64() == -1<<31 || x == r { if x != r { // This code compensates for the fact that the register allocator // doesn't understand 2-address instructions yet. TODO: fix that. @@ -4086,10 +4086,10 @@ func (s *genState) genValue(v *ssa.Value) { } p := Prog(v.Op.Asm()) p.From.Type = obj.TYPE_CONST - p.From.Offset = v.AuxInt + p.From.Offset = v.AuxInt2Int64() p.To.Type = obj.TYPE_REG p.To.Reg = r - } else if x == r && v.AuxInt == -1 { + } else if x == r && v.AuxInt2Int64() == -1 { var asm int // x = x - (-1) is the same as x++ // See OpAMD64ADDQconst comments about inc vs add $1,reg @@ -4104,7 +4104,7 @@ func (s *genState) genValue(v *ssa.Value) { p := Prog(asm) p.To.Type = obj.TYPE_REG p.To.Reg = r - } else if x == r && v.AuxInt == 1 { + } else if x == r && v.AuxInt2Int64() == 1 { var asm int switch v.Op { case ssa.OpAMD64SUBQconst: @@ -4130,7 +4130,7 @@ func (s *genState) genValue(v *ssa.Value) { p := Prog(asm) p.From.Type = obj.TYPE_MEM p.From.Reg = x - p.From.Offset = -v.AuxInt + p.From.Offset = -v.AuxInt2Int64() p.To.Type = obj.TYPE_REG p.To.Reg = r } @@ -4157,7 +4157,7 @@ func (s *genState) genValue(v *ssa.Value) { } p := Prog(v.Op.Asm()) p.From.Type = obj.TYPE_CONST - p.From.Offset = v.AuxInt + p.From.Offset = v.AuxInt2Int64() p.To.Type = obj.TYPE_REG p.To.Reg = r case ssa.OpAMD64SBBQcarrymask, ssa.OpAMD64SBBLcarrymask: @@ -4204,29 +4204,18 @@ func (s *genState) genValue(v *ssa.Value) { p.From.Type = obj.TYPE_REG p.From.Reg = regnum(v.Args[0]) p.To.Type = obj.TYPE_CONST - p.To.Offset = v.AuxInt + p.To.Offset = v.AuxInt2Int64() case ssa.OpAMD64TESTQconst, ssa.OpAMD64TESTLconst, ssa.OpAMD64TESTWconst, ssa.OpAMD64TESTBconst: p := Prog(v.Op.Asm()) p.From.Type = obj.TYPE_CONST - p.From.Offset = v.AuxInt + p.From.Offset = v.AuxInt2Int64() p.To.Type = obj.TYPE_REG p.To.Reg = regnum(v.Args[0]) case ssa.OpAMD64MOVBconst, ssa.OpAMD64MOVWconst, ssa.OpAMD64MOVLconst, ssa.OpAMD64MOVQconst: x := regnum(v) p := Prog(v.Op.Asm()) p.From.Type = obj.TYPE_CONST - var i int64 - switch v.Op { - case ssa.OpAMD64MOVBconst: - i = int64(v.AuxInt8()) - case ssa.OpAMD64MOVWconst: - i = int64(v.AuxInt16()) - case ssa.OpAMD64MOVLconst: - i = int64(v.AuxInt32()) - case ssa.OpAMD64MOVQconst: - i = v.AuxInt - } - p.From.Offset = i + p.From.Offset = v.AuxInt2Int64() p.To.Type = obj.TYPE_REG p.To.Reg = x // If flags are live at this instruction, suppress the diff --git a/src/cmd/compile/internal/gc/testdata/arith_ssa.go b/src/cmd/compile/internal/gc/testdata/arith_ssa.go index 821c0dd12d..f4bea0ed11 100644 --- a/src/cmd/compile/internal/gc/testdata/arith_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/arith_ssa.go @@ -10,6 +10,42 @@ package main import "fmt" +const ( + y = 0x0fffFFFF +) + +//go:noinline +func invalidAdd_ssa(x uint32) uint32 { + return x + y + y + y + y + y + y + y + y + y + y + y + y + y + y + y + y + y +} + +//go:noinline +func invalidSub_ssa(x uint32) uint32 { + return x - y - y - y - y - y - y - y - y - y - y - y - y - y - y - y - y - y +} + +//go:noinline +func invalidMul_ssa(x uint32) uint32 { + return x * y * y * y * y * y * y * y * y * y * y * y * y * y * y * y * y * y +} + +// testLargeConst tests a situation where larger than 32 bit consts were passed to ADDL +// causing an invalid instruction error. +func testLargeConst() { + if want, got := uint32(268435440), invalidAdd_ssa(1); want != got { + println("testLargeConst add failed, wanted", want, "got", got) + failed = true + } + if want, got := uint32(4026531858), invalidSub_ssa(1); want != got { + println("testLargeConst sub failed, wanted", want, "got", got) + failed = true + } + if want, got := uint32(268435455), invalidMul_ssa(1); want != got { + println("testLargeConst mul failed, wanted", want, "got", got) + failed = true + } +} + // testArithRshConst ensures that "const >> const" right shifts correctly perform // sign extension on the lhs constant func testArithRshConst() { @@ -394,6 +430,7 @@ func main() { testOverflowConstShift() testArithConstShift() testArithRshConst() + testLargeConst() if failed { panic("failed") diff --git a/src/cmd/compile/internal/ssa/value.go b/src/cmd/compile/internal/ssa/value.go index c2ea6ee202..cc8c9fe871 100644 --- a/src/cmd/compile/internal/ssa/value.go +++ b/src/cmd/compile/internal/ssa/value.go @@ -77,6 +77,25 @@ func (v *Value) AuxInt32() int32 { } return int32(v.AuxInt) } + +// AuxInt2Int64 is used to sign extend the lower bits of AuxInt according to +// the size of AuxInt specified in the opcode table. +func (v *Value) AuxInt2Int64() int64 { + switch opcodeTable[v.Op].auxType { + case auxInt64: + return v.AuxInt + case auxInt32: + return int64(int32(v.AuxInt)) + case auxInt16: + return int64(int16(v.AuxInt)) + case auxInt8: + return int64(int8(v.AuxInt)) + default: + v.Fatalf("op %s doesn't have an aux int field", v.Op) + return -1 + } +} + func (v *Value) AuxFloat() float64 { if opcodeTable[v.Op].auxType != auxFloat { v.Fatalf("op %s doesn't have a float aux field", v.Op) -- cgit v1.3