From: Keith Randall Date: Mon, 19 Oct 2015 20:56:55 +0000 (-0700) Subject: [dev.ssa] Merge remote-tracking branch 'origin/master' into mergebranch X-Git-Tag: go1.7beta1~1623^2^2~134^2 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=7c4fbb650c3448a19dfcfe39ac46f8a25e0d2314;p=gostls13.git [dev.ssa] Merge remote-tracking branch 'origin/master' into mergebranch The only major fixup is that duffzero changed from 8-byte writes to 16-byte writes. Change-Id: I1762b74ce67a8e4b81c11568027cdb3572f7f87c --- 7c4fbb650c3448a19dfcfe39ac46f8a25e0d2314 diff --cc src/cmd/compile/internal/gc/ssa.go index 7219ffd653,0000000000..36f7435241 mode 100644,000000..100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@@ -1,4399 -1,0 +1,4402 @@@ +// 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 gc + +import ( + "bytes" + "crypto/sha1" + "fmt" + "html" + "math" + "os" + "strings" + + "cmd/compile/internal/ssa" + "cmd/internal/obj" + "cmd/internal/obj/x86" +) + +// buildssa builds an SSA function +// and reports whether it should be used. +// Once the SSA implementation is complete, +// 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") || strings.Contains(name, "_ssa.") || name == os.Getenv("GOSSAFUNC") + + if usessa { + fmt.Println("generating SSA for", name) + dumplist("buildssa-enter", fn.Func.Enter) + dumplist("buildssa-body", fn.Nbody) + dumplist("buildssa-exit", fn.Func.Exit) + } + + var s state + s.pushLine(fn.Lineno) + defer s.popLine() + + // TODO(khr): build config just once at the start of the compiler binary + + var e ssaExport + e.log = usessa + s.config = ssa.NewConfig(Thearch.Thestring, &e) + s.f = s.config.NewFunc() + s.f.Name = name + s.exitCode = fn.Func.Exit + + if name == os.Getenv("GOSSAFUNC") { + // TODO: tempfile? it is handy to have the location + // of this file be stable, so you can just reload in the browser. + s.config.HTML = ssa.NewHTMLWriter("ssa.html", &s, name) + // TODO: generate and print a mapping from nodes to values and blocks + } + defer func() { + if !usessa { + s.config.HTML.Close() + } + }() + + // If SSA support for the function is incomplete, + // assume that any panics are due to violated + // invariants. Swallow them silently. + defer func() { + if err := recover(); err != nil { + if !e.unimplemented { + panic(err) + } + } + }() + + // We construct SSA using an algorithm similar to + // Brau, Buchwald, Hack, Leißa, Mallon, and Zwinkau + // http://pp.info.uni-karlsruhe.de/uploads/publikationen/braun13cc.pdf + // TODO: check this comment + + // Allocate starting block + s.f.Entry = s.f.NewBlock(ssa.BlockPlain) + + // Allocate starting values + 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 + + s.varsyms = map[*Node]interface{}{} + + // 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: + aux := s.lookupSymbol(n, &ssa.ArgSymbol{Typ: n.Type, Node: n}) + s.decladdrs[n] = s.entryNewValue1A(ssa.OpAddr, Ptrto(n.Type), aux, s.sp) + case PAUTO | PHEAP: + // TODO this looks wrong for PAUTO|PHEAP, no vardef, but also no definition + aux := s.lookupSymbol(n, &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: + // 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: + // local function - already handled by frontend + default: + str := "" + if n.Class&PHEAP != 0 { + str = ",heap" + } + s.Unimplementedf("local variable with class %s%s unimplemented", classnames[n.Class&^PHEAP], str) + } + } + // nodfp is a special argument which is the function's FP. + aux := &ssa.ArgSymbol{Typ: Types[TUINTPTR], Node: nodfp} + s.decladdrs[nodfp] = s.entryNewValue1A(ssa.OpAddr, Types[TUINTPTR], aux, s.sp) + + // Convert the AST-based IR to the SSA-based IR + s.stmtList(fn.Func.Enter) + s.stmtList(fn.Nbody) + + // fallthrough to exit + if s.curBlock != nil { + s.stmtList(s.exitCode) + m := s.mem() + b := s.endBlock() + b.Kind = ssa.BlockRet + b.Control = m + } + + // 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() + + // Don't carry reference this around longer than necessary + s.exitCode = nil + + // Main call to ssa package to compile function + ssa.Compile(s.f) + + // Calculate stats about what percentage of functions SSA handles. + if false { + fmt.Printf("SSA implemented: %t\n", !e.unimplemented) + } + + if e.unimplemented { + return nil, false + } + + // TODO: enable codegen more broadly once the codegen stabilizes + // and runtime support is in (gc maps, write barriers, etc.) + if usessa { + return s.f, true + } + if localpkg.Name != os.Getenv("GOSSAPKG") { + return s.f, false + } + if os.Getenv("GOSSAHASH") == "" { + // Use everything in the package + return s.f, true + } + // Check the hash of the name against a partial input hash. + // We use this feature to do a binary search within a package to + // find a function that is incorrectly compiled. + hstr := "" + for _, b := range sha1.Sum([]byte(name)) { + hstr += fmt.Sprintf("%08b", b) + } + if strings.HasSuffix(hstr, os.Getenv("GOSSAHASH")) { + fmt.Printf("GOSSAHASH triggered %s\n", name) + return s.f, true + } + return s.f, false +} + +type state struct { + // configuration (arch) information + config *ssa.Config + + // function we're building + f *ssa.Func + + // 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 + // Code that must precede any return + // (e.g., copying value of heap-escaped paramout back to true paramout) + exitCode *NodeList + + // 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 + + // variable assignments in the current block (map from variable symbol to ssa value) + // *Node is the unique identifier (an ONAME Node) for the variable. + vars map[*Node]*ssa.Value + + // all defined variables at the end of each block. Indexed by block ID. + defvars []map[*Node]*ssa.Value + + // addresses of PPARAM and PPARAMOUT variables. + decladdrs map[*Node]*ssa.Value + + // symbols for PEXTERN, PAUTO and PPARAMOUT variables so they can be reused. + varsyms map[*Node]interface{} + + // starting values. Memory, frame pointer, and stack pointer + startmem *ssa.Value + sp *ssa.Value + sb *ssa.Value + + // line number stack. The current line number is top of stack + 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...) } + +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) { + if s.curBlock != nil { + s.Fatalf("starting block %v when block %v has not ended", b, s.curBlock) + } + s.curBlock = b + s.vars = map[*Node]*ssa.Value{} +} + +// endBlock marks the end of generating code for the current block. +// Returns the (former) current block. Returns nil if there is no current +// block, i.e. if no code flows to the current execution point. +func (s *state) endBlock() *ssa.Block { + b := s.curBlock + if b == nil { + return nil + } + for len(s.defvars) <= int(b.ID) { + s.defvars = append(s.defvars, nil) + } + s.defvars[b.ID] = s.vars + s.curBlock = nil + s.vars = nil + b.Line = s.peekLine() + return b +} + +// pushLine pushes a line number on the line number stack. +func (s *state) pushLine(line int32) { + s.line = append(s.line, line) +} + +// popLine pops the top of the line number stack. +func (s *state) popLine() { + s.line = s.line[:len(s.line)-1] +} + +// peekLine peek the top of the line number stack. +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) +} + +// newValue0A adds a new value with no arguments and an aux value to the current block. +func (s *state) newValue0A(op ssa.Op, t ssa.Type, aux interface{}) *ssa.Value { + return s.curBlock.NewValue0A(s.peekLine(), op, t, aux) +} + +// newValue0I adds a new value with no arguments and an auxint value to the current block. +func (s *state) newValue0I(op ssa.Op, t ssa.Type, auxint int64) *ssa.Value { + return s.curBlock.NewValue0I(s.peekLine(), op, t, auxint) +} + +// newValue1 adds a new value with one argument to the current block. +func (s *state) newValue1(op ssa.Op, t ssa.Type, arg *ssa.Value) *ssa.Value { + return s.curBlock.NewValue1(s.peekLine(), op, t, arg) +} + +// newValue1A adds a new value with one argument and an aux value to the current block. +func (s *state) newValue1A(op ssa.Op, t ssa.Type, aux interface{}, arg *ssa.Value) *ssa.Value { + return s.curBlock.NewValue1A(s.peekLine(), op, t, aux, arg) +} + +// newValue1I adds a new value with one argument and an auxint value to the current block. +func (s *state) newValue1I(op ssa.Op, t ssa.Type, aux int64, arg *ssa.Value) *ssa.Value { + return s.curBlock.NewValue1I(s.peekLine(), op, t, aux, arg) +} + +// newValue2 adds a new value with two arguments to the current block. +func (s *state) newValue2(op ssa.Op, t ssa.Type, arg0, arg1 *ssa.Value) *ssa.Value { + return s.curBlock.NewValue2(s.peekLine(), op, t, arg0, arg1) +} + +// newValue2I adds a new value with two arguments and an auxint value to the current block. +func (s *state) newValue2I(op ssa.Op, t ssa.Type, aux int64, arg0, arg1 *ssa.Value) *ssa.Value { + return s.curBlock.NewValue2I(s.peekLine(), op, t, aux, arg0, arg1) +} + +// newValue3 adds a new value with three arguments to the current block. +func (s *state) newValue3(op ssa.Op, t ssa.Type, arg0, arg1, arg2 *ssa.Value) *ssa.Value { + 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) +} + +// entryNewValue0 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) +} + +// entryNewValue0A adds a new value with no arguments and an aux value to the entry block. +func (s *state) entryNewValue0A(op ssa.Op, t ssa.Type, aux interface{}) *ssa.Value { + return s.f.Entry.NewValue0A(s.peekLine(), op, t, aux) +} + +// entryNewValue0I adds a new value with no arguments and an auxint value to the entry block. +func (s *state) entryNewValue0I(op ssa.Op, t ssa.Type, auxint int64) *ssa.Value { + return s.f.Entry.NewValue0I(s.peekLine(), op, t, auxint) +} + +// entryNewValue1 adds a new value with one argument to the entry block. +func (s *state) entryNewValue1(op ssa.Op, t ssa.Type, arg *ssa.Value) *ssa.Value { + return s.f.Entry.NewValue1(s.peekLine(), op, t, arg) +} + +// entryNewValue1 adds a new value with one argument and an auxint value to the entry block. +func (s *state) entryNewValue1I(op ssa.Op, t ssa.Type, auxint int64, arg *ssa.Value) *ssa.Value { + return s.f.Entry.NewValue1I(s.peekLine(), op, t, auxint, arg) +} + +// entryNewValue1A adds a new value with one argument and an aux value to the entry block. +func (s *state) entryNewValue1A(op ssa.Op, t ssa.Type, aux interface{}, arg *ssa.Value) *ssa.Value { + return s.f.Entry.NewValue1A(s.peekLine(), op, t, aux, arg) +} + +// entryNewValue2 adds a new value with two arguments to the entry block. +func (s *state) entryNewValue2(op ssa.Op, t ssa.Type, arg0, arg1 *ssa.Value) *ssa.Value { + return s.f.Entry.NewValue2(s.peekLine(), op, t, arg0, arg1) +} + +// const* routines add a new const value to the entry block. +func (s *state) constBool(c bool) *ssa.Value { + return s.f.ConstBool(s.peekLine(), Types[TBOOL], c) +} +func (s *state) constInt8(t ssa.Type, c int8) *ssa.Value { + return s.f.ConstInt8(s.peekLine(), t, c) +} +func (s *state) constInt16(t ssa.Type, c int16) *ssa.Value { + return s.f.ConstInt16(s.peekLine(), t, c) +} +func (s *state) constInt32(t ssa.Type, c int32) *ssa.Value { + return s.f.ConstInt32(s.peekLine(), t, c) +} +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) + } + return s.f.ConstIntPtr(s.peekLine(), t, c) +} +func (s *state) constInt(t ssa.Type, c int64) *ssa.Value { + if s.config.IntSize == 8 { + return s.constInt64(t, c) + } + if int64(int32(c)) != c { + s.Fatalf("integer constant too big %d", c) + } + return s.constInt32(t, int32(c)) +} + +// ssaStmtList converts the statement n to SSA and adds it to s. +func (s *state) stmtList(l *NodeList) { + for ; l != nil; l = l.Next { + s.stmt(l.N) + } +} + +// ssaStmt converts the statement n to SSA and adds it to s. +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 { + + case OBLOCK: + s.stmtList(n.List) + + // No-ops + case OEMPTY, ODCLCONST, ODCLTYPE, OFALL: + + // Expression statements + case OCALLFUNC, OCALLMETH, OCALLINTER: + s.call(n, callNormal) + case ODEFER: + s.call(n.Left, callDefer) + 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 + } + if compiling_runtime != 0 { + Fatalf("%v escapes to heap, not allowed in runtime.", n) + } + + // TODO: the old pass hides the details of PHEAP + // variables behind ONAME nodes. Figure out if it's better + // to rewrite the tree and make the heapaddr construct explicit + // or to keep this detail hidden behind the scenes. + palloc := prealloc[n.Left] + if palloc == nil { + palloc = callnew(n.Left.Type) + prealloc[n.Left] = palloc + } + r := s.expr(palloc) + s.assign(n.Left.Name.Heapaddr, r, false) + + case OLABEL: + sym := n.Left.Sym + + if isblanksym(sym) { + // Empty identifier is valid but useless. + // See issues 11589, 11593. + return + } + + 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 + } + } + + 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) + } + + // go to that label (we pretend "label:" is preceded by "goto label") + b := s.endBlock() + b.AddEdgeTo(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 lab.defined() { + s.checkgoto(n, lab.defNode) + } else { + s.fwdGotos = append(s.fwdGotos, n) + } + + b := s.endBlock() + b.AddEdgeTo(lab.target) + + case OAS, OASWB: + // Check whether we can generate static data rather than code. + // If so, ignore n and defer data generation until codegen. + // Failure to do this causes writes to readonly symbols. + if gen_as_init(n, true) { + var data []*Node + if s.f.StaticData != nil { + data = s.f.StaticData.([]*Node) + } + s.f.StaticData = append(data, n) + return + } + var r *ssa.Value + if n.Right != nil { + if n.Right.Op == OSTRUCTLIT || n.Right.Op == OARRAYLIT { + // All literals with nonzero fields have already been + // rewritten during walk. Any that remain are just T{} + // or equivalents. Leave r = nil to get zeroing behavior. + if !iszero(n.Right) { + Fatalf("literal with nonzero value in SSA: %v", n.Right) + } + } else { + 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: + cond := s.expr(n.Left) + b := s.endBlock() + b.Kind = ssa.BlockIf + b.Control = cond + b.Likely = ssa.BranchPrediction(n.Likely) // gc and ssa both use -1/0/+1 for likeliness + + bThen := s.f.NewBlock(ssa.BlockPlain) + bEnd := s.f.NewBlock(ssa.BlockPlain) + var bElse *ssa.Block + + if n.Rlist == nil { + b.AddEdgeTo(bThen) + b.AddEdgeTo(bEnd) + } else { + bElse = s.f.NewBlock(ssa.BlockPlain) + b.AddEdgeTo(bThen) + b.AddEdgeTo(bElse) + } + + s.startBlock(bThen) + s.stmtList(n.Nbody) + if b := s.endBlock(); b != nil { + b.AddEdgeTo(bEnd) + } + + if n.Rlist != nil { + s.startBlock(bElse) + s.stmtList(n.Rlist) + if b := s.endBlock(); b != nil { + b.AddEdgeTo(bEnd) + } + } + s.startBlock(bEnd) + + case ORETURN: + s.stmtList(n.List) + s.stmtList(s.exitCode) + m := s.mem() + b := s.endBlock() + b.Kind = ssa.BlockRet + b.Control = m + case ORETJMP: + s.stmtList(n.List) + s.stmtList(s.exitCode) + m := s.mem() + b := s.endBlock() + b.Kind = ssa.BlockRetJmp + b.Aux = n.Left.Sym + b.Control = m + + 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() + b.AddEdgeTo(to) + + case OFOR: + // OFOR: for Ninit; Left; Right { Nbody } + bCond := s.f.NewBlock(ssa.BlockPlain) + bBody := s.f.NewBlock(ssa.BlockPlain) + bIncr := s.f.NewBlock(ssa.BlockPlain) + bEnd := s.f.NewBlock(ssa.BlockPlain) + + // first, jump to condition test + b := s.endBlock() + b.AddEdgeTo(bCond) + + // generate code to test condition + s.startBlock(bCond) + var cond *ssa.Value + if n.Left != nil { + cond = s.expr(n.Left) + } else { + cond = s.constBool(true) + } + b = s.endBlock() + b.Kind = ssa.BlockIf + b.Control = cond + b.Likely = ssa.BranchLikely + b.AddEdgeTo(bBody) + b.AddEdgeTo(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 { + b.AddEdgeTo(bIncr) + } + + // generate incr + s.startBlock(bIncr) + if n.Right != nil { + s.stmt(n.Right) + } + if b := s.endBlock(); b != nil { + b.AddEdgeTo(bCond) + } + 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 { + b.AddEdgeTo(bEnd) + } + s.startBlock(bEnd) + + case OVARKILL: + // Insert a varkill op to record that a variable is no longer live. + // We only care about liveness info at call sites, so putting the + // varkill in the store chain is enough to keep it correctly ordered + // with respect to call ops. + if !canSSA(n.Left) { + s.vars[&memVar] = s.newValue1A(ssa.OpVarKill, ssa.TypeMem, n.Left, s.mem()) + } + + case OCHECKNIL: + p := s.expr(n.Left) + s.nilCheck(p) + + default: + s.Unimplementedf("unhandled stmt %s", opnames[n.Op]) + } +} + +type opAndType struct { + op uint8 + etype uint8 +} + +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{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, + + 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, + opAndType{OCOM, TINT16}: ssa.OpCom16, + opAndType{OCOM, TUINT16}: ssa.OpCom16, + opAndType{OCOM, TINT32}: ssa.OpCom32, + opAndType{OCOM, TUINT32}: ssa.OpCom32, + opAndType{OCOM, TINT64}: ssa.OpCom64, + opAndType{OCOM, TUINT64}: ssa.OpCom64, + + opAndType{OIMAG, TCOMPLEX64}: ssa.OpComplexImag, + opAndType{OIMAG, TCOMPLEX128}: ssa.OpComplexImag, + opAndType{OREAL, TCOMPLEX64}: ssa.OpComplexReal, + opAndType{OREAL, TCOMPLEX128}: ssa.OpComplexReal, + + 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{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, + 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{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, + opAndType{OAND, TUINT16}: ssa.OpAnd16, + opAndType{OAND, TINT32}: ssa.OpAnd32, + opAndType{OAND, TUINT32}: ssa.OpAnd32, + 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{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, + opAndType{OEQ, TINT16}: ssa.OpEq16, + opAndType{OEQ, TUINT16}: ssa.OpEq16, + opAndType{OEQ, TINT32}: ssa.OpEq32, + opAndType{OEQ, TUINT32}: ssa.OpEq32, + opAndType{OEQ, TINT64}: ssa.OpEq64, + opAndType{OEQ, TUINT64}: ssa.OpEq64, + opAndType{OEQ, TINTER}: ssa.OpEqInter, + opAndType{OEQ, TARRAY}: ssa.OpEqSlice, + opAndType{OEQ, TFUNC}: ssa.OpEqPtr, + opAndType{OEQ, TMAP}: ssa.OpEqPtr, + opAndType{OEQ, TCHAN}: ssa.OpEqPtr, + opAndType{OEQ, TPTR64}: 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, + opAndType{ONE, TUINT8}: ssa.OpNeq8, + opAndType{ONE, TINT16}: ssa.OpNeq16, + opAndType{ONE, TUINT16}: ssa.OpNeq16, + opAndType{ONE, TINT32}: ssa.OpNeq32, + opAndType{ONE, TUINT32}: ssa.OpNeq32, + opAndType{ONE, TINT64}: ssa.OpNeq64, + opAndType{ONE, TUINT64}: ssa.OpNeq64, + opAndType{ONE, TINTER}: ssa.OpNeqInter, + opAndType{ONE, TARRAY}: ssa.OpNeqSlice, + opAndType{ONE, TFUNC}: ssa.OpNeqPtr, + opAndType{ONE, TMAP}: ssa.OpNeqPtr, + opAndType{ONE, TCHAN}: ssa.OpNeqPtr, + opAndType{ONE, TPTR64}: ssa.OpNeqPtr, + opAndType{ONE, TUINTPTR}: ssa.OpNeqPtr, + opAndType{ONE, TUNSAFEPTR}: ssa.OpNeqPtr, + 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, + opAndType{OLROT, TUINT32}: ssa.OpLrot32, + opAndType{OLROT, TUINT64}: ssa.OpLrot64, + + opAndType{OSQRT, TFLOAT64}: ssa.OpSqrt, +} + +func (s *state) concreteEtype(t *Type) uint8 { + e := t.Etype + switch e { + default: + return e + case TINT: + if s.config.IntSize == 8 { + return TINT64 + } + return TINT32 + case TUINT: + if s.config.IntSize == 8 { + return TUINT64 + } + return TUINT32 + case TUINTPTR: + if s.config.PtrSize == 8 { + return TUINT64 + } + return TUINT32 + } +} + +func (s *state) ssaOp(op uint8, t *Type) ssa.Op { + etype := s.concreteEtype(t) + x, ok := opToSSA[opAndType{op, etype}] + if !ok { + s.Unimplementedf("unhandled binary op %s %s", opnames[op], Econv(int(etype), 0)) + } + 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 + etype2 uint8 +} + +type twoTypes struct { + etype1 uint8 + etype2 uint8 +} + +type twoOpsAndType struct { + op1 ssa.Op + op2 ssa.Op + intermediateType uint8 +} + +var fpConvOpToSSA = map[twoTypes]twoOpsAndType{ + + twoTypes{TINT8, TFLOAT32}: twoOpsAndType{ssa.OpSignExt8to32, ssa.OpCvt32to32F, TINT32}, + twoTypes{TINT16, TFLOAT32}: twoOpsAndType{ssa.OpSignExt16to32, ssa.OpCvt32to32F, TINT32}, + twoTypes{TINT32, TFLOAT32}: twoOpsAndType{ssa.OpCopy, ssa.OpCvt32to32F, TINT32}, + twoTypes{TINT64, TFLOAT32}: twoOpsAndType{ssa.OpCopy, ssa.OpCvt64to32F, TINT64}, + + twoTypes{TINT8, TFLOAT64}: twoOpsAndType{ssa.OpSignExt8to32, ssa.OpCvt32to64F, TINT32}, + twoTypes{TINT16, TFLOAT64}: twoOpsAndType{ssa.OpSignExt16to32, ssa.OpCvt32to64F, TINT32}, + twoTypes{TINT32, TFLOAT64}: twoOpsAndType{ssa.OpCopy, ssa.OpCvt32to64F, TINT32}, + twoTypes{TINT64, TFLOAT64}: twoOpsAndType{ssa.OpCopy, ssa.OpCvt64to64F, TINT64}, + + twoTypes{TFLOAT32, TINT8}: twoOpsAndType{ssa.OpCvt32Fto32, ssa.OpTrunc32to8, TINT32}, + twoTypes{TFLOAT32, TINT16}: twoOpsAndType{ssa.OpCvt32Fto32, ssa.OpTrunc32to16, TINT32}, + twoTypes{TFLOAT32, TINT32}: twoOpsAndType{ssa.OpCvt32Fto32, ssa.OpCopy, TINT32}, + twoTypes{TFLOAT32, TINT64}: twoOpsAndType{ssa.OpCvt32Fto64, ssa.OpCopy, TINT64}, + + twoTypes{TFLOAT64, TINT8}: twoOpsAndType{ssa.OpCvt64Fto32, ssa.OpTrunc32to8, TINT32}, + twoTypes{TFLOAT64, TINT16}: twoOpsAndType{ssa.OpCvt64Fto32, ssa.OpTrunc32to16, TINT32}, + twoTypes{TFLOAT64, TINT32}: twoOpsAndType{ssa.OpCvt64Fto32, ssa.OpCopy, TINT32}, + twoTypes{TFLOAT64, TINT64}: twoOpsAndType{ssa.OpCvt64Fto64, ssa.OpCopy, TINT64}, + // unsigned + twoTypes{TUINT8, TFLOAT32}: twoOpsAndType{ssa.OpZeroExt8to32, ssa.OpCvt32to32F, TINT32}, + twoTypes{TUINT16, TFLOAT32}: twoOpsAndType{ssa.OpZeroExt16to32, ssa.OpCvt32to32F, TINT32}, + twoTypes{TUINT32, TFLOAT32}: twoOpsAndType{ssa.OpZeroExt32to64, ssa.OpCvt64to32F, TINT64}, // go wide to dodge unsigned + twoTypes{TUINT64, TFLOAT32}: twoOpsAndType{ssa.OpCopy, ssa.OpInvalid, TUINT64}, // Cvt64Uto32F, branchy code expansion instead + + twoTypes{TUINT8, TFLOAT64}: twoOpsAndType{ssa.OpZeroExt8to32, ssa.OpCvt32to64F, TINT32}, + twoTypes{TUINT16, TFLOAT64}: twoOpsAndType{ssa.OpZeroExt16to32, ssa.OpCvt32to64F, TINT32}, + twoTypes{TUINT32, TFLOAT64}: twoOpsAndType{ssa.OpZeroExt32to64, ssa.OpCvt64to64F, TINT64}, // go wide to dodge unsigned + twoTypes{TUINT64, TFLOAT64}: twoOpsAndType{ssa.OpCopy, ssa.OpInvalid, TUINT64}, // Cvt64Uto64F, branchy code expansion instead + + twoTypes{TFLOAT32, TUINT8}: twoOpsAndType{ssa.OpCvt32Fto32, ssa.OpTrunc32to8, TINT32}, + twoTypes{TFLOAT32, TUINT16}: twoOpsAndType{ssa.OpCvt32Fto32, ssa.OpTrunc32to16, TINT32}, + twoTypes{TFLOAT32, TUINT32}: twoOpsAndType{ssa.OpCvt32Fto64, ssa.OpTrunc64to32, TINT64}, // go wide to dodge unsigned + twoTypes{TFLOAT32, TUINT64}: twoOpsAndType{ssa.OpInvalid, ssa.OpCopy, TUINT64}, // Cvt32Fto64U, branchy code expansion instead + + twoTypes{TFLOAT64, TUINT8}: twoOpsAndType{ssa.OpCvt64Fto32, ssa.OpTrunc32to8, TINT32}, + twoTypes{TFLOAT64, TUINT16}: twoOpsAndType{ssa.OpCvt64Fto32, ssa.OpTrunc32to16, TINT32}, + twoTypes{TFLOAT64, TUINT32}: twoOpsAndType{ssa.OpCvt64Fto64, ssa.OpTrunc64to32, TINT64}, // go wide to dodge unsigned + twoTypes{TFLOAT64, TUINT64}: twoOpsAndType{ssa.OpInvalid, ssa.OpCopy, TUINT64}, // Cvt64Fto64U, branchy code expansion instead + + // float + twoTypes{TFLOAT64, TFLOAT32}: twoOpsAndType{ssa.OpCvt64Fto32F, ssa.OpCopy, TFLOAT32}, + twoTypes{TFLOAT64, TFLOAT64}: twoOpsAndType{ssa.OpCopy, ssa.OpCopy, TFLOAT64}, + twoTypes{TFLOAT32, TFLOAT32}: twoOpsAndType{ssa.OpCopy, ssa.OpCopy, TFLOAT32}, + twoTypes{TFLOAT32, TFLOAT64}: twoOpsAndType{ssa.OpCvt32Fto64F, ssa.OpCopy, TFLOAT64}, +} + +var shiftOpToSSA = map[opAndTwoTypes]ssa.Op{ + opAndTwoTypes{OLSH, TINT8, TUINT8}: ssa.OpLsh8x8, + opAndTwoTypes{OLSH, TUINT8, TUINT8}: ssa.OpLsh8x8, + opAndTwoTypes{OLSH, TINT8, TUINT16}: ssa.OpLsh8x16, + opAndTwoTypes{OLSH, TUINT8, TUINT16}: ssa.OpLsh8x16, + opAndTwoTypes{OLSH, TINT8, TUINT32}: ssa.OpLsh8x32, + opAndTwoTypes{OLSH, TUINT8, TUINT32}: ssa.OpLsh8x32, + opAndTwoTypes{OLSH, TINT8, TUINT64}: ssa.OpLsh8x64, + opAndTwoTypes{OLSH, TUINT8, TUINT64}: ssa.OpLsh8x64, + + opAndTwoTypes{OLSH, TINT16, TUINT8}: ssa.OpLsh16x8, + opAndTwoTypes{OLSH, TUINT16, TUINT8}: ssa.OpLsh16x8, + opAndTwoTypes{OLSH, TINT16, TUINT16}: ssa.OpLsh16x16, + opAndTwoTypes{OLSH, TUINT16, TUINT16}: ssa.OpLsh16x16, + opAndTwoTypes{OLSH, TINT16, TUINT32}: ssa.OpLsh16x32, + opAndTwoTypes{OLSH, TUINT16, TUINT32}: ssa.OpLsh16x32, + opAndTwoTypes{OLSH, TINT16, TUINT64}: ssa.OpLsh16x64, + opAndTwoTypes{OLSH, TUINT16, TUINT64}: ssa.OpLsh16x64, + + opAndTwoTypes{OLSH, TINT32, TUINT8}: ssa.OpLsh32x8, + opAndTwoTypes{OLSH, TUINT32, TUINT8}: ssa.OpLsh32x8, + opAndTwoTypes{OLSH, TINT32, TUINT16}: ssa.OpLsh32x16, + opAndTwoTypes{OLSH, TUINT32, TUINT16}: ssa.OpLsh32x16, + opAndTwoTypes{OLSH, TINT32, TUINT32}: ssa.OpLsh32x32, + opAndTwoTypes{OLSH, TUINT32, TUINT32}: ssa.OpLsh32x32, + opAndTwoTypes{OLSH, TINT32, TUINT64}: ssa.OpLsh32x64, + opAndTwoTypes{OLSH, TUINT32, TUINT64}: ssa.OpLsh32x64, + + opAndTwoTypes{OLSH, TINT64, TUINT8}: ssa.OpLsh64x8, + opAndTwoTypes{OLSH, TUINT64, TUINT8}: ssa.OpLsh64x8, + opAndTwoTypes{OLSH, TINT64, TUINT16}: ssa.OpLsh64x16, + opAndTwoTypes{OLSH, TUINT64, TUINT16}: ssa.OpLsh64x16, + opAndTwoTypes{OLSH, TINT64, TUINT32}: ssa.OpLsh64x32, + opAndTwoTypes{OLSH, TUINT64, TUINT32}: ssa.OpLsh64x32, + opAndTwoTypes{OLSH, TINT64, TUINT64}: ssa.OpLsh64x64, + opAndTwoTypes{OLSH, TUINT64, TUINT64}: ssa.OpLsh64x64, + + opAndTwoTypes{ORSH, TINT8, TUINT8}: ssa.OpRsh8x8, + opAndTwoTypes{ORSH, TUINT8, TUINT8}: ssa.OpRsh8Ux8, + opAndTwoTypes{ORSH, TINT8, TUINT16}: ssa.OpRsh8x16, + opAndTwoTypes{ORSH, TUINT8, TUINT16}: ssa.OpRsh8Ux16, + opAndTwoTypes{ORSH, TINT8, TUINT32}: ssa.OpRsh8x32, + opAndTwoTypes{ORSH, TUINT8, TUINT32}: ssa.OpRsh8Ux32, + opAndTwoTypes{ORSH, TINT8, TUINT64}: ssa.OpRsh8x64, + opAndTwoTypes{ORSH, TUINT8, TUINT64}: ssa.OpRsh8Ux64, + + opAndTwoTypes{ORSH, TINT16, TUINT8}: ssa.OpRsh16x8, + opAndTwoTypes{ORSH, TUINT16, TUINT8}: ssa.OpRsh16Ux8, + opAndTwoTypes{ORSH, TINT16, TUINT16}: ssa.OpRsh16x16, + opAndTwoTypes{ORSH, TUINT16, TUINT16}: ssa.OpRsh16Ux16, + opAndTwoTypes{ORSH, TINT16, TUINT32}: ssa.OpRsh16x32, + opAndTwoTypes{ORSH, TUINT16, TUINT32}: ssa.OpRsh16Ux32, + opAndTwoTypes{ORSH, TINT16, TUINT64}: ssa.OpRsh16x64, + opAndTwoTypes{ORSH, TUINT16, TUINT64}: ssa.OpRsh16Ux64, + + opAndTwoTypes{ORSH, TINT32, TUINT8}: ssa.OpRsh32x8, + opAndTwoTypes{ORSH, TUINT32, TUINT8}: ssa.OpRsh32Ux8, + opAndTwoTypes{ORSH, TINT32, TUINT16}: ssa.OpRsh32x16, + opAndTwoTypes{ORSH, TUINT32, TUINT16}: ssa.OpRsh32Ux16, + opAndTwoTypes{ORSH, TINT32, TUINT32}: ssa.OpRsh32x32, + opAndTwoTypes{ORSH, TUINT32, TUINT32}: ssa.OpRsh32Ux32, + opAndTwoTypes{ORSH, TINT32, TUINT64}: ssa.OpRsh32x64, + opAndTwoTypes{ORSH, TUINT32, TUINT64}: ssa.OpRsh32Ux64, + + opAndTwoTypes{ORSH, TINT64, TUINT8}: ssa.OpRsh64x8, + opAndTwoTypes{ORSH, TUINT64, TUINT8}: ssa.OpRsh64Ux8, + opAndTwoTypes{ORSH, TINT64, TUINT16}: ssa.OpRsh64x16, + opAndTwoTypes{ORSH, TUINT64, TUINT16}: ssa.OpRsh64Ux16, + opAndTwoTypes{ORSH, TINT64, TUINT32}: ssa.OpRsh64x32, + opAndTwoTypes{ORSH, TUINT64, TUINT32}: ssa.OpRsh64Ux32, + opAndTwoTypes{ORSH, TINT64, TUINT64}: ssa.OpRsh64x64, + opAndTwoTypes{ORSH, TUINT64, TUINT64}: ssa.OpRsh64Ux64, +} + +func (s *state) ssaShiftOp(op uint8, t *Type, u *Type) ssa.Op { + etype1 := s.concreteEtype(t) + etype2 := s.concreteEtype(u) + x, ok := shiftOpToSSA[opAndTwoTypes{op, etype1, etype2}] + if !ok { + s.Unimplementedf("unhandled shift op %s etype=%s/%s", opnames[op], Econv(int(etype1), 0), Econv(int(etype2), 0)) + } + 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) + defer s.popLine() + + s.stmtList(n.Ninit) + switch n.Op { + case OCFUNC: + aux := s.lookupSymbol(n, &ssa.ExternSymbol{n.Type, n.Left.Sym}) + return s.entryNewValue1A(ssa.OpAddr, n.Type, aux, s.sb) + case OPARAM: + addr := s.addr(n, false) + return s.newValue2(ssa.OpLoad, n.Left.Type, addr, s.mem()) + case ONAME: + if n.Class == PFUNC { + // "value" of a function is the address of the function's closure + sym := funcsym(n.Sym) + aux := &ssa.ExternSymbol{n.Type, sym} + return s.entryNewValue1A(ssa.OpAddr, Ptrto(n.Type), aux, s.sb) + } + if canSSA(n) { + return s.variable(n, n.Type) + } + addr := s.addr(n, false) + return s.newValue2(ssa.OpLoad, n.Type, addr, s.mem()) + case OCLOSUREVAR: + addr := s.addr(n, false) + return s.newValue2(ssa.OpLoad, n.Type, addr, s.mem()) + case OLITERAL: + switch n.Val().Ctype() { + case CTINT: + i := Mpgetfix(n.Val().U.(*Mpint)) + switch n.Type.Size() { + case 1: + return s.constInt8(n.Type, int8(i)) + case 2: + return s.constInt16(n.Type, int16(i)) + case 4: + return s.constInt32(n.Type, int32(i)) + case 8: + return s.constInt64(n.Type, i) + default: + s.Fatalf("bad integer size %d", n.Type.Size()) + return nil + } + case CTSTR: + return s.entryNewValue0A(ssa.OpConstString, n.Type, n.Val().U) + case CTBOOL: + return s.constBool(n.Val().U.(bool)) + case CTNIL: + 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() { + case 4: + // -0.0 literals need to be treated as if they were 0.0, adding 0.0 here + // accomplishes this while not affecting other values. + return s.constFloat32(n.Type, mpgetflt32(f)+0.0) + case 8: + return s.constFloat64(n.Type, mpgetflt(f)+0.0) + default: + 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] + // -0.0 literals need to be treated as if they were 0.0, adding 0.0 here + // accomplishes this while not affecting other values. + return s.newValue2(ssa.OpComplexMake, n.Type, + s.constFloat32(pt, mpgetflt32(r)+0.0), + s.constFloat32(pt, mpgetflt32(i)+0.0)) + } + case 16: + { + pt := Types[TFLOAT64] + return s.newValue2(ssa.OpComplexMake, n.Type, + s.constFloat64(pt, mpgetflt(r)+0.0), + s.constFloat64(pt, mpgetflt(i)+0.0)) + } + default: + s.Fatalf("bad float size %d", n.Type.Size()) + return nil + } + + default: + s.Unimplementedf("unhandled OLITERAL %v", n.Val().Ctype()) + return nil + } + case OCONVNOP: + to := n.Type + from := n.Left.Type + + // 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 + } + // unsafe.Pointer <--> *T + if to.Etype == TUNSAFEPTR && from.IsPtr() || from.Etype == TUNSAFEPTR && to.IsPtr() { + return v + } + + dowidth(from) + dowidth(to) + if from.Width != to.Width { + s.Fatalf("CONVNOP width mismatch %v (%d) -> %v (%d)\n", from, from.Width, to, to.Width) + return nil + } + if etypesign(from.Etype) != etypesign(to.Etype) { + s.Fatalf("CONVNOP sign mismatch %v (%s) -> %v (%s)\n", from, Econv(int(from.Etype), 0), to, Econv(int(to.Etype), 0)) + return nil + } + + if flag_race != 0 { + // These appear to be fine, but they fail the + // integer constraint below, so okay them here. + // Sample non-integer conversion: map[string]string -> *uint8 + return v + } + + if etypesign(from.Etype) == 0 { + s.Fatalf("CONVNOP unrecognized non-integer %v -> %v\n", from, to) + return nil + } + + // integer, same width, same sign + return v + + case OCONV: + x := s.expr(n.Left) + ft := n.Left.Type // from type + tt := n.Type // to type + if ft.IsInteger() && tt.IsInteger() { + var op ssa.Op + if tt.Size() == ft.Size() { + op = ssa.OpCopy + } else if tt.Size() < ft.Size() { + // truncation + switch 10*ft.Size() + tt.Size() { + case 21: + op = ssa.OpTrunc16to8 + case 41: + op = ssa.OpTrunc32to8 + case 42: + op = ssa.OpTrunc32to16 + case 81: + op = ssa.OpTrunc64to8 + case 82: + op = ssa.OpTrunc64to16 + case 84: + op = ssa.OpTrunc64to32 + default: + s.Fatalf("weird integer truncation %s -> %s", ft, tt) + } + } else if ft.IsSigned() { + // sign extension + switch 10*ft.Size() + tt.Size() { + case 12: + op = ssa.OpSignExt8to16 + case 14: + op = ssa.OpSignExt8to32 + case 18: + op = ssa.OpSignExt8to64 + case 24: + op = ssa.OpSignExt16to32 + case 28: + op = ssa.OpSignExt16to64 + case 48: + op = ssa.OpSignExt32to64 + default: + s.Fatalf("bad integer sign extension %s -> %s", ft, tt) + } + } else { + // zero extension + switch 10*ft.Size() + tt.Size() { + case 12: + op = ssa.OpZeroExt8to16 + case 14: + op = ssa.OpZeroExt8to32 + case 18: + op = ssa.OpZeroExt8to64 + case 24: + op = ssa.OpZeroExt16to32 + case 28: + op = ssa.OpZeroExt16to64 + case 48: + op = ssa.OpZeroExt32to64 + default: + s.Fatalf("weird integer sign extension %s -> %s", ft, tt) + } + } + return s.newValue1(op, n.Type, x) + } + + if ft.IsFloat() || tt.IsFloat() { + conv, ok := fpConvOpToSSA[twoTypes{s.concreteEtype(ft), s.concreteEtype(tt)}] + if !ok { + s.Fatalf("weird float conversion %s -> %s", ft, tt) + } + op1, op2, it := conv.op1, conv.op2, conv.intermediateType + + if op1 != ssa.OpInvalid && op2 != ssa.OpInvalid { + // normal case, not tripping over unsigned 64 + if op1 == ssa.OpCopy { + if op2 == ssa.OpCopy { + return x + } + return s.newValue1(op2, n.Type, x) + } + if op2 == ssa.OpCopy { + return s.newValue1(op1, n.Type, x) + } + return s.newValue1(op2, n.Type, s.newValue1(op1, Types[it], x)) + } + // Tricky 64-bit unsigned cases. + if ft.IsInteger() { + // therefore tt is float32 or float64, and ft is also unsigned + if tt.Size() == 4 { + return s.uint64Tofloat32(n, x, ft, tt) + } + if tt.Size() == 8 { + return s.uint64Tofloat64(n, x, ft, tt) + } + s.Fatalf("weird unsigned integer to float conversion %s -> %s", ft, tt) + } + // therefore ft is float32 or float64, and tt is unsigned integer + if ft.Size() == 4 { + return s.float32ToUint64(n, x, ft, tt) + } + if ft.Size() == 8 { + return s.float64ToUint64(n, x, ft, tt) + } + s.Fatalf("weird float to unsigned integer conversion %s -> %s", ft, tt) + return nil + } + + 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 + + case ODOTTYPE: + res, _ := s.dottype(n, false) + return res + + // binary ops + 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.Left.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) + 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) + case OLSH, ORSH: + 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 + // variable is associated with the OANDAND node in the + // s.vars table (normally variables are only + // associated with ONAME nodes). We convert + // A && B + // to + // var = A + // if var { + // var = B + // } + // Using var in the subsequent block introduces the + // necessary phi variable. + el := s.expr(n.Left) + s.vars[n] = el + + b := s.endBlock() + b.Kind = ssa.BlockIf + b.Control = el + // In theory, we should set b.Likely here based on context. + // However, gc only gives us likeliness hints + // in a single place, for plain OIF statements, + // and passing around context is finnicky, so don't bother for now. + + bRight := s.f.NewBlock(ssa.BlockPlain) + bResult := s.f.NewBlock(ssa.BlockPlain) + if n.Op == OANDAND { + b.AddEdgeTo(bRight) + b.AddEdgeTo(bResult) + } else if n.Op == OOROR { + b.AddEdgeTo(bResult) + b.AddEdgeTo(bRight) + } + + s.startBlock(bRight) + er := s.expr(n.Right) + s.vars[n] = er + + b = s.endBlock() + b.AddEdgeTo(bResult) + + s.startBlock(bResult) + return s.variable(n, Types[TBOOL]) + case OCOMPLEX: + r := s.expr(n.Left) + i := s.expr(n.Right) + return s.newValue2(ssa.OpComplexMake, n.Type, r, i) + + // 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, OSQRT: + 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) + + case OADDR: + return s.addr(n.Left, n.Bounded) + + case OINDREG: + if int(n.Reg) != Thearch.REGSP { + s.Unimplementedf("OINDREG of non-SP register %s in expr: %v", obj.Rconv(int(n.Reg)), n) + return nil + } + addr := s.entryNewValue1I(ssa.OpOffPtr, Ptrto(n.Type), n.Xoffset, s.sp) + return s.newValue2(ssa.OpLoad, n.Type, addr, s.mem()) + + case OIND: + p := s.expr(n.Left) + s.nilCheck(p) + return s.newValue2(ssa.OpLoad, n.Type, p, s.mem()) + + case ODOT: + // TODO: fix when we can SSA struct types. + p := s.addr(n, false) + return s.newValue2(ssa.OpLoad, n.Type, p, s.mem()) + + case ODOTPTR: + p := s.expr(n.Left) + s.nilCheck(p) + p = s.newValue2(ssa.OpAddPtr, p.Type, p, s.constIntPtr(Types[TUINTPTR], n.Xoffset)) + return s.newValue2(ssa.OpLoad, n.Type, p, s.mem()) + + case OINDEX: + switch { + case n.Left.Type.IsString(): + a := s.expr(n.Left) + i := s.expr(n.Right) + i = s.extendIndex(i) + 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()) + case n.Left.Type.IsSlice(): + p := s.addr(n, false) + return s.newValue2(ssa.OpLoad, n.Left.Type.Type, p, s.mem()) + case n.Left.Type.IsArray(): + // TODO: fix when we can SSA arrays of length 1. + p := s.addr(n, false) + return s.newValue2(ssa.OpLoad, n.Left.Type.Type, p, s.mem()) + default: + s.Fatalf("bad type for index %v", n.Left.Type) + return nil + } + + case OLEN, OCAP: + switch { + case n.Left.Type.IsSlice(): + op := ssa.OpSliceLen + if n.Op == OCAP { + op = ssa.OpSliceCap + } + 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(), n.Left.Type.IsChan(): + return s.referenceTypeBuiltin(n, s.expr(n.Left)) + default: // array + return s.constInt(Types[TINT], n.Left.Type.Bound) + } + + case OSPTR: + a := s.expr(n.Left) + if n.Left.Type.IsSlice() { + return s.newValue1(ssa.OpSlicePtr, n.Type, a) + } else { + return s.newValue1(ssa.OpStringPtr, n.Type, a) + } + + case OITAB: + a := s.expr(n.Left) + return s.newValue1(ssa.OpITab, n.Type, a) + + case OEFACE: + tab := s.expr(n.Left) + data := s.expr(n.Right) + // The frontend allows putting things like struct{*byte} in + // the data portion of an eface. But we don't want struct{*byte} + // as a register type because (among other reasons) the liveness + // analysis is confused by the "fat" variables that result from + // such types being spilled. + // So here we ensure that we are selecting the underlying pointer + // when we build an eface. + for !data.Type.IsPtr() { + switch { + case data.Type.IsArray(): + data = s.newValue2(ssa.OpArrayIndex, data.Type.Elem(), data, s.constInt(Types[TINT], 0)) + case data.Type.IsStruct(): + for i := data.Type.NumFields() - 1; i >= 0; i-- { + f := data.Type.FieldType(i) + if f.Size() == 0 { + // eface type could also be struct{p *byte; q [0]int} + continue + } + data = s.newValue1I(ssa.OpStructSelect, f, data.Type.FieldOff(i), data) + break + } + default: + s.Fatalf("type being put into an eface isn't a pointer") + } + } + 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: + 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, _ := 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)) + } + 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, OCALLINTER, OCALLMETH: + return s.call(n, callNormal) + + 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) + + // Allocate new blocks + grow := s.f.NewBlock(ssa.BlockPlain) + assign := s.f.NewBlock(ssa.BlockPlain) + + // Decide if we need to grow + nargs := int64(count(n.List) - 1) + 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) + + r := s.rtcall(growslice, true, []*Type{pt, Types[TINT], Types[TINT]}, taddr, p, l, c, nl) + + s.vars[&ptrVar] = r[0] + // Note: we don't need to read r[1], the result's length. It will be nl. + // (or maybe we should, we just have to spill/restore nl otherwise?) + s.vars[&capVar] = r[2] + b = s.endBlock() + b.AddEdgeTo(assign) + + // assign new elements to slots + s.startBlock(assign) + + // Evaluate args + args := make([]*ssa.Value, 0, nargs) + store := make([]bool, 0, nargs) + for l := n.List.Next; l != nil; l = l.Next { + if canSSAType(l.N.Type) { + args = append(args, s.expr(l.N)) + store = append(store, true) + } else { + args = append(args, s.addr(l.N, false)) + store = append(store, false) + } + } + + 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))) + if store[i] { + s.vars[&memVar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, et.Size(), addr, arg, s.mem()) + } else { + s.vars[&memVar] = s.newValue3I(ssa.OpMove, 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 + delete(s.vars, &ptrVar) + delete(s.vars, &capVar) + return s.newValue3(ssa.OpSliceMake, n.Type, p, nl, c) + + default: + s.Unimplementedf("unhandled expr %s", opnames[n.Op]) + return nil + } +} + +func (s *state) assign(left *Node, right *ssa.Value, wb bool) { + if left.Op == ONAME && isblank(left) { + return + } + t := left.Type + dowidth(t) + if right == nil { + // right == nil means use the zero value of the assigned type. + if !canSSA(left) { + // if we can't ssa this memory, treat it as just zeroing out the backing memory + addr := s.addr(left, false) + if left.Op == ONAME { + s.vars[&memVar] = s.newValue1A(ssa.OpVarDef, ssa.TypeMem, left, s.mem()) + } + s.vars[&memVar] = s.newValue2I(ssa.OpZero, ssa.TypeMem, t.Size(), addr, s.mem()) + return + } + right = s.zeroVal(t) + } + if left.Op == ONAME && canSSA(left) { + // Update variable assignment. + s.vars[left] = right + return + } + // not ssa-able. Treat as a store. + addr := s.addr(left, false) + if left.Op == ONAME { + s.vars[&memVar] = s.newValue1A(ssa.OpVarDef, ssa.TypeMem, left, s.mem()) + } + s.vars[&memVar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, t.Size(), addr, right, s.mem()) + if wb { + s.insertWB(left.Type, addr) + } +} + +// zeroVal returns the zero value for type t. +func (s *state) zeroVal(t *Type) *ssa.Value { + switch { + case t.IsInteger(): + switch t.Size() { + case 1: + return s.constInt8(t, 0) + case 2: + return s.constInt16(t, 0) + case 4: + return s.constInt32(t, 0) + case 8: + return s.constInt64(t, 0) + default: + s.Fatalf("bad sized integer type %s", t) + } + case t.IsFloat(): + switch t.Size() { + case 4: + return s.constFloat32(t, 0) + case 8: + return s.constFloat64(t, 0) + 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.entryNewValue2(ssa.OpComplexMake, t, z, z) + case 16: + z := s.constFloat64(Types[TFLOAT64], 0) + return s.entryNewValue2(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(): + return s.entryNewValue0(ssa.OpConstNil, t) + case t.IsBoolean(): + return s.constBool(false) + 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 +} + +type callKind int8 + +const ( + callNormal callKind = iota + callDefer + callGo +) + +func (s *state) call(n *Node, k callKind) *ssa.Value { + var sym *Sym // target symbol (if static) + var closure *ssa.Value // ptr to closure to run (if dynamic) + var codeptr *ssa.Value // ptr to target code (if dynamic) + var rcvr *ssa.Value // receiver to set + fn := n.Left + switch n.Op { + case OCALLFUNC: + if k == callNormal && fn.Op == ONAME && fn.Class == PFUNC { + sym = fn.Sym + break + } + closure = s.expr(fn) + if closure == nil { + return nil // TODO: remove when expr always returns non-nil + } + case OCALLMETH: + if fn.Op != ODOTMETH { + Fatalf("OCALLMETH: n.Left not an ODOTMETH: %v", fn) + } + if fn.Right.Op != ONAME { + Fatalf("OCALLMETH: n.Left.Right not a ONAME: %v", fn.Right) + } + if k == callNormal { + sym = fn.Right.Sym + break + } + n2 := *fn.Right + n2.Class = PFUNC + closure = s.expr(&n2) + // Note: receiver is already assigned in n.List, so we don't + // want to set it here. + case OCALLINTER: + if fn.Op != ODOTINTER { + Fatalf("OCALLINTER: n.Left not an ODOTINTER: %v", Oconv(int(fn.Op), 0)) + } + i := s.expr(fn.Left) + itab := s.newValue1(ssa.OpITab, Types[TUINTPTR], i) + itabidx := fn.Xoffset + 3*int64(Widthptr) + 8 // offset of fun field in runtime.itab + itab = s.newValue1I(ssa.OpOffPtr, Types[TUINTPTR], itabidx, itab) + if k == callNormal { + codeptr = s.newValue2(ssa.OpLoad, Types[TUINTPTR], itab, s.mem()) + } else { + closure = itab + } + rcvr = s.newValue1(ssa.OpIData, Types[TUINTPTR], i) + } + dowidth(fn.Type) + stksize := fn.Type.Argwid // includes receiver + + // Run all argument assignments. The arg slots have already + // been offset by the appropriate amount (+2*widthptr for go/defer, + // +widthptr for interface calls). + // For OCALLMETH, the receiver is set in these statements. + s.stmtList(n.List) + + // Set receiver (for interface calls) + if rcvr != nil { - var argStart int64 - if HasLinkRegister() { - argStart += int64(Widthptr) - } ++ argStart := Ctxt.FixedFrameSize() + if k != callNormal { + argStart += int64(2 * Widthptr) + } + addr := s.entryNewValue1I(ssa.OpOffPtr, Types[TUINTPTR], argStart, s.sp) + s.vars[&memVar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, int64(Widthptr), addr, rcvr, s.mem()) + } + + // Defer/go args + if k != callNormal { + // Write argsize and closure (args to Newproc/Deferproc). + argsize := s.constInt32(Types[TUINT32], int32(stksize)) + s.vars[&memVar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, 4, s.sp, argsize, s.mem()) + addr := s.entryNewValue1I(ssa.OpOffPtr, Ptrto(Types[TUINTPTR]), int64(Widthptr), s.sp) + s.vars[&memVar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, int64(Widthptr), addr, closure, s.mem()) + stksize += 2 * int64(Widthptr) + } + + // call target + bNext := s.f.NewBlock(ssa.BlockPlain) + var call *ssa.Value + switch { + case k == callDefer: + call = s.newValue1(ssa.OpDeferCall, ssa.TypeMem, s.mem()) + case k == callGo: + call = s.newValue1(ssa.OpGoCall, ssa.TypeMem, s.mem()) + case closure != nil: + codeptr = s.newValue2(ssa.OpLoad, Types[TUINTPTR], closure, s.mem()) + call = s.newValue3(ssa.OpClosureCall, ssa.TypeMem, codeptr, closure, s.mem()) + case codeptr != nil: + call = s.newValue2(ssa.OpInterCall, ssa.TypeMem, codeptr, s.mem()) + case sym != nil: + call = s.newValue1A(ssa.OpStaticCall, ssa.TypeMem, sym, s.mem()) + default: + Fatalf("bad call type %s %v", opnames[n.Op], n) + } + call.AuxInt = stksize // Call operations carry the argsize of the callee along with them + + // Finish call block + s.vars[&memVar] = call + b := s.endBlock() + b.Kind = ssa.BlockCall + b.Control = call + b.AddEdgeTo(bNext) + + // Read result from stack at the start of the fallthrough block + s.startBlock(bNext) + var titer Iter + fp := Structfirst(&titer, Getoutarg(n.Left.Type)) + if fp == nil || k != callNormal { + // call has no return value. Continue with the next statement. + return nil + } + a := s.entryNewValue1I(ssa.OpOffPtr, Ptrto(fp.Type), fp.Width, s.sp) + return s.newValue2(ssa.OpLoad, fp.Type, a, call) +} + +// etypesign returns the signed-ness of e, for integer/pointer etypes. +// -1 means signed, +1 means unsigned, 0 means non-integer/non-pointer. +func etypesign(e uint8) int8 { + switch e { + case TINT8, TINT16, TINT32, TINT64, TINT: + return -1 + case TUINT8, TUINT16, TUINT32, TUINT64, TUINT, TUINTPTR, TUNSAFEPTR: + return +1 + } + return 0 +} + +// lookupSymbol is used to retrieve the symbol (Extern, Arg or Auto) used for a particular node. +// This improves the effectiveness of cse by using the same Aux values for the +// same symbols. +func (s *state) lookupSymbol(n *Node, sym interface{}) interface{} { + switch sym.(type) { + default: + s.Fatalf("sym %v is of uknown type %T", sym, sym) + case *ssa.ExternSymbol, *ssa.ArgSymbol, *ssa.AutoSymbol: + // these are the only valid types + } + + if lsym, ok := s.varsyms[n]; ok { + return lsym + } else { + s.varsyms[n] = sym + return sym + } +} + +// addr converts the address of the expression n to SSA, adds it to s and returns the SSA result. +// The value that the returned Value represents is guaranteed to be non-nil. +// If bounded is true then this address does not require a nil check for its operand +// even if that would otherwise be implied. +func (s *state) addr(n *Node, bounded bool) *ssa.Value { + switch n.Op { + case ONAME: + switch n.Class { + case PEXTERN: + // global variable + aux := &ssa.ExternSymbol{n.Type, n.Sym} + v := s.entryNewValue1A(ssa.OpAddr, Ptrto(n.Type), aux, s.sb) + // TODO: Make OpAddr use AuxInt as well as Aux. + if n.Xoffset != 0 { + v = s.entryNewValue1I(ssa.OpOffPtr, v.Type, n.Xoffset, v) + } + return v + case PPARAM: + // parameter slot + v := s.decladdrs[n] + if v == nil { + if flag_race != 0 && n.String() == ".fp" { + s.Unimplementedf("race detector mishandles nodfp") + } + s.Fatalf("addr of undeclared ONAME %v. declared: %v", n, s.decladdrs) + } + return v + case PAUTO: + // We need to regenerate the address of autos + // at every use. This prevents LEA instructions + // from occurring before the corresponding VarDef + // op and confusing the liveness analysis into thinking + // the variable is live at function entry. + // TODO: I'm not sure if this really works or we're just + // getting lucky. We might need a real dependency edge + // 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 PPARAMOUT: // Same as PAUTO -- cannot generate LEA early. + // ensure that we reuse symbols for out parameters so + // that cse works on their addresses + aux := s.lookupSymbol(n, &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) + return nil + } + case OINDREG: + // indirect off a register + // used for storing/loading arguments/returns to/from callees + if int(n.Reg) != Thearch.REGSP { + s.Unimplementedf("OINDREG of non-SP register %s in addr: %v", obj.Rconv(int(n.Reg)), n) + return nil + } + return s.entryNewValue1I(ssa.OpOffPtr, Ptrto(n.Type), n.Xoffset, s.sp) + case OINDEX: + if n.Left.Type.IsSlice() { + a := s.expr(n.Left) + i := s.expr(n.Right) + i = s.extendIndex(i) + len := s.newValue1(ssa.OpSliceLen, Types[TUINTPTR], a) + 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 + a := s.addr(n.Left, bounded) + i := s.expr(n.Right) + i = s.extendIndex(i) + len := s.constInt(Types[TINT], n.Left.Type.Bound) + if !n.Bounded { + s.boundsCheck(i, len) + } + return s.newValue2(ssa.OpPtrIndex, Ptrto(n.Left.Type.Type), a, i) + } + case OIND: + p := s.expr(n.Left) + if !bounded { + s.nilCheck(p) + } + return p + case ODOT: + p := s.addr(n.Left, bounded) + return s.newValue2(ssa.OpAddPtr, p.Type, p, s.constIntPtr(Types[TUINTPTR], n.Xoffset)) + case ODOTPTR: + p := s.expr(n.Left) + if !bounded { + 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)) + case OPARAM: + 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} + return s.entryNewValue1A(ssa.OpAddr, Ptrto(n.Type), aux, s.sp) + case OCONVNOP: + addr := s.addr(n.Left, bounded) + to := Ptrto(n.Type) + return s.newValue1(ssa.OpCopy, to, addr) // ensure that addr has the right type + + default: + s.Unimplementedf("unhandled addr %v", Oconv(int(n.Op), 0)) + return nil + } +} + +// canSSA reports whether n is SSA-able. +// n must be an ONAME. +func canSSA(n *Node) bool { + if n.Op != ONAME { + return false + } + if n.Addrtaken { + return false + } + if n.Class&PHEAP != 0 { + return false + } + switch n.Class { + case PEXTERN, PPARAMOUT, PPARAMREF: + return false + } + if n.Class == PPARAM && n.String() == ".this" { + // wrappers generated by genwrapper need to update + // the .this pointer in place. + return false + } + 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 + } + 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. +// Starts a new block on return, unless nil checks are disabled. +// Used only for automatically inserted nil checks, +// not for user code like 'x != nil'. +func (s *state) nilCheck(ptr *ssa.Value) { + if Disable_checknil != 0 { + return + } + c := s.newValue1(ssa.OpIsNonNil, Types[TBOOL], ptr) + b := s.endBlock() + b.Kind = ssa.BlockIf + b.Control = c + b.Likely = ssa.BranchLikely + bNext := s.f.NewBlock(ssa.BlockPlain) + bPanic := s.f.NewBlock(ssa.BlockPlain) + b.AddEdgeTo(bNext) + b.AddEdgeTo(bPanic) + s.startBlock(bPanic) + // TODO: implicit nil checks somehow? + chk := s.newValue2(ssa.OpPanicNilCheck, ssa.TypeMem, ptr, s.mem()) + s.endBlock() + bPanic.Kind = ssa.BlockExit + bPanic.Control = chk + s.startBlock(bNext) +} + +// boundsCheck generates bounds checking code. Checks if 0 <= idx < len, branches to exit if not. +// Starts a new block on return. +func (s *state) boundsCheck(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.OpIsInBounds, Types[TBOOL], idx, len) + s.check(cmp, Panicindex) +} + +// 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, panicslice) +} + +// If cmp (a bool) is true, panic using the given function. +func (s *state) check(cmp *ssa.Value, fn *Node) { + b := s.endBlock() + b.Kind = ssa.BlockIf + b.Control = cmp + b.Likely = ssa.BranchLikely + bNext := s.f.NewBlock(ssa.BlockPlain) + bPanic := s.f.NewBlock(ssa.BlockPlain) + b.AddEdgeTo(bNext) + b.AddEdgeTo(bPanic) + s.startBlock(bPanic) + // The panic call takes/returns memory to ensure that the right + // memory state is observed if the panic happens. + s.rtcall(fn, false, nil) + + s.startBlock(bNext) +} + +// rtcall issues a call to the given runtime function fn with the listed args. +// Returns a slice of results of the given result types. +// The call is added to the end of the current block. +// If returns is false, the block is marked as an exit block. +// If returns is true, the block is marked as a call block. A new block +// is started to load the return values. +func (s *state) rtcall(fn *Node, returns bool, results []*Type, args ...*ssa.Value) []*ssa.Value { + // Write args to the stack + var off int64 // TODO: arch-dependent starting offset? + for _, arg := range args { + t := arg.Type + off = Rnd(off, t.Alignment()) + ptr := s.sp + if off != 0 { + ptr = s.newValue1I(ssa.OpOffPtr, Types[TUINTPTR], off, s.sp) + } + size := t.Size() + s.vars[&memVar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, size, ptr, arg, s.mem()) + off += size + } + off = Rnd(off, int64(Widthptr)) + + // Issue call + call := s.newValue1A(ssa.OpStaticCall, ssa.TypeMem, fn.Sym, s.mem()) + s.vars[&memVar] = call + + // Finish block + b := s.endBlock() + if !returns { + b.Kind = ssa.BlockExit + b.Control = call + call.AuxInt = off + if len(results) > 0 { + Fatalf("panic call can't have results") + } + return nil + } + b.Kind = ssa.BlockCall + b.Control = call + bNext := s.f.NewBlock(ssa.BlockPlain) + b.AddEdgeTo(bNext) + s.startBlock(bNext) + + // Load results + res := make([]*ssa.Value, len(results)) + for i, t := range results { + off = Rnd(off, t.Alignment()) + ptr := s.sp + if off != 0 { + ptr = s.newValue1I(ssa.OpOffPtr, Types[TUINTPTR], off, s.sp) + } + res[i] = s.newValue2(ssa.OpLoad, t, ptr, s.mem()) + off += t.Size() + } + off = Rnd(off, int64(Widthptr)) + + // Remember how much callee stack space we needed. + call.AuxInt = off + + return res +} + +// 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) + + 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) + + 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.rtcall(typedmemmove_nostore, true, nil, taddr, p) + + b.AddEdgeTo(s.curBlock) +} + +// 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 +} + +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) + // result = result + result + // } + // + // 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) + + b.AddEdgeTo(bThen) + s.startBlock(bThen) + a0 := s.newValue1(cvttab.cvt2F, tt, x) + s.vars[n] = a0 + s.endBlock() + bThen.AddEdgeTo(bAfter) + + b.AddEdgeTo(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() + bElse.AddEdgeTo(bAfter) + + s.startBlock(bAfter) + return s.variable(n, n.Type) +} + +// 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]) + cmp := s.newValue2(ssa.OpEqPtr, Types[TBOOL], x, nilValue) + 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/capacity of a nil map/chan is zero + b.AddEdgeTo(bThen) + s.startBlock(bThen) + s.vars[n] = s.zeroVal(lenType) + s.endBlock() + bThen.AddEdgeTo(bAfter) + + b.AddEdgeTo(bElse) + s.startBlock(bElse) + 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() + bElse.AddEdgeTo(bAfter) + + s.startBlock(bAfter) + 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) + + b.AddEdgeTo(bThen) + s.startBlock(bThen) + a0 := s.newValue1(cvttab.cvt2U, tt, x) + s.vars[n] = a0 + s.endBlock() + bThen.AddEdgeTo(bAfter) + + b.AddEdgeTo(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() + bElse.AddEdgeTo(bAfter) + + s.startBlock(bAfter) + 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) + taddr := s.newValue1A(ssa.OpAddr, byteptr, &ssa.ExternSymbol{byteptr, typenamesym(n.Left.Type)}, s.sb) + s.rtcall(panicdottype, false, nil, typ, target, taddr) + + // 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, +// 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 { + v := s.vars[name] + if v == nil { + // TODO: get type? Take Sym as arg? + v = s.newValue0A(ssa.OpFwdRef, t, name) + s.vars[name] = v + } + return v +} + +func (s *state) mem() *ssa.Value { + return s.variable(&memVar, ssa.TypeMem) +} + +func (s *state) linkForwardReferences() { + // Build ssa graph. Each variable on its first use in a basic block + // leaves a FwdRef in that block representing the incoming value + // of that variable. This function links that ref up with possible definitions, + // inserting Phi values as needed. This is essentially the algorithm + // described by Brau, Buchwald, Hack, Leißa, Mallon, and Zwinkau: + // http://pp.info.uni-karlsruhe.de/uploads/publikationen/braun13cc.pdf + for _, b := range s.f.Blocks { + for _, v := range b.Values { + if v.Op != ssa.OpFwdRef { + continue + } + name := v.Aux.(*Node) + v.Op = ssa.OpCopy + v.Aux = nil + v.SetArgs1(s.lookupVarIncoming(b, v.Type, name)) + } + } +} + +// lookupVarIncoming finds the variable's value at the start of block b. +func (s *state) lookupVarIncoming(b *ssa.Block, t ssa.Type, name *Node) *ssa.Value { + // TODO(khr): have lookupVarIncoming overwrite the fwdRef or copy it + // will be used in, instead of having the result used in a copy value. + if b == s.f.Entry { + if name == &memVar { + return s.startmem + } + // variable is live at the entry block. Load it. + addr := s.decladdrs[name] + if addr == nil { + // TODO: closure args reach here. + s.Unimplementedf("unhandled closure arg %s at entry to function %s", name, b.Func.Name) + } + if _, ok := addr.Aux.(*ssa.ArgSymbol); !ok { + s.Fatalf("variable live at start of function %s is not an argument %s", b.Func.Name, name) + } + return s.entryNewValue2(ssa.OpLoad, t, addr, s.startmem) + } + var vals []*ssa.Value + for _, p := range b.Preds { + vals = append(vals, s.lookupVarOutgoing(p, t, name)) + } + if len(vals) == 0 { + // 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++ { + if vals[i] != v0 { + // need a phi value + v := b.NewValue0(s.peekLine(), ssa.OpPhi, t) + v.AddArgs(vals...) + return v + } + } + return v0 +} + +// lookupVarOutgoing finds the variable's value at the end of block b. +func (s *state) lookupVarOutgoing(b *ssa.Block, t ssa.Type, name *Node) *ssa.Value { + m := s.defvars[b.ID] + if v, ok := m[name]; ok { + return v + } + // The variable is not defined by b and we haven't + // looked it up yet. Generate v, a copy value which + // will be the outgoing value of the variable. Then + // look up w, the incoming value of the variable. + // Make v = copy(w). We need the extra copy to + // prevent infinite recursion when looking up the + // incoming value of the variable. + v := b.NewValue0(s.peekLine(), ssa.OpCopy, t) + m[name] = v + v.AddArg(s.lookupVarIncoming(b, t, name)) + return v +} + +// TODO: the above mutually recursive functions can lead to very deep stacks. Fix that. + +// an unresolved branch +type branch struct { + p *obj.Prog // branch instruction + b *ssa.Block // target +} + +type genState struct { + // branches remembers all the branch instructions we've seen + // and where they would like to go. + branches []branch + + // bstart remembers where each block starts (indexed by block ID) + bstart []*obj.Prog + + // deferBranches remembers all the defer branches we've seen. + deferBranches []*obj.Prog + + // deferTarget remembers the (last) deferreturn call site. + deferTarget *obj.Prog +} + +// genssa appends entries to ptxt for each instruction in f. +// gcargs and gclocals are filled in with pointer maps for the frame. +func genssa(f *ssa.Func, ptxt *obj.Prog, gcargs, gclocals *Sym) { + var s genState + + e := f.Config.Frontend().(*ssaExport) + // We're about to emit a bunch of Progs. + // Since the only way to get here is to explicitly request it, + // just fail on unimplemented instead of trying to unwind our mess. + e.mustImplement = true + + // Remember where each block starts. + s.bstart = make([]*obj.Prog, f.NumBlocks()) + + var valueProgs map[*obj.Prog]*ssa.Value + var blockProgs map[*obj.Prog]*ssa.Block + const logProgs = true + if logProgs { + valueProgs = make(map[*obj.Prog]*ssa.Value, f.NumValues()) + blockProgs = make(map[*obj.Prog]*ssa.Block, f.NumBlocks()) + f.Logf("genssa %s\n", f.Name) + blockProgs[Pc] = f.Blocks[0] + } + + // Emit basic blocks + for i, b := range f.Blocks { + s.bstart[b.ID] = Pc + // Emit values in block + for _, v := range b.Values { + x := Pc + s.genValue(v) + if logProgs { + for ; x != Pc; x = x.Link { + valueProgs[x] = v + } + } + } + // Emit control flow instructions for block + var next *ssa.Block + if i < len(f.Blocks)-1 { + next = f.Blocks[i+1] + } + x := Pc + s.genBlock(b, next) + if logProgs { + for ; x != Pc; x = x.Link { + blockProgs[x] = b + } + } + } + + // Resolve branches + 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 + } + + if logProgs { + for p := ptxt; p != nil; p = p.Link { + var s string + if v, ok := valueProgs[p]; ok { + s = v.String() + } else if b, ok := blockProgs[p]; ok { + s = b.String() + } else { + s = " " // most value and branch strings are 2-3 characters long + } + f.Logf("%s\t%s\n", s, p) + } + if f.Config.HTML != nil { + saved := ptxt.Ctxt.LineHist.PrintFilenameOnly + ptxt.Ctxt.LineHist.PrintFilenameOnly = true + var buf bytes.Buffer + buf.WriteString("") + buf.WriteString("
") + for p := ptxt; p != nil; p = p.Link { + buf.WriteString("
") + if v, ok := valueProgs[p]; ok { + buf.WriteString(v.HTML()) + } else if b, ok := blockProgs[p]; ok { + buf.WriteString(b.HTML()) + } + buf.WriteString("
") + buf.WriteString("
") + buf.WriteString(html.EscapeString(p.String())) + buf.WriteString("
") + buf.WriteString("") + } + buf.WriteString("
") + buf.WriteString("
") + f.Config.HTML.WriteColumn("genssa", buf.String()) + ptxt.Ctxt.LineHist.PrintFilenameOnly = saved + } + } + + // Emit static data + if f.StaticData != nil { + for _, n := range f.StaticData.([]*Node) { + if !gen_as_init(n, false) { + Fatalf("non-static data marked as static: %v\n\n", n, f) + } + } + } + + // Allocate stack frame + allocauto(ptxt) + + // Generate gc bitmaps. + liveness(Curfn, ptxt, gcargs, gclocals) + gcsymdup(gcargs) + gcsymdup(gclocals) + + // Add frame prologue. Zero ambiguously live variables. + Thearch.Defframe(ptxt) + if Debug['f'] != 0 { + frame(0) + } + + // Remove leftover instrumentation from the instruction stream. + removevardef(ptxt) + + f.Config.HTML.Close() +} + +// opregreg emits instructions for +// 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 { + 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 (s *genState) genValue(v *ssa.Value) { + lineno = v.Line + switch v.Op { + case ssa.OpAMD64ADDQ: + // TODO: use addq instead of leaq if target is in the right register. + p := Prog(x86.ALEAQ) + p.From.Type = obj.TYPE_MEM + p.From.Reg = regnum(v.Args[0]) + p.From.Scale = 1 + p.From.Index = regnum(v.Args[1]) + p.To.Type = obj.TYPE_REG + p.To.Reg = regnum(v) + case ssa.OpAMD64ADDL: + p := Prog(x86.ALEAL) + p.From.Type = obj.TYPE_MEM + p.From.Reg = regnum(v.Args[0]) + p.From.Scale = 1 + p.From.Index = regnum(v.Args[1]) + p.To.Type = obj.TYPE_REG + p.To.Reg = regnum(v) + case ssa.OpAMD64ADDW: + p := Prog(x86.ALEAW) + p.From.Type = obj.TYPE_MEM + p.From.Reg = regnum(v.Args[0]) + p.From.Scale = 1 + p.From.Index = regnum(v.Args[1]) + p.To.Type = obj.TYPE_REG + p.To.Reg = regnum(v) + // 2-address opcode arithmetic, symmetric + 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.OpAMD64MULSS, ssa.OpAMD64MULSD, ssa.OpAMD64PXOR: + r := regnum(v) + x := regnum(v.Args[0]) + y := regnum(v.Args[1]) + if x != r && y != r { + opregreg(regMoveByTypeAMD64(v.Type), r, x) + x = r + } + p := Prog(v.Op.Asm()) + p.From.Type = obj.TYPE_REG + p.To.Type = obj.TYPE_REG + p.To.Reg = r + if x == r { + p.From.Reg = y + } else { + p.From.Reg = x + } + // 2-address opcode arithmetic, not symmetric + case ssa.OpAMD64SUBQ, ssa.OpAMD64SUBL, ssa.OpAMD64SUBW, ssa.OpAMD64SUBB: + r := regnum(v) + x := regnum(v.Args[0]) + y := regnum(v.Args[1]) + var neg bool + if y == r { + // compute -(y-x) instead + x, y = y, x + neg = true + } + if x != r { + opregreg(regMoveByTypeAMD64(v.Type), r, x) + } + opregreg(v.Op.Asm(), r, 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.OpAMD64DIVQ, ssa.OpAMD64DIVL, ssa.OpAMD64DIVW, + 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. + var j *obj.Prog + if v.Op == ssa.OpAMD64DIVQ || v.Op == ssa.OpAMD64DIVL || + 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, ssa.OpAMD64MODQ: + c = Prog(x86.ACMPQ) + 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) + 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.To.Type = obj.TYPE_BRANCH + + } + + // 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 + } + + 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 + + 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 + } + + 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: + x := regnum(v.Args[0]) + r := regnum(v) + if x != r { + if r == x86.REG_CX { + v.Fatalf("can't implement %s, target and shift both in CX", v.LongString()) + } + 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 + } + p := Prog(v.Op.Asm()) + p.From.Type = obj.TYPE_REG + p.From.Reg = regnum(v.Args[1]) // should be CX + p.To.Type = obj.TYPE_REG + p.To.Reg = r + case ssa.OpAMD64ADDQconst, ssa.OpAMD64ADDLconst, ssa.OpAMD64ADDWconst: + // TODO: use addq instead of leaq if target is in the right register. + var asm int + switch v.Op { + case ssa.OpAMD64ADDQconst: + asm = x86.ALEAQ + case ssa.OpAMD64ADDLconst: + asm = x86.ALEAL + case ssa.OpAMD64ADDWconst: + asm = x86.ALEAW + } + p := Prog(asm) + p.From.Type = obj.TYPE_MEM + p.From.Reg = regnum(v.Args[0]) + p.From.Offset = v.AuxInt + p.To.Type = obj.TYPE_REG + p.To.Reg = regnum(v) + case ssa.OpAMD64MULQconst, ssa.OpAMD64MULLconst, ssa.OpAMD64MULWconst, ssa.OpAMD64MULBconst: + r := regnum(v) + x := regnum(v.Args[0]) + if r != x { + 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 + } + p := Prog(v.Op.Asm()) + p.From.Type = obj.TYPE_CONST + p.From.Offset = v.AuxInt + p.To.Type = obj.TYPE_REG + p.To.Reg = r + // TODO: Teach doasm to compile the three-address multiply imul $c, r1, r2 + // instead of using the MOVQ above. + //p.From3 = new(obj.Addr) + //p.From3.Type = obj.TYPE_REG + //p.From3.Reg = regnum(v.Args[0]) + case ssa.OpAMD64ADDBconst, + ssa.OpAMD64ANDQconst, ssa.OpAMD64ANDLconst, ssa.OpAMD64ANDWconst, ssa.OpAMD64ANDBconst, + ssa.OpAMD64ORQconst, ssa.OpAMD64ORLconst, ssa.OpAMD64ORWconst, ssa.OpAMD64ORBconst, + ssa.OpAMD64XORQconst, ssa.OpAMD64XORLconst, ssa.OpAMD64XORWconst, ssa.OpAMD64XORBconst, + 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.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]) + r := regnum(v) + 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 + } + p := Prog(v.Op.Asm()) + p.From.Type = obj.TYPE_CONST + p.From.Offset = v.AuxInt + p.To.Type = obj.TYPE_REG + p.To.Reg = r + case ssa.OpAMD64SBBQcarrymask, ssa.OpAMD64SBBLcarrymask: + r := regnum(v) + p := Prog(v.Op.Asm()) + p.From.Type = obj.TYPE_REG + p.From.Reg = r + p.To.Type = obj.TYPE_REG + p.To.Reg = r + case ssa.OpAMD64LEAQ1, ssa.OpAMD64LEAQ2, ssa.OpAMD64LEAQ4, ssa.OpAMD64LEAQ8: + p := Prog(x86.ALEAQ) + p.From.Type = obj.TYPE_MEM + p.From.Reg = regnum(v.Args[0]) + switch v.Op { + case ssa.OpAMD64LEAQ1: + p.From.Scale = 1 + case ssa.OpAMD64LEAQ2: + p.From.Scale = 2 + case ssa.OpAMD64LEAQ4: + p.From.Scale = 4 + case ssa.OpAMD64LEAQ8: + p.From.Scale = 8 + } + p.From.Index = regnum(v.Args[1]) + addAux(&p.From, v) + p.To.Type = obj.TYPE_REG + p.To.Reg = regnum(v) + case ssa.OpAMD64LEAQ: + p := Prog(x86.ALEAQ) + 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.OpAMD64CMPQ, ssa.OpAMD64CMPL, ssa.OpAMD64CMPW, ssa.OpAMD64CMPB, + ssa.OpAMD64TESTQ, ssa.OpAMD64TESTL, ssa.OpAMD64TESTW, ssa.OpAMD64TESTB: + 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()) + p.From.Type = obj.TYPE_REG + p.From.Reg = regnum(v.Args[0]) + p.To.Type = obj.TYPE_CONST + p.To.Offset = v.AuxInt + 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(int8(v.AuxInt)) + case ssa.OpAMD64MOVWconst: + i = int64(int16(v.AuxInt)) + case ssa.OpAMD64MOVLconst: + i = int64(int32(v.AuxInt)) + case ssa.OpAMD64MOVQconst: + i = v.AuxInt + } + p.From.Offset = i + p.To.Type = obj.TYPE_REG + p.To.Reg = x + case ssa.OpAMD64MOVSSconst, ssa.OpAMD64MOVSDconst: + x := regnum(v) + p := Prog(v.Op.Asm()) + p.From.Type = obj.TYPE_FCONST + 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: + 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, ssa.OpAMD64MOVSDloadidx8: + 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 = 8 + p.From.Index = regnum(v.Args[1]) + p.To.Type = obj.TYPE_REG + p.To.Reg = regnum(v) + 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, 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 + p.To.Reg = regnum(v.Args[0]) + 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, + ssa.OpAMD64CVTSL2SS, ssa.OpAMD64CVTSL2SD, ssa.OpAMD64CVTSQ2SS, ssa.OpAMD64CVTSQ2SD, + ssa.OpAMD64CVTTSS2SL, ssa.OpAMD64CVTTSD2SL, ssa.OpAMD64CVTTSS2SQ, ssa.OpAMD64CVTTSD2SQ, + ssa.OpAMD64CVTSS2SD, ssa.OpAMD64CVTSD2SS: + opregreg(v.Op.Asm(), regnum(v), regnum(v.Args[0])) + 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.OpAMD64MOVOconst: ++ if v.AuxInt != 0 { ++ v.Unimplementedf("MOVOconst can only do constant=0") ++ } ++ r := regnum(v) ++ opregreg(x86.AXORPS, r, r) + + case ssa.OpCopy: // TODO: lower to MOVQ earlier? + if v.Type.IsMemory() { + return + } + x := regnum(v.Args[0]) + y := regnum(v) + if x != 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(movSizeByType(v.Type)) + n := autoVar(v.Args[0]) + p.From.Type = obj.TYPE_MEM + p.From.Name = obj.NAME_AUTO + p.From.Node = n + p.From.Sym = Linksym(n.Sym) + 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(movSizeByType(v.Type)) + p.From.Type = obj.TYPE_REG + p.From.Reg = regnum(v.Args[0]) + n := autoVar(v) + p.To.Type = obj.TYPE_MEM + p.To.Name = obj.NAME_AUTO + p.To.Node = n + p.To.Sym = Linksym(n.Sym) + case ssa.OpPhi: + // 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 { + if aloc := f.RegAlloc[a.ID]; aloc != loc { // TODO: .Equal() instead? + 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, + 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. + case ssa.OpAMD64LoweredPanicNilCheck: + if Debug_checknil != 0 && v.Line > 1 { // v.Line==1 in generated wrappers + Warnl(int(v.Line), "generated nil check") + } + // Write to memory address 0. It doesn't matter what we write; use AX. + // Input 0 is the pointer we just checked, use it as the destination. + r := regnum(v.Args[0]) + q := Prog(x86.AMOVL) + q.From.Type = obj.TYPE_REG + 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 + // near CanUse1InsnTLS for a detailed explanation of these instructions. + if x86.CanUse1InsnTLS(Ctxt) { + // MOVQ (TLS), r + p := Prog(x86.AMOVQ) + p.From.Type = obj.TYPE_MEM + p.From.Reg = x86.REG_TLS + p.To.Type = obj.TYPE_REG + p.To.Reg = r + } else { + // MOVQ TLS, r + // MOVQ (r)(TLS*1), r + p := Prog(x86.AMOVQ) + p.From.Type = obj.TYPE_REG + p.From.Reg = x86.REG_TLS + p.To.Type = obj.TYPE_REG + p.To.Reg = r + q := Prog(x86.AMOVQ) + q.From.Type = obj.TYPE_MEM + q.From.Reg = r + q.From.Index = x86.REG_TLS + q.From.Scale = 1 + q.To.Type = obj.TYPE_REG + q.To.Reg = r + } + case ssa.OpAMD64CALLstatic: + p := Prog(obj.ACALL) + p.To.Type = obj.TYPE_MEM + p.To.Name = obj.NAME_EXTERN + p.To.Sym = Linksym(v.Aux.(*Sym)) + if Maxarg < v.AuxInt { + Maxarg = v.AuxInt + } + case ssa.OpAMD64CALLclosure: + p := Prog(obj.ACALL) + p.To.Type = obj.TYPE_REG + p.To.Reg = regnum(v.Args[0]) + if Maxarg < v.AuxInt { + Maxarg = v.AuxInt + } + case ssa.OpAMD64CALLdefer: + p := Prog(obj.ACALL) + p.To.Type = obj.TYPE_MEM + p.To.Name = obj.NAME_EXTERN + p.To.Sym = Linksym(Deferproc.Sym) + if Maxarg < v.AuxInt { + Maxarg = v.AuxInt + } + // defer returns in rax: + // 0 if we should continue executing + // 1 if we should jump to deferreturn call + p = Prog(x86.ATESTL) + p.From.Type = obj.TYPE_REG + p.From.Reg = x86.REG_AX + p.To.Type = obj.TYPE_REG + p.To.Reg = x86.REG_AX + p = Prog(x86.AJNE) + p.To.Type = obj.TYPE_BRANCH + s.deferBranches = append(s.deferBranches, p) + case ssa.OpAMD64CALLgo: + p := Prog(obj.ACALL) + p.To.Type = obj.TYPE_MEM + p.To.Name = obj.NAME_EXTERN + p.To.Sym = Linksym(Newproc.Sym) + if Maxarg < v.AuxInt { + Maxarg = v.AuxInt + } + case ssa.OpAMD64CALLinter: + p := Prog(obj.ACALL) + p.To.Type = obj.TYPE_REG + p.To.Reg = regnum(v.Args[0]) + if Maxarg < v.AuxInt { + Maxarg = v.AuxInt + } + case ssa.OpAMD64NEGQ, ssa.OpAMD64NEGL, ssa.OpAMD64NEGW, ssa.OpAMD64NEGB, + ssa.OpAMD64NOTQ, ssa.OpAMD64NOTL, ssa.OpAMD64NOTW, ssa.OpAMD64NOTB: + x := regnum(v.Args[0]) + r := regnum(v) + 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 + } + p := Prog(v.Op.Asm()) + p.To.Type = obj.TYPE_REG + p.To.Reg = r + case ssa.OpAMD64SQRTSD: + 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.OpSP, ssa.OpSB: + // nothing to do + 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: + Prog(x86.AREP) + Prog(x86.ASTOSQ) + case ssa.OpAMD64REPMOVSB: + Prog(x86.AREP) + Prog(x86.AMOVSB) + case ssa.OpVarDef: + Gvardef(v.Aux.(*Node)) + case ssa.OpVarKill: + gvarkill(v.Aux.(*Node)) + default: + v.Unimplementedf("genValue not implemented: %s", v.LongString()) + } +} + +// 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 +func movZero(as int, width int64, nbytes int64, offset int64, regnum int16) (nleft int64, noff int64) { + p := Prog(as) + // TODO: use zero register on archs that support it. + p.From.Type = obj.TYPE_CONST + p.From.Offset = 0 + p.To.Type = obj.TYPE_MEM + p.To.Reg = regnum + p.To.Offset = offset + offset += width + nleft = nbytes - width + return nleft, offset +} + +var blockJump = [...]struct { + asm, invasm int +}{ + ssa.BlockAMD64EQ: {x86.AJEQ, x86.AJNE}, + ssa.BlockAMD64NE: {x86.AJNE, x86.AJEQ}, + ssa.BlockAMD64LT: {x86.AJLT, x86.AJGE}, + ssa.BlockAMD64GE: {x86.AJGE, x86.AJLT}, + ssa.BlockAMD64LE: {x86.AJLE, x86.AJGT}, + ssa.BlockAMD64GT: {x86.AJGT, x86.AJLE}, + ssa.BlockAMD64ULT: {x86.AJCS, x86.AJCC}, + 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(s *genState, b, next *ssa.Block, jumps *[2][2]floatingEQNEJump) { + likely := b.Likely + switch next { + case b.Succs[0]: + s.branches = oneFPJump(b, &jumps[0][0], likely, s.branches) + s.branches = oneFPJump(b, &jumps[0][1], likely, s.branches) + case b.Succs[1]: + s.branches = oneFPJump(b, &jumps[1][0], likely, s.branches) + s.branches = oneFPJump(b, &jumps[1][1], likely, s.branches) + default: + s.branches = oneFPJump(b, &jumps[1][0], likely, s.branches) + s.branches = oneFPJump(b, &jumps[1][1], likely, s.branches) + q := Prog(obj.AJMP) + q.To.Type = obj.TYPE_BRANCH + s.branches = append(s.branches, branch{q, b.Succs[1]}) + } +} + +func (s *genState) genBlock(b, next *ssa.Block) { + lineno = b.Line + + switch b.Kind { + case ssa.BlockPlain, ssa.BlockCall: + if b.Succs[0] != next { + p := Prog(obj.AJMP) + p.To.Type = obj.TYPE_BRANCH + s.branches = append(s.branches, branch{p, b.Succs[0]}) + } + case ssa.BlockExit: + Prog(obj.AUNDEF) // tell plive.go that we never reach here + case ssa.BlockRet: + if hasdefer { + s.deferReturn() + } + Prog(obj.ARET) + case ssa.BlockRetJmp: + p := Prog(obj.AJMP) + p.To.Type = obj.TYPE_MEM + p.To.Name = obj.NAME_EXTERN + p.To.Sym = Linksym(b.Aux.(*Sym)) + + case ssa.BlockAMD64EQF: + genFPJump(s, b, next, &eqfJumps) + + case ssa.BlockAMD64NEF: + genFPJump(s, b, next, &nefJumps) + + 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 + switch next { + case b.Succs[0]: + p = Prog(jmp.invasm) + likely *= -1 + p.To.Type = obj.TYPE_BRANCH + s.branches = append(s.branches, branch{p, b.Succs[1]}) + case b.Succs[1]: + p = Prog(jmp.asm) + p.To.Type = obj.TYPE_BRANCH + s.branches = append(s.branches, branch{p, b.Succs[0]}) + default: + p = Prog(jmp.asm) + p.To.Type = obj.TYPE_BRANCH + s.branches = append(s.branches, branch{p, b.Succs[0]}) + q := Prog(obj.AJMP) + q.To.Type = obj.TYPE_BRANCH + s.branches = append(s.branches, branch{q, b.Succs[1]}) + } + + // 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 + } + + default: + b.Unimplementedf("branch not implemented: %s. Control: %s", b.LongString(), b.Control.LongString()) + } +} + +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 { + v.Fatalf("bad addAux addr %s", a) + } + // add integer offset + a.Offset += v.AuxInt + + // If no additional symbol offset, we're done. + if v.Aux == nil { + return + } + // Add symbol's offset from its base register. + switch sym := v.Aux.(type) { + case *ssa.ExternSymbol: + a.Name = obj.NAME_EXTERN + a.Sym = Linksym(sym.Sym.(*Sym)) + case *ssa.ArgSymbol: + n := sym.Node.(*Node) + a.Name = obj.NAME_PARAM + a.Node = n + a.Sym = Linksym(n.Orig.Sym) + a.Offset += n.Xoffset // TODO: why do I have to add this here? I don't for auto variables. + case *ssa.AutoSymbol: + n := sym.Node.(*Node) + a.Name = obj.NAME_AUTO + a.Node = n + a.Sym = Linksym(n.Sym) + default: + v.Fatalf("aux in %s not implemented %#v", v, v.Aux) + } +} + +// extendIndex extends v to a full pointer width. +func (s *state) extendIndex(v *ssa.Value) *ssa.Value { + size := v.Type.Size() + if size == s.config.PtrSize { + return v + } + if size > s.config.PtrSize { + // TODO: truncate 64-bit indexes on 32-bit pointer archs. We'd need to test + // the high word and branch to out-of-bounds failure if it is not 0. + s.Unimplementedf("64->32 index truncation not implemented") + return v + } + + // Extend value to the required size + var op ssa.Op + if v.Type.IsSigned() { + switch 10*size + s.config.PtrSize { + case 14: + op = ssa.OpSignExt8to32 + case 18: + op = ssa.OpSignExt8to64 + case 24: + op = ssa.OpSignExt16to32 + case 28: + op = ssa.OpSignExt16to64 + case 48: + op = ssa.OpSignExt32to64 + default: + s.Fatalf("bad signed index extension %s", v.Type) + } + } else { + switch 10*size + s.config.PtrSize { + case 14: + op = ssa.OpZeroExt8to32 + case 18: + op = ssa.OpZeroExt8to64 + case 24: + op = ssa.OpZeroExt16to32 + case 28: + op = ssa.OpZeroExt16to64 + case 48: + op = ssa.OpZeroExt32to64 + default: + s.Fatalf("bad unsigned index extension %s", v.Type) + } + } + return s.newValue1(op, Types[TUINTPTR], v) +} + +// ssaRegToReg maps ssa register numbers to obj register numbers. +var ssaRegToReg = [...]int16{ + x86.REG_AX, + x86.REG_CX, + x86.REG_DX, + x86.REG_BX, + x86.REG_SP, + x86.REG_BP, + x86.REG_SI, + x86.REG_DI, + x86.REG_R8, + x86.REG_R9, + x86.REG_R10, + x86.REG_R11, + x86.REG_R12, + x86.REG_R13, + x86.REG_R14, + x86.REG_R15, + x86.REG_X0, + x86.REG_X1, + x86.REG_X2, + x86.REG_X3, + x86.REG_X4, + x86.REG_X5, + x86.REG_X6, + x86.REG_X7, + x86.REG_X8, + x86.REG_X9, + x86.REG_X10, + x86.REG_X11, + x86.REG_X12, + x86.REG_X13, + x86.REG_X14, + x86.REG_X15, + 0, // SB isn't a real register. We fill an Addr.Reg field with 0 in this case. + // TODO: arch-dependent +} + +// regMoveAMD64 returns the register->register move opcode for the given width. +// TODO: generalize for all architectures? +func regMoveAMD64(width int64) int { + 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") + } +} + +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. +// TODO: Make this panic again once it stops happening routinely. +func regnum(v *ssa.Value) int16 { + reg := v.Block.Func.RegAlloc[v.ID] + if reg == nil { + v.Unimplementedf("nil regnum for value: %s\n%s\n", v.LongString(), v.Block.Func) + return 0 + } + return ssaRegToReg[reg.(*ssa.Register).Num] +} + +// autoVar returns a *Node representing the auto variable assigned to v. +func autoVar(v *ssa.Value) *Node { + return v.Block.Func.RegAlloc[v.ID].(*ssa.LocalSlot).N.(*Node) +} + +// ssaExport exports a bunch of compiler services for the ssa backend. +type ssaExport struct { + log bool + unimplemented bool + mustImplement bool +} + +func (s *ssaExport) TypeBool() ssa.Type { return Types[TBOOL] } +func (s *ssaExport) TypeInt8() ssa.Type { return Types[TINT8] } +func (s *ssaExport) TypeInt16() ssa.Type { return Types[TINT16] } +func (s *ssaExport) TypeInt32() ssa.Type { return Types[TINT32] } +func (s *ssaExport) TypeInt64() ssa.Type { return Types[TINT64] } +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] } +func (s *ssaExport) TypeBytePtr() ssa.Type { return Ptrto(Types[TUINT8]) } + +// StringData returns a symbol (a *Sym wrapped in an interface) which +// is the data component of a global string constant containing s. +func (*ssaExport) StringData(s string) interface{} { + // TODO: is idealstring correct? It might not matter... + _, data := stringsym(s) + return &ssa.ExternSymbol{Typ: idealstring, Sym: data} +} + +func (e *ssaExport) Auto(t ssa.Type) fmt.Stringer { + n := temp(t.(*Type)) // Note: adds new auto to Curfn.Func.Dcl list + e.mustImplement = true // This modifies the input to SSA, so we want to make sure we succeed from here! + return n +} + +func (e ssaExport) CanSSA(t ssa.Type) bool { + return canSSAType(t.(*Type)) +} + +// Log logs a message from the compiler. +func (e *ssaExport) Logf(msg string, args ...interface{}) { + // If e was marked as unimplemented, anything could happen. Ignore. + if e.log && !e.unimplemented { + fmt.Printf(msg, args...) + } +} + +// Fatal reports a compiler error and exits. +func (e *ssaExport) Fatalf(msg string, args ...interface{}) { + // If e was marked as unimplemented, anything could happen. Ignore. + if !e.unimplemented { + Fatalf(msg, args...) + } +} + +// Unimplemented reports that the function cannot be compiled. +// It will be removed once SSA work is complete. +func (e *ssaExport) Unimplementedf(msg string, args ...interface{}) { + if e.mustImplement { + Fatalf(msg, args...) + } + const alwaysLog = false // enable to calculate top unimplemented features + if !e.unimplemented && (e.log || alwaysLog) { + // first implementation failure, print explanation + fmt.Printf("SSA unimplemented: "+msg+"\n", args...) + } + e.unimplemented = true +} diff --cc src/cmd/compile/internal/ssa/gen/AMD64.rules index f160ce81af,0000000000..ffa5feaabf mode 100644,000000..100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64.rules +++ b/src/cmd/compile/internal/ssa/gen/AMD64.rules @@@ -1,726 -1,0 +1,728 @@@ +// 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. + +// x86 register conventions: +// - Integer types live in the low portion of registers. Upper portions are junk. +// - Boolean types use the low-order byte of a register. Upper bytes are junk. +// - We do not use AH,BH,CH,DH registers. +// - Floating-point types will live in the low natural slot of an sse2 register. +// Unused portions are junk. + +// Lowering arithmetic +(Add64 x y) -> (ADDQ x y) +(AddPtr x y) -> (ADDQ x y) +(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) +(SubPtr 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) + +(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)) + +(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) + +(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) +(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) + +(Xor64 x y) -> (XORQ x y) +(Xor32 x y) -> (XORL x y) +(Xor16 x y) -> (XORW x y) +(Xor8 x y) -> (XORB x y) + +(Neg64 x) -> (NEGQ x) +(Neg32 x) -> (NEGL x) +(Neg16 x) -> (NEGW x) +(Neg8 x) -> (NEGB x) +(Neg32F x) -> (PXOR x (MOVSSconst [f2i(math.Copysign(0, -1))])) +(Neg64F x) -> (PXOR x (MOVSDconst [f2i(math.Copysign(0, -1))])) + +(Com64 x) -> (NOTQ x) +(Com32 x) -> (NOTL x) +(Com16 x) -> (NOTW x) +(Com8 x) -> (NOTB x) + +(Sqrt x) -> (SQRTSD x) + +// Note: we always extend to 64 bits even though some ops don't need that many result bits. +(SignExt8to16 x) -> (MOVBQSX x) +(SignExt8to32 x) -> (MOVBQSX x) +(SignExt8to64 x) -> (MOVBQSX x) +(SignExt16to32 x) -> (MOVWQSX x) +(SignExt16to64 x) -> (MOVWQSX x) +(SignExt32to64 x) -> (MOVLQSX x) + +(ZeroExt8to16 x) -> (MOVBQZX x) +(ZeroExt8to32 x) -> (MOVBQZX x) +(ZeroExt8to64 x) -> (MOVBQZX x) +(ZeroExt16to32 x) -> (MOVWQZX x) +(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) -> (CVTTSS2SL x) +(Cvt32Fto64 x) -> (CVTTSS2SQ x) +(Cvt64Fto32 x) -> (CVTTSD2SL x) +(Cvt64Fto64 x) -> (CVTTSD2SQ 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 +(Trunc32to16 x) -> x +(Trunc64to8 x) -> x +(Trunc64to16 x) -> x +(Trunc64to32 x) -> x + +// Lowering shifts +// Unsigned shifts need to return 0 if shift amount is >= width of shifted value. +// result = (arg << shift) & (shift >= argbits ? 0 : 0xffffffffffffffff) +// Note: for small shifts we generate 32 bits of mask even when we don't need it all. +(Lsh64x64 x y) -> (ANDQ (SHLQ x y) (SBBQcarrymask (CMPQconst [64] y))) +(Lsh64x32 x y) -> (ANDQ (SHLQ x y) (SBBQcarrymask (CMPLconst [64] y))) +(Lsh64x16 x y) -> (ANDQ (SHLQ x y) (SBBQcarrymask (CMPWconst [64] y))) +(Lsh64x8 x y) -> (ANDQ (SHLQ x y) (SBBQcarrymask (CMPBconst [64] y))) + +(Lsh32x64 x y) -> (ANDL (SHLL x y) (SBBLcarrymask (CMPQconst [32] y))) +(Lsh32x32 x y) -> (ANDL (SHLL x y) (SBBLcarrymask (CMPLconst [32] y))) +(Lsh32x16 x y) -> (ANDL (SHLL x y) (SBBLcarrymask (CMPWconst [32] y))) +(Lsh32x8 x y) -> (ANDL (SHLL x y) (SBBLcarrymask (CMPBconst [32] y))) + +(Lsh16x64 x y) -> (ANDW (SHLW x y) (SBBLcarrymask (CMPQconst [16] y))) +(Lsh16x32 x y) -> (ANDW (SHLW x y) (SBBLcarrymask (CMPLconst [16] y))) +(Lsh16x16 x y) -> (ANDW (SHLW x y) (SBBLcarrymask (CMPWconst [16] y))) +(Lsh16x8 x y) -> (ANDW (SHLW x y) (SBBLcarrymask (CMPBconst [16] y))) + +(Lsh8x64 x y) -> (ANDB (SHLB x y) (SBBLcarrymask (CMPQconst [8] y))) +(Lsh8x32 x y) -> (ANDB (SHLB x y) (SBBLcarrymask (CMPLconst [8] y))) +(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))) +(Rsh64Ux8 x y) -> (ANDQ (SHRQ x y) (SBBQcarrymask (CMPBconst [64] y))) + +(Rsh32Ux64 x y) -> (ANDL (SHRL x y) (SBBLcarrymask (CMPQconst [32] y))) +(Rsh32Ux32 x y) -> (ANDL (SHRL x y) (SBBLcarrymask (CMPLconst [32] y))) +(Rsh32Ux16 x y) -> (ANDL (SHRL x y) (SBBLcarrymask (CMPWconst [32] y))) +(Rsh32Ux8 x y) -> (ANDL (SHRL x y) (SBBLcarrymask (CMPBconst [32] y))) + +(Rsh16Ux64 x y) -> (ANDW (SHRW x y) (SBBLcarrymask (CMPQconst [16] y))) +(Rsh16Ux32 x y) -> (ANDW (SHRW x y) (SBBLcarrymask (CMPLconst [16] y))) +(Rsh16Ux16 x y) -> (ANDW (SHRW x y) (SBBLcarrymask (CMPWconst [16] y))) +(Rsh16Ux8 x y) -> (ANDW (SHRW x y) (SBBLcarrymask (CMPBconst [16] y))) + +(Rsh8Ux64 x y) -> (ANDB (SHRB x y) (SBBLcarrymask (CMPQconst [8] y))) +(Rsh8Ux32 x y) -> (ANDB (SHRB x y) (SBBLcarrymask (CMPLconst [8] y))) +(Rsh8Ux16 x y) -> (ANDB (SHRB x y) (SBBLcarrymask (CMPWconst [8] y))) +(Rsh8Ux8 x y) -> (ANDB (SHRB x y) (SBBLcarrymask (CMPBconst [8] y))) + +// Signed right shift needs to return 0/-1 if shift amount is >= width of shifted value. +// We implement this by setting the shift value to -1 (all ones) if the shift value is >= width. +// Note: for small shift widths we generate 32 bits of mask even when we don't need it all. +(Rsh64x64 x y) -> (SARQ x (ORQ y (NOTQ (SBBQcarrymask (CMPQconst [64] y))))) +(Rsh64x32 x y) -> (SARQ x (ORL y (NOTL (SBBLcarrymask (CMPLconst [64] y))))) +(Rsh64x16 x y) -> (SARQ x (ORW y (NOTL (SBBLcarrymask (CMPWconst [64] y))))) +(Rsh64x8 x y) -> (SARQ x (ORB y (NOTL (SBBLcarrymask (CMPBconst [64] y))))) + +(Rsh32x64 x y) -> (SARL x (ORQ y (NOTQ (SBBQcarrymask (CMPQconst [32] y))))) +(Rsh32x32 x y) -> (SARL x (ORL y (NOTL (SBBLcarrymask (CMPLconst [32] y))))) +(Rsh32x16 x y) -> (SARL x (ORW y (NOTL (SBBLcarrymask (CMPWconst [32] y))))) +(Rsh32x8 x y) -> (SARL x (ORB y (NOTL (SBBLcarrymask (CMPBconst [32] y))))) + +(Rsh16x64 x y) -> (SARW x (ORQ y (NOTQ (SBBQcarrymask (CMPQconst [16] y))))) +(Rsh16x32 x y) -> (SARW x (ORL y (NOTL (SBBLcarrymask (CMPLconst [16] y))))) +(Rsh16x16 x y) -> (SARW x (ORW y (NOTL (SBBLcarrymask (CMPWconst [16] y))))) +(Rsh16x8 x y) -> (SARW x (ORB y (NOTL (SBBLcarrymask (CMPBconst [16] y))))) + +(Rsh8x64 x y) -> (SARB x (ORQ y (NOTQ (SBBQcarrymask (CMPQconst [8] y))))) +(Rsh8x32 x y) -> (SARB x (ORL y (NOTL (SBBLcarrymask (CMPLconst [8] y))))) +(Rsh8x16 x y) -> (SARB x (ORW y (NOTL (SBBLcarrymask (CMPWconst [8] y))))) +(Rsh8x8 x y) -> (SARB x (ORB y (NOTL (SBBLcarrymask (CMPBconst [8] y))))) + +(Less64 x y) -> (SETL (CMPQ x y)) +(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) +(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) +(Store [1] ptr val mem) -> (MOVBstore ptr val mem) + +// 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) +(GetG) -> (LoweredGetG) +(GetClosurePtr) -> (LoweredGetClosurePtr) + +(Move [size] dst src mem) -> (REPMOVSB dst src (MOVQconst [size]) mem) + +(Not x) -> (XORBconst [1] x) + +(OffPtr [off] ptr) -> (ADDQconst [off] ptr) + +(Const8 [val]) -> (MOVBconst [val]) +(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]) -> (MOVBconst [b]) + +(Addr {sym} base) -> (LEAQ {sym} base) + +(ITab (Load ptr mem)) -> (MOVQload ptr mem) + +// block rewrites +(If (SETL cmp) yes no) -> (LT cmp yes no) +(If (SETLE cmp) yes no) -> (LE cmp yes no) +(If (SETG cmp) yes no) -> (GT cmp yes no) +(If (SETGE cmp) yes no) -> (GE cmp yes no) +(If (SETEQ cmp) yes no) -> (EQ cmp yes no) +(If (SETNE cmp) yes no) -> (NE cmp yes no) +(If (SETB cmp) yes no) -> (ULT cmp yes no) +(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) + +// 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) +(NE (TESTB (SETLE cmp)) yes no) -> (LE cmp yes no) +(NE (TESTB (SETG cmp)) yes no) -> (GT cmp yes no) +(NE (TESTB (SETGE cmp)) yes no) -> (GE cmp yes no) +(NE (TESTB (SETEQ cmp)) yes no) -> (EQ cmp yes no) +(NE (TESTB (SETNE cmp)) yes no) -> (NE cmp yes no) +(NE (TESTB (SETB cmp)) yes no) -> (ULT cmp yes no) +(NE (TESTB (SETBE cmp)) yes no) -> (ULE cmp yes no) +(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) +(DeferCall [argwid] mem) -> (CALLdefer [argwid] mem) +(GoCall [argwid] mem) -> (CALLgo [argwid] mem) +(InterCall [argwid] entry mem) -> (CALLinter [argwid] entry mem) + +// Rules below here apply some simple optimizations after lowering. +// TODO: Should this be a separate pass? + +// fold constants into instructions +(ADDQ x (MOVQconst [c])) && is32Bit(c) -> (ADDQconst [c] x) +(ADDQ (MOVQconst [c]) x) && is32Bit(c) -> (ADDQconst [c] x) +(ADDL x (MOVLconst [c])) -> (ADDLconst [c] x) +(ADDL (MOVLconst [c]) x) -> (ADDLconst [c] x) +(ADDW x (MOVWconst [c])) -> (ADDWconst [c] x) +(ADDW (MOVWconst [c]) x) -> (ADDWconst [c] x) +(ADDB x (MOVBconst [c])) -> (ADDBconst [c] x) +(ADDB (MOVBconst [c]) x) -> (ADDBconst [c] x) + +(SUBQ x (MOVQconst [c])) && is32Bit(c) -> (SUBQconst x [c]) +(SUBQ (MOVQconst [c]) x) && is32Bit(c) -> (NEGQ (SUBQconst x [c])) +(SUBL x (MOVLconst [c])) -> (SUBLconst x [c]) +(SUBL (MOVLconst [c]) x) -> (NEGL (SUBLconst x [c])) +(SUBW x (MOVWconst [c])) -> (SUBWconst x [c]) +(SUBW (MOVWconst [c]) x) -> (NEGW (SUBWconst x [c])) +(SUBB x (MOVBconst [c])) -> (SUBBconst x [c]) +(SUBB (MOVBconst [c]) x) -> (NEGB (SUBBconst x [c])) + +(MULQ x (MOVQconst [c])) && is32Bit(c) -> (MULQconst [c] x) +(MULQ (MOVQconst [c]) x) && is32Bit(c) -> (MULQconst [c] x) +(MULL x (MOVLconst [c])) -> (MULLconst [c] x) +(MULL (MOVLconst [c]) x) -> (MULLconst [c] x) +(MULW x (MOVWconst [c])) -> (MULWconst [c] x) +(MULW (MOVWconst [c]) x) -> (MULWconst [c] x) +(MULB x (MOVBconst [c])) -> (MULBconst [c] x) +(MULB (MOVBconst [c]) x) -> (MULBconst [c] x) + +(ANDQ x (MOVQconst [c])) && is32Bit(c) -> (ANDQconst [c] x) +(ANDQ (MOVQconst [c]) x) && is32Bit(c) -> (ANDQconst [c] x) +(ANDL x (MOVLconst [c])) -> (ANDLconst [c] x) +(ANDL (MOVLconst [c]) x) -> (ANDLconst [c] x) +(ANDW x (MOVLconst [c])) -> (ANDWconst [c] x) +(ANDW (MOVLconst [c]) x) -> (ANDWconst [c] x) +(ANDW x (MOVWconst [c])) -> (ANDWconst [c] x) +(ANDW (MOVWconst [c]) x) -> (ANDWconst [c] x) +(ANDB x (MOVLconst [c])) -> (ANDBconst [c] x) +(ANDB (MOVLconst [c]) x) -> (ANDBconst [c] x) +(ANDB x (MOVBconst [c])) -> (ANDBconst [c] x) +(ANDB (MOVBconst [c]) x) -> (ANDBconst [c] x) + +(ORQ x (MOVQconst [c])) && is32Bit(c) -> (ORQconst [c] x) +(ORQ (MOVQconst [c]) x) && is32Bit(c) -> (ORQconst [c] x) +(ORL x (MOVLconst [c])) -> (ORLconst [c] x) +(ORL (MOVLconst [c]) x) -> (ORLconst [c] x) +(ORW x (MOVWconst [c])) -> (ORWconst [c] x) +(ORW (MOVWconst [c]) x) -> (ORWconst [c] x) +(ORB x (MOVBconst [c])) -> (ORBconst [c] x) +(ORB (MOVBconst [c]) x) -> (ORBconst [c] x) + +(XORQ x (MOVQconst [c])) && is32Bit(c) -> (XORQconst [c] x) +(XORQ (MOVQconst [c]) x) && is32Bit(c) -> (XORQconst [c] x) +(XORL x (MOVLconst [c])) -> (XORLconst [c] x) +(XORL (MOVLconst [c]) x) -> (XORLconst [c] x) +(XORW x (MOVWconst [c])) -> (XORWconst [c] x) +(XORW (MOVWconst [c]) x) -> (XORWconst [c] x) +(XORB x (MOVBconst [c])) -> (XORBconst [c] x) +(XORB (MOVBconst [c]) x) -> (XORBconst [c] x) + +(SHLQ x (MOVQconst [c])) -> (SHLQconst [c&63] x) +(SHLL x (MOVLconst [c])) -> (SHLLconst [c&31] x) +(SHLW x (MOVWconst [c])) -> (SHLWconst [c&31] x) +(SHLB x (MOVBconst [c])) -> (SHLBconst [c&31] x) + +(SHRQ x (MOVQconst [c])) -> (SHRQconst [c&63] x) +(SHRL x (MOVLconst [c])) -> (SHRLconst [c&31] x) +(SHRW x (MOVWconst [c])) -> (SHRWconst [c&31] x) +(SHRB x (MOVBconst [c])) -> (SHRBconst [c&31] x) + +(SARQ x (MOVQconst [c])) -> (SARQconst [c&63] x) +(SARL x (MOVLconst [c])) -> (SARLconst [c&31] x) +(SARW x (MOVWconst [c])) -> (SARWconst [c&31] x) +(SARB x (MOVBconst [c])) -> (SARBconst [c&31] x) + +// Note: the word and byte shifts keep the low 5 bits (not the low 4 or 3 bits) +// because the x86 instructions are defined to use all 5 bits of the shift even +// for the small shifts. I don't think we'll ever generate a weird shift (e.g. +// (SHLW x (MOVWconst [24])), but just in case. + +(CMPQ x (MOVQconst [c])) && is32Bit(c) -> (CMPQconst x [c]) +(CMPQ (MOVQconst [c]) x) && is32Bit(c) -> (InvertFlags (CMPQconst x [c])) +(CMPL x (MOVLconst [c])) -> (CMPLconst x [c]) +(CMPL (MOVLconst [c]) x) -> (InvertFlags (CMPLconst x [c])) +(CMPW x (MOVWconst [c])) -> (CMPWconst x [c]) +(CMPW (MOVWconst [c]) x) -> (InvertFlags (CMPWconst x [c])) +(CMPB x (MOVBconst [c])) -> (CMPBconst x [c]) +(CMPB (MOVBconst [c]) x) -> (InvertFlags (CMPBconst x [c])) + +// strength reduction +(MULQconst [-1] x) -> (NEGQ x) +(MULQconst [0] _) -> (MOVQconst [0]) +(MULQconst [1] x) -> x +(MULQconst [3] x) -> (LEAQ2 x x) +(MULQconst [5] x) -> (LEAQ4 x x) +(MULQconst [9] x) -> (LEAQ8 x x) +(MULQconst [c] x) && isPowerOfTwo(c) -> (SHLQconst [log2(c)] x) + +// fold add/shift into leaq +(ADDQ x (SHLQconst [3] y)) -> (LEAQ8 x y) +(ADDQconst [c] (LEAQ8 [d] x y)) -> (LEAQ8 [addOff(c, d)] x y) + +// reverse ordering of compare instruction +(SETL (InvertFlags x)) -> (SETG x) +(SETG (InvertFlags x)) -> (SETL x) +(SETB (InvertFlags x)) -> (SETA x) +(SETA (InvertFlags x)) -> (SETB x) +(SETLE (InvertFlags x)) -> (SETGE x) +(SETGE (InvertFlags x)) -> (SETLE x) +(SETBE (InvertFlags x)) -> (SETAE x) +(SETAE (InvertFlags x)) -> (SETBE x) +(SETEQ (InvertFlags x)) -> (SETEQ x) +(SETNE (InvertFlags x)) -> (SETNE x) + +// sign extended loads +// 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. +(MOVBQSX (MOVBload [off] {sym} ptr mem)) -> @v.Args[0].Block (MOVBQSXload [off] {sym} ptr mem) +(MOVBQZX (MOVBload [off] {sym} ptr mem)) -> @v.Args[0].Block (MOVBQZXload [off] {sym} ptr mem) +// TODO: more + +// Don't extend before storing +(MOVLstore [off] {sym} ptr (MOVLQSX x) mem) -> (MOVLstore [off] {sym} ptr x mem) +(MOVWstore [off] {sym} ptr (MOVWQSX x) mem) -> (MOVWstore [off] {sym} ptr x mem) +(MOVBstore [off] {sym} ptr (MOVBQSX x) mem) -> (MOVBstore [off] {sym} ptr x mem) +(MOVLstore [off] {sym} ptr (MOVLQZX x) mem) -> (MOVLstore [off] {sym} ptr x mem) +(MOVWstore [off] {sym} ptr (MOVWQZX x) mem) -> (MOVWstore [off] {sym} ptr x mem) +(MOVBstore [off] {sym} ptr (MOVBQZX x) mem) -> (MOVBstore [off] {sym} ptr x mem) + +// fold constants into memory operations +// Note that this is not always a good idea because if not all the uses of +// the ADDQconst get eliminated, we still have to compute the ADDQconst and we now +// have potentially two live values (ptr and (ADDQconst [off] ptr)) instead of one. +// Nevertheless, let's do it! +(MOVQload [off1] {sym} (ADDQconst [off2] ptr) mem) -> (MOVQload [addOff(off1, off2)] {sym} ptr mem) +(MOVLload [off1] {sym} (ADDQconst [off2] ptr) mem) -> (MOVLload [addOff(off1, off2)] {sym} ptr mem) +(MOVWload [off1] {sym} (ADDQconst [off2] ptr) mem) -> (MOVWload [addOff(off1, off2)] {sym} ptr mem) +(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) + +(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) +(MOVWstore [off1] {sym} (ADDQconst [off2] ptr) val mem) -> (MOVWstore [addOff(off1, off2)] {sym} ptr val mem) +(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) + +// 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. +(MOVQload [off1] {sym1} (LEAQ [off2] {sym2} base) mem) && canMergeSym(sym1, sym2) -> + (MOVQload [addOff(off1,off2)] {mergeSym(sym1,sym2)} base mem) +(MOVLload [off1] {sym1} (LEAQ [off2] {sym2} base) mem) && canMergeSym(sym1, sym2) -> + (MOVLload [addOff(off1,off2)] {mergeSym(sym1,sym2)} base mem) +(MOVWload [off1] {sym1} (LEAQ [off2] {sym2} base) mem) && canMergeSym(sym1, sym2) -> + (MOVWload [addOff(off1,off2)] {mergeSym(sym1,sym2)} base mem) +(MOVBload [off1] {sym1} (LEAQ [off2] {sym2} base) mem) && canMergeSym(sym1, sym2) -> + (MOVBload [addOff(off1,off2)] {mergeSym(sym1,sym2)} base mem) +(MOVSSload [off1] {sym1} (LEAQ [off2] {sym2} base) mem) && canMergeSym(sym1, sym2) -> + (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) + +(MOVQstore [off1] {sym1} (LEAQ [off2] {sym2} base) val mem) && canMergeSym(sym1, sym2) -> + (MOVQstore [addOff(off1,off2)] {mergeSym(sym1,sym2)} base val mem) +(MOVLstore [off1] {sym1} (LEAQ [off2] {sym2} base) val mem) && canMergeSym(sym1, sym2) -> + (MOVLstore [addOff(off1,off2)] {mergeSym(sym1,sym2)} base val mem) +(MOVWstore [off1] {sym1} (LEAQ [off2] {sym2} base) val mem) && canMergeSym(sym1, sym2) -> + (MOVWstore [addOff(off1,off2)] {mergeSym(sym1,sym2)} base val mem) +(MOVBstore [off1] {sym1} (LEAQ [off2] {sym2} base) val mem) && canMergeSym(sym1, sym2) -> + (MOVBstore [addOff(off1,off2)] {mergeSym(sym1,sym2)} base val mem) +(MOVSSstore [off1] {sym1} (LEAQ [off2] {sym2} base) val mem) && canMergeSym(sym1, sym2) -> + (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) + +// indexed loads and stores +(MOVQloadidx8 [off1] {sym} (ADDQconst [off2] ptr) idx mem) -> (MOVQloadidx8 [addOff(off1, off2)] {sym} ptr idx mem) +(MOVQstoreidx8 [off1] {sym} (ADDQconst [off2] ptr) idx val mem) -> (MOVQstoreidx8 [addOff(off1, off2)] {sym} ptr idx val mem) +(MOVSSloadidx4 [off1] {sym} (ADDQconst [off2] {sym} ptr) idx mem) -> (MOVSSloadidx4 [addOff(off1, off2)] {sym} ptr idx mem) +(MOVSSstoreidx4 [off1] {sym} (ADDQconst [off2] {sym} ptr) idx val mem) -> (MOVSSstoreidx4 [addOff(off1, off2)] {sym} ptr idx val mem) +(MOVSDloadidx8 [off1] {sym} (ADDQconst [off2] {sym} ptr) idx mem) -> (MOVSDloadidx8 [addOff(off1, off2)] {sym} ptr idx mem) +(MOVSDstoreidx8 [off1] {sym} (ADDQconst [off2] {sym} ptr) idx val mem) -> (MOVSDstoreidx8 [addOff(off1, off2)] {sym} ptr idx val mem) + +(MOVQload [off1] {sym1} (LEAQ8 [off2] {sym2} ptr idx) mem) && canMergeSym(sym1, sym2) -> + (MOVQloadidx8 [addOff(off1, off2)] {mergeSym(sym1,sym2)} ptr idx mem) +(MOVQstore [off1] {sym1} (LEAQ8 [off2] {sym2} ptr idx) val mem) && canMergeSym(sym1, sym2) -> + (MOVQstoreidx8 [addOff(off1, off2)] {mergeSym(sym1,sym2)} ptr idx val mem) + +(MOVSSload [off1] {sym1} (LEAQ4 [off2] {sym2} ptr idx) mem) && canMergeSym(sym1, sym2) -> + (MOVSSloadidx4 [addOff(off1, off2)] {mergeSym(sym1,sym2)} ptr idx mem) +(MOVSSstore [off1] {sym1} (LEAQ4 [off2] {sym2} ptr idx) val mem) && canMergeSym(sym1, sym2) -> + (MOVSSstoreidx4 [addOff(off1, off2)] {mergeSym(sym1,sym2)} ptr idx val mem) + +(MOVSDload [off1] {sym1} (LEAQ8 [off2] {sym2} ptr idx) mem) && canMergeSym(sym1, sym2) -> + (MOVSDloadidx8 [addOff(off1, off2)] {mergeSym(sym1,sym2)} ptr idx mem) +(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 +(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) + +(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) ++(Zero [size] destptr mem) && size <= 1024 && size%8 == 0 && size%16 != 0 -> ++ (Zero [size-8] (ADDQconst [8] destptr) (MOVQstore destptr (MOVQconst [0]) mem)) ++(Zero [size] destptr mem) && size <= 1024 && size%16 == 0 -> ++ (DUFFZERO [duffStart(size)] (ADDQconst [duffAdj(size)] destptr) (MOVOconst [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) +(GT (InvertFlags cmp) yes no) -> (LT cmp yes no) +(LE (InvertFlags cmp) yes no) -> (GE cmp yes no) +(GE (InvertFlags cmp) yes no) -> (LE cmp yes no) +(ULT (InvertFlags cmp) yes no) -> (UGT cmp yes no) +(UGT (InvertFlags cmp) yes no) -> (ULT cmp yes no) +(ULE (InvertFlags cmp) yes no) -> (UGE cmp yes no) +(UGE (InvertFlags cmp) yes no) -> (ULE cmp yes no) +(EQ (InvertFlags cmp) yes no) -> (EQ cmp yes no) +(NE (InvertFlags cmp) yes no) -> (NE cmp yes no) + +// get rid of overflow code for constant shifts +(SBBQcarrymask (CMPQconst [c] (MOVQconst [d]))) && inBounds64(d, c) -> (MOVQconst [-1]) +(SBBQcarrymask (CMPQconst [c] (MOVQconst [d]))) && !inBounds64(d, c) -> (MOVQconst [0]) +(SBBQcarrymask (CMPLconst [c] (MOVLconst [d]))) && inBounds32(d, c) -> (MOVQconst [-1]) +(SBBQcarrymask (CMPLconst [c] (MOVLconst [d]))) && !inBounds32(d, c) -> (MOVQconst [0]) +(SBBQcarrymask (CMPWconst [c] (MOVWconst [d]))) && inBounds16(d, c) -> (MOVQconst [-1]) +(SBBQcarrymask (CMPWconst [c] (MOVWconst [d]))) && !inBounds16(d, c) -> (MOVQconst [0]) +(SBBQcarrymask (CMPBconst [c] (MOVBconst [d]))) && inBounds8(d, c) -> (MOVQconst [-1]) +(SBBQcarrymask (CMPBconst [c] (MOVBconst [d]))) && !inBounds8(d, c) -> (MOVQconst [0]) +(SBBLcarrymask (CMPQconst [c] (MOVQconst [d]))) && inBounds64(d, c) -> (MOVLconst [-1]) +(SBBLcarrymask (CMPQconst [c] (MOVQconst [d]))) && !inBounds64(d, c) -> (MOVLconst [0]) +(SBBLcarrymask (CMPLconst [c] (MOVLconst [d]))) && inBounds32(d, c) -> (MOVLconst [-1]) +(SBBLcarrymask (CMPLconst [c] (MOVLconst [d]))) && !inBounds32(d, c) -> (MOVLconst [0]) +(SBBLcarrymask (CMPWconst [c] (MOVWconst [d]))) && inBounds16(d, c) -> (MOVLconst [-1]) +(SBBLcarrymask (CMPWconst [c] (MOVWconst [d]))) && !inBounds16(d, c) -> (MOVLconst [0]) +(SBBLcarrymask (CMPBconst [c] (MOVBconst [d]))) && inBounds8(d, c) -> (MOVLconst [-1]) +(SBBLcarrymask (CMPBconst [c] (MOVBconst [d]))) && !inBounds8(d, c) -> (MOVLconst [0]) +(ANDQconst [0] _) -> (MOVQconst [0]) +(ANDLconst [c] _) && int32(c)==0 -> (MOVLconst [0]) +(ANDWconst [c] _) && int16(c)==0 -> (MOVWconst [0]) +(ANDBconst [c] _) && int8(c)==0 -> (MOVBconst [0]) +(ANDQconst [-1] x) -> x +(ANDLconst [c] x) && int32(c)==-1 -> x +(ANDWconst [c] x) && int16(c)==-1 -> x +(ANDBconst [c] x) && int8(c)==-1 -> x +(ORQconst [0] x) -> x +(ORLconst [c] x) && int32(c)==0 -> x +(ORWconst [c] x) && int16(c)==0 -> x +(ORBconst [c] x) && int8(c)==0 -> x +(ORQconst [-1] _) -> (MOVQconst [-1]) +(ORLconst [c] _) && int32(c)==-1 -> (MOVLconst [-1]) +(ORWconst [c] _) && int16(c)==-1 -> (MOVWconst [-1]) +(ORBconst [c] _) && int8(c)==-1 -> (MOVBconst [-1]) + +// generic constant folding +// TODO: more of this +(ADDQconst [c] (MOVQconst [d])) -> (MOVQconst [c+d]) +(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 [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) +(SARQconst [c] (MOVQconst [d])) -> (MOVQconst [d>>uint64(c)]) +(SARLconst [c] (MOVQconst [d])) -> (MOVQconst [d>>uint64(c)]) +(SARWconst [c] (MOVQconst [d])) -> (MOVQconst [d>>uint64(c)]) +(SARBconst [c] (MOVQconst [d])) -> (MOVQconst [d>>uint64(c)]) +(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]) +(MULBconst [c] (MOVBconst [d])) -> (MOVBconst [c*d]) +(ANDQconst [c] (MOVQconst [d])) -> (MOVQconst [c&d]) +(ANDLconst [c] (MOVLconst [d])) -> (MOVLconst [c&d]) +(ANDWconst [c] (MOVWconst [d])) -> (MOVWconst [c&d]) +(ANDBconst [c] (MOVBconst [d])) -> (MOVBconst [c&d]) +(ORQconst [c] (MOVQconst [d])) -> (MOVQconst [c|d]) +(ORLconst [c] (MOVLconst [d])) -> (MOVLconst [c|d]) +(ORWconst [c] (MOVWconst [d])) -> (MOVWconst [c|d]) +(ORBconst [c] (MOVBconst [d])) -> (MOVBconst [c|d]) +(XORQconst [c] (MOVQconst [d])) -> (MOVQconst [c^d]) +(XORLconst [c] (MOVLconst [d])) -> (MOVLconst [c^d]) +(XORWconst [c] (MOVWconst [d])) -> (MOVWconst [c^d]) +(XORBconst [c] (MOVBconst [d])) -> (MOVBconst [c^d]) +(NOTQ (MOVQconst [c])) -> (MOVQconst [^c]) +(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) -> x +(ANDL x x) -> x +(ANDW x x) -> x +(ANDB x x) -> x +(ORQ x x) -> x +(ORL x x) -> x +(ORW x x) -> x +(ORB x x) -> x +(XORQ x x) -> (MOVQconst [0]) +(XORL x x) -> (MOVLconst [0]) +(XORW x x) -> (MOVWconst [0]) +(XORB x x) -> (MOVBconst [0]) diff --cc src/cmd/compile/internal/ssa/gen/AMD64Ops.go index 5d171dc87a,0000000000..c9b7f31b9d mode 100644,000000..100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go @@@ -1,451 -1,0 +1,452 @@@ +// 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 "strings" + +// copied from ../../amd64/reg.go +var regNamesAMD64 = []string{ + ".AX", + ".CX", + ".DX", + ".BX", + ".SP", + ".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", + + // pseudo-registers + ".SB", + ".FLAGS", +} + +func init() { + // Make map from reg names to reg integers. + if len(regNamesAMD64) > 64 { + panic("too many registers") + } + num := map[string]int{} + for i, name := range regNamesAMD64 { + if name[0] != '.' { + panic("register name " + name + " does not start with '.'") + } + num[name[1:]] = i + } + buildReg := func(s string) regMask { + m := regMask(0) + for _, r := range strings.Split(s, " ") { + if n, ok := num[r]; ok { + m |= regMask(1) << uint(n) + continue + } + panic("register " + r + " not found") + } + return m + } + + // 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") + gpsp = gp | buildReg("SP") + gpspsb = gpsp | buildReg("SB") + flags = buildReg("FLAGS") + callerSave = gp | fp | flags + ) + // Common slices of register masks + var ( + gponly = []regMask{gp} + fponly = []regMask{fp} + flagsonly = []regMask{flags} + ) + + // 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} + gp21 = regInfo{inputs: []regMask{gpsp, gpsp}, outputs: gponly, clobbers: flags} + gp21sb = regInfo{inputs: []regMask{gpspsb, gpsp}, outputs: gponly} + 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} + 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} + gp1flags = regInfo{inputs: []regMask{gpsp}, outputs: flagsonly} + flagsgp = regInfo{inputs: flagsonly, outputs: gponly} + readflags = regInfo{inputs: flagsonly, outputs: gponly} + flagsgpax = regInfo{inputs: flagsonly, clobbers: ax | flags, outputs: []regMask{gp &^ ax}} + + gpload = regInfo{inputs: []regMask{gpspsb, 0}, outputs: gponly} + gploadidx = regInfo{inputs: []regMask{gpspsb, gpsp, 0}, outputs: gponly} + + 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} + 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} + 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}} + ) + // 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 + + // 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 + {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 + {name: "SUBW", reg: gp21, asm: "SUBW"}, // arg0 - arg1 + {name: "SUBB", reg: gp21, asm: "SUBB"}, // arg0 - arg1 + {name: "SUBQconst", reg: gp11, asm: "SUBQ"}, // arg0 - auxint + {name: "SUBLconst", reg: gp11, asm: "SUBL"}, // arg0 - auxint + {name: "SUBWconst", reg: gp11, asm: "SUBW"}, // arg0 - auxint + {name: "SUBBconst", reg: gp11, asm: "SUBB"}, // arg0 - auxint + + {name: "MULQ", reg: gp21, asm: "IMULQ"}, // arg0 * arg1 + {name: "MULL", reg: gp21, asm: "IMULL"}, // arg0 * arg1 + {name: "MULW", reg: gp21, asm: "IMULW"}, // arg0 * arg1 + {name: "MULB", reg: gp21, asm: "IMULW"}, // arg0 * arg1 + {name: "MULQconst", reg: gp11, asm: "IMULQ"}, // arg0 * auxint + {name: "MULLconst", reg: gp11, asm: "IMULL"}, // arg0 * auxint + {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 + + {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 + {name: "ANDB", reg: gp21, asm: "ANDB"}, // arg0 & arg1 + {name: "ANDQconst", reg: gp11, asm: "ANDQ"}, // arg0 & auxint + {name: "ANDLconst", reg: gp11, asm: "ANDL"}, // arg0 & auxint + {name: "ANDWconst", reg: gp11, asm: "ANDW"}, // arg0 & auxint + {name: "ANDBconst", reg: gp11, asm: "ANDB"}, // arg0 & auxint + + {name: "ORQ", reg: gp21, asm: "ORQ"}, // arg0 | arg1 + {name: "ORL", reg: gp21, asm: "ORL"}, // arg0 | arg1 + {name: "ORW", reg: gp21, asm: "ORW"}, // arg0 | arg1 + {name: "ORB", reg: gp21, asm: "ORB"}, // arg0 | arg1 + {name: "ORQconst", reg: gp11, asm: "ORQ"}, // arg0 | auxint + {name: "ORLconst", reg: gp11, asm: "ORL"}, // arg0 | auxint + {name: "ORWconst", reg: gp11, asm: "ORW"}, // arg0 | auxint + {name: "ORBconst", reg: gp11, asm: "ORB"}, // arg0 | auxint + + {name: "XORQ", reg: gp21, asm: "XORQ"}, // arg0 ^ arg1 + {name: "XORL", reg: gp21, asm: "XORL"}, // arg0 ^ arg1 + {name: "XORW", reg: gp21, asm: "XORW"}, // arg0 ^ arg1 + {name: "XORB", reg: gp21, asm: "XORB"}, // arg0 ^ arg1 + {name: "XORQconst", reg: gp11, asm: "XORQ"}, // arg0 ^ auxint + {name: "XORLconst", reg: gp11, asm: "XORL"}, // arg0 ^ auxint + {name: "XORWconst", reg: gp11, asm: "XORW"}, // arg0 ^ auxint + {name: "XORBconst", reg: gp11, asm: "XORB"}, // arg0 ^ auxint + + {name: "CMPQ", reg: gp2flags, asm: "CMPQ", typ: "Flags"}, // arg0 compare to arg1 + {name: "CMPL", reg: gp2flags, asm: "CMPL", typ: "Flags"}, // arg0 compare to arg1 + {name: "CMPW", reg: gp2flags, asm: "CMPW", typ: "Flags"}, // arg0 compare to arg1 + {name: "CMPB", reg: gp2flags, asm: "CMPB", typ: "Flags"}, // arg0 compare to arg1 + {name: "CMPQconst", reg: gp1flags, asm: "CMPQ", typ: "Flags"}, // arg0 compare to auxint + {name: "CMPLconst", reg: gp1flags, asm: "CMPL", typ: "Flags"}, // arg0 compare to auxint + {name: "CMPWconst", reg: gp1flags, asm: "CMPW", typ: "Flags"}, // arg0 compare to auxint + {name: "CMPBconst", reg: gp1flags, asm: "CMPB", typ: "Flags"}, // arg0 compare to auxint + + {name: "UCOMISS", reg: fp2flags, asm: "UCOMISS", typ: "Flags"}, // arg0 compare to arg1, f32 + {name: "UCOMISD", reg: fp2flags, asm: "UCOMISD", typ: "Flags"}, // arg0 compare to arg1, f64 + + {name: "TESTQ", reg: gp2flags, asm: "TESTQ", typ: "Flags"}, // (arg0 & arg1) compare to 0 + {name: "TESTL", reg: gp2flags, asm: "TESTL", typ: "Flags"}, // (arg0 & arg1) compare to 0 + {name: "TESTW", reg: gp2flags, asm: "TESTW", typ: "Flags"}, // (arg0 & arg1) compare to 0 + {name: "TESTB", reg: gp2flags, asm: "TESTB", typ: "Flags"}, // (arg0 & arg1) compare to 0 + {name: "TESTQconst", reg: gp1flags, asm: "TESTQ", typ: "Flags"}, // (arg0 & auxint) compare to 0 + {name: "TESTLconst", reg: gp1flags, asm: "TESTL", typ: "Flags"}, // (arg0 & auxint) compare to 0 + {name: "TESTWconst", reg: gp1flags, asm: "TESTW", typ: "Flags"}, // (arg0 & auxint) compare to 0 + {name: "TESTBconst", reg: gp1flags, asm: "TESTB", typ: "Flags"}, // (arg0 & auxint) compare to 0 + + {name: "SHLQ", reg: gp21shift, asm: "SHLQ"}, // arg0 << arg1, shift amount is mod 64 + {name: "SHLL", reg: gp21shift, asm: "SHLL"}, // arg0 << arg1, shift amount is mod 32 + {name: "SHLW", reg: gp21shift, asm: "SHLW"}, // arg0 << arg1, shift amount is mod 32 + {name: "SHLB", reg: gp21shift, asm: "SHLB"}, // arg0 << arg1, shift amount is mod 32 + {name: "SHLQconst", reg: gp11, asm: "SHLQ"}, // arg0 << auxint, shift amount 0-63 + {name: "SHLLconst", reg: gp11, asm: "SHLL"}, // arg0 << auxint, shift amount 0-31 + {name: "SHLWconst", reg: gp11, asm: "SHLW"}, // arg0 << auxint, shift amount 0-31 + {name: "SHLBconst", reg: gp11, asm: "SHLB"}, // arg0 << auxint, shift amount 0-31 + // Note: x86 is weird, the 16 and 8 byte shifts still use all 5 bits of shift amount! + + {name: "SHRQ", reg: gp21shift, asm: "SHRQ"}, // unsigned arg0 >> arg1, shift amount is mod 64 + {name: "SHRL", reg: gp21shift, asm: "SHRL"}, // unsigned arg0 >> arg1, shift amount is mod 32 + {name: "SHRW", reg: gp21shift, asm: "SHRW"}, // unsigned arg0 >> arg1, shift amount is mod 32 + {name: "SHRB", reg: gp21shift, asm: "SHRB"}, // unsigned arg0 >> arg1, shift amount is mod 32 + {name: "SHRQconst", reg: gp11, asm: "SHRQ"}, // unsigned arg0 >> auxint, shift amount 0-63 + {name: "SHRLconst", reg: gp11, asm: "SHRL"}, // unsigned arg0 >> auxint, shift amount 0-31 + {name: "SHRWconst", reg: gp11, asm: "SHRW"}, // unsigned arg0 >> auxint, shift amount 0-31 + {name: "SHRBconst", reg: gp11, asm: "SHRB"}, // unsigned arg0 >> auxint, shift amount 0-31 + + {name: "SARQ", reg: gp21shift, asm: "SARQ"}, // signed arg0 >> arg1, shift amount is mod 64 + {name: "SARL", reg: gp21shift, asm: "SARL"}, // signed arg0 >> arg1, shift amount is mod 32 + {name: "SARW", reg: gp21shift, asm: "SARW"}, // signed arg0 >> arg1, shift amount is mod 32 + {name: "SARB", reg: gp21shift, asm: "SARB"}, // signed arg0 >> arg1, shift amount is mod 32 + {name: "SARQconst", reg: gp11, asm: "SARQ"}, // signed arg0 >> auxint, shift amount 0-63 + {name: "SARLconst", reg: gp11, asm: "SARL"}, // signed arg0 >> auxint, shift amount 0-31 + {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 + {name: "NEGW", reg: gp11, asm: "NEGW"}, // -arg0 + {name: "NEGB", reg: gp11, asm: "NEGB"}, // -arg0 + + {name: "NOTQ", reg: gp11, asm: "NOTQ"}, // ^arg0 + {name: "NOTL", reg: gp11, asm: "NOTL"}, // ^arg0 + {name: "NOTW", reg: gp11, asm: "NOTW"}, // ^arg0 + {name: "NOTB", reg: gp11, asm: "NOTB"}, // ^arg0 + + {name: "SQRTSD", reg: fp11, asm: "SQRTSD"}, // sqrt(arg0) + + {name: "SBBQcarrymask", reg: flagsgp, asm: "SBBQ"}, // (int64)(-1) if carry is set, 0 if carry is clear. + {name: "SBBLcarrymask", reg: flagsgp, asm: "SBBL"}, // (int32)(-1) if carry is set, 0 if carry is clear. + // Note: SBBW and SBBB are subsumed by SBBL + + {name: "SETEQ", reg: readflags, asm: "SETEQ"}, // extract == condition from arg0 + {name: "SETNE", reg: readflags, asm: "SETNE"}, // extract != condition from arg0 + {name: "SETL", reg: readflags, asm: "SETLT"}, // extract signed < condition from arg0 + {name: "SETLE", reg: readflags, asm: "SETLE"}, // extract signed <= condition from arg0 + {name: "SETG", reg: readflags, asm: "SETGT"}, // extract signed > condition from arg0 + {name: "SETGE", reg: readflags, asm: "SETGE"}, // extract signed >= condition from arg0 + {name: "SETB", reg: readflags, asm: "SETCS"}, // extract unsigned < condition from arg0 + {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 + {name: "MOVWQSX", reg: gp11nf, asm: "MOVWQSX"}, // sign extend arg0 from int16 to int64 + {name: "MOVWQZX", reg: gp11nf, asm: "MOVWQZX"}, // zero extend arg0 from int16 to int64 + {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 + + // 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", 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 + {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. + + {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 + {name: "LEAQ4", reg: gp21sb}, // arg0 + 4*arg1 + auxint + {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 + + // 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")}, ++ inputs: []regMask{buildReg("DI"), buildReg("X0")}, + clobbers: buildReg("DI FLAGS"), + }, + }, ++ {name: "MOVOconst", reg: regInfo{nil, 0, []regMask{fp}}, typ: "Float64"}, + + // 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 + {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 + + // (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. + // Rewrites will convert this to (SETG (CMPQ b a)). + // InvertFlags is a pseudo-op which can't appear in assembly output. + {name: "InvertFlags"}, // reverse direction of arg0 + + // 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{ + {name: "EQ"}, + {name: "NE"}, + {name: "LT"}, + {name: "LE"}, + {name: "GT"}, + {name: "GE"}, + {name: "ULT"}, + {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 --cc src/cmd/compile/internal/ssa/opGen.go index c52ef2d352,0000000000..d86dce354b mode 100644,000000..100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@@ -1,4191 -1,0 +1,4200 @@@ +// autogenerated: do not edit! +// generated from gen/*Ops.go +package ssa + +import "cmd/internal/obj/x86" + +const ( + BlockInvalid BlockKind = iota + + BlockAMD64EQ + BlockAMD64NE + BlockAMD64LT + BlockAMD64LE + BlockAMD64GT + BlockAMD64GE + BlockAMD64ULT + BlockAMD64ULE + BlockAMD64UGT + BlockAMD64UGE + BlockAMD64EQF + BlockAMD64NEF + BlockAMD64ORD + BlockAMD64NAN + + BlockPlain + BlockIf + BlockCall + BlockRet + BlockRetJmp + BlockExit + BlockFirst + BlockDead +) + +var blockString = [...]string{ + BlockInvalid: "BlockInvalid", + + BlockAMD64EQ: "EQ", + BlockAMD64NE: "NE", + BlockAMD64LT: "LT", + BlockAMD64LE: "LE", + BlockAMD64GT: "GT", + BlockAMD64GE: "GE", + BlockAMD64ULT: "ULT", + BlockAMD64ULE: "ULE", + BlockAMD64UGT: "UGT", + BlockAMD64UGE: "UGE", + BlockAMD64EQF: "EQF", + BlockAMD64NEF: "NEF", + BlockAMD64ORD: "ORD", + BlockAMD64NAN: "NAN", + + BlockPlain: "Plain", + BlockIf: "If", + BlockCall: "Call", + BlockRet: "Ret", + BlockRetJmp: "RetJmp", + BlockExit: "Exit", + BlockFirst: "First", + BlockDead: "Dead", +} + +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 + OpAMD64ADDB + OpAMD64ADDQconst + OpAMD64ADDLconst + OpAMD64ADDWconst + OpAMD64ADDBconst + OpAMD64SUBQ + OpAMD64SUBL + OpAMD64SUBW + OpAMD64SUBB + OpAMD64SUBQconst + OpAMD64SUBLconst + OpAMD64SUBWconst + OpAMD64SUBBconst + OpAMD64MULQ + OpAMD64MULL + OpAMD64MULW + OpAMD64MULB + OpAMD64MULQconst + OpAMD64MULLconst + OpAMD64MULWconst + OpAMD64MULBconst + OpAMD64HMULL + OpAMD64HMULW + OpAMD64HMULB + OpAMD64HMULLU + OpAMD64HMULWU + OpAMD64HMULBU + OpAMD64DIVQ + OpAMD64DIVL + OpAMD64DIVW + OpAMD64DIVQU + OpAMD64DIVLU + OpAMD64DIVWU + OpAMD64MODQ + OpAMD64MODL + OpAMD64MODW + OpAMD64MODQU + OpAMD64MODLU + OpAMD64MODWU + OpAMD64ANDQ + OpAMD64ANDL + OpAMD64ANDW + OpAMD64ANDB + OpAMD64ANDQconst + OpAMD64ANDLconst + OpAMD64ANDWconst + OpAMD64ANDBconst + OpAMD64ORQ + OpAMD64ORL + OpAMD64ORW + OpAMD64ORB + OpAMD64ORQconst + OpAMD64ORLconst + OpAMD64ORWconst + OpAMD64ORBconst + OpAMD64XORQ + OpAMD64XORL + OpAMD64XORW + OpAMD64XORB + OpAMD64XORQconst + OpAMD64XORLconst + OpAMD64XORWconst + OpAMD64XORBconst + OpAMD64CMPQ + OpAMD64CMPL + OpAMD64CMPW + OpAMD64CMPB + OpAMD64CMPQconst + OpAMD64CMPLconst + OpAMD64CMPWconst + OpAMD64CMPBconst + OpAMD64UCOMISS + OpAMD64UCOMISD + OpAMD64TESTQ + OpAMD64TESTL + OpAMD64TESTW + OpAMD64TESTB + OpAMD64TESTQconst + OpAMD64TESTLconst + OpAMD64TESTWconst + OpAMD64TESTBconst + OpAMD64SHLQ + OpAMD64SHLL + OpAMD64SHLW + OpAMD64SHLB + OpAMD64SHLQconst + OpAMD64SHLLconst + OpAMD64SHLWconst + OpAMD64SHLBconst + OpAMD64SHRQ + OpAMD64SHRL + OpAMD64SHRW + OpAMD64SHRB + OpAMD64SHRQconst + OpAMD64SHRLconst + OpAMD64SHRWconst + OpAMD64SHRBconst + OpAMD64SARQ + OpAMD64SARL + OpAMD64SARW + OpAMD64SARB + OpAMD64SARQconst + OpAMD64SARLconst + OpAMD64SARWconst + OpAMD64SARBconst + OpAMD64ROLQconst + OpAMD64ROLLconst + OpAMD64ROLWconst + OpAMD64ROLBconst + OpAMD64NEGQ + OpAMD64NEGL + OpAMD64NEGW + OpAMD64NEGB + OpAMD64NOTQ + OpAMD64NOTL + OpAMD64NOTW + OpAMD64NOTB + OpAMD64SQRTSD + OpAMD64SBBQcarrymask + OpAMD64SBBLcarrymask + OpAMD64SETEQ + OpAMD64SETNE + OpAMD64SETL + OpAMD64SETLE + OpAMD64SETG + OpAMD64SETGE + OpAMD64SETB + OpAMD64SETBE + OpAMD64SETA + OpAMD64SETAE + OpAMD64SETEQF + OpAMD64SETNEF + OpAMD64SETORD + OpAMD64SETNAN + OpAMD64SETGF + OpAMD64SETGEF + OpAMD64MOVBQSX + OpAMD64MOVBQZX + OpAMD64MOVWQSX + OpAMD64MOVWQZX + OpAMD64MOVLQSX + OpAMD64MOVLQZX + OpAMD64MOVBconst + OpAMD64MOVWconst + OpAMD64MOVLconst + OpAMD64MOVQconst + OpAMD64CVTTSD2SL + OpAMD64CVTTSD2SQ + OpAMD64CVTTSS2SL + OpAMD64CVTTSS2SQ + OpAMD64CVTSL2SS + OpAMD64CVTSL2SD + OpAMD64CVTSQ2SS + OpAMD64CVTSQ2SD + OpAMD64CVTSD2SS + OpAMD64CVTSS2SD + OpAMD64PXOR + OpAMD64LEAQ + OpAMD64LEAQ1 + OpAMD64LEAQ2 + OpAMD64LEAQ4 + OpAMD64LEAQ8 + OpAMD64MOVBload + OpAMD64MOVBQSXload + OpAMD64MOVBQZXload + OpAMD64MOVWload + OpAMD64MOVLload + OpAMD64MOVQload + OpAMD64MOVQloadidx8 + OpAMD64MOVBstore + OpAMD64MOVWstore + OpAMD64MOVLstore + OpAMD64MOVQstore + OpAMD64MOVQstoreidx8 + OpAMD64DUFFZERO ++ OpAMD64MOVOconst + OpAMD64REPSTOSQ + OpAMD64CALLstatic + OpAMD64CALLclosure + OpAMD64CALLdefer + OpAMD64CALLgo + OpAMD64CALLinter + OpAMD64REPMOVSB + OpAMD64InvertFlags + OpAMD64LoweredPanicNilCheck + OpAMD64LoweredGetG + OpAMD64LoweredGetClosurePtr + + OpAdd8 + OpAdd16 + OpAdd32 + OpAdd64 + OpAddPtr + OpAdd32F + OpAdd64F + OpSub8 + OpSub16 + OpSub32 + OpSub64 + OpSubPtr + OpSub32F + OpSub64F + OpMul8 + OpMul16 + OpMul32 + OpMul64 + OpMulPtr + OpMul32F + OpMul64F + OpDiv32F + OpDiv64F + OpHmul8 + OpHmul8u + OpHmul16 + OpHmul16u + OpHmul32 + OpHmul32u + OpDiv8 + OpDiv8u + OpDiv16 + OpDiv16u + OpDiv32 + OpDiv32u + OpDiv64 + OpDiv64u + OpMod8 + OpMod8u + OpMod16 + OpMod16u + OpMod32 + OpMod32u + OpMod64 + OpMod64u + OpAnd8 + OpAnd16 + OpAnd32 + OpAnd64 + OpOr8 + OpOr16 + OpOr32 + OpOr64 + OpXor8 + OpXor16 + OpXor32 + OpXor64 + OpLsh8x8 + OpLsh8x16 + OpLsh8x32 + OpLsh8x64 + OpLsh16x8 + OpLsh16x16 + OpLsh16x32 + OpLsh16x64 + OpLsh32x8 + OpLsh32x16 + OpLsh32x32 + OpLsh32x64 + OpLsh64x8 + OpLsh64x16 + OpLsh64x32 + OpLsh64x64 + OpRsh8x8 + OpRsh8x16 + OpRsh8x32 + OpRsh8x64 + OpRsh16x8 + OpRsh16x16 + OpRsh16x32 + OpRsh16x64 + OpRsh32x8 + OpRsh32x16 + OpRsh32x32 + OpRsh32x64 + OpRsh64x8 + OpRsh64x16 + OpRsh64x32 + OpRsh64x64 + OpRsh8Ux8 + OpRsh8Ux16 + OpRsh8Ux32 + OpRsh8Ux64 + OpRsh16Ux8 + OpRsh16Ux16 + OpRsh16Ux32 + OpRsh16Ux64 + OpRsh32Ux8 + OpRsh32Ux16 + OpRsh32Ux32 + OpRsh32Ux64 + OpRsh64Ux8 + OpRsh64Ux16 + OpRsh64Ux32 + OpRsh64Ux64 + OpLrot8 + OpLrot16 + OpLrot32 + OpLrot64 + OpEq8 + OpEq16 + OpEq32 + OpEq64 + OpEqPtr + OpEqInter + OpEqSlice + OpEq32F + OpEq64F + OpNeq8 + OpNeq16 + OpNeq32 + OpNeq64 + OpNeqPtr + OpNeqInter + OpNeqSlice + OpNeq32F + OpNeq64F + OpLess8 + OpLess8U + OpLess16 + OpLess16U + OpLess32 + OpLess32U + OpLess64 + OpLess64U + OpLess32F + OpLess64F + OpLeq8 + OpLeq8U + OpLeq16 + OpLeq16U + OpLeq32 + OpLeq32U + OpLeq64 + OpLeq64U + OpLeq32F + OpLeq64F + OpGreater8 + OpGreater8U + OpGreater16 + OpGreater16U + OpGreater32 + OpGreater32U + OpGreater64 + OpGreater64U + OpGreater32F + OpGreater64F + OpGeq8 + OpGeq8U + OpGeq16 + OpGeq16U + OpGeq32 + OpGeq32U + OpGeq64 + OpGeq64U + OpGeq32F + OpGeq64F + OpNot + OpNeg8 + OpNeg16 + OpNeg32 + OpNeg64 + OpNeg32F + OpNeg64F + OpCom8 + OpCom16 + OpCom32 + OpCom64 + OpSqrt + OpPhi + OpCopy + OpConstBool + OpConstString + OpConstNil + OpConst8 + OpConst16 + OpConst32 + OpConst64 + OpConst32F + OpConst64F + OpConstPtr + OpConstInterface + OpConstSlice + OpArg + OpAddr + OpSP + OpSB + OpFunc + OpLoad + OpStore + OpMove + OpZero + OpClosureCall + OpStaticCall + OpDeferCall + OpGoCall + OpInterCall + OpSignExt8to16 + OpSignExt8to32 + OpSignExt8to64 + OpSignExt16to32 + OpSignExt16to64 + OpSignExt32to64 + OpZeroExt8to16 + OpZeroExt8to32 + OpZeroExt8to64 + OpZeroExt16to32 + OpZeroExt16to64 + OpZeroExt32to64 + OpTrunc16to8 + OpTrunc32to8 + OpTrunc32to16 + OpTrunc64to8 + OpTrunc64to16 + OpTrunc64to32 + OpCvt32to32F + OpCvt32to64F + OpCvt64to32F + OpCvt64to64F + OpCvt32Fto32 + OpCvt32Fto64 + OpCvt64Fto32 + OpCvt64Fto64 + OpCvt32Fto64F + OpCvt64Fto32F + OpIsNonNil + OpIsInBounds + OpIsSliceInBounds + OpPanicNilCheck + OpGetG + OpGetClosurePtr + OpArrayIndex + OpPtrIndex + OpOffPtr + OpStructSelect + OpSliceMake + OpSlicePtr + OpSliceLen + OpSliceCap + OpComplexMake + OpComplexReal + OpComplexImag + OpStringMake + OpStringPtr + OpStringLen + OpIMake + OpITab + OpIData + OpStoreReg + OpLoadReg + OpFwdRef + OpVarDef + OpVarKill +) + +var opcodeTable = [...]opInfo{ + {name: "OpInvalid"}, + + { + name: "ADDSS", + asm: x86.AADDSS, + 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: "ADDSD", + asm: x86.AADDSD, + 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: "SUBSS", + asm: x86.ASUBSS, + reg: regInfo{ + 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{ + 2147418112, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 + }, + }, + }, + { + name: "SUBSD", + asm: x86.ASUBSD, + reg: regInfo{ + 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{ + 2147418112, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 + }, + }, + }, + { + name: "MULSS", + asm: x86.AMULSS, + 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: "MULSD", + asm: x86.AMULSD, + 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: "DIVSS", + asm: x86.ADIVSS, + reg: regInfo{ + 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{ + 2147418112, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 + }, + }, + }, + { + name: "DIVSD", + asm: x86.ADIVSD, + reg: regInfo{ + 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{ + 2147418112, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 + }, + }, + }, + { + name: "MOVSSload", + asm: x86.AMOVSS, + 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: "MOVSDload", + asm: x86.AMOVSD, + 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: "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: []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 + }, + }, + }, + { + name: "MOVSDloadidx8", + asm: x86.AMOVSD, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "MOVSSstore", + asm: x86.AMOVSS, + 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: "MOVSDstore", + asm: x86.AMOVSD, + 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: "MOVSSstoreidx4", + asm: x86.AMOVSS, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "MOVSDstoreidx8", + asm: x86.AMOVSD, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "ADDQ", + asm: x86.AADDQ, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "ADDL", + asm: x86.AADDL, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "ADDW", + asm: x86.AADDW, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "ADDB", + asm: x86.AADDB, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "ADDQconst", + asm: x86.AADDQ, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "ADDLconst", + asm: x86.AADDL, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "ADDWconst", + asm: x86.AADDW, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "ADDBconst", + asm: x86.AADDB, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "SUBQ", + asm: x86.ASUBQ, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "SUBL", + asm: x86.ASUBL, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "SUBW", + asm: x86.ASUBW, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "SUBB", + asm: x86.ASUBB, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "SUBQconst", + asm: x86.ASUBQ, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "SUBLconst", + asm: x86.ASUBL, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "SUBWconst", + asm: x86.ASUBW, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "SUBBconst", + asm: x86.ASUBB, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "MULQ", + asm: x86.AIMULQ, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "MULL", + asm: x86.AIMULL, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "MULW", + asm: x86.AIMULW, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "MULB", + asm: x86.AIMULW, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "MULQconst", + asm: x86.AIMULQ, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "MULLconst", + asm: x86.AIMULL, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "MULWconst", + asm: x86.AIMULW, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "MULBconst", + asm: x86.AIMULW, + reg: regInfo{ + 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 + }, + }, + }, + { + 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, + 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: "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, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "ANDL", + asm: x86.AANDL, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "ANDW", + asm: x86.AANDW, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "ANDB", + asm: x86.AANDB, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "ANDQconst", + asm: x86.AANDQ, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "ANDLconst", + asm: x86.AANDL, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "ANDWconst", + asm: x86.AANDW, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "ANDBconst", + asm: x86.AANDB, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "ORQ", + asm: x86.AORQ, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "ORL", + asm: x86.AORL, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "ORW", + asm: x86.AORW, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "ORB", + asm: x86.AORB, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "ORQconst", + asm: x86.AORQ, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "ORLconst", + asm: x86.AORL, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "ORWconst", + asm: x86.AORW, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "ORBconst", + asm: x86.AORB, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "XORQ", + asm: x86.AXORQ, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "XORL", + asm: x86.AXORL, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "XORW", + asm: x86.AXORW, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "XORB", + asm: x86.AXORB, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "XORQconst", + asm: x86.AXORQ, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "XORLconst", + asm: x86.AXORL, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "XORWconst", + asm: x86.AXORW, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "XORBconst", + asm: x86.AXORB, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "CMPQ", + asm: x86.ACMPQ, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "CMPL", + asm: x86.ACMPL, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "CMPW", + asm: x86.ACMPW, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "CMPB", + asm: x86.ACMPB, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "CMPQconst", + asm: x86.ACMPQ, + reg: regInfo{ + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + outputs: []regMask{ + 8589934592, // .FLAGS + }, + }, + }, + { + name: "CMPLconst", + asm: x86.ACMPL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + outputs: []regMask{ + 8589934592, // .FLAGS + }, + }, + }, + { + name: "CMPWconst", + asm: x86.ACMPW, + reg: regInfo{ + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + outputs: []regMask{ + 8589934592, // .FLAGS + }, + }, + }, + { + name: "CMPBconst", + asm: x86.ACMPB, + reg: regInfo{ + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + outputs: []regMask{ + 8589934592, // .FLAGS + }, + }, + }, + { + 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, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "TESTL", + asm: x86.ATESTL, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "TESTW", + asm: x86.ATESTW, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "TESTB", + asm: x86.ATESTB, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "TESTQconst", + asm: x86.ATESTQ, + reg: regInfo{ + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + outputs: []regMask{ + 8589934592, // .FLAGS + }, + }, + }, + { + name: "TESTLconst", + asm: x86.ATESTL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + outputs: []regMask{ + 8589934592, // .FLAGS + }, + }, + }, + { + name: "TESTWconst", + asm: x86.ATESTW, + reg: regInfo{ + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + outputs: []regMask{ + 8589934592, // .FLAGS + }, + }, + }, + { + name: "TESTBconst", + asm: x86.ATESTB, + reg: regInfo{ + inputs: []inputInfo{ + {0, 65535}, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + outputs: []regMask{ + 8589934592, // .FLAGS + }, + }, + }, + { + name: "SHLQ", + asm: x86.ASHLQ, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "SHLL", + asm: x86.ASHLL, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "SHLW", + asm: x86.ASHLW, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "SHLB", + asm: x86.ASHLB, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "SHLQconst", + asm: x86.ASHLQ, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "SHLLconst", + asm: x86.ASHLL, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "SHLWconst", + asm: x86.ASHLW, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "SHLBconst", + asm: x86.ASHLB, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "SHRQ", + asm: x86.ASHRQ, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "SHRL", + asm: x86.ASHRL, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "SHRW", + asm: x86.ASHRW, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "SHRB", + asm: x86.ASHRB, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "SHRQconst", + asm: x86.ASHRQ, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "SHRLconst", + asm: x86.ASHRL, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "SHRWconst", + asm: x86.ASHRW, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "SHRBconst", + asm: x86.ASHRB, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "SARQ", + asm: x86.ASARQ, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "SARL", + asm: x86.ASARL, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "SARW", + asm: x86.ASARW, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "SARB", + asm: x86.ASARB, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "SARQconst", + asm: x86.ASARQ, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "SARLconst", + asm: x86.ASARL, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "SARWconst", + asm: x86.ASARW, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "SARBconst", + asm: x86.ASARB, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "ROLQconst", + asm: x86.AROLQ, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "ROLLconst", + asm: x86.AROLL, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "ROLWconst", + asm: x86.AROLW, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "ROLBconst", + asm: x86.AROLB, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "NEGQ", + asm: x86.ANEGQ, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "NEGL", + asm: x86.ANEGL, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "NEGW", + asm: x86.ANEGW, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "NEGB", + asm: x86.ANEGB, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "NOTQ", + asm: x86.ANOTQ, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "NOTL", + asm: x86.ANOTL, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "NOTW", + asm: x86.ANOTW, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "NOTB", + asm: x86.ANOTB, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "SQRTSD", + asm: x86.ASQRTSD, + 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: "SBBQcarrymask", + asm: x86.ASBBQ, + reg: regInfo{ + inputs: []inputInfo{ + {0, 8589934592}, // .FLAGS + }, + outputs: []regMask{ + 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + }, + }, + { + name: "SBBLcarrymask", + asm: x86.ASBBL, + reg: regInfo{ + inputs: []inputInfo{ + {0, 8589934592}, // .FLAGS + }, + outputs: []regMask{ + 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + }, + }, + { + name: "SETEQ", + asm: x86.ASETEQ, + reg: regInfo{ + inputs: []inputInfo{ + {0, 8589934592}, // .FLAGS + }, + outputs: []regMask{ + 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + }, + }, + { + name: "SETNE", + asm: x86.ASETNE, + reg: regInfo{ + inputs: []inputInfo{ + {0, 8589934592}, // .FLAGS + }, + outputs: []regMask{ + 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + }, + }, + { + name: "SETL", + asm: x86.ASETLT, + reg: regInfo{ + inputs: []inputInfo{ + {0, 8589934592}, // .FLAGS + }, + outputs: []regMask{ + 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + }, + }, + { + name: "SETLE", + asm: x86.ASETLE, + reg: regInfo{ + inputs: []inputInfo{ + {0, 8589934592}, // .FLAGS + }, + outputs: []regMask{ + 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + }, + }, + { + name: "SETG", + asm: x86.ASETGT, + reg: regInfo{ + inputs: []inputInfo{ + {0, 8589934592}, // .FLAGS + }, + outputs: []regMask{ + 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + }, + }, + { + name: "SETGE", + asm: x86.ASETGE, + reg: regInfo{ + inputs: []inputInfo{ + {0, 8589934592}, // .FLAGS + }, + outputs: []regMask{ + 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + }, + }, + { + name: "SETB", + asm: x86.ASETCS, + reg: regInfo{ + inputs: []inputInfo{ + {0, 8589934592}, // .FLAGS + }, + outputs: []regMask{ + 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + }, + }, + { + name: "SETBE", + asm: x86.ASETLS, + reg: regInfo{ + inputs: []inputInfo{ + {0, 8589934592}, // .FLAGS + }, + outputs: []regMask{ + 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + }, + }, + { + name: "SETA", + asm: x86.ASETHI, + reg: regInfo{ + inputs: []inputInfo{ + {0, 8589934592}, // .FLAGS + }, + outputs: []regMask{ + 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + }, + }, + { + name: "SETAE", + asm: x86.ASETCC, + reg: regInfo{ + inputs: []inputInfo{ + {0, 8589934592}, // .FLAGS + }, + outputs: []regMask{ + 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + }, + }, + { + 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 + }, + 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 + }, + 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 + }, + 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 + }, + outputs: []regMask{ + 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + }, + }, + { + name: "MOVBQSX", + asm: x86.AMOVBQSX, + 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: "MOVBQZX", + asm: x86.AMOVBQZX, + 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: "MOVWQSX", + asm: x86.AMOVWQSX, + 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: "MOVWQZX", + asm: x86.AMOVWQZX, + 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: "MOVLQSX", + asm: x86.AMOVLQSX, + 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: "MOVLQZX", + asm: x86.AMOVLQZX, + 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: "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 + }, + }, + }, + { + 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 + }, + }, + }, + { + 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 + }, + }, + }, + { + 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 + }, + }, + }, + { + 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 + }, + outputs: []regMask{ + 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + }, + }, + { + 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 + }, + outputs: []regMask{ + 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + }, + }, + { + 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 + }, + outputs: []regMask{ + 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + }, + }, + { + 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 + }, + 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: "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{ + 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 + }, + }, + }, + { + name: "LEAQ1", + reg: regInfo{ + 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 + }, + }, + }, + { + name: "LEAQ2", + reg: regInfo{ + 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 + }, + }, + }, + { + name: "LEAQ4", + reg: regInfo{ + 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 + }, + }, + }, + { + name: "LEAQ8", + reg: regInfo{ + 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 + }, + }, + }, + { + name: "MOVBload", + asm: x86.AMOVB, + 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{ + 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + }, + }, + { + name: "MOVBQSXload", + asm: x86.AMOVBQSX, + 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{ + 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + }, + }, + { + name: "MOVBQZXload", + asm: x86.AMOVBQZX, + 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{ + 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + }, + }, + { + name: "MOVWload", + asm: x86.AMOVW, + 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{ + 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + }, + }, + { + name: "MOVLload", + asm: x86.AMOVL, + 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{ + 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + }, + }, + { + name: "MOVQload", + asm: x86.AMOVQ, + 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{ + 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + }, + }, + { + name: "MOVQloadidx8", + asm: x86.AMOVQ, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "MOVBstore", + asm: x86.AMOVB, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "MOVWstore", + asm: x86.AMOVW, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "MOVLstore", + asm: x86.AMOVL, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "MOVQstore", + asm: x86.AMOVQ, + reg: regInfo{ + 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 + }, + }, + }, + { + name: "MOVQstoreidx8", + asm: x86.AMOVQ, + reg: regInfo{ + 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: "DUFFZERO", + reg: regInfo{ + inputs: []inputInfo{ - {0, 128}, // .DI - {1, 1}, // .AX ++ {0, 128}, // .DI ++ {1, 65536}, // .X0 + }, + clobbers: 8589934720, // .DI .FLAGS + }, + }, ++ { ++ name: "MOVOconst", ++ reg: regInfo{ ++ outputs: []regMask{ ++ 4294901760, // .X0 .X1 .X2 .X3 .X4 .X5 .X6 .X7 .X8 .X9 .X10 .X11 .X12 .X13 .X14 .X15 ++ }, ++ }, ++ }, + { + name: "REPSTOSQ", + reg: regInfo{ + inputs: []inputInfo{ + {0, 128}, // .DI + {1, 2}, // .CX + {2, 1}, // .AX + }, + clobbers: 8589934722, // .CX .DI .FLAGS + }, + }, + { + name: "CALLstatic", + 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: []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: "CALLdefer", + 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: "CALLgo", + 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: "CALLinter", + reg: regInfo{ + inputs: []inputInfo{ + {0, 65519}, // .AX .CX .DX .BX .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: []inputInfo{ + {0, 128}, // .DI + {1, 64}, // .SI + {2, 2}, // .CX + }, + clobbers: 194, // .CX .SI .DI + }, + }, + { + name: "InvertFlags", + reg: regInfo{}, + }, + { + name: "LoweredPanicNilCheck", + reg: regInfo{ + inputs: []inputInfo{ + {0, 65519}, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + }, + }, + { + name: "LoweredGetG", + reg: regInfo{ + outputs: []regMask{ + 65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 + }, + }, + }, + { + name: "LoweredGetClosurePtr", + reg: regInfo{ + outputs: []regMask{ + 4, // .DX + }, + }, + }, + + { + name: "Add8", + generic: true, + }, + { + name: "Add16", + generic: true, + }, + { + name: "Add32", + generic: true, + }, + { + name: "Add64", + generic: true, + }, + { + name: "AddPtr", + generic: true, + }, + { + name: "Add32F", + generic: true, + }, + { + name: "Add64F", + generic: true, + }, + { + name: "Sub8", + generic: true, + }, + { + name: "Sub16", + generic: true, + }, + { + name: "Sub32", + generic: true, + }, + { + name: "Sub64", + generic: true, + }, + { + name: "SubPtr", + generic: true, + }, + { + name: "Sub32F", + generic: true, + }, + { + name: "Sub64F", + generic: true, + }, + { + name: "Mul8", + generic: true, + }, + { + name: "Mul16", + generic: true, + }, + { + name: "Mul32", + generic: true, + }, + { + name: "Mul64", + generic: true, + }, + { + name: "MulPtr", + generic: true, + }, + { + name: "Mul32F", + generic: true, + }, + { + name: "Mul64F", + generic: true, + }, + { + name: "Div32F", + generic: true, + }, + { + 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, + }, + { + 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: "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, + }, + { + name: "And16", + generic: true, + }, + { + name: "And32", + generic: true, + }, + { + name: "And64", + generic: true, + }, + { + name: "Or8", + generic: true, + }, + { + name: "Or16", + generic: true, + }, + { + name: "Or32", + generic: true, + }, + { + name: "Or64", + generic: true, + }, + { + name: "Xor8", + generic: true, + }, + { + name: "Xor16", + generic: true, + }, + { + name: "Xor32", + generic: true, + }, + { + name: "Xor64", + generic: true, + }, + { + name: "Lsh8x8", + generic: true, + }, + { + name: "Lsh8x16", + generic: true, + }, + { + name: "Lsh8x32", + generic: true, + }, + { + name: "Lsh8x64", + generic: true, + }, + { + name: "Lsh16x8", + generic: true, + }, + { + name: "Lsh16x16", + generic: true, + }, + { + name: "Lsh16x32", + generic: true, + }, + { + name: "Lsh16x64", + generic: true, + }, + { + name: "Lsh32x8", + generic: true, + }, + { + name: "Lsh32x16", + generic: true, + }, + { + name: "Lsh32x32", + generic: true, + }, + { + name: "Lsh32x64", + generic: true, + }, + { + name: "Lsh64x8", + generic: true, + }, + { + name: "Lsh64x16", + generic: true, + }, + { + name: "Lsh64x32", + generic: true, + }, + { + name: "Lsh64x64", + generic: true, + }, + { + name: "Rsh8x8", + generic: true, + }, + { + name: "Rsh8x16", + generic: true, + }, + { + name: "Rsh8x32", + generic: true, + }, + { + name: "Rsh8x64", + generic: true, + }, + { + name: "Rsh16x8", + generic: true, + }, + { + name: "Rsh16x16", + generic: true, + }, + { + name: "Rsh16x32", + generic: true, + }, + { + name: "Rsh16x64", + generic: true, + }, + { + name: "Rsh32x8", + generic: true, + }, + { + name: "Rsh32x16", + generic: true, + }, + { + name: "Rsh32x32", + generic: true, + }, + { + name: "Rsh32x64", + generic: true, + }, + { + name: "Rsh64x8", + generic: true, + }, + { + name: "Rsh64x16", + generic: true, + }, + { + name: "Rsh64x32", + generic: true, + }, + { + name: "Rsh64x64", + generic: true, + }, + { + name: "Rsh8Ux8", + generic: true, + }, + { + name: "Rsh8Ux16", + generic: true, + }, + { + name: "Rsh8Ux32", + generic: true, + }, + { + name: "Rsh8Ux64", + generic: true, + }, + { + name: "Rsh16Ux8", + generic: true, + }, + { + name: "Rsh16Ux16", + generic: true, + }, + { + name: "Rsh16Ux32", + generic: true, + }, + { + name: "Rsh16Ux64", + generic: true, + }, + { + name: "Rsh32Ux8", + generic: true, + }, + { + name: "Rsh32Ux16", + generic: true, + }, + { + name: "Rsh32Ux32", + generic: true, + }, + { + name: "Rsh32Ux64", + generic: true, + }, + { + name: "Rsh64Ux8", + generic: true, + }, + { + name: "Rsh64Ux16", + generic: true, + }, + { + name: "Rsh64Ux32", + generic: true, + }, + { + name: "Rsh64Ux64", + generic: true, + }, + { + name: "Lrot8", + generic: true, + }, + { + name: "Lrot16", + generic: true, + }, + { + name: "Lrot32", + generic: true, + }, + { + name: "Lrot64", + generic: true, + }, + { + name: "Eq8", + generic: true, + }, + { + name: "Eq16", + generic: true, + }, + { + name: "Eq32", + generic: true, + }, + { + name: "Eq64", + generic: true, + }, + { + name: "EqPtr", + generic: true, + }, + { + name: "EqInter", + generic: true, + }, + { + name: "EqSlice", + generic: true, + }, + { + name: "Eq32F", + generic: true, + }, + { + name: "Eq64F", + generic: true, + }, + { + name: "Neq8", + generic: true, + }, + { + name: "Neq16", + generic: true, + }, + { + name: "Neq32", + generic: true, + }, + { + name: "Neq64", + generic: true, + }, + { + name: "NeqPtr", + generic: true, + }, + { + name: "NeqInter", + generic: true, + }, + { + name: "NeqSlice", + generic: true, + }, + { + name: "Neq32F", + generic: true, + }, + { + name: "Neq64F", + generic: true, + }, + { + name: "Less8", + generic: true, + }, + { + name: "Less8U", + generic: true, + }, + { + name: "Less16", + generic: true, + }, + { + name: "Less16U", + generic: true, + }, + { + name: "Less32", + generic: true, + }, + { + name: "Less32U", + generic: true, + }, + { + name: "Less64", + generic: true, + }, + { + name: "Less64U", + generic: true, + }, + { + name: "Less32F", + generic: true, + }, + { + name: "Less64F", + generic: true, + }, + { + name: "Leq8", + generic: true, + }, + { + name: "Leq8U", + generic: true, + }, + { + name: "Leq16", + generic: true, + }, + { + name: "Leq16U", + generic: true, + }, + { + name: "Leq32", + generic: true, + }, + { + name: "Leq32U", + generic: true, + }, + { + name: "Leq64", + generic: true, + }, + { + name: "Leq64U", + generic: true, + }, + { + name: "Leq32F", + generic: true, + }, + { + name: "Leq64F", + generic: true, + }, + { + name: "Greater8", + generic: true, + }, + { + name: "Greater8U", + generic: true, + }, + { + name: "Greater16", + generic: true, + }, + { + name: "Greater16U", + generic: true, + }, + { + name: "Greater32", + generic: true, + }, + { + name: "Greater32U", + generic: true, + }, + { + name: "Greater64", + generic: true, + }, + { + name: "Greater64U", + generic: true, + }, + { + name: "Greater32F", + generic: true, + }, + { + name: "Greater64F", + generic: true, + }, + { + name: "Geq8", + generic: true, + }, + { + name: "Geq8U", + generic: true, + }, + { + name: "Geq16", + generic: true, + }, + { + name: "Geq16U", + generic: true, + }, + { + name: "Geq32", + generic: true, + }, + { + name: "Geq32U", + generic: true, + }, + { + name: "Geq64", + generic: true, + }, + { + name: "Geq64U", + generic: true, + }, + { + name: "Geq32F", + generic: true, + }, + { + name: "Geq64F", + generic: true, + }, + { + name: "Not", + generic: true, + }, + { + name: "Neg8", + generic: true, + }, + { + name: "Neg16", + generic: true, + }, + { + name: "Neg32", + generic: true, + }, + { + name: "Neg64", + generic: true, + }, + { + name: "Neg32F", + generic: true, + }, + { + name: "Neg64F", + generic: true, + }, + { + name: "Com8", + generic: true, + }, + { + name: "Com16", + generic: true, + }, + { + name: "Com32", + generic: true, + }, + { + name: "Com64", + generic: true, + }, + { + name: "Sqrt", + generic: true, + }, + { + name: "Phi", + generic: true, + }, + { + name: "Copy", + generic: true, + }, + { + name: "ConstBool", + generic: true, + }, + { + name: "ConstString", + generic: true, + }, + { + name: "ConstNil", + generic: true, + }, + { + name: "Const8", + generic: true, + }, + { + name: "Const16", + generic: true, + }, + { + name: "Const32", + generic: true, + }, + { + name: "Const64", + generic: true, + }, + { + name: "Const32F", + generic: true, + }, + { + name: "Const64F", + generic: true, + }, + { + name: "ConstPtr", + generic: true, + }, + { + name: "ConstInterface", + generic: true, + }, + { + name: "ConstSlice", + generic: true, + }, + { + name: "Arg", + generic: true, + }, + { + name: "Addr", + generic: true, + }, + { + name: "SP", + generic: true, + }, + { + name: "SB", + generic: true, + }, + { + name: "Func", + generic: true, + }, + { + name: "Load", + generic: true, + }, + { + name: "Store", + generic: true, + }, + { + name: "Move", + generic: true, + }, + { + name: "Zero", + generic: true, + }, + { + name: "ClosureCall", + generic: true, + }, + { + name: "StaticCall", + generic: true, + }, + { + name: "DeferCall", + generic: true, + }, + { + name: "GoCall", + generic: true, + }, + { + name: "InterCall", + generic: true, + }, + { + name: "SignExt8to16", + generic: true, + }, + { + name: "SignExt8to32", + generic: true, + }, + { + name: "SignExt8to64", + generic: true, + }, + { + name: "SignExt16to32", + generic: true, + }, + { + name: "SignExt16to64", + generic: true, + }, + { + name: "SignExt32to64", + generic: true, + }, + { + name: "ZeroExt8to16", + generic: true, + }, + { + name: "ZeroExt8to32", + generic: true, + }, + { + name: "ZeroExt8to64", + generic: true, + }, + { + name: "ZeroExt16to32", + generic: true, + }, + { + name: "ZeroExt16to64", + generic: true, + }, + { + name: "ZeroExt32to64", + generic: true, + }, + { + name: "Trunc16to8", + generic: true, + }, + { + name: "Trunc32to8", + generic: true, + }, + { + name: "Trunc32to16", + generic: true, + }, + { + name: "Trunc64to8", + generic: true, + }, + { + name: "Trunc64to16", + generic: true, + }, + { + 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, + }, + { + name: "IsInBounds", + generic: true, + }, + { + name: "IsSliceInBounds", + generic: true, + }, + { + name: "PanicNilCheck", + generic: true, + }, + { + name: "GetG", + generic: true, + }, + { + name: "GetClosurePtr", + generic: true, + }, + { + name: "ArrayIndex", + generic: true, + }, + { + name: "PtrIndex", + generic: true, + }, + { + name: "OffPtr", + generic: true, + }, + { + name: "StructSelect", + generic: true, + }, + { + name: "SliceMake", + generic: true, + }, + { + name: "SlicePtr", + generic: true, + }, + { + name: "SliceLen", + generic: true, + }, + { + name: "SliceCap", + generic: true, + }, + { + name: "ComplexMake", + generic: true, + }, + { + name: "ComplexReal", + generic: true, + }, + { + name: "ComplexImag", + generic: true, + }, + { + name: "StringMake", + generic: true, + }, + { + name: "StringPtr", + generic: true, + }, + { + name: "StringLen", + generic: true, + }, + { + name: "IMake", + generic: true, + }, + { + name: "ITab", + generic: true, + }, + { + name: "IData", + generic: true, + }, + { + name: "StoreReg", + generic: true, + }, + { + name: "LoadReg", + generic: true, + }, + { + name: "FwdRef", + generic: true, + }, + { + name: "VarDef", + generic: true, + }, + { + name: "VarKill", + generic: true, + }, +} + +func (o Op) Asm() int { return opcodeTable[o].asm } +func (o Op) String() string { return opcodeTable[o].name } diff --cc src/cmd/compile/internal/ssa/rewrite.go index 4e783062ec,0000000000..c1e446fce1 mode 100644,000000..100644 --- a/src/cmd/compile/internal/ssa/rewrite.go +++ b/src/cmd/compile/internal/ssa/rewrite.go @@@ -1,229 -1,0 +1,226 @@@ +// 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 + +import ( + "fmt" + "math" +) + +func applyRewrite(f *Func, rb func(*Block) bool, rv func(*Value, *Config) bool) { + // repeat rewrites until we find no more rewrites + var curb *Block + var curv *Value + defer func() { + if curb != nil { + curb.Fatalf("panic during rewrite of block %s\n", curb.LongString()) + } + if curv != nil { + curv.Fatalf("panic during rewrite of value %s\n", curv.LongString()) + // TODO(khr): print source location also + } + }() + config := f.Config + for { + change := false + for _, b := range f.Blocks { + if b.Kind == BlockDead { + continue + } + if b.Control != nil && b.Control.Op == OpCopy { + for b.Control.Op == OpCopy { + b.Control = b.Control.Args[0] + } + } + curb = b + if rb(b) { + change = true + } + curb = nil + for _, v := range b.Values { + // elide any copies generated during rewriting + for i, a := range v.Args { + if a.Op != OpCopy { + continue + } + // Rewriting can generate OpCopy loops. + // They are harmless (see removePredecessor), + // but take care to stop if we find a cycle. + slow := a // advances every other iteration + var advance bool + for a.Op == OpCopy { + a = a.Args[0] + if slow == a { + break + } + if advance { + slow = a + } + advance = !advance + } + v.Args[i] = a + } + + // apply rewrite function + curv = v + if rv(v, config) { + change = true + } + curv = nil + } + } + if !change { + return + } + } +} + +// 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() +} + +func is32BitInt(t Type) bool { + return t.Size() == 4 && t.IsInteger() +} + +func is16BitInt(t Type) bool { + return t.Size() == 2 && t.IsInteger() +} + +func is8BitInt(t Type) bool { + return t.Size() == 1 && t.IsInteger() +} + +func isPtr(t Type) bool { + return t.IsPtr() +} + +func isSigned(t Type) bool { + return t.IsSigned() +} + +func typeSize(t Type) int64 { + return t.Size() +} + +// addOff adds two int64 offsets. Fails if wraparound happens. +func addOff(x, y int64) int64 { + z := x + y + // x and y have same sign and z has a different sign => overflow + if x^y >= 0 && x^z < 0 { + panic(fmt.Sprintf("offset overflow %d %d", x, y)) + } + return z +} + +// mergeSym merges two symbolic offsets. There is no real merging of +// offsets, we just pick the non-nil one. +func mergeSym(x, y interface{}) interface{} { + if x == nil { + return y + } + if y == nil { + return x + } + panic(fmt.Sprintf("mergeSym with two non-nil syms %s %s", x, y)) + return nil +} +func canMergeSym(x, y interface{}) bool { + return x == nil || y == nil +} + +func inBounds8(idx, len int64) bool { return int8(idx) >= 0 && int8(idx) < int8(len) } +func inBounds16(idx, len int64) bool { return int16(idx) >= 0 && int16(idx) < int16(len) } +func inBounds32(idx, len int64) bool { return int32(idx) >= 0 && int32(idx) < int32(len) } +func inBounds64(idx, len int64) bool { return idx >= 0 && idx < len } + +// log2 returns logarithm in base of n. +// expects n to be a power of 2. +func log2(n int64) (l int64) { + for n > 1 { + l++ + n >>= 1 + } + return l +} + +// 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)) +} + +// b2i translates a boolean value to 0 or 1 for assigning to auxInt. +func b2i(b bool) int64 { + if b { + return 1 + } + return 0 +} + +// f2i is used in the rules for storing a float in AuxInt. +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. ++// DUFFZERO consists of repeated blocks of 4 MOVUPSs + ADD, +// See runtime/mkduff.go. +const ( - dzBlocks = 31 // number of MOV/ADD blocks ++ dzBlocks = 16 // 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 ++ dzClearStep = 16 // 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 ++ dzClearLen = dzClearStep * dzBlockLen // bytes cleared by one block ++ dzSize = dzBlocks * dzBlockSize +) + +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 { ++ if size < 32 || size > 1024 || size%dzClearStep != 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 ++ steps := size / dzClearStep ++ blocks := steps / dzBlockLen ++ steps %= dzBlockLen ++ off := dzBlockSize * (dzBlocks - blocks) + var adj int64 - if singles > 0 { - off -= dzAddSize + dzMovSize*singles - adj -= dzDIStep * (dzBlockLen - singles) ++ if steps != 0 { ++ off -= dzAddSize ++ off -= dzMovSize * steps ++ adj -= dzClearStep * (dzBlockLen - steps) + } + return off, adj +} diff --cc src/cmd/compile/internal/ssa/rewriteAMD64.go index 4ac4744b64,0000000000..8160156651 mode 100644,000000..100644 --- a/src/cmd/compile/internal/ssa/rewriteAMD64.go +++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go @@@ -1,11631 -1,0 +1,11665 @@@ +// autogenerated from gen/AMD64.rules: do not edit! +// 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 { + case OpAMD64ADDB: + // match: (ADDB x (MOVBconst [c])) + // cond: + // result: (ADDBconst [c] x) + { + x := v.Args[0] + if v.Args[1].Op != OpAMD64MOVBconst { + goto endab690db69bfd8192eea57a2f9f76bf84 + } + c := v.Args[1].AuxInt + v.Op = OpAMD64ADDBconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c + v.AddArg(x) + return true + } + goto endab690db69bfd8192eea57a2f9f76bf84 + endab690db69bfd8192eea57a2f9f76bf84: + ; + // match: (ADDB (MOVBconst [c]) x) + // cond: + // result: (ADDBconst [c] x) + { + if v.Args[0].Op != OpAMD64MOVBconst { + goto end28aa1a4abe7e1abcdd64135e9967d39d + } + c := v.Args[0].AuxInt + x := v.Args[1] + v.Op = OpAMD64ADDBconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c + v.AddArg(x) + return true + } + 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: + // result: (MOVBconst [c+d]) + { + c := v.AuxInt + if v.Args[0].Op != OpAMD64MOVBconst { + goto enda9b1e9e31ccdf0af5f4fe57bf4b1343f + } + d := v.Args[0].AuxInt + v.Op = OpAMD64MOVBconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c + d + return true + } + 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: + // result: (ADDLconst [c] x) + { + x := v.Args[0] + if v.Args[1].Op != OpAMD64MOVLconst { + goto end8d6d3b99a7be8da6b7a254b7e709cc95 + } + c := v.Args[1].AuxInt + v.Op = OpAMD64ADDLconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c + v.AddArg(x) + return true + } + goto end8d6d3b99a7be8da6b7a254b7e709cc95 + end8d6d3b99a7be8da6b7a254b7e709cc95: + ; + // match: (ADDL (MOVLconst [c]) x) + // cond: + // result: (ADDLconst [c] x) + { + if v.Args[0].Op != OpAMD64MOVLconst { + goto end739561e08a561e26ce3634dc0d5ec733 + } + c := v.Args[0].AuxInt + x := v.Args[1] + v.Op = OpAMD64ADDLconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c + v.AddArg(x) + return true + } + 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: + // result: (MOVLconst [c+d]) + { + c := v.AuxInt + if v.Args[0].Op != OpAMD64MOVLconst { + goto ende04850e987890abf1d66199042a19c23 + } + d := v.Args[0].AuxInt + v.Op = OpAMD64MOVLconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c + d + return true + } + 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) + // result: (ADDQconst [c] x) + { + x := v.Args[0] + if v.Args[1].Op != OpAMD64MOVQconst { + goto end1de8aeb1d043e0dadcffd169a99ce5c0 + } + c := v.Args[1].AuxInt + if !(is32Bit(c)) { + goto end1de8aeb1d043e0dadcffd169a99ce5c0 + } + v.Op = OpAMD64ADDQconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c + v.AddArg(x) + return true + } + goto end1de8aeb1d043e0dadcffd169a99ce5c0 + end1de8aeb1d043e0dadcffd169a99ce5c0: + ; + // match: (ADDQ (MOVQconst [c]) x) + // cond: is32Bit(c) + // result: (ADDQconst [c] x) + { + if v.Args[0].Op != OpAMD64MOVQconst { + 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 + v.resetArgs() + v.AuxInt = c + v.AddArg(x) + return true + } + goto endca635e3bdecd9e3aeb892f841021dfaa + endca635e3bdecd9e3aeb892f841021dfaa: + ; + // match: (ADDQ x (SHLQconst [3] y)) + // cond: + // result: (LEAQ8 x y) + { + x := v.Args[0] + if v.Args[1].Op != OpAMD64SHLQconst { + goto endc02313d35a0525d1d680cd58992e820d + } + if v.Args[1].AuxInt != 3 { + goto endc02313d35a0525d1d680cd58992e820d + } + y := v.Args[1].Args[0] + v.Op = OpAMD64LEAQ8 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + 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: + // result: (LEAQ8 [addOff(c, d)] x y) + { + c := v.AuxInt + if v.Args[0].Op != OpAMD64LEAQ8 { + goto ende2cc681c9abf9913288803fb1b39e639 + } + d := v.Args[0].AuxInt + x := v.Args[0].Args[0] + y := v.Args[0].Args[1] + v.Op = OpAMD64LEAQ8 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = addOff(c, d) + v.AddArg(x) + v.AddArg(y) + return true + } + goto ende2cc681c9abf9913288803fb1b39e639 + ende2cc681c9abf9913288803fb1b39e639: + ; + // match: (ADDQconst [0] x) + // cond: + // result: x + { + if v.AuxInt != 0 { + goto end03d9f5a3e153048b0afa781401e2a849 + } + x := v.Args[0] + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = x.Type + v.AddArg(x) + return true + } + goto end03d9f5a3e153048b0afa781401e2a849 + end03d9f5a3e153048b0afa781401e2a849: + ; + // match: (ADDQconst [c] (MOVQconst [d])) + // cond: + // result: (MOVQconst [c+d]) + { + c := v.AuxInt + if v.Args[0].Op != OpAMD64MOVQconst { + goto end09dc54395b4e96e8332cf8e4e7481c52 + } + d := v.Args[0].AuxInt + v.Op = OpAMD64MOVQconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c + d + return true + } + 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: + // result: (ADDWconst [c] x) + { + x := v.Args[0] + if v.Args[1].Op != OpAMD64MOVWconst { + goto end1aabd2317de77c7dfc4876fd7e4c5011 + } + c := v.Args[1].AuxInt + v.Op = OpAMD64ADDWconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c + v.AddArg(x) + return true + } + goto end1aabd2317de77c7dfc4876fd7e4c5011 + end1aabd2317de77c7dfc4876fd7e4c5011: + ; + // match: (ADDW (MOVWconst [c]) x) + // cond: + // result: (ADDWconst [c] x) + { + if v.Args[0].Op != OpAMD64MOVWconst { + goto ende3aede99966f388afc624f9e86676fd2 + } + c := v.Args[0].AuxInt + x := v.Args[1] + v.Op = OpAMD64ADDWconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c + v.AddArg(x) + return true + } + 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: + // result: (MOVWconst [c+d]) + { + c := v.AuxInt + if v.Args[0].Op != OpAMD64MOVWconst { + goto end32541920f2f5a920dfae41d8ebbef00f + } + d := v.Args[0].AuxInt + v.Op = OpAMD64MOVWconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c + d + return true + } + 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 (MOVLconst [c])) + // cond: + // result: (ANDBconst [c] x) + { + x := v.Args[0] + if v.Args[1].Op != OpAMD64MOVLconst { + goto end01100cd255396e29bfdb130f4fbc9bbc + } + c := v.Args[1].AuxInt + v.Op = OpAMD64ANDBconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c + v.AddArg(x) + return true + } + goto end01100cd255396e29bfdb130f4fbc9bbc + end01100cd255396e29bfdb130f4fbc9bbc: + ; + // match: (ANDB (MOVLconst [c]) x) + // cond: + // result: (ANDBconst [c] x) + { + if v.Args[0].Op != OpAMD64MOVLconst { + goto end70830ce2834dc5f8d786fa6789460926 + } + c := v.Args[0].AuxInt + x := v.Args[1] + v.Op = OpAMD64ANDBconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c + v.AddArg(x) + return true + } + goto end70830ce2834dc5f8d786fa6789460926 + end70830ce2834dc5f8d786fa6789460926: + ; + // match: (ANDB x (MOVBconst [c])) + // cond: + // result: (ANDBconst [c] x) + { + x := v.Args[0] + if v.Args[1].Op != OpAMD64MOVBconst { + goto endd275ec2e73768cb3d201478fc934e06c + } + c := v.Args[1].AuxInt + v.Op = OpAMD64ANDBconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c + v.AddArg(x) + return true + } + goto endd275ec2e73768cb3d201478fc934e06c + endd275ec2e73768cb3d201478fc934e06c: + ; + // match: (ANDB (MOVBconst [c]) x) + // cond: + // result: (ANDBconst [c] x) + { + if v.Args[0].Op != OpAMD64MOVBconst { + goto end4068edac2ae0f354cf581db210288b98 + } + c := v.Args[0].AuxInt + x := v.Args[1] + v.Op = OpAMD64ANDBconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c + v.AddArg(x) + return true + } + goto end4068edac2ae0f354cf581db210288b98 + end4068edac2ae0f354cf581db210288b98: + ; + // match: (ANDB x x) + // cond: + // result: x + { + x := v.Args[0] + if v.Args[1] != x { + goto endb8ff272a1456513da708603abe37541c + } + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = x.Type + v.AddArg(x) + return true + } + goto endb8ff272a1456513da708603abe37541c + endb8ff272a1456513da708603abe37541c: + ; + case OpAMD64ANDBconst: + // match: (ANDBconst [c] _) + // cond: int8(c)==0 + // result: (MOVBconst [0]) + { + c := v.AuxInt + if !(int8(c) == 0) { + goto end2106d410c949da14d7c00041f40eca76 + } + v.Op = OpAMD64MOVBconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = 0 + return true + } + goto end2106d410c949da14d7c00041f40eca76 + end2106d410c949da14d7c00041f40eca76: + ; + // match: (ANDBconst [c] x) + // cond: int8(c)==-1 + // result: x + { + c := v.AuxInt + x := v.Args[0] + if !(int8(c) == -1) { + goto enda0b78503c204c8225de1433949a71fe4 + } + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = x.Type + v.AddArg(x) + return true + } + goto enda0b78503c204c8225de1433949a71fe4 + enda0b78503c204c8225de1433949a71fe4: + ; + // match: (ANDBconst [c] (MOVBconst [d])) + // cond: + // result: (MOVBconst [c&d]) + { + c := v.AuxInt + if v.Args[0].Op != OpAMD64MOVBconst { + goto end946312b1f216933da86febe293eb956f + } + d := v.Args[0].AuxInt + v.Op = OpAMD64MOVBconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c & d + return true + } + goto end946312b1f216933da86febe293eb956f + end946312b1f216933da86febe293eb956f: + ; + case OpAMD64ANDL: + // match: (ANDL x (MOVLconst [c])) + // cond: + // result: (ANDLconst [c] x) + { + x := v.Args[0] + if v.Args[1].Op != OpAMD64MOVLconst { + goto end0a4c49d9a26759c0fd21369dafcd7abb + } + c := v.Args[1].AuxInt + v.Op = OpAMD64ANDLconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c + v.AddArg(x) + return true + } + goto end0a4c49d9a26759c0fd21369dafcd7abb + end0a4c49d9a26759c0fd21369dafcd7abb: + ; + // match: (ANDL (MOVLconst [c]) x) + // cond: + // result: (ANDLconst [c] x) + { + if v.Args[0].Op != OpAMD64MOVLconst { + goto end0529ba323d9b6f15c41add401ef67959 + } + c := v.Args[0].AuxInt + x := v.Args[1] + v.Op = OpAMD64ANDLconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c + v.AddArg(x) + return true + } + goto end0529ba323d9b6f15c41add401ef67959 + end0529ba323d9b6f15c41add401ef67959: + ; + // match: (ANDL x x) + // cond: + // result: x + { + x := v.Args[0] + if v.Args[1] != x { + goto enddfb08a0d0c262854db3905cb323388c7 + } + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = x.Type + v.AddArg(x) + return true + } + goto enddfb08a0d0c262854db3905cb323388c7 + enddfb08a0d0c262854db3905cb323388c7: + ; + case OpAMD64ANDLconst: + // match: (ANDLconst [c] _) + // cond: int32(c)==0 + // result: (MOVLconst [0]) + { + c := v.AuxInt + if !(int32(c) == 0) { + goto end5efb241208aef28c950b7bcf8d85d5de + } + v.Op = OpAMD64MOVLconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = 0 + return true + } + goto end5efb241208aef28c950b7bcf8d85d5de + end5efb241208aef28c950b7bcf8d85d5de: + ; + // match: (ANDLconst [c] x) + // cond: int32(c)==-1 + // result: x + { + c := v.AuxInt + x := v.Args[0] + if !(int32(c) == -1) { + goto end0e852ae30bb8289d6ffee0c9267e3e0c + } + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = x.Type + v.AddArg(x) + return true + } + goto end0e852ae30bb8289d6ffee0c9267e3e0c + end0e852ae30bb8289d6ffee0c9267e3e0c: + ; + // match: (ANDLconst [c] (MOVLconst [d])) + // cond: + // result: (MOVLconst [c&d]) + { + c := v.AuxInt + if v.Args[0].Op != OpAMD64MOVLconst { + goto end7bfd24059369753eadd235f07e2dd7b8 + } + d := v.Args[0].AuxInt + v.Op = OpAMD64MOVLconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c & d + return true + } + goto end7bfd24059369753eadd235f07e2dd7b8 + end7bfd24059369753eadd235f07e2dd7b8: + ; + case OpAMD64ANDQ: + // match: (ANDQ x (MOVQconst [c])) + // cond: is32Bit(c) + // result: (ANDQconst [c] x) + { + x := v.Args[0] + if v.Args[1].Op != OpAMD64MOVQconst { + goto end048fadc69e81103480015b84b9cafff7 + } + c := v.Args[1].AuxInt + if !(is32Bit(c)) { + goto end048fadc69e81103480015b84b9cafff7 + } + v.Op = OpAMD64ANDQconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c + v.AddArg(x) + return true + } + goto end048fadc69e81103480015b84b9cafff7 + end048fadc69e81103480015b84b9cafff7: + ; + // match: (ANDQ (MOVQconst [c]) x) + // cond: is32Bit(c) + // result: (ANDQconst [c] x) + { + if v.Args[0].Op != OpAMD64MOVQconst { + goto end3035a3bf650b708705fd27dd857ab0a4 + } + c := v.Args[0].AuxInt + x := v.Args[1] + if !(is32Bit(c)) { + goto end3035a3bf650b708705fd27dd857ab0a4 + } + v.Op = OpAMD64ANDQconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c + v.AddArg(x) + return true + } + goto end3035a3bf650b708705fd27dd857ab0a4 + end3035a3bf650b708705fd27dd857ab0a4: + ; + // match: (ANDQ x x) + // cond: + // result: x + { + x := v.Args[0] + if v.Args[1] != x { + goto end06b5ec19efdd4e79f03a5e4a2c3c3427 + } + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = x.Type + v.AddArg(x) + return true + } + goto end06b5ec19efdd4e79f03a5e4a2c3c3427 + end06b5ec19efdd4e79f03a5e4a2c3c3427: + ; + case OpAMD64ANDQconst: + // match: (ANDQconst [0] _) + // cond: + // result: (MOVQconst [0]) + { + if v.AuxInt != 0 { + goto end57018c1d0f54fd721521095b4832bab2 + } + v.Op = OpAMD64MOVQconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = 0 + return true + } + goto end57018c1d0f54fd721521095b4832bab2 + end57018c1d0f54fd721521095b4832bab2: + ; + // match: (ANDQconst [-1] x) + // cond: + // result: x + { + if v.AuxInt != -1 { + goto endb542c4b42ab94a7bedb32dec8f610d67 + } + x := v.Args[0] + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = x.Type + v.AddArg(x) + return true + } + goto endb542c4b42ab94a7bedb32dec8f610d67 + endb542c4b42ab94a7bedb32dec8f610d67: + ; + // match: (ANDQconst [c] (MOVQconst [d])) + // cond: + // result: (MOVQconst [c&d]) + { + c := v.AuxInt + if v.Args[0].Op != OpAMD64MOVQconst { + goto end67ca66494705b0345a5f22c710225292 + } + d := v.Args[0].AuxInt + v.Op = OpAMD64MOVQconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c & d + return true + } + goto end67ca66494705b0345a5f22c710225292 + end67ca66494705b0345a5f22c710225292: + ; + case OpAMD64ANDW: + // match: (ANDW x (MOVLconst [c])) + // cond: + // result: (ANDWconst [c] x) + { + x := v.Args[0] + if v.Args[1].Op != OpAMD64MOVLconst { + goto endce6f557823ee2fdd7a8f47b6f925fc7c + } + c := v.Args[1].AuxInt + v.Op = OpAMD64ANDWconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c + v.AddArg(x) + return true + } + goto endce6f557823ee2fdd7a8f47b6f925fc7c + endce6f557823ee2fdd7a8f47b6f925fc7c: + ; + // match: (ANDW (MOVLconst [c]) x) + // cond: + // result: (ANDWconst [c] x) + { + if v.Args[0].Op != OpAMD64MOVLconst { + goto endc46af0d9265c08b09f1f1fba24feda80 + } + c := v.Args[0].AuxInt + x := v.Args[1] + v.Op = OpAMD64ANDWconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c + v.AddArg(x) + return true + } + goto endc46af0d9265c08b09f1f1fba24feda80 + endc46af0d9265c08b09f1f1fba24feda80: + ; + // match: (ANDW x (MOVWconst [c])) + // cond: + // result: (ANDWconst [c] x) + { + x := v.Args[0] + if v.Args[1].Op != OpAMD64MOVWconst { + goto enda77a39f65a5eb3436a5842eab69a3103 + } + c := v.Args[1].AuxInt + v.Op = OpAMD64ANDWconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c + v.AddArg(x) + return true + } + goto enda77a39f65a5eb3436a5842eab69a3103 + enda77a39f65a5eb3436a5842eab69a3103: + ; + // match: (ANDW (MOVWconst [c]) x) + // cond: + // result: (ANDWconst [c] x) + { + if v.Args[0].Op != OpAMD64MOVWconst { + goto endea2a25eb525a5dbf6d5132d84ea4e7a5 + } + c := v.Args[0].AuxInt + x := v.Args[1] + v.Op = OpAMD64ANDWconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c + v.AddArg(x) + return true + } + goto endea2a25eb525a5dbf6d5132d84ea4e7a5 + endea2a25eb525a5dbf6d5132d84ea4e7a5: + ; + // match: (ANDW x x) + // cond: + // result: x + { + x := v.Args[0] + if v.Args[1] != x { + goto end3a26cf52dd1b77f07cc9e005760dbb11 + } + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = x.Type + v.AddArg(x) + return true + } + goto end3a26cf52dd1b77f07cc9e005760dbb11 + end3a26cf52dd1b77f07cc9e005760dbb11: + ; + case OpAMD64ANDWconst: + // match: (ANDWconst [c] _) + // cond: int16(c)==0 + // result: (MOVWconst [0]) + { + c := v.AuxInt + if !(int16(c) == 0) { + goto end336ece33b4f0fb44dfe1f24981df7b74 + } + v.Op = OpAMD64MOVWconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = 0 + return true + } + goto end336ece33b4f0fb44dfe1f24981df7b74 + end336ece33b4f0fb44dfe1f24981df7b74: + ; + // match: (ANDWconst [c] x) + // cond: int16(c)==-1 + // result: x + { + c := v.AuxInt + x := v.Args[0] + if !(int16(c) == -1) { + goto endfb111c3afa8c5c4040fa6000fadee810 + } + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = x.Type + v.AddArg(x) + return true + } + goto endfb111c3afa8c5c4040fa6000fadee810 + endfb111c3afa8c5c4040fa6000fadee810: + ; + // match: (ANDWconst [c] (MOVWconst [d])) + // cond: + // result: (MOVWconst [c&d]) + { + c := v.AuxInt + if v.Args[0].Op != OpAMD64MOVWconst { + goto end250eb27fcac10bf6c0d96ce66a21726e + } + d := v.Args[0].AuxInt + v.Op = OpAMD64MOVWconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c & d + return true + } + goto end250eb27fcac10bf6c0d96ce66a21726e + end250eb27fcac10bf6c0d96ce66a21726e: + ; + case OpAdd16: + // match: (Add16 x y) + // cond: + // result: (ADDW x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64ADDW + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto ende604481c6de9fe4574cb2954ba2ddc67 + ende604481c6de9fe4574cb2954ba2ddc67: + ; + case OpAdd32: + // match: (Add32 x y) + // cond: + // result: (ADDL x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64ADDL + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + 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: + // result: (ADDQ x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64ADDQ + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + 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: + // result: (ADDB x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64ADDB + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto end6117c84a6b75c1b816b3fb095bc5f656 + end6117c84a6b75c1b816b3fb095bc5f656: + ; + case OpAddPtr: + // match: (AddPtr x y) + // cond: + // result: (ADDQ x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64ADDQ + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto enda1d5640788c7157996f9d4af602dec1c + enda1d5640788c7157996f9d4af602dec1c: + ; + case OpAddr: + // match: (Addr {sym} base) + // cond: + // result: (LEAQ {sym} base) + { + sym := v.Aux + base := v.Args[0] + v.Op = OpAMD64LEAQ + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Aux = sym + v.AddArg(base) + return true + } + goto end53cad0c3c9daa5575680e77c14e05e72 + end53cad0c3c9daa5575680e77c14e05e72: + ; + case OpAnd16: + // match: (And16 x y) + // cond: + // result: (ANDW x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64ANDW + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto end1c01f04a173d86ce1a6d1ef59e753014 + end1c01f04a173d86ce1a6d1ef59e753014: + ; + case OpAnd32: + // match: (And32 x y) + // cond: + // result: (ANDL x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64ANDL + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto end6b9eb9375b3a859028a6ba6bf6b8ec88 + end6b9eb9375b3a859028a6ba6bf6b8ec88: + ; + case OpAnd64: + // match: (And64 x y) + // cond: + // result: (ANDQ x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64ANDQ + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto enda0bde5853819d05fa2b7d3b723629552 + enda0bde5853819d05fa2b7d3b723629552: + ; + case OpAnd8: + // match: (And8 x y) + // cond: + // result: (ANDB x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64ANDB + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto end0f53bee6291f1229b43aa1b5f977b4f2 + end0f53bee6291f1229b43aa1b5f977b4f2: + ; + case OpAMD64CMPB: + // match: (CMPB x (MOVBconst [c])) + // cond: + // result: (CMPBconst x [c]) + { + x := v.Args[0] + if v.Args[1].Op != OpAMD64MOVBconst { + goto end52190c0b8759133aa6c540944965c4c0 + } + c := v.Args[1].AuxInt + v.Op = OpAMD64CMPBconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AuxInt = c + return true + } + goto end52190c0b8759133aa6c540944965c4c0 + end52190c0b8759133aa6c540944965c4c0: + ; + // match: (CMPB (MOVBconst [c]) x) + // cond: + // result: (InvertFlags (CMPBconst x [c])) + { + if v.Args[0].Op != OpAMD64MOVBconst { + goto end25ab646f9eb8749ea58c8fbbb4bf6bcd + } + c := v.Args[0].AuxInt + x := v.Args[1] + v.Op = OpAMD64InvertFlags + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64CMPBconst, TypeInvalid) + v0.AddArg(x) + v0.AuxInt = c + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto end25ab646f9eb8749ea58c8fbbb4bf6bcd + end25ab646f9eb8749ea58c8fbbb4bf6bcd: + ; + case OpAMD64CMPL: + // match: (CMPL x (MOVLconst [c])) + // cond: + // result: (CMPLconst x [c]) + { + x := v.Args[0] + if v.Args[1].Op != OpAMD64MOVLconst { + goto end49ff4559c4bdecb2aef0c905e2d9a6cf + } + c := v.Args[1].AuxInt + v.Op = OpAMD64CMPLconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AuxInt = c + return true + } + goto end49ff4559c4bdecb2aef0c905e2d9a6cf + end49ff4559c4bdecb2aef0c905e2d9a6cf: + ; + // match: (CMPL (MOVLconst [c]) x) + // cond: + // result: (InvertFlags (CMPLconst x [c])) + { + if v.Args[0].Op != OpAMD64MOVLconst { + goto end7d89230086678ab4ed5cc96a3ae358d6 + } + c := v.Args[0].AuxInt + x := v.Args[1] + v.Op = OpAMD64InvertFlags + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64CMPLconst, TypeInvalid) + v0.AddArg(x) + v0.AuxInt = c + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto end7d89230086678ab4ed5cc96a3ae358d6 + end7d89230086678ab4ed5cc96a3ae358d6: + ; + case OpAMD64CMPQ: + // match: (CMPQ x (MOVQconst [c])) + // cond: is32Bit(c) + // result: (CMPQconst x [c]) + { + x := v.Args[0] + if v.Args[1].Op != OpAMD64MOVQconst { + goto end3bbb2c6caa57853a7561738ce3c0c630 + } + c := v.Args[1].AuxInt + if !(is32Bit(c)) { + goto end3bbb2c6caa57853a7561738ce3c0c630 + } + v.Op = OpAMD64CMPQconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AuxInt = c + return true + } + goto end3bbb2c6caa57853a7561738ce3c0c630 + end3bbb2c6caa57853a7561738ce3c0c630: + ; + // match: (CMPQ (MOVQconst [c]) x) + // cond: is32Bit(c) + // result: (InvertFlags (CMPQconst x [c])) + { + if v.Args[0].Op != OpAMD64MOVQconst { + goto end153e951c4d9890ee40bf6f189ff6280e + } + c := v.Args[0].AuxInt + x := v.Args[1] + if !(is32Bit(c)) { + goto end153e951c4d9890ee40bf6f189ff6280e + } + v.Op = OpAMD64InvertFlags + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64CMPQconst, TypeInvalid) + v0.AddArg(x) + v0.AuxInt = c + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto end153e951c4d9890ee40bf6f189ff6280e + end153e951c4d9890ee40bf6f189ff6280e: + ; + case OpAMD64CMPW: + // match: (CMPW x (MOVWconst [c])) + // cond: + // result: (CMPWconst x [c]) + { + x := v.Args[0] + if v.Args[1].Op != OpAMD64MOVWconst { + goto end310a9ba58ac35c97587e08c63fe8a46c + } + c := v.Args[1].AuxInt + v.Op = OpAMD64CMPWconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AuxInt = c + return true + } + goto end310a9ba58ac35c97587e08c63fe8a46c + end310a9ba58ac35c97587e08c63fe8a46c: + ; + // match: (CMPW (MOVWconst [c]) x) + // cond: + // result: (InvertFlags (CMPWconst x [c])) + { + if v.Args[0].Op != OpAMD64MOVWconst { + goto end3c52d0ae6e3d186bf131b41276c21889 + } + c := v.Args[0].AuxInt + x := v.Args[1] + v.Op = OpAMD64InvertFlags + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64CMPWconst, TypeInvalid) + v0.AddArg(x) + v0.AuxInt = c + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto end3c52d0ae6e3d186bf131b41276c21889 + end3c52d0ae6e3d186bf131b41276c21889: + ; + case OpClosureCall: + // match: (ClosureCall [argwid] entry closure mem) + // cond: + // result: (CALLclosure [argwid] entry closure mem) + { + argwid := v.AuxInt + entry := v.Args[0] + closure := v.Args[1] + mem := v.Args[2] + v.Op = OpAMD64CALLclosure + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = argwid + v.AddArg(entry) + v.AddArg(closure) + v.AddArg(mem) + return true + } + goto endfd75d26316012d86cb71d0dd1214259b + endfd75d26316012d86cb71d0dd1214259b: + ; + case OpCom16: + // match: (Com16 x) + // cond: + // result: (NOTW x) + { + x := v.Args[0] + v.Op = OpAMD64NOTW + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto end1b14ba8d7d7aa585ec0a211827f280ae + end1b14ba8d7d7aa585ec0a211827f280ae: + ; + case OpCom32: + // match: (Com32 x) + // cond: + // result: (NOTL x) + { + x := v.Args[0] + v.Op = OpAMD64NOTL + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto end6eb124ba3bdb3fd6031414370852feb6 + end6eb124ba3bdb3fd6031414370852feb6: + ; + case OpCom64: + // match: (Com64 x) + // cond: + // result: (NOTQ x) + { + x := v.Args[0] + v.Op = OpAMD64NOTQ + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto endf5f3b355a87779c347e305719dddda05 + endf5f3b355a87779c347e305719dddda05: + ; + case OpCom8: + // match: (Com8 x) + // cond: + // result: (NOTB x) + { + x := v.Args[0] + v.Op = OpAMD64NOTB + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto end1c7c5c055d663ccf1f05fbc4883030c6 + end1c7c5c055d663ccf1f05fbc4883030c6: + ; + case OpConst16: + // match: (Const16 [val]) + // cond: + // result: (MOVWconst [val]) + { + val := v.AuxInt + v.Op = OpAMD64MOVWconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = val + return true + } + goto end2c6c92f297873b8ac12bd035d56d001e + end2c6c92f297873b8ac12bd035d56d001e: + ; + case OpConst32: + // match: (Const32 [val]) + // cond: + // result: (MOVLconst [val]) + { + val := v.AuxInt + v.Op = OpAMD64MOVLconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = val + return true + } + goto enddae5807662af67143a3ac3ad9c63bae5 + enddae5807662af67143a3ac3ad9c63bae5: + ; + case OpConst32F: + // match: (Const32F [val]) + // cond: + // result: (MOVSSconst [val]) + { + val := v.AuxInt + v.Op = OpAMD64MOVSSconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = val + return true + } + goto endfabcef2d57a8f36eaa6041de6f112b89 + endfabcef2d57a8f36eaa6041de6f112b89: + ; + case OpConst64: + // match: (Const64 [val]) + // cond: + // result: (MOVQconst [val]) + { + val := v.AuxInt + v.Op = OpAMD64MOVQconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = val + return true + } + goto endc630434ae7f143ab69d5f482a9b52b5f + endc630434ae7f143ab69d5f482a9b52b5f: + ; + case OpConst64F: + // match: (Const64F [val]) + // cond: + // result: (MOVSDconst [val]) + { + val := v.AuxInt + v.Op = OpAMD64MOVSDconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = val + return true + } + goto endae6cf7189e464bbde17b98635a20f0ff + endae6cf7189e464bbde17b98635a20f0ff: + ; + case OpConst8: + // match: (Const8 [val]) + // cond: + // result: (MOVBconst [val]) + { + val := v.AuxInt + v.Op = OpAMD64MOVBconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = val + return true + } + goto end200524c722ed14ca935ba47f8f30327d + end200524c722ed14ca935ba47f8f30327d: + ; + case OpConstBool: + // match: (ConstBool [b]) + // cond: + // result: (MOVBconst [b]) + { + b := v.AuxInt + v.Op = OpAMD64MOVBconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = b + return true + } + goto end6d919011283330dcbcb3826f0adc6793 + end6d919011283330dcbcb3826f0adc6793: + ; + case OpConstNil: + // match: (ConstNil) + // cond: + // result: (MOVQconst [0]) + { + v.Op = OpAMD64MOVQconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = 0 + return true + } + goto endea557d921056c25b945a49649e4b9b91 + endea557d921056c25b945a49649e4b9b91: + ; + case OpConstPtr: + // match: (ConstPtr [val]) + // cond: + // result: (MOVQconst [val]) + { + val := v.AuxInt + v.Op = OpAMD64MOVQconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = val + return true + } + goto endc395c0a53eeccf597e225a07b53047d1 + endc395c0a53eeccf597e225a07b53047d1: + ; + case OpCvt32Fto32: + // match: (Cvt32Fto32 x) + // cond: + // result: (CVTTSS2SL x) + { + x := v.Args[0] + v.Op = OpAMD64CVTTSS2SL + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto enda410209d31804e1bce7bdc235fc62342 + enda410209d31804e1bce7bdc235fc62342: + ; + case OpCvt32Fto64: + // match: (Cvt32Fto64 x) + // cond: + // result: (CVTTSS2SQ x) + { + x := v.Args[0] + v.Op = OpAMD64CVTTSS2SQ + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto enddb02fa4f3230a14d557d6c90cdadd523 + enddb02fa4f3230a14d557d6c90cdadd523: + ; + 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: (CVTTSD2SL x) + { + x := v.Args[0] + v.Op = OpAMD64CVTTSD2SL + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto endc213dd690dfe568607dec717b2c385b7 + endc213dd690dfe568607dec717b2c385b7: + ; + 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: (CVTTSD2SQ x) + { + x := v.Args[0] + v.Op = OpAMD64CVTTSD2SQ + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto end0bf3e4468047fd20714266ff05797454 + end0bf3e4468047fd20714266ff05797454: + ; + 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 OpDeferCall: + // match: (DeferCall [argwid] mem) + // cond: + // result: (CALLdefer [argwid] mem) + { + argwid := v.AuxInt + mem := v.Args[0] + v.Op = OpAMD64CALLdefer + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = argwid + v.AddArg(mem) + return true + } + goto end1c408581037450df959dd1fb7554a022 + end1c408581037450df959dd1fb7554a022: + ; + 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: + // 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 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: + // 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 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.AddArg(x) + v0.Type = config.fe.TypeInt16() + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpSignExt8to16, TypeInvalid) + v1.AddArg(y) + v1.Type = config.fe.TypeInt16() + v.AddArg(v1) + return true + } + goto endeee2bc780a73ec2ccb1a66c527816ee0 + endeee2bc780a73ec2ccb1a66c527816ee0: + ; + 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.AddArg(x) + v0.Type = config.fe.TypeUInt16() + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpZeroExt8to16, TypeInvalid) + v1.AddArg(y) + v1.Type = config.fe.TypeUInt16() + v.AddArg(v1) + return true + } + goto end39da6664d6434d844303f6924cc875dd + end39da6664d6434d844303f6924cc875dd: + ; + case OpEq16: + // match: (Eq16 x y) + // cond: + // result: (SETEQ (CMPW x y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETEQ + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64CMPW, TypeInvalid) + v0.AddArg(x) + v0.AddArg(y) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto endd7f668b1d23603b0949953ee8dec8107 + endd7f668b1d23603b0949953ee8dec8107: + ; + case OpEq32: + // match: (Eq32 x y) + // cond: + // result: (SETEQ (CMPL x y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETEQ + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64CMPL, TypeInvalid) + v0.AddArg(x) + v0.AddArg(y) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto endf28041ae0c73fb341cc0d2f4903fb2fb + endf28041ae0c73fb341cc0d2f4903fb2fb: + ; + 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.AddArg(x) + v0.AddArg(y) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto endb2c12933769e5faa8fc238048e113dee + endb2c12933769e5faa8fc238048e113dee: + ; + case OpEq64: + // match: (Eq64 x y) + // cond: + // result: (SETEQ (CMPQ x y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETEQ + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64CMPQ, TypeInvalid) + v0.AddArg(x) + v0.AddArg(y) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto ende07a380487b710b51bcd5aa6d3144b8c + ende07a380487b710b51bcd5aa6d3144b8c: + ; + 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.AddArg(x) + v0.AddArg(y) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto end68e20c0c1b3ee62fbd17af07ac100704 + end68e20c0c1b3ee62fbd17af07ac100704: + ; + case OpEq8: + // match: (Eq8 x y) + // cond: + // result: (SETEQ (CMPB x y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETEQ + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64CMPB, TypeInvalid) + v0.AddArg(x) + v0.AddArg(y) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto end359e5a51d2ab928a455f0ae5adb42ab0 + end359e5a51d2ab928a455f0ae5adb42ab0: + ; + case OpEqPtr: + // match: (EqPtr x y) + // cond: + // result: (SETEQ (CMPQ x y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETEQ + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64CMPQ, TypeInvalid) + v0.AddArg(x) + v0.AddArg(y) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto endf19bd3c0eb99d15718bef4066d62560c + endf19bd3c0eb99d15718bef4066d62560c: + ; + case OpGeq16: + // match: (Geq16 x y) + // cond: + // result: (SETGE (CMPW x y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETGE + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64CMPW, TypeInvalid) + v0.AddArg(x) + v0.AddArg(y) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto end0a3f723d5c0b877c473b0043d814867b + end0a3f723d5c0b877c473b0043d814867b: + ; + case OpGeq16U: + // match: (Geq16U x y) + // cond: + // result: (SETAE (CMPW x y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETAE + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64CMPW, TypeInvalid) + v0.AddArg(x) + v0.AddArg(y) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto end79d754a28ee34eff95140635b26f0248 + end79d754a28ee34eff95140635b26f0248: + ; + case OpGeq32: + // match: (Geq32 x y) + // cond: + // result: (SETGE (CMPL x y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETGE + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64CMPL, TypeInvalid) + v0.AddArg(x) + v0.AddArg(y) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto endfb1f6286a1b153b2a3f5b8548a782c8c + endfb1f6286a1b153b2a3f5b8548a782c8c: + ; + 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.AddArg(x) + v0.AddArg(y) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto end7a8d6107a945410e64db06669a61da97 + end7a8d6107a945410e64db06669a61da97: + ; + case OpGeq32U: + // match: (Geq32U x y) + // cond: + // result: (SETAE (CMPL x y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETAE + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64CMPL, TypeInvalid) + v0.AddArg(x) + v0.AddArg(y) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto endc5d3478a626df01ede063564f4cb80d0 + endc5d3478a626df01ede063564f4cb80d0: + ; + case OpGeq64: + // match: (Geq64 x y) + // cond: + // result: (SETGE (CMPQ x y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETGE + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64CMPQ, TypeInvalid) + v0.AddArg(x) + v0.AddArg(y) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto end74bddb7905ab865de5b041e7e4789911 + end74bddb7905ab865de5b041e7e4789911: + ; + 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.AddArg(x) + v0.AddArg(y) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto end9fac9bd98ef58b7fbbe1a31f84bdcccf + end9fac9bd98ef58b7fbbe1a31f84bdcccf: + ; + case OpGeq64U: + // match: (Geq64U x y) + // cond: + // result: (SETAE (CMPQ x y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETAE + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64CMPQ, TypeInvalid) + v0.AddArg(x) + v0.AddArg(y) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto end95101721fc8f5be9969e50e364143e7f + end95101721fc8f5be9969e50e364143e7f: + ; + case OpGeq8: + // match: (Geq8 x y) + // cond: + // result: (SETGE (CMPB x y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETGE + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64CMPB, TypeInvalid) + v0.AddArg(x) + v0.AddArg(y) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto end983070a3db317bdb64b5a0fb104d267c + end983070a3db317bdb64b5a0fb104d267c: + ; + case OpGeq8U: + // match: (Geq8U x y) + // cond: + // result: (SETAE (CMPB x y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETAE + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64CMPB, TypeInvalid) + v0.AddArg(x) + v0.AddArg(y) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + 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: + // result: (LoweredGetG) + { + v.Op = OpAMD64LoweredGetG + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + return true + } + goto endb17140e71dd641aa4d89e14479160260 + endb17140e71dd641aa4d89e14479160260: + ; + case OpGoCall: + // match: (GoCall [argwid] mem) + // cond: + // result: (CALLgo [argwid] mem) + { + argwid := v.AuxInt + mem := v.Args[0] + v.Op = OpAMD64CALLgo + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = argwid + v.AddArg(mem) + return true + } + goto end1cef0f92c46e6aaa2c7abdf5f2794baf + end1cef0f92c46e6aaa2c7abdf5f2794baf: + ; + case OpGreater16: + // match: (Greater16 x y) + // cond: + // result: (SETG (CMPW x y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETG + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64CMPW, TypeInvalid) + v0.AddArg(x) + v0.AddArg(y) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto end4e4a1307c61240af9a86d8fe4f834ee8 + end4e4a1307c61240af9a86d8fe4f834ee8: + ; + case OpGreater16U: + // match: (Greater16U x y) + // cond: + // result: (SETA (CMPW x y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETA + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64CMPW, TypeInvalid) + v0.AddArg(x) + v0.AddArg(y) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto end7c66c75f4b8ec1db593f3e60cfba9592 + end7c66c75f4b8ec1db593f3e60cfba9592: + ; + case OpGreater32: + // match: (Greater32 x y) + // cond: + // result: (SETG (CMPL x y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETG + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64CMPL, TypeInvalid) + v0.AddArg(x) + v0.AddArg(y) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto end6fb0eae4a0e0e81b4afb085d398d873b + end6fb0eae4a0e0e81b4afb085d398d873b: + ; + 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.AddArg(x) + v0.AddArg(y) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto end94df0bd5cedad8ce8021df1b24da40c6 + end94df0bd5cedad8ce8021df1b24da40c6: + ; + case OpGreater32U: + // match: (Greater32U x y) + // cond: + // result: (SETA (CMPL x y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETA + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64CMPL, TypeInvalid) + v0.AddArg(x) + v0.AddArg(y) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto end18da022a28eae8bd0771e0c948aadaf8 + end18da022a28eae8bd0771e0c948aadaf8: + ; + case OpGreater64: + // match: (Greater64 x y) + // cond: + // result: (SETG (CMPQ x y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETG + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64CMPQ, TypeInvalid) + v0.AddArg(x) + v0.AddArg(y) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto endc025c908708f939780fba0da0c1148b4 + endc025c908708f939780fba0da0c1148b4: + ; + 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.AddArg(x) + v0.AddArg(y) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto end033ca5181b18376e7215c02812ef5a6b + end033ca5181b18376e7215c02812ef5a6b: + ; + case OpGreater64U: + // match: (Greater64U x y) + // cond: + // result: (SETA (CMPQ x y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETA + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64CMPQ, TypeInvalid) + v0.AddArg(x) + v0.AddArg(y) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto endb3e25347041760a04d3fc8321c3f3d00 + endb3e25347041760a04d3fc8321c3f3d00: + ; + case OpGreater8: + // match: (Greater8 x y) + // cond: + // result: (SETG (CMPB x y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETG + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64CMPB, TypeInvalid) + v0.AddArg(x) + v0.AddArg(y) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto enda3eeb5da2e69cb54a1515601d4b360d4 + enda3eeb5da2e69cb54a1515601d4b360d4: + ; + case OpGreater8U: + // match: (Greater8U x y) + // cond: + // result: (SETA (CMPB x y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETA + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64CMPB, TypeInvalid) + v0.AddArg(x) + v0.AddArg(y) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto endd2027f3b6471262f42b90c8cc0413667 + endd2027f3b6471262f42b90c8cc0413667: + ; + 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: + // result: (MOVQload ptr mem) + { + if v.Args[0].Op != OpLoad { + goto enda49fcae3630a097c78aa58189c90a97a + } + ptr := v.Args[0].Args[0] + mem := v.Args[0].Args[1] + v.Op = OpAMD64MOVQload + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(ptr) + v.AddArg(mem) + return true + } + goto enda49fcae3630a097c78aa58189c90a97a + enda49fcae3630a097c78aa58189c90a97a: + ; + case OpInterCall: + // match: (InterCall [argwid] entry mem) + // cond: + // result: (CALLinter [argwid] entry mem) + { + argwid := v.AuxInt + entry := v.Args[0] + mem := v.Args[1] + v.Op = OpAMD64CALLinter + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = argwid + v.AddArg(entry) + v.AddArg(mem) + return true + } + goto endc04351e492ed362efc6aa75121bca305 + endc04351e492ed362efc6aa75121bca305: + ; + case OpIsInBounds: + // match: (IsInBounds idx len) + // cond: + // result: (SETB (CMPQ idx len)) + { + idx := v.Args[0] + len := v.Args[1] + v.Op = OpAMD64SETB + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64CMPQ, TypeInvalid) + v0.AddArg(idx) + v0.AddArg(len) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto endfff988d5f1912886d73be3bb563c37d9 + endfff988d5f1912886d73be3bb563c37d9: + ; + case OpIsNonNil: + // match: (IsNonNil p) + // cond: + // result: (SETNE (TESTQ p p)) + { + p := v.Args[0] + v.Op = OpAMD64SETNE + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64TESTQ, TypeInvalid) + v0.AddArg(p) + v0.AddArg(p) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto end0af5ec868ede9ea73fb0602d54b863e9 + end0af5ec868ede9ea73fb0602d54b863e9: + ; + 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.AddArg(idx) + v0.AddArg(len) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto end02799ad95fe7fb5ce3c2c8ab313b737c + end02799ad95fe7fb5ce3c2c8ab313b737c: + ; + case OpLeq16: + // match: (Leq16 x y) + // cond: + // result: (SETLE (CMPW x y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETLE + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64CMPW, TypeInvalid) + v0.AddArg(x) + v0.AddArg(y) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto end586c647ca6bb8ec725eea917c743d1ea + end586c647ca6bb8ec725eea917c743d1ea: + ; + case OpLeq16U: + // match: (Leq16U x y) + // cond: + // result: (SETBE (CMPW x y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETBE + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64CMPW, TypeInvalid) + v0.AddArg(x) + v0.AddArg(y) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto end9c24a81bc6a4a92267bd6638362dfbfc + end9c24a81bc6a4a92267bd6638362dfbfc: + ; + case OpLeq32: + // match: (Leq32 x y) + // cond: + // result: (SETLE (CMPL x y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETLE + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64CMPL, TypeInvalid) + v0.AddArg(x) + v0.AddArg(y) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto end595ee99a9fc3460b2748b9129b139f88 + end595ee99a9fc3460b2748b9129b139f88: + ; + 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.AddArg(y) + v0.AddArg(x) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto endfee4b989a80cc43328b24f7017e80a17 + endfee4b989a80cc43328b24f7017e80a17: + ; + case OpLeq32U: + // match: (Leq32U x y) + // cond: + // result: (SETBE (CMPL x y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETBE + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64CMPL, TypeInvalid) + v0.AddArg(x) + v0.AddArg(y) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto end1a59850aad6cb17c295d0dc359013420 + end1a59850aad6cb17c295d0dc359013420: + ; + case OpLeq64: + // match: (Leq64 x y) + // cond: + // result: (SETLE (CMPQ x y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETLE + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64CMPQ, TypeInvalid) + v0.AddArg(x) + v0.AddArg(y) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto end406def83fcbf29cd8fa306170b512de2 + end406def83fcbf29cd8fa306170b512de2: + ; + 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.AddArg(y) + v0.AddArg(x) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto end6e3de6d4b5668f673e3822d5947edbd0 + end6e3de6d4b5668f673e3822d5947edbd0: + ; + case OpLeq64U: + // match: (Leq64U x y) + // cond: + // result: (SETBE (CMPQ x y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETBE + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64CMPQ, TypeInvalid) + v0.AddArg(x) + v0.AddArg(y) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto end52f23c145b80639c8d60420ad4057bc7 + end52f23c145b80639c8d60420ad4057bc7: + ; + case OpLeq8: + // match: (Leq8 x y) + // cond: + // result: (SETLE (CMPB x y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETLE + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64CMPB, TypeInvalid) + v0.AddArg(x) + v0.AddArg(y) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto end72ecba6f2a7062cb266923dfec811f79 + end72ecba6f2a7062cb266923dfec811f79: + ; + case OpLeq8U: + // match: (Leq8U x y) + // cond: + // result: (SETBE (CMPB x y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETBE + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64CMPB, TypeInvalid) + v0.AddArg(x) + v0.AddArg(y) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto endb043b338cced4f15400d8d6e584ebea7 + endb043b338cced4f15400d8d6e584ebea7: + ; + case OpLess16: + // match: (Less16 x y) + // cond: + // result: (SETL (CMPW x y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETL + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64CMPW, TypeInvalid) + v0.AddArg(x) + v0.AddArg(y) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto end2f6c6ba80eda8d68e77a58cba13d3f16 + end2f6c6ba80eda8d68e77a58cba13d3f16: + ; + case OpLess16U: + // match: (Less16U x y) + // cond: + // result: (SETB (CMPW x y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETB + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64CMPW, TypeInvalid) + v0.AddArg(x) + v0.AddArg(y) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto end9f65eefe7b83a3c436b5c16664c93703 + end9f65eefe7b83a3c436b5c16664c93703: + ; + case OpLess32: + // match: (Less32 x y) + // cond: + // result: (SETL (CMPL x y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETL + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64CMPL, TypeInvalid) + v0.AddArg(x) + v0.AddArg(y) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto end6632ff4ee994eb5b14cdf60c99ac3798 + end6632ff4ee994eb5b14cdf60c99ac3798: + ; + 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.AddArg(y) + v0.AddArg(x) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto end5b3b0c96a7fc2ede81bc89c9abaac9d0 + end5b3b0c96a7fc2ede81bc89c9abaac9d0: + ; + case OpLess32U: + // match: (Less32U x y) + // cond: + // result: (SETB (CMPL x y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETB + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64CMPL, TypeInvalid) + v0.AddArg(x) + v0.AddArg(y) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto end39e5a513c7fb0a42817a6cf9c6143b60 + end39e5a513c7fb0a42817a6cf9c6143b60: + ; + case OpLess64: + // match: (Less64 x y) + // cond: + // result: (SETL (CMPQ x y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETL + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64CMPQ, TypeInvalid) + v0.AddArg(x) + v0.AddArg(y) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto enddce827d3e922e8487b61a88c2b1510f2 + enddce827d3e922e8487b61a88c2b1510f2: + ; + 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.AddArg(y) + v0.AddArg(x) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto endf2be3d2dcb6543d2159e7fff5ccbbb55 + endf2be3d2dcb6543d2159e7fff5ccbbb55: + ; + case OpLess64U: + // match: (Less64U x y) + // cond: + // result: (SETB (CMPQ x y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETB + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64CMPQ, TypeInvalid) + v0.AddArg(x) + v0.AddArg(y) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto endb76d7768f175a44baf6d63d12ab6e81d + endb76d7768f175a44baf6d63d12ab6e81d: + ; + case OpLess8: + // match: (Less8 x y) + // cond: + // result: (SETL (CMPB x y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETL + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64CMPB, TypeInvalid) + v0.AddArg(x) + v0.AddArg(y) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto end314fbffe99f3bd4b07857a80c0b914cd + end314fbffe99f3bd4b07857a80c0b914cd: + ; + case OpLess8U: + // match: (Less8U x y) + // cond: + // result: (SETB (CMPB x y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETB + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64CMPB, TypeInvalid) + v0.AddArg(x) + v0.AddArg(y) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto endadccc5d80fd053a33004ed0759f64d93 + endadccc5d80fd053a33004ed0759f64d93: + ; + case OpLoad: + // match: (Load ptr mem) + // cond: (is64BitInt(t) || isPtr(t)) + // result: (MOVQload ptr mem) + { + t := v.Type + ptr := v.Args[0] + mem := v.Args[1] + if !(is64BitInt(t) || isPtr(t)) { + goto end7c4c53acf57ebc5f03273652ba1d5934 + } + v.Op = OpAMD64MOVQload + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(ptr) + v.AddArg(mem) + return true + } + goto end7c4c53acf57ebc5f03273652ba1d5934 + end7c4c53acf57ebc5f03273652ba1d5934: + ; + // match: (Load ptr mem) + // cond: is32BitInt(t) + // result: (MOVLload ptr mem) + { + t := v.Type + ptr := v.Args[0] + mem := v.Args[1] + if !(is32BitInt(t)) { + goto ende1cfcb15bfbcfd448ce303d0882a4057 + } + v.Op = OpAMD64MOVLload + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(ptr) + v.AddArg(mem) + return true + } + goto ende1cfcb15bfbcfd448ce303d0882a4057 + ende1cfcb15bfbcfd448ce303d0882a4057: + ; + // match: (Load ptr mem) + // cond: is16BitInt(t) + // result: (MOVWload ptr mem) + { + t := v.Type + ptr := v.Args[0] + mem := v.Args[1] + if !(is16BitInt(t)) { + goto end2d0a1304501ed9f4e9e2d288505a9c7c + } + v.Op = OpAMD64MOVWload + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(ptr) + v.AddArg(mem) + return true + } + goto end2d0a1304501ed9f4e9e2d288505a9c7c + end2d0a1304501ed9f4e9e2d288505a9c7c: + ; + // match: (Load ptr mem) + // cond: (t.IsBoolean() || is8BitInt(t)) + // result: (MOVBload ptr mem) + { + t := v.Type + ptr := v.Args[0] + mem := v.Args[1] + if !(t.IsBoolean() || is8BitInt(t)) { + goto end8f83bf72293670e75b22d6627bd13f0b + } + v.Op = OpAMD64MOVBload + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(ptr) + v.AddArg(mem) + return true + } + 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: + // 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: + // result: (ANDW (SHLW x y) (SBBLcarrymask (CMPWconst [16] y))) + { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64ANDW + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64SHLW, TypeInvalid) + v0.Type = t + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpAMD64SBBLcarrymask, TypeInvalid) + v1.Type = t + v2 := b.NewValue0(v.Line, OpAMD64CMPWconst, TypeInvalid) + v2.AuxInt = 16 + v2.AddArg(y) + v2.Type = TypeFlags + v1.AddArg(v2) + v.AddArg(v1) + return true + } + goto end7ffc4f31c526f7fcb2283215b458f589 + end7ffc4f31c526f7fcb2283215b458f589: + ; + case OpLsh16x32: + // match: (Lsh16x32 x y) + // cond: + // result: (ANDW (SHLW x y) (SBBLcarrymask (CMPLconst [16] y))) + { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64ANDW + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64SHLW, TypeInvalid) + v0.Type = t + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpAMD64SBBLcarrymask, TypeInvalid) + v1.Type = t + v2 := b.NewValue0(v.Line, OpAMD64CMPLconst, TypeInvalid) + v2.AuxInt = 16 + v2.AddArg(y) + v2.Type = TypeFlags + v1.AddArg(v2) + v.AddArg(v1) + return true + } + goto enddcc0e751d315967423c99518c0cc065e + enddcc0e751d315967423c99518c0cc065e: + ; + case OpLsh16x64: + // match: (Lsh16x64 x y) + // cond: + // result: (ANDW (SHLW x y) (SBBLcarrymask (CMPQconst [16] y))) + { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64ANDW + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64SHLW, TypeInvalid) + v0.Type = t + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpAMD64SBBLcarrymask, TypeInvalid) + v1.Type = t + v2 := b.NewValue0(v.Line, OpAMD64CMPQconst, TypeInvalid) + v2.AuxInt = 16 + v2.AddArg(y) + v2.Type = TypeFlags + v1.AddArg(v2) + v.AddArg(v1) + return true + } + goto endf6368b59d046ca83050cd75fbe8715d2 + endf6368b59d046ca83050cd75fbe8715d2: + ; + case OpLsh16x8: + // match: (Lsh16x8 x y) + // cond: + // result: (ANDW (SHLW x y) (SBBLcarrymask (CMPBconst [16] y))) + { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64ANDW + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64SHLW, TypeInvalid) + v0.Type = t + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpAMD64SBBLcarrymask, TypeInvalid) + v1.Type = t + v2 := b.NewValue0(v.Line, OpAMD64CMPBconst, TypeInvalid) + v2.AuxInt = 16 + v2.AddArg(y) + v2.Type = TypeFlags + v1.AddArg(v2) + v.AddArg(v1) + return true + } + goto end8730d944c8fb358001ba2d165755bdc4 + end8730d944c8fb358001ba2d165755bdc4: + ; + case OpLsh32x16: + // match: (Lsh32x16 x y) + // cond: + // result: (ANDL (SHLL x y) (SBBLcarrymask (CMPWconst [32] y))) + { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64ANDL + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64SHLL, TypeInvalid) + v0.Type = t + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpAMD64SBBLcarrymask, TypeInvalid) + v1.Type = t + v2 := b.NewValue0(v.Line, OpAMD64CMPWconst, TypeInvalid) + v2.AuxInt = 32 + v2.AddArg(y) + v2.Type = TypeFlags + v1.AddArg(v2) + v.AddArg(v1) + return true + } + goto end5a43b7e9b0780e62f622bac0a68524d2 + end5a43b7e9b0780e62f622bac0a68524d2: + ; + case OpLsh32x32: + // match: (Lsh32x32 x y) + // cond: + // result: (ANDL (SHLL x y) (SBBLcarrymask (CMPLconst [32] y))) + { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64ANDL + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64SHLL, TypeInvalid) + v0.Type = t + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpAMD64SBBLcarrymask, TypeInvalid) + v1.Type = t + v2 := b.NewValue0(v.Line, OpAMD64CMPLconst, TypeInvalid) + v2.AuxInt = 32 + v2.AddArg(y) + v2.Type = TypeFlags + v1.AddArg(v2) + v.AddArg(v1) + return true + } + goto end9ce0ab6f9095c24ea46ca8fe2d7e5507 + end9ce0ab6f9095c24ea46ca8fe2d7e5507: + ; + case OpLsh32x64: + // match: (Lsh32x64 x y) + // cond: + // result: (ANDL (SHLL x y) (SBBLcarrymask (CMPQconst [32] y))) + { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64ANDL + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64SHLL, TypeInvalid) + v0.Type = t + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpAMD64SBBLcarrymask, TypeInvalid) + v1.Type = t + v2 := b.NewValue0(v.Line, OpAMD64CMPQconst, TypeInvalid) + v2.AuxInt = 32 + v2.AddArg(y) + v2.Type = TypeFlags + v1.AddArg(v2) + v.AddArg(v1) + return true + } + goto end646b5471b709d5ea6c21f49a2815236f + end646b5471b709d5ea6c21f49a2815236f: + ; + case OpLsh32x8: + // match: (Lsh32x8 x y) + // cond: + // result: (ANDL (SHLL x y) (SBBLcarrymask (CMPBconst [32] y))) + { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64ANDL + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64SHLL, TypeInvalid) + v0.Type = t + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpAMD64SBBLcarrymask, TypeInvalid) + v1.Type = t + v2 := b.NewValue0(v.Line, OpAMD64CMPBconst, TypeInvalid) + v2.AuxInt = 32 + v2.AddArg(y) + v2.Type = TypeFlags + v1.AddArg(v2) + v.AddArg(v1) + return true + } + goto end96a677c71370e7c9179125f92cbdfda8 + end96a677c71370e7c9179125f92cbdfda8: + ; + case OpLsh64x16: + // match: (Lsh64x16 x y) + // cond: + // result: (ANDQ (SHLQ x y) (SBBQcarrymask (CMPWconst [64] y))) + { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64ANDQ + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64SHLQ, TypeInvalid) + v0.Type = t + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpAMD64SBBQcarrymask, TypeInvalid) + v1.Type = t + v2 := b.NewValue0(v.Line, OpAMD64CMPWconst, TypeInvalid) + v2.AuxInt = 64 + v2.AddArg(y) + v2.Type = TypeFlags + v1.AddArg(v2) + v.AddArg(v1) + return true + } + goto end5f88f241d68d38954222d81559cd7f9f + end5f88f241d68d38954222d81559cd7f9f: + ; + case OpLsh64x32: + // match: (Lsh64x32 x y) + // cond: + // result: (ANDQ (SHLQ x y) (SBBQcarrymask (CMPLconst [64] y))) + { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64ANDQ + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64SHLQ, TypeInvalid) + v0.Type = t + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpAMD64SBBQcarrymask, TypeInvalid) + v1.Type = t + v2 := b.NewValue0(v.Line, OpAMD64CMPLconst, TypeInvalid) + v2.AuxInt = 64 + v2.AddArg(y) + v2.Type = TypeFlags + v1.AddArg(v2) + v.AddArg(v1) + return true + } + goto endae1705f03ed3d6f43cd63b53496a910a + endae1705f03ed3d6f43cd63b53496a910a: + ; + case OpLsh64x64: + // match: (Lsh64x64 x y) + // cond: + // result: (ANDQ (SHLQ x y) (SBBQcarrymask (CMPQconst [64] y))) + { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64ANDQ + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64SHLQ, TypeInvalid) + v0.Type = t + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpAMD64SBBQcarrymask, TypeInvalid) + v1.Type = t + v2 := b.NewValue0(v.Line, OpAMD64CMPQconst, TypeInvalid) + v2.AuxInt = 64 + v2.AddArg(y) + v2.Type = TypeFlags + v1.AddArg(v2) + v.AddArg(v1) + return true + } + goto end1f6f5f510c5c68e4ce4a78643e6d85a1 + end1f6f5f510c5c68e4ce4a78643e6d85a1: + ; + case OpLsh64x8: + // match: (Lsh64x8 x y) + // cond: + // result: (ANDQ (SHLQ x y) (SBBQcarrymask (CMPBconst [64] y))) + { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64ANDQ + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64SHLQ, TypeInvalid) + v0.Type = t + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpAMD64SBBQcarrymask, TypeInvalid) + v1.Type = t + v2 := b.NewValue0(v.Line, OpAMD64CMPBconst, TypeInvalid) + v2.AuxInt = 64 + v2.AddArg(y) + v2.Type = TypeFlags + v1.AddArg(v2) + v.AddArg(v1) + return true + } + goto endd14f5c89e3496b0e425aa1ae366f4b53 + endd14f5c89e3496b0e425aa1ae366f4b53: + ; + case OpLsh8x16: + // match: (Lsh8x16 x y) + // cond: + // result: (ANDB (SHLB x y) (SBBLcarrymask (CMPWconst [8] y))) + { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64ANDB + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64SHLB, TypeInvalid) + v0.Type = t + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpAMD64SBBLcarrymask, TypeInvalid) + v1.Type = t + v2 := b.NewValue0(v.Line, OpAMD64CMPWconst, TypeInvalid) + v2.AuxInt = 8 + v2.AddArg(y) + v2.Type = TypeFlags + v1.AddArg(v2) + v.AddArg(v1) + return true + } + goto end0926c3d8b9a0776ba5058946f6e1a4b7 + end0926c3d8b9a0776ba5058946f6e1a4b7: + ; + case OpLsh8x32: + // match: (Lsh8x32 x y) + // cond: + // result: (ANDB (SHLB x y) (SBBLcarrymask (CMPLconst [8] y))) + { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64ANDB + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64SHLB, TypeInvalid) + v0.Type = t + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpAMD64SBBLcarrymask, TypeInvalid) + v1.Type = t + v2 := b.NewValue0(v.Line, OpAMD64CMPLconst, TypeInvalid) + v2.AuxInt = 8 + v2.AddArg(y) + v2.Type = TypeFlags + v1.AddArg(v2) + v.AddArg(v1) + return true + } + goto end5987682d77f197ef0fd95251f413535a + end5987682d77f197ef0fd95251f413535a: + ; + case OpLsh8x64: + // match: (Lsh8x64 x y) + // cond: + // result: (ANDB (SHLB x y) (SBBLcarrymask (CMPQconst [8] y))) + { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64ANDB + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64SHLB, TypeInvalid) + v0.Type = t + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpAMD64SBBLcarrymask, TypeInvalid) + v1.Type = t + v2 := b.NewValue0(v.Line, OpAMD64CMPQconst, TypeInvalid) + v2.AuxInt = 8 + v2.AddArg(y) + v2.Type = TypeFlags + v1.AddArg(v2) + v.AddArg(v1) + return true + } + goto end9ffe6731d7d6514b8c0482f1645eee18 + end9ffe6731d7d6514b8c0482f1645eee18: + ; + case OpLsh8x8: + // match: (Lsh8x8 x y) + // cond: + // result: (ANDB (SHLB x y) (SBBLcarrymask (CMPBconst [8] y))) + { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64ANDB + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64SHLB, TypeInvalid) + v0.Type = t + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpAMD64SBBLcarrymask, TypeInvalid) + v1.Type = t + v2 := b.NewValue0(v.Line, OpAMD64CMPBconst, TypeInvalid) + v2.AuxInt = 8 + v2.AddArg(y) + v2.Type = TypeFlags + v1.AddArg(v2) + v.AddArg(v1) + return true + } + goto end2b75242a31c3713ffbfdd8f0288b1c12 + end2b75242a31c3713ffbfdd8f0288b1c12: + ; + case OpAMD64MOVBQSX: + // match: (MOVBQSX (MOVBload [off] {sym} ptr mem)) + // cond: + // result: @v.Args[0].Block (MOVBQSXload [off] {sym} ptr mem) + { + if v.Args[0].Op != OpAMD64MOVBload { + goto end19c38f3a1a37dca50637c917fa26e4f7 + } + off := v.Args[0].AuxInt + sym := v.Args[0].Aux + ptr := v.Args[0].Args[0] + mem := v.Args[0].Args[1] + v0 := v.Args[0].Block.NewValue0(v.Line, OpAMD64MOVBQSXload, TypeInvalid) + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(v0) + v0.Type = v.Type + v0.AuxInt = off + v0.Aux = sym + v0.AddArg(ptr) + v0.AddArg(mem) + return true + } + goto end19c38f3a1a37dca50637c917fa26e4f7 + end19c38f3a1a37dca50637c917fa26e4f7: + ; + case OpAMD64MOVBQZX: + // match: (MOVBQZX (MOVBload [off] {sym} ptr mem)) + // cond: + // result: @v.Args[0].Block (MOVBQZXload [off] {sym} ptr mem) + { + if v.Args[0].Op != OpAMD64MOVBload { + goto end1169bcf3d56fa24321b002eaebd5a62d + } + off := v.Args[0].AuxInt + sym := v.Args[0].Aux + ptr := v.Args[0].Args[0] + mem := v.Args[0].Args[1] + v0 := v.Args[0].Block.NewValue0(v.Line, OpAMD64MOVBQZXload, TypeInvalid) + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(v0) + v0.Type = v.Type + v0.AuxInt = off + v0.Aux = sym + v0.AddArg(ptr) + v0.AddArg(mem) + return true + } + goto end1169bcf3d56fa24321b002eaebd5a62d + end1169bcf3d56fa24321b002eaebd5a62d: + ; + case OpAMD64MOVBload: + // match: (MOVBload [off1] {sym} (ADDQconst [off2] ptr) mem) + // cond: + // result: (MOVBload [addOff(off1, off2)] {sym} ptr mem) + { + off1 := v.AuxInt + sym := v.Aux + if v.Args[0].Op != OpAMD64ADDQconst { + goto end7ec9147ab863c1bd59190fed81f894b6 + } + off2 := v.Args[0].AuxInt + ptr := v.Args[0].Args[0] + mem := v.Args[1] + v.Op = OpAMD64MOVBload + 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 end7ec9147ab863c1bd59190fed81f894b6 + end7ec9147ab863c1bd59190fed81f894b6: + ; + // match: (MOVBload [off1] {sym1} (LEAQ [off2] {sym2} base) mem) + // cond: canMergeSym(sym1, sym2) + // result: (MOVBload [addOff(off1,off2)] {mergeSym(sym1,sym2)} base mem) + { + off1 := v.AuxInt + sym1 := v.Aux + if v.Args[0].Op != OpAMD64LEAQ { + goto end3771a59cf66b0df99120d76f4c358fab + } + 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 end3771a59cf66b0df99120d76f4c358fab + } + v.Op = OpAMD64MOVBload + 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 end3771a59cf66b0df99120d76f4c358fab + end3771a59cf66b0df99120d76f4c358fab: + ; + case OpAMD64MOVBstore: + // match: (MOVBstore [off] {sym} ptr (MOVBQSX x) mem) + // cond: + // result: (MOVBstore [off] {sym} ptr x mem) + { + off := v.AuxInt + sym := v.Aux + ptr := v.Args[0] + if v.Args[1].Op != OpAMD64MOVBQSX { + goto end5b3f41f0770d566ff1647dea1d4a40e8 + } + x := v.Args[1].Args[0] + mem := v.Args[2] + v.Op = OpAMD64MOVBstore + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = off + v.Aux = sym + v.AddArg(ptr) + v.AddArg(x) + v.AddArg(mem) + return true + } + goto end5b3f41f0770d566ff1647dea1d4a40e8 + end5b3f41f0770d566ff1647dea1d4a40e8: + ; + // match: (MOVBstore [off] {sym} ptr (MOVBQZX x) mem) + // cond: + // result: (MOVBstore [off] {sym} ptr x mem) + { + off := v.AuxInt + sym := v.Aux + ptr := v.Args[0] + if v.Args[1].Op != OpAMD64MOVBQZX { + goto end3a2e55db7e03920700c4875f6a55de3b + } + x := v.Args[1].Args[0] + mem := v.Args[2] + v.Op = OpAMD64MOVBstore + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = off + v.Aux = sym + v.AddArg(ptr) + v.AddArg(x) + v.AddArg(mem) + return true + } + goto end3a2e55db7e03920700c4875f6a55de3b + end3a2e55db7e03920700c4875f6a55de3b: + ; + // match: (MOVBstore [off1] {sym} (ADDQconst [off2] ptr) val mem) + // cond: + // result: (MOVBstore [addOff(off1, off2)] {sym} ptr val mem) + { + off1 := v.AuxInt + sym := v.Aux + if v.Args[0].Op != OpAMD64ADDQconst { + goto ende6347ac19d0469ee59d2e7f2e18d1070 + } + off2 := v.Args[0].AuxInt + ptr := v.Args[0].Args[0] + val := v.Args[1] + mem := v.Args[2] + v.Op = OpAMD64MOVBstore + 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 ende6347ac19d0469ee59d2e7f2e18d1070 + ende6347ac19d0469ee59d2e7f2e18d1070: + ; + // match: (MOVBstore [off1] {sym1} (LEAQ [off2] {sym2} base) val mem) + // cond: canMergeSym(sym1, sym2) + // result: (MOVBstore [addOff(off1,off2)] {mergeSym(sym1,sym2)} base val mem) + { + off1 := v.AuxInt + sym1 := v.Aux + if v.Args[0].Op != OpAMD64LEAQ { + goto enda7086cf7f6b8cf81972e2c3d4b12f3fc + } + 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 enda7086cf7f6b8cf81972e2c3d4b12f3fc + } + v.Op = OpAMD64MOVBstore + 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 enda7086cf7f6b8cf81972e2c3d4b12f3fc + enda7086cf7f6b8cf81972e2c3d4b12f3fc: + ; + case OpAMD64MOVLload: + // match: (MOVLload [off1] {sym} (ADDQconst [off2] ptr) mem) + // cond: + // result: (MOVLload [addOff(off1, off2)] {sym} ptr mem) + { + off1 := v.AuxInt + sym := v.Aux + if v.Args[0].Op != OpAMD64ADDQconst { + goto end0c8b8a40360c5c581d92723eca04d340 + } + off2 := v.Args[0].AuxInt + ptr := v.Args[0].Args[0] + mem := v.Args[1] + v.Op = OpAMD64MOVLload + 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 end0c8b8a40360c5c581d92723eca04d340 + end0c8b8a40360c5c581d92723eca04d340: + ; + // match: (MOVLload [off1] {sym1} (LEAQ [off2] {sym2} base) mem) + // cond: canMergeSym(sym1, sym2) + // result: (MOVLload [addOff(off1,off2)] {mergeSym(sym1,sym2)} base mem) + { + off1 := v.AuxInt + sym1 := v.Aux + if v.Args[0].Op != OpAMD64LEAQ { + goto enddb9e59335876d8a565c425731438a1b3 + } + 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 enddb9e59335876d8a565c425731438a1b3 + } + v.Op = OpAMD64MOVLload + 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 enddb9e59335876d8a565c425731438a1b3 + enddb9e59335876d8a565c425731438a1b3: + ; + case OpAMD64MOVLstore: + // match: (MOVLstore [off] {sym} ptr (MOVLQSX x) mem) + // cond: + // result: (MOVLstore [off] {sym} ptr x mem) + { + off := v.AuxInt + sym := v.Aux + ptr := v.Args[0] + if v.Args[1].Op != OpAMD64MOVLQSX { + goto end1fb7b2ae707c76d30927c21f85d77472 + } + x := v.Args[1].Args[0] + mem := v.Args[2] + v.Op = OpAMD64MOVLstore + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = off + v.Aux = sym + v.AddArg(ptr) + v.AddArg(x) + v.AddArg(mem) + return true + } + goto end1fb7b2ae707c76d30927c21f85d77472 + end1fb7b2ae707c76d30927c21f85d77472: + ; + // match: (MOVLstore [off] {sym} ptr (MOVLQZX x) mem) + // cond: + // result: (MOVLstore [off] {sym} ptr x mem) + { + off := v.AuxInt + sym := v.Aux + ptr := v.Args[0] + if v.Args[1].Op != OpAMD64MOVLQZX { + goto end199e8c23a5e7e99728a43d6a83b2c2cf + } + x := v.Args[1].Args[0] + mem := v.Args[2] + v.Op = OpAMD64MOVLstore + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = off + v.Aux = sym + v.AddArg(ptr) + v.AddArg(x) + v.AddArg(mem) + return true + } + goto end199e8c23a5e7e99728a43d6a83b2c2cf + end199e8c23a5e7e99728a43d6a83b2c2cf: + ; + // match: (MOVLstore [off1] {sym} (ADDQconst [off2] ptr) val mem) + // cond: + // result: (MOVLstore [addOff(off1, off2)] {sym} ptr val mem) + { + off1 := v.AuxInt + sym := v.Aux + if v.Args[0].Op != OpAMD64ADDQconst { + goto end43bffdb8d9c1fc85a95778d4911955f1 + } + off2 := v.Args[0].AuxInt + ptr := v.Args[0].Args[0] + val := v.Args[1] + mem := v.Args[2] + v.Op = OpAMD64MOVLstore + 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 end43bffdb8d9c1fc85a95778d4911955f1 + end43bffdb8d9c1fc85a95778d4911955f1: + ; + // match: (MOVLstore [off1] {sym1} (LEAQ [off2] {sym2} base) val mem) + // cond: canMergeSym(sym1, sym2) + // result: (MOVLstore [addOff(off1,off2)] {mergeSym(sym1,sym2)} base val mem) + { + off1 := v.AuxInt + sym1 := v.Aux + if v.Args[0].Op != OpAMD64LEAQ { + goto endd57b1e4313fc7a3331340a9af00ba116 + } + 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 endd57b1e4313fc7a3331340a9af00ba116 + } + v.Op = OpAMD64MOVLstore + 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 endd57b1e4313fc7a3331340a9af00ba116 + endd57b1e4313fc7a3331340a9af00ba116: + ; + case OpAMD64MOVQload: + // match: (MOVQload [off1] {sym} (ADDQconst [off2] ptr) mem) + // cond: + // result: (MOVQload [addOff(off1, off2)] {sym} ptr mem) + { + off1 := v.AuxInt + sym := v.Aux + if v.Args[0].Op != OpAMD64ADDQconst { + goto end0b8c50dd7faefb7d046f9a27e054df77 + } + off2 := v.Args[0].AuxInt + ptr := v.Args[0].Args[0] + mem := v.Args[1] + v.Op = OpAMD64MOVQload + 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 end0b8c50dd7faefb7d046f9a27e054df77 + end0b8c50dd7faefb7d046f9a27e054df77: + ; + // match: (MOVQload [off1] {sym1} (LEAQ [off2] {sym2} base) mem) + // cond: canMergeSym(sym1, sym2) + // result: (MOVQload [addOff(off1,off2)] {mergeSym(sym1,sym2)} base mem) + { + off1 := v.AuxInt + sym1 := v.Aux + if v.Args[0].Op != OpAMD64LEAQ { + goto endd0c093adc4f05f2037005734c77d3cc4 + } + 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 endd0c093adc4f05f2037005734c77d3cc4 + } + v.Op = OpAMD64MOVQload + 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 endd0c093adc4f05f2037005734c77d3cc4 + endd0c093adc4f05f2037005734c77d3cc4: + ; + // match: (MOVQload [off1] {sym1} (LEAQ8 [off2] {sym2} ptr idx) mem) + // cond: canMergeSym(sym1, sym2) + // result: (MOVQloadidx8 [addOff(off1, off2)] {mergeSym(sym1,sym2)} ptr idx mem) + { + off1 := v.AuxInt + sym1 := v.Aux + if v.Args[0].Op != OpAMD64LEAQ8 { + goto end74a50d810fb3945e809f608cd094a59c + } + off2 := v.Args[0].AuxInt + sym2 := v.Args[0].Aux + ptr := v.Args[0].Args[0] + idx := v.Args[0].Args[1] + mem := v.Args[1] + if !(canMergeSym(sym1, sym2)) { + goto end74a50d810fb3945e809f608cd094a59c + } + v.Op = OpAMD64MOVQloadidx8 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = addOff(off1, off2) + v.Aux = mergeSym(sym1, sym2) + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + goto end74a50d810fb3945e809f608cd094a59c + end74a50d810fb3945e809f608cd094a59c: + ; + case OpAMD64MOVQloadidx8: + // match: (MOVQloadidx8 [off1] {sym} (ADDQconst [off2] ptr) idx mem) + // cond: + // result: (MOVQloadidx8 [addOff(off1, off2)] {sym} ptr idx mem) + { + off1 := v.AuxInt + sym := v.Aux + if v.Args[0].Op != OpAMD64ADDQconst { + goto endb138bf9b0b33ec824bf0aff619f8bafa + } + off2 := v.Args[0].AuxInt + ptr := v.Args[0].Args[0] + idx := v.Args[1] + mem := v.Args[2] + v.Op = OpAMD64MOVQloadidx8 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = addOff(off1, off2) + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + goto endb138bf9b0b33ec824bf0aff619f8bafa + endb138bf9b0b33ec824bf0aff619f8bafa: + ; + case OpAMD64MOVQstore: + // match: (MOVQstore [off1] {sym} (ADDQconst [off2] ptr) val mem) + // cond: + // result: (MOVQstore [addOff(off1, off2)] {sym} ptr val mem) + { + off1 := v.AuxInt + sym := v.Aux + if v.Args[0].Op != OpAMD64ADDQconst { + goto end0a110b5e42a4576c32fda50590092848 + } + off2 := v.Args[0].AuxInt + ptr := v.Args[0].Args[0] + val := v.Args[1] + mem := v.Args[2] + v.Op = OpAMD64MOVQstore + 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 end0a110b5e42a4576c32fda50590092848 + end0a110b5e42a4576c32fda50590092848: + ; + // match: (MOVQstore [off1] {sym1} (LEAQ [off2] {sym2} base) val mem) + // cond: canMergeSym(sym1, sym2) + // result: (MOVQstore [addOff(off1,off2)] {mergeSym(sym1,sym2)} base val mem) + { + off1 := v.AuxInt + sym1 := v.Aux + if v.Args[0].Op != OpAMD64LEAQ { + goto end9a0cfe20b3b0f587e252760907c1b5c0 + } + 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 end9a0cfe20b3b0f587e252760907c1b5c0 + } + v.Op = OpAMD64MOVQstore + 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 end9a0cfe20b3b0f587e252760907c1b5c0 + end9a0cfe20b3b0f587e252760907c1b5c0: + ; + // match: (MOVQstore [off1] {sym1} (LEAQ8 [off2] {sym2} ptr idx) val mem) + // cond: canMergeSym(sym1, sym2) + // result: (MOVQstoreidx8 [addOff(off1, off2)] {mergeSym(sym1,sym2)} ptr idx val mem) + { + off1 := v.AuxInt + sym1 := v.Aux + if v.Args[0].Op != OpAMD64LEAQ8 { + goto end442c322e6719e280b6be1c12858e49d7 + } + off2 := v.Args[0].AuxInt + sym2 := v.Args[0].Aux + ptr := v.Args[0].Args[0] + idx := v.Args[0].Args[1] + val := v.Args[1] + mem := v.Args[2] + if !(canMergeSym(sym1, sym2)) { + goto end442c322e6719e280b6be1c12858e49d7 + } + v.Op = OpAMD64MOVQstoreidx8 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = addOff(off1, off2) + v.Aux = mergeSym(sym1, sym2) + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(val) + v.AddArg(mem) + return true + } + goto end442c322e6719e280b6be1c12858e49d7 + end442c322e6719e280b6be1c12858e49d7: + ; + case OpAMD64MOVQstoreidx8: + // match: (MOVQstoreidx8 [off1] {sym} (ADDQconst [off2] ptr) idx val mem) + // cond: + // result: (MOVQstoreidx8 [addOff(off1, off2)] {sym} ptr idx val mem) + { + off1 := v.AuxInt + sym := v.Aux + if v.Args[0].Op != OpAMD64ADDQconst { + goto end50671766fdab364c1edbd2072fb8e525 + } + 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 = OpAMD64MOVQstoreidx8 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = addOff(off1, off2) + v.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(val) + v.AddArg(mem) + return true + } + goto end50671766fdab364c1edbd2072fb8e525 + end50671766fdab364c1edbd2072fb8e525: + ; + case OpAMD64MOVSDload: + // match: (MOVSDload [off1] {sym} (ADDQconst [off2] ptr) mem) + // cond: + // result: (MOVSDload [addOff(off1, off2)] {sym} ptr mem) + { + off1 := v.AuxInt + sym := v.Aux + if v.Args[0].Op != OpAMD64ADDQconst { + goto end6dad9bf78e7368bb095eb2dfba7e244a + } + 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.Aux = sym + v.AddArg(ptr) + v.AddArg(mem) + return true + } + goto end6dad9bf78e7368bb095eb2dfba7e244a + end6dad9bf78e7368bb095eb2dfba7e244a: + ; + // match: (MOVSDload [off1] {sym1} (LEAQ [off2] {sym2} base) mem) + // cond: canMergeSym(sym1, sym2) + // result: (MOVSDload [addOff(off1,off2)] {mergeSym(sym1,sym2)} base mem) + { + off1 := v.AuxInt + sym1 := v.Aux + if v.Args[0].Op != OpAMD64LEAQ { + goto end96fa9c439e31050aa91582bc2a9f2c20 + } + 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 end96fa9c439e31050aa91582bc2a9f2c20 + } + 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 end96fa9c439e31050aa91582bc2a9f2c20 + end96fa9c439e31050aa91582bc2a9f2c20: + ; + // match: (MOVSDload [off1] {sym1} (LEAQ8 [off2] {sym2} ptr idx) mem) + // cond: canMergeSym(sym1, sym2) + // result: (MOVSDloadidx8 [addOff(off1, off2)] {mergeSym(sym1,sym2)} ptr idx mem) + { + off1 := v.AuxInt + sym1 := v.Aux + if v.Args[0].Op != OpAMD64LEAQ8 { + goto endbcb2ce441824d0e3a4b501018cfa7f60 + } + off2 := v.Args[0].AuxInt + sym2 := v.Args[0].Aux + ptr := v.Args[0].Args[0] + idx := v.Args[0].Args[1] + mem := v.Args[1] + if !(canMergeSym(sym1, sym2)) { + goto endbcb2ce441824d0e3a4b501018cfa7f60 + } + v.Op = OpAMD64MOVSDloadidx8 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = addOff(off1, off2) + v.Aux = mergeSym(sym1, sym2) + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + goto endbcb2ce441824d0e3a4b501018cfa7f60 + endbcb2ce441824d0e3a4b501018cfa7f60: + ; + case OpAMD64MOVSDloadidx8: + // match: (MOVSDloadidx8 [off1] {sym} (ADDQconst [off2] {sym} ptr) idx mem) + // cond: + // result: (MOVSDloadidx8 [addOff(off1, off2)] {sym} ptr idx mem) + { + off1 := v.AuxInt + sym := v.Aux + if v.Args[0].Op != OpAMD64ADDQconst { + goto end84f0f457e271104a92343e3b1d2804c6 + } + off2 := v.Args[0].AuxInt + if v.Args[0].Aux != v.Aux { + goto end84f0f457e271104a92343e3b1d2804c6 + } + 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.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + goto end84f0f457e271104a92343e3b1d2804c6 + end84f0f457e271104a92343e3b1d2804c6: + ; + case OpAMD64MOVSDstore: + // match: (MOVSDstore [off1] {sym} (ADDQconst [off2] ptr) val mem) + // cond: + // result: (MOVSDstore [addOff(off1, off2)] {sym} ptr val mem) + { + off1 := v.AuxInt + sym := v.Aux + if v.Args[0].Op != OpAMD64ADDQconst { + goto end6c6160664143cc66e63e67b9aa43a7ef + } + 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.Aux = sym + v.AddArg(ptr) + v.AddArg(val) + v.AddArg(mem) + return true + } + goto end6c6160664143cc66e63e67b9aa43a7ef + end6c6160664143cc66e63e67b9aa43a7ef: + ; + // match: (MOVSDstore [off1] {sym1} (LEAQ [off2] {sym2} base) val mem) + // cond: canMergeSym(sym1, sym2) + // result: (MOVSDstore [addOff(off1,off2)] {mergeSym(sym1,sym2)} base val mem) + { + off1 := v.AuxInt + sym1 := v.Aux + if v.Args[0].Op != OpAMD64LEAQ { + goto end415dde14f3400bec1b2756174a5d7179 + } + 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 end415dde14f3400bec1b2756174a5d7179 + } + 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 end415dde14f3400bec1b2756174a5d7179 + end415dde14f3400bec1b2756174a5d7179: + ; + // match: (MOVSDstore [off1] {sym1} (LEAQ8 [off2] {sym2} ptr idx) val mem) + // cond: canMergeSym(sym1, sym2) + // result: (MOVSDstoreidx8 [addOff(off1, off2)] {mergeSym(sym1,sym2)} ptr idx val mem) + { + off1 := v.AuxInt + sym1 := v.Aux + if v.Args[0].Op != OpAMD64LEAQ8 { + goto end1ad6fc0c5b59610dabf7f9595a48a230 + } + off2 := v.Args[0].AuxInt + sym2 := v.Args[0].Aux + ptr := v.Args[0].Args[0] + idx := v.Args[0].Args[1] + val := v.Args[1] + mem := v.Args[2] + if !(canMergeSym(sym1, sym2)) { + goto end1ad6fc0c5b59610dabf7f9595a48a230 + } + v.Op = OpAMD64MOVSDstoreidx8 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = addOff(off1, off2) + v.Aux = mergeSym(sym1, sym2) + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(val) + v.AddArg(mem) + return true + } + goto end1ad6fc0c5b59610dabf7f9595a48a230 + end1ad6fc0c5b59610dabf7f9595a48a230: + ; + case OpAMD64MOVSDstoreidx8: + // match: (MOVSDstoreidx8 [off1] {sym} (ADDQconst [off2] {sym} ptr) idx val mem) + // cond: + // result: (MOVSDstoreidx8 [addOff(off1, off2)] {sym} ptr idx val mem) + { + off1 := v.AuxInt + sym := v.Aux + if v.Args[0].Op != OpAMD64ADDQconst { + goto endc0e28f57697cb6038d5d09eafe26c947 + } + off2 := v.Args[0].AuxInt + if v.Args[0].Aux != v.Aux { + goto endc0e28f57697cb6038d5d09eafe26c947 + } + 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.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(val) + v.AddArg(mem) + return true + } + goto endc0e28f57697cb6038d5d09eafe26c947 + endc0e28f57697cb6038d5d09eafe26c947: + ; + case OpAMD64MOVSSload: + // match: (MOVSSload [off1] {sym} (ADDQconst [off2] ptr) mem) + // cond: + // result: (MOVSSload [addOff(off1, off2)] {sym} ptr mem) + { + off1 := v.AuxInt + sym := v.Aux + if v.Args[0].Op != OpAMD64ADDQconst { + goto end96d63dbb64b0adfa944684c9e939c972 + } + 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.Aux = sym + v.AddArg(ptr) + v.AddArg(mem) + return true + } + goto end96d63dbb64b0adfa944684c9e939c972 + end96d63dbb64b0adfa944684c9e939c972: + ; + // match: (MOVSSload [off1] {sym1} (LEAQ [off2] {sym2} base) mem) + // cond: canMergeSym(sym1, sym2) + // result: (MOVSSload [addOff(off1,off2)] {mergeSym(sym1,sym2)} base mem) + { + off1 := v.AuxInt + sym1 := v.Aux + if v.Args[0].Op != OpAMD64LEAQ { + goto end15f2583bd72ad7fc077b3952634a1c85 + } + 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 end15f2583bd72ad7fc077b3952634a1c85 + } + 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 end15f2583bd72ad7fc077b3952634a1c85 + end15f2583bd72ad7fc077b3952634a1c85: + ; + // match: (MOVSSload [off1] {sym1} (LEAQ4 [off2] {sym2} ptr idx) mem) + // cond: canMergeSym(sym1, sym2) + // result: (MOVSSloadidx4 [addOff(off1, off2)] {mergeSym(sym1,sym2)} ptr idx mem) + { + off1 := v.AuxInt + sym1 := v.Aux + if v.Args[0].Op != OpAMD64LEAQ4 { + goto end49722f4a0adba31bb143601ce1d2aae0 + } + off2 := v.Args[0].AuxInt + sym2 := v.Args[0].Aux + ptr := v.Args[0].Args[0] + idx := v.Args[0].Args[1] + mem := v.Args[1] + if !(canMergeSym(sym1, sym2)) { + goto end49722f4a0adba31bb143601ce1d2aae0 + } + v.Op = OpAMD64MOVSSloadidx4 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = addOff(off1, off2) + v.Aux = mergeSym(sym1, sym2) + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + goto end49722f4a0adba31bb143601ce1d2aae0 + end49722f4a0adba31bb143601ce1d2aae0: + ; + case OpAMD64MOVSSloadidx4: + // match: (MOVSSloadidx4 [off1] {sym} (ADDQconst [off2] {sym} ptr) idx mem) + // cond: + // result: (MOVSSloadidx4 [addOff(off1, off2)] {sym} ptr idx mem) + { + off1 := v.AuxInt + sym := v.Aux + if v.Args[0].Op != OpAMD64ADDQconst { + goto end7eb5a1ab1e2508683d879ec25286754b + } + off2 := v.Args[0].AuxInt + if v.Args[0].Aux != v.Aux { + goto end7eb5a1ab1e2508683d879ec25286754b + } + 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.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(mem) + return true + } + goto end7eb5a1ab1e2508683d879ec25286754b + end7eb5a1ab1e2508683d879ec25286754b: + ; + case OpAMD64MOVSSstore: + // match: (MOVSSstore [off1] {sym} (ADDQconst [off2] ptr) val mem) + // cond: + // result: (MOVSSstore [addOff(off1, off2)] {sym} ptr val mem) + { + off1 := v.AuxInt + sym := v.Aux + if v.Args[0].Op != OpAMD64ADDQconst { + goto endf711aa4081a9b2924b55387d4f70cfd6 + } + 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.Aux = sym + v.AddArg(ptr) + v.AddArg(val) + v.AddArg(mem) + return true + } + goto endf711aa4081a9b2924b55387d4f70cfd6 + endf711aa4081a9b2924b55387d4f70cfd6: + ; + // match: (MOVSSstore [off1] {sym1} (LEAQ [off2] {sym2} base) val mem) + // cond: canMergeSym(sym1, sym2) + // result: (MOVSSstore [addOff(off1,off2)] {mergeSym(sym1,sym2)} base val mem) + { + off1 := v.AuxInt + sym1 := v.Aux + if v.Args[0].Op != OpAMD64LEAQ { + goto end70ebc170131920e515e3f416a6b952c5 + } + 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 end70ebc170131920e515e3f416a6b952c5 + } + 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 end70ebc170131920e515e3f416a6b952c5 + end70ebc170131920e515e3f416a6b952c5: + ; + // match: (MOVSSstore [off1] {sym1} (LEAQ4 [off2] {sym2} ptr idx) val mem) + // cond: canMergeSym(sym1, sym2) + // result: (MOVSSstoreidx4 [addOff(off1, off2)] {mergeSym(sym1,sym2)} ptr idx val mem) + { + off1 := v.AuxInt + sym1 := v.Aux + if v.Args[0].Op != OpAMD64LEAQ4 { + goto end1622dc435e45833eda4d29d44df7cc34 + } + off2 := v.Args[0].AuxInt + sym2 := v.Args[0].Aux + ptr := v.Args[0].Args[0] + idx := v.Args[0].Args[1] + val := v.Args[1] + mem := v.Args[2] + if !(canMergeSym(sym1, sym2)) { + goto end1622dc435e45833eda4d29d44df7cc34 + } + v.Op = OpAMD64MOVSSstoreidx4 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = addOff(off1, off2) + v.Aux = mergeSym(sym1, sym2) + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(val) + v.AddArg(mem) + return true + } + goto end1622dc435e45833eda4d29d44df7cc34 + end1622dc435e45833eda4d29d44df7cc34: + ; + case OpAMD64MOVSSstoreidx4: + // match: (MOVSSstoreidx4 [off1] {sym} (ADDQconst [off2] {sym} ptr) idx val mem) + // cond: + // result: (MOVSSstoreidx4 [addOff(off1, off2)] {sym} ptr idx val mem) + { + off1 := v.AuxInt + sym := v.Aux + if v.Args[0].Op != OpAMD64ADDQconst { + goto end66e4853026306cd46f414c22d281254f + } + off2 := v.Args[0].AuxInt + if v.Args[0].Aux != v.Aux { + goto end66e4853026306cd46f414c22d281254f + } + 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.Aux = sym + v.AddArg(ptr) + v.AddArg(idx) + v.AddArg(val) + v.AddArg(mem) + return true + } + goto end66e4853026306cd46f414c22d281254f + end66e4853026306cd46f414c22d281254f: + ; + case OpAMD64MOVWload: + // match: (MOVWload [off1] {sym} (ADDQconst [off2] ptr) mem) + // cond: + // result: (MOVWload [addOff(off1, off2)] {sym} ptr mem) + { + off1 := v.AuxInt + sym := v.Aux + if v.Args[0].Op != OpAMD64ADDQconst { + goto endfcb0ce76f96e8b0c2eb19a9b827c1b73 + } + off2 := v.Args[0].AuxInt + ptr := v.Args[0].Args[0] + mem := v.Args[1] + v.Op = OpAMD64MOVWload + 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 endfcb0ce76f96e8b0c2eb19a9b827c1b73 + endfcb0ce76f96e8b0c2eb19a9b827c1b73: + ; + // match: (MOVWload [off1] {sym1} (LEAQ [off2] {sym2} base) mem) + // cond: canMergeSym(sym1, sym2) + // result: (MOVWload [addOff(off1,off2)] {mergeSym(sym1,sym2)} base mem) + { + off1 := v.AuxInt + sym1 := v.Aux + if v.Args[0].Op != OpAMD64LEAQ { + goto end7a79314cb49bf53d79c38c3077d87457 + } + 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 end7a79314cb49bf53d79c38c3077d87457 + } + v.Op = OpAMD64MOVWload + 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 end7a79314cb49bf53d79c38c3077d87457 + end7a79314cb49bf53d79c38c3077d87457: + ; + case OpAMD64MOVWstore: + // match: (MOVWstore [off] {sym} ptr (MOVWQSX x) mem) + // cond: + // result: (MOVWstore [off] {sym} ptr x mem) + { + off := v.AuxInt + sym := v.Aux + ptr := v.Args[0] + if v.Args[1].Op != OpAMD64MOVWQSX { + goto endca90c534e75c7f5cb803504d119a853f + } + x := v.Args[1].Args[0] + mem := v.Args[2] + v.Op = OpAMD64MOVWstore + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = off + v.Aux = sym + v.AddArg(ptr) + v.AddArg(x) + v.AddArg(mem) + return true + } + goto endca90c534e75c7f5cb803504d119a853f + endca90c534e75c7f5cb803504d119a853f: + ; + // match: (MOVWstore [off] {sym} ptr (MOVWQZX x) mem) + // cond: + // result: (MOVWstore [off] {sym} ptr x mem) + { + off := v.AuxInt + sym := v.Aux + ptr := v.Args[0] + if v.Args[1].Op != OpAMD64MOVWQZX { + goto end187fe73dfaf9cf5f4c349283b4dfd9d1 + } + x := v.Args[1].Args[0] + mem := v.Args[2] + v.Op = OpAMD64MOVWstore + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = off + v.Aux = sym + v.AddArg(ptr) + v.AddArg(x) + v.AddArg(mem) + return true + } + goto end187fe73dfaf9cf5f4c349283b4dfd9d1 + end187fe73dfaf9cf5f4c349283b4dfd9d1: + ; + // match: (MOVWstore [off1] {sym} (ADDQconst [off2] ptr) val mem) + // cond: + // result: (MOVWstore [addOff(off1, off2)] {sym} ptr val mem) + { + off1 := v.AuxInt + sym := v.Aux + if v.Args[0].Op != OpAMD64ADDQconst { + goto endda15fdd59aa956ded0440188f38de1aa + } + off2 := v.Args[0].AuxInt + ptr := v.Args[0].Args[0] + val := v.Args[1] + mem := v.Args[2] + v.Op = OpAMD64MOVWstore + 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 endda15fdd59aa956ded0440188f38de1aa + endda15fdd59aa956ded0440188f38de1aa: + ; + // match: (MOVWstore [off1] {sym1} (LEAQ [off2] {sym2} base) val mem) + // cond: canMergeSym(sym1, sym2) + // result: (MOVWstore [addOff(off1,off2)] {mergeSym(sym1,sym2)} base val mem) + { + off1 := v.AuxInt + sym1 := v.Aux + if v.Args[0].Op != OpAMD64LEAQ { + goto end4cc466ede8e64e415c899ccac81c0f27 + } + 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 end4cc466ede8e64e415c899ccac81c0f27 + } + v.Op = OpAMD64MOVWstore + 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 end4cc466ede8e64e415c899ccac81c0f27 + end4cc466ede8e64e415c899ccac81c0f27: + ; + case OpAMD64MULB: + // match: (MULB x (MOVBconst [c])) + // cond: + // result: (MULBconst [c] x) + { + x := v.Args[0] + if v.Args[1].Op != OpAMD64MOVBconst { + goto end66c6419213ddeb52b1c53fb589a70e5f + } + c := v.Args[1].AuxInt + v.Op = OpAMD64MULBconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c + v.AddArg(x) + return true + } + goto end66c6419213ddeb52b1c53fb589a70e5f + end66c6419213ddeb52b1c53fb589a70e5f: + ; + // match: (MULB (MOVBconst [c]) x) + // cond: + // result: (MULBconst [c] x) + { + if v.Args[0].Op != OpAMD64MOVBconst { + goto end7e82c8dbbba265b78035ca7df394bb06 + } + c := v.Args[0].AuxInt + x := v.Args[1] + v.Op = OpAMD64MULBconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c + v.AddArg(x) + return true + } + goto end7e82c8dbbba265b78035ca7df394bb06 + end7e82c8dbbba265b78035ca7df394bb06: + ; + case OpAMD64MULBconst: + // match: (MULBconst [c] (MOVBconst [d])) + // cond: + // result: (MOVBconst [c*d]) + { + c := v.AuxInt + if v.Args[0].Op != OpAMD64MOVBconst { + goto endf2db9f96016085f8cb4082b4af01b2aa + } + d := v.Args[0].AuxInt + v.Op = OpAMD64MOVBconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c * d + return true + } + goto endf2db9f96016085f8cb4082b4af01b2aa + endf2db9f96016085f8cb4082b4af01b2aa: + ; + case OpAMD64MULL: + // match: (MULL x (MOVLconst [c])) + // cond: + // result: (MULLconst [c] x) + { + x := v.Args[0] + if v.Args[1].Op != OpAMD64MOVLconst { + goto end893477a261bcad6c2821b77c83075c6c + } + c := v.Args[1].AuxInt + v.Op = OpAMD64MULLconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c + v.AddArg(x) + return true + } + goto end893477a261bcad6c2821b77c83075c6c + end893477a261bcad6c2821b77c83075c6c: + ; + // match: (MULL (MOVLconst [c]) x) + // cond: + // result: (MULLconst [c] x) + { + if v.Args[0].Op != OpAMD64MOVLconst { + goto end8a0f957c528a54eecb0dbfc5d96e017a + } + c := v.Args[0].AuxInt + x := v.Args[1] + v.Op = OpAMD64MULLconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c + v.AddArg(x) + return true + } + goto end8a0f957c528a54eecb0dbfc5d96e017a + end8a0f957c528a54eecb0dbfc5d96e017a: + ; + case OpAMD64MULLconst: + // match: (MULLconst [c] (MOVLconst [d])) + // cond: + // result: (MOVLconst [c*d]) + { + c := v.AuxInt + if v.Args[0].Op != OpAMD64MOVLconst { + goto endd5732835ed1276ef8b728bcfc1289f73 + } + d := v.Args[0].AuxInt + v.Op = OpAMD64MOVLconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c * d + return true + } + goto endd5732835ed1276ef8b728bcfc1289f73 + endd5732835ed1276ef8b728bcfc1289f73: + ; + case OpAMD64MULQ: + // match: (MULQ x (MOVQconst [c])) + // cond: is32Bit(c) + // result: (MULQconst [c] x) + { + x := v.Args[0] + if v.Args[1].Op != OpAMD64MOVQconst { + goto endb38c6e3e0ddfa25ba0ef9684ac1528c0 + } + c := v.Args[1].AuxInt + if !(is32Bit(c)) { + goto endb38c6e3e0ddfa25ba0ef9684ac1528c0 + } + v.Op = OpAMD64MULQconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c + v.AddArg(x) + return true + } + goto endb38c6e3e0ddfa25ba0ef9684ac1528c0 + endb38c6e3e0ddfa25ba0ef9684ac1528c0: + ; + // match: (MULQ (MOVQconst [c]) x) + // cond: is32Bit(c) + // result: (MULQconst [c] x) + { + if v.Args[0].Op != OpAMD64MOVQconst { + 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 + v.resetArgs() + v.AuxInt = c + v.AddArg(x) + return true + } + goto end9cb4f29b0bd7141639416735dcbb3b87 + end9cb4f29b0bd7141639416735dcbb3b87: + ; + case OpAMD64MULQconst: + // match: (MULQconst [-1] x) + // cond: + // result: (NEGQ x) + { + if v.AuxInt != -1 { + goto end82501cca6b5fb121a7f8b197e55f2fec + } + x := v.Args[0] + v.Op = OpAMD64NEGQ + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto end82501cca6b5fb121a7f8b197e55f2fec + end82501cca6b5fb121a7f8b197e55f2fec: + ; + // match: (MULQconst [0] _) + // cond: + // result: (MOVQconst [0]) + { + if v.AuxInt != 0 { + goto endcb9faa068e3558ff44daaf1d47d091b5 + } + v.Op = OpAMD64MOVQconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = 0 + return true + } + goto endcb9faa068e3558ff44daaf1d47d091b5 + endcb9faa068e3558ff44daaf1d47d091b5: + ; + // match: (MULQconst [1] x) + // cond: + // result: x + { + if v.AuxInt != 1 { + goto end0b527e71db2b288b2841a1f757aa580d + } + x := v.Args[0] + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = x.Type + v.AddArg(x) + return true + } + goto end0b527e71db2b288b2841a1f757aa580d + end0b527e71db2b288b2841a1f757aa580d: + ; + // match: (MULQconst [3] x) + // cond: + // result: (LEAQ2 x x) + { + if v.AuxInt != 3 { + goto end34a86f261671b5852bec6c57155fe0da + } + x := v.Args[0] + v.Op = OpAMD64LEAQ2 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(x) + return true + } + goto end34a86f261671b5852bec6c57155fe0da + end34a86f261671b5852bec6c57155fe0da: + ; + // match: (MULQconst [5] x) + // cond: + // result: (LEAQ4 x x) + { + if v.AuxInt != 5 { + goto end534601906c45a9171a9fec3e4b82b189 + } + x := v.Args[0] + v.Op = OpAMD64LEAQ4 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(x) + return true + } + goto end534601906c45a9171a9fec3e4b82b189 + end534601906c45a9171a9fec3e4b82b189: + ; + // match: (MULQconst [9] x) + // cond: + // result: (LEAQ8 x x) + { + if v.AuxInt != 9 { + goto end48a2280b6459821289c56073b8354997 + } + x := v.Args[0] + v.Op = OpAMD64LEAQ8 + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(x) + return true + } + goto end48a2280b6459821289c56073b8354997 + end48a2280b6459821289c56073b8354997: + ; + // match: (MULQconst [c] x) + // cond: isPowerOfTwo(c) + // result: (SHLQconst [log2(c)] x) + { + c := v.AuxInt + x := v.Args[0] + if !(isPowerOfTwo(c)) { + goto end75076953dbfe022526a153eda99b39b2 + } + v.Op = OpAMD64SHLQconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = log2(c) + v.AddArg(x) + return true + } + goto end75076953dbfe022526a153eda99b39b2 + end75076953dbfe022526a153eda99b39b2: + ; + // match: (MULQconst [c] (MOVQconst [d])) + // cond: + // result: (MOVQconst [c*d]) + { + c := v.AuxInt + if v.Args[0].Op != OpAMD64MOVQconst { + goto end55c38c5c405101e610d7ba7fc702ddc0 + } + d := v.Args[0].AuxInt + v.Op = OpAMD64MOVQconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c * d + return true + } + goto end55c38c5c405101e610d7ba7fc702ddc0 + end55c38c5c405101e610d7ba7fc702ddc0: + ; + case OpAMD64MULW: + // match: (MULW x (MOVWconst [c])) + // cond: + // result: (MULWconst [c] x) + { + x := v.Args[0] + if v.Args[1].Op != OpAMD64MOVWconst { + goto end542112cc08217d4bdffc1a645d290ffb + } + c := v.Args[1].AuxInt + v.Op = OpAMD64MULWconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c + v.AddArg(x) + return true + } + goto end542112cc08217d4bdffc1a645d290ffb + end542112cc08217d4bdffc1a645d290ffb: + ; + // match: (MULW (MOVWconst [c]) x) + // cond: + // result: (MULWconst [c] x) + { + if v.Args[0].Op != OpAMD64MOVWconst { + goto endd97b4245ced2b3d27d8c555b06281de4 + } + c := v.Args[0].AuxInt + x := v.Args[1] + v.Op = OpAMD64MULWconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c + v.AddArg(x) + return true + } + goto endd97b4245ced2b3d27d8c555b06281de4 + endd97b4245ced2b3d27d8c555b06281de4: + ; + case OpAMD64MULWconst: + // match: (MULWconst [c] (MOVWconst [d])) + // cond: + // result: (MOVWconst [c*d]) + { + c := v.AuxInt + if v.Args[0].Op != OpAMD64MOVWconst { + goto end61dbc9d9e93dd6946a20a1f475b3f74b + } + d := v.Args[0].AuxInt + v.Op = OpAMD64MOVWconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c * d + return true + } + 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.AddArg(x) + v0.Type = config.fe.TypeInt16() + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpSignExt8to16, TypeInvalid) + v1.AddArg(y) + v1.Type = config.fe.TypeInt16() + v.AddArg(v1) + return true + } + goto endf959fc16e72bc6dc47ab7c9ee3778901 + endf959fc16e72bc6dc47ab7c9ee3778901: + ; + 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.AddArg(x) + v0.Type = config.fe.TypeUInt16() + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpZeroExt8to16, TypeInvalid) + v1.AddArg(y) + v1.Type = config.fe.TypeUInt16() + v.AddArg(v1) + return true + } + goto end9b3274d9dd7f1e91c75ce5e7b548fe97 + end9b3274d9dd7f1e91c75ce5e7b548fe97: + ; + case OpMove: + // match: (Move [size] dst src mem) + // cond: + // result: (REPMOVSB dst src (MOVQconst [size]) mem) + { + size := v.AuxInt + dst := v.Args[0] + src := v.Args[1] + mem := v.Args[2] + v.Op = OpAMD64REPMOVSB + 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 + v.AddArg(v0) + v.AddArg(mem) + return true + } + goto end4dd156b33beb9981378c91e46f055a56 + end4dd156b33beb9981378c91e46f055a56: + ; + case OpMul16: + // match: (Mul16 x y) + // cond: + // result: (MULW x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64MULW + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto end1addf5ea2c885aa1729b8f944859d00c + end1addf5ea2c885aa1729b8f944859d00c: + ; + case OpMul32: + // match: (Mul32 x y) + // cond: + // result: (MULL x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64MULL + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + 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: + // result: (MULQ x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64MULQ + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + 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: + // result: (MULB x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64MULB + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto endd876d6bc42a2285b801f42dadbd8757c + endd876d6bc42a2285b801f42dadbd8757c: + ; + case OpMulPtr: + // match: (MulPtr x y) + // cond: + // result: (MULQ x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64MULQ + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + 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: + // result: (MOVBconst [^c]) + { + if v.Args[0].Op != OpAMD64MOVBconst { + goto end9e383a9ceb29a9e2bf890ec6a67212a8 + } + c := v.Args[0].AuxInt + v.Op = OpAMD64MOVBconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = ^c + return true + } + goto end9e383a9ceb29a9e2bf890ec6a67212a8 + end9e383a9ceb29a9e2bf890ec6a67212a8: + ; + case OpAMD64NOTL: + // match: (NOTL (MOVLconst [c])) + // cond: + // result: (MOVLconst [^c]) + { + if v.Args[0].Op != OpAMD64MOVLconst { + goto endcc73972c088d5e652a1370a96e56502d + } + c := v.Args[0].AuxInt + v.Op = OpAMD64MOVLconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = ^c + return true + } + goto endcc73972c088d5e652a1370a96e56502d + endcc73972c088d5e652a1370a96e56502d: + ; + case OpAMD64NOTQ: + // match: (NOTQ (MOVQconst [c])) + // cond: + // result: (MOVQconst [^c]) + { + if v.Args[0].Op != OpAMD64MOVQconst { + goto endb39ddb6bf7339d46f74114baad4333b6 + } + c := v.Args[0].AuxInt + v.Op = OpAMD64MOVQconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = ^c + return true + } + goto endb39ddb6bf7339d46f74114baad4333b6 + endb39ddb6bf7339d46f74114baad4333b6: + ; + case OpAMD64NOTW: + // match: (NOTW (MOVWconst [c])) + // cond: + // result: (MOVWconst [^c]) + { + if v.Args[0].Op != OpAMD64MOVWconst { + goto end35848095ebcf894c6957ad3be5f82c43 + } + c := v.Args[0].AuxInt + v.Op = OpAMD64MOVWconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = ^c + return true + } + goto end35848095ebcf894c6957ad3be5f82c43 + end35848095ebcf894c6957ad3be5f82c43: + ; + case OpNeg16: + // match: (Neg16 x) + // cond: + // result: (NEGW x) + { + x := v.Args[0] + v.Op = OpAMD64NEGW + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto end7a8c652f4ffeb49656119af69512edb2 + end7a8c652f4ffeb49656119af69512edb2: + ; + case OpNeg32: + // match: (Neg32 x) + // cond: + // result: (NEGL x) + { + x := v.Args[0] + v.Op = OpAMD64NEGL + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto endce1f7e17fc193f6c076e47d5e401e126 + endce1f7e17fc193f6c076e47d5e401e126: + ; + case OpNeg32F: + // match: (Neg32F x) + // cond: + // result: (PXOR x (MOVSSconst [f2i(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.AuxInt = f2i(math.Copysign(0, -1)) + v.AddArg(v0) + return true + } + goto end685a5fc899e195b9091afbe2a7146051 + end685a5fc899e195b9091afbe2a7146051: + ; + case OpNeg64: + // match: (Neg64 x) + // cond: + // result: (NEGQ x) + { + x := v.Args[0] + v.Op = OpAMD64NEGQ + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto enda06c5b1718f2b96aba10bf5a5c437c6c + enda06c5b1718f2b96aba10bf5a5c437c6c: + ; + case OpNeg64F: + // match: (Neg64F x) + // cond: + // result: (PXOR x (MOVSDconst [f2i(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.AuxInt = f2i(math.Copysign(0, -1)) + v.AddArg(v0) + return true + } + goto ende85ae82b7a51e75000eb9158d584acb2 + ende85ae82b7a51e75000eb9158d584acb2: + ; + case OpNeg8: + // match: (Neg8 x) + // cond: + // result: (NEGB x) + { + x := v.Args[0] + v.Op = OpAMD64NEGB + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto end1e5f495a2ac6cdea47b1ae5ba62aa95d + end1e5f495a2ac6cdea47b1ae5ba62aa95d: + ; + case OpNeq16: + // match: (Neq16 x y) + // cond: + // result: (SETNE (CMPW x y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETNE + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64CMPW, TypeInvalid) + v0.AddArg(x) + v0.AddArg(y) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto end6413ee42d523a005cce9e3372ff2c8e9 + end6413ee42d523a005cce9e3372ff2c8e9: + ; + case OpNeq32: + // match: (Neq32 x y) + // cond: + // result: (SETNE (CMPL x y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETNE + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64CMPL, TypeInvalid) + v0.AddArg(x) + v0.AddArg(y) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto endb1a3ad499a09d8262952e6cbc47a23a8 + endb1a3ad499a09d8262952e6cbc47a23a8: + ; + 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.AddArg(x) + v0.AddArg(y) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto end2a001b2774f58aaf8c1e9efce6ae59e7 + end2a001b2774f58aaf8c1e9efce6ae59e7: + ; + case OpNeq64: + // match: (Neq64 x y) + // cond: + // result: (SETNE (CMPQ x y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETNE + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64CMPQ, TypeInvalid) + v0.AddArg(x) + v0.AddArg(y) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto end092b9159bce08d2ef7896f7d3da5a595 + end092b9159bce08d2ef7896f7d3da5a595: + ; + 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.AddArg(x) + v0.AddArg(y) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto endb9c010023c38bd2fee7800fbefc85d98 + endb9c010023c38bd2fee7800fbefc85d98: + ; + case OpNeq8: + // match: (Neq8 x y) + // cond: + // result: (SETNE (CMPB x y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETNE + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64CMPB, TypeInvalid) + v0.AddArg(x) + v0.AddArg(y) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto end89e59f45e068c89458cc4db1692bf3bb + end89e59f45e068c89458cc4db1692bf3bb: + ; + case OpNeqPtr: + // match: (NeqPtr x y) + // cond: + // result: (SETNE (CMPQ x y)) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SETNE + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64CMPQ, TypeInvalid) + v0.AddArg(x) + v0.AddArg(y) + v0.Type = TypeFlags + v.AddArg(v0) + return true + } + goto end3b8bb3b4952011d1d40f993d8717cf16 + end3b8bb3b4952011d1d40f993d8717cf16: + ; + case OpNot: + // match: (Not x) + // cond: + // result: (XORBconst [1] x) + { + x := v.Args[0] + v.Op = OpAMD64XORBconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = 1 + v.AddArg(x) + return true + } + goto end73973101aad60079c62fa64624e21db1 + end73973101aad60079c62fa64624e21db1: + ; + case OpAMD64ORB: + // match: (ORB x (MOVBconst [c])) + // cond: + // result: (ORBconst [c] x) + { + x := v.Args[0] + if v.Args[1].Op != OpAMD64MOVBconst { + goto end7b63870decde2515cb77ec4f8f76817c + } + c := v.Args[1].AuxInt + v.Op = OpAMD64ORBconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c + v.AddArg(x) + return true + } + goto end7b63870decde2515cb77ec4f8f76817c + end7b63870decde2515cb77ec4f8f76817c: + ; + // match: (ORB (MOVBconst [c]) x) + // cond: + // result: (ORBconst [c] x) + { + if v.Args[0].Op != OpAMD64MOVBconst { + goto end70b43d531e2097a4f6293f66256a642e + } + c := v.Args[0].AuxInt + x := v.Args[1] + v.Op = OpAMD64ORBconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c + v.AddArg(x) + return true + } + goto end70b43d531e2097a4f6293f66256a642e + end70b43d531e2097a4f6293f66256a642e: + ; + // match: (ORB x x) + // cond: + // result: x + { + x := v.Args[0] + if v.Args[1] != x { + goto enddca5ce800a9eca157f243cb2fdb1408a + } + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = x.Type + v.AddArg(x) + return true + } + goto enddca5ce800a9eca157f243cb2fdb1408a + enddca5ce800a9eca157f243cb2fdb1408a: + ; + case OpAMD64ORBconst: + // match: (ORBconst [c] x) + // cond: int8(c)==0 + // result: x + { + c := v.AuxInt + x := v.Args[0] + if !(int8(c) == 0) { + goto end565f78e3a843dc73943b59227b39a1b3 + } + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = x.Type + v.AddArg(x) + return true + } + goto end565f78e3a843dc73943b59227b39a1b3 + end565f78e3a843dc73943b59227b39a1b3: + ; + // match: (ORBconst [c] _) + // cond: int8(c)==-1 + // result: (MOVBconst [-1]) + { + c := v.AuxInt + if !(int8(c) == -1) { + goto end6033c7910d8cd536b31446e179e4610d + } + v.Op = OpAMD64MOVBconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = -1 + return true + } + goto end6033c7910d8cd536b31446e179e4610d + end6033c7910d8cd536b31446e179e4610d: + ; + // match: (ORBconst [c] (MOVBconst [d])) + // cond: + // result: (MOVBconst [c|d]) + { + c := v.AuxInt + if v.Args[0].Op != OpAMD64MOVBconst { + goto endbe5263f022dc10a5cf53c118937d79dd + } + d := v.Args[0].AuxInt + v.Op = OpAMD64MOVBconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c | d + return true + } + goto endbe5263f022dc10a5cf53c118937d79dd + endbe5263f022dc10a5cf53c118937d79dd: + ; + case OpAMD64ORL: + // match: (ORL x (MOVLconst [c])) + // cond: + // result: (ORLconst [c] x) + { + x := v.Args[0] + if v.Args[1].Op != OpAMD64MOVLconst { + goto end1b883e30d860b6fac14ae98462c4f61a + } + c := v.Args[1].AuxInt + v.Op = OpAMD64ORLconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c + v.AddArg(x) + return true + } + goto end1b883e30d860b6fac14ae98462c4f61a + end1b883e30d860b6fac14ae98462c4f61a: + ; + // match: (ORL (MOVLconst [c]) x) + // cond: + // result: (ORLconst [c] x) + { + if v.Args[0].Op != OpAMD64MOVLconst { + goto enda5bc49524a0cbd2241f792837d0a48a8 + } + c := v.Args[0].AuxInt + x := v.Args[1] + v.Op = OpAMD64ORLconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c + v.AddArg(x) + return true + } + goto enda5bc49524a0cbd2241f792837d0a48a8 + enda5bc49524a0cbd2241f792837d0a48a8: + ; + // match: (ORL x x) + // cond: + // result: x + { + x := v.Args[0] + if v.Args[1] != x { + goto end2dd719b68f4938777ef0d820aab93659 + } + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = x.Type + v.AddArg(x) + return true + } + goto end2dd719b68f4938777ef0d820aab93659 + end2dd719b68f4938777ef0d820aab93659: + ; + case OpAMD64ORLconst: + // match: (ORLconst [c] x) + // cond: int32(c)==0 + // result: x + { + c := v.AuxInt + x := v.Args[0] + if !(int32(c) == 0) { + goto end5b52623a724e8a7167c71289fb7192f1 + } + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = x.Type + v.AddArg(x) + return true + } + goto end5b52623a724e8a7167c71289fb7192f1 + end5b52623a724e8a7167c71289fb7192f1: + ; + // match: (ORLconst [c] _) + // cond: int32(c)==-1 + // result: (MOVLconst [-1]) + { + c := v.AuxInt + if !(int32(c) == -1) { + goto end345a8ea439ef2ef54bd84fc8a0f73e97 + } + v.Op = OpAMD64MOVLconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = -1 + return true + } + goto end345a8ea439ef2ef54bd84fc8a0f73e97 + end345a8ea439ef2ef54bd84fc8a0f73e97: + ; + // match: (ORLconst [c] (MOVLconst [d])) + // cond: + // result: (MOVLconst [c|d]) + { + c := v.AuxInt + if v.Args[0].Op != OpAMD64MOVLconst { + goto ende9ca05024248f782c88084715f81d727 + } + d := v.Args[0].AuxInt + v.Op = OpAMD64MOVLconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c | d + return true + } + goto ende9ca05024248f782c88084715f81d727 + ende9ca05024248f782c88084715f81d727: + ; + case OpAMD64ORQ: + // match: (ORQ x (MOVQconst [c])) + // cond: is32Bit(c) + // result: (ORQconst [c] x) + { + x := v.Args[0] + if v.Args[1].Op != OpAMD64MOVQconst { + goto end601f2bb3ccda102e484ff60adeaf6d26 + } + c := v.Args[1].AuxInt + if !(is32Bit(c)) { + goto end601f2bb3ccda102e484ff60adeaf6d26 + } + v.Op = OpAMD64ORQconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c + v.AddArg(x) + return true + } + goto end601f2bb3ccda102e484ff60adeaf6d26 + end601f2bb3ccda102e484ff60adeaf6d26: + ; + // match: (ORQ (MOVQconst [c]) x) + // cond: is32Bit(c) + // result: (ORQconst [c] x) + { + if v.Args[0].Op != OpAMD64MOVQconst { + goto end010afbebcd314e288509d79a16a6d5cc + } + c := v.Args[0].AuxInt + x := v.Args[1] + if !(is32Bit(c)) { + goto end010afbebcd314e288509d79a16a6d5cc + } + v.Op = OpAMD64ORQconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c + v.AddArg(x) + return true + } + goto end010afbebcd314e288509d79a16a6d5cc + end010afbebcd314e288509d79a16a6d5cc: + ; + // match: (ORQ x x) + // cond: + // result: x + { + x := v.Args[0] + if v.Args[1] != x { + goto end47a27d30b82db576978c5a3a57b520fb + } + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = x.Type + v.AddArg(x) + return true + } + goto end47a27d30b82db576978c5a3a57b520fb + end47a27d30b82db576978c5a3a57b520fb: + ; + case OpAMD64ORQconst: + // match: (ORQconst [0] x) + // cond: + // result: x + { + if v.AuxInt != 0 { + goto end44534da6b9ce98d33fad7e20f0be1fbd + } + x := v.Args[0] + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = x.Type + v.AddArg(x) + return true + } + goto end44534da6b9ce98d33fad7e20f0be1fbd + end44534da6b9ce98d33fad7e20f0be1fbd: + ; + // match: (ORQconst [-1] _) + // cond: + // result: (MOVQconst [-1]) + { + if v.AuxInt != -1 { + goto endcde9b9d7c4527eaa5d50b252f50b43c1 + } + v.Op = OpAMD64MOVQconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = -1 + return true + } + goto endcde9b9d7c4527eaa5d50b252f50b43c1 + endcde9b9d7c4527eaa5d50b252f50b43c1: + ; + // match: (ORQconst [c] (MOVQconst [d])) + // cond: + // result: (MOVQconst [c|d]) + { + c := v.AuxInt + if v.Args[0].Op != OpAMD64MOVQconst { + goto enda2488509b71db9abcb06a5115c4ddc2c + } + d := v.Args[0].AuxInt + v.Op = OpAMD64MOVQconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c | d + return true + } + goto enda2488509b71db9abcb06a5115c4ddc2c + enda2488509b71db9abcb06a5115c4ddc2c: + ; + case OpAMD64ORW: + // match: (ORW x (MOVWconst [c])) + // cond: + // result: (ORWconst [c] x) + { + x := v.Args[0] + if v.Args[1].Op != OpAMD64MOVWconst { + goto end9f98df10892dbf170b49aace86ee0d7f + } + c := v.Args[1].AuxInt + v.Op = OpAMD64ORWconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c + v.AddArg(x) + return true + } + goto end9f98df10892dbf170b49aace86ee0d7f + end9f98df10892dbf170b49aace86ee0d7f: + ; + // match: (ORW (MOVWconst [c]) x) + // cond: + // result: (ORWconst [c] x) + { + if v.Args[0].Op != OpAMD64MOVWconst { + goto end96405942c9ceb5fcb0ddb85a8709d015 + } + c := v.Args[0].AuxInt + x := v.Args[1] + v.Op = OpAMD64ORWconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c + v.AddArg(x) + return true + } + goto end96405942c9ceb5fcb0ddb85a8709d015 + end96405942c9ceb5fcb0ddb85a8709d015: + ; + // match: (ORW x x) + // cond: + // result: x + { + x := v.Args[0] + if v.Args[1] != x { + goto endc6a23b64e541dc9cfc6a90fd7028e8c1 + } + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = x.Type + v.AddArg(x) + return true + } + goto endc6a23b64e541dc9cfc6a90fd7028e8c1 + endc6a23b64e541dc9cfc6a90fd7028e8c1: + ; + case OpAMD64ORWconst: + // match: (ORWconst [c] x) + // cond: int16(c)==0 + // result: x + { + c := v.AuxInt + x := v.Args[0] + if !(int16(c) == 0) { + goto endbbbdec9091c8b4c58e587eac8a43402d + } + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = x.Type + v.AddArg(x) + return true + } + goto endbbbdec9091c8b4c58e587eac8a43402d + endbbbdec9091c8b4c58e587eac8a43402d: + ; + // match: (ORWconst [c] _) + // cond: int16(c)==-1 + // result: (MOVWconst [-1]) + { + c := v.AuxInt + if !(int16(c) == -1) { + goto ended87a5775f5e04b2d2a117a63d82dd9b + } + v.Op = OpAMD64MOVWconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = -1 + return true + } + goto ended87a5775f5e04b2d2a117a63d82dd9b + ended87a5775f5e04b2d2a117a63d82dd9b: + ; + // match: (ORWconst [c] (MOVWconst [d])) + // cond: + // result: (MOVWconst [c|d]) + { + c := v.AuxInt + if v.Args[0].Op != OpAMD64MOVWconst { + goto endba9221a8462b5c62e8d7c686f64c2778 + } + d := v.Args[0].AuxInt + v.Op = OpAMD64MOVWconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c | d + return true + } + goto endba9221a8462b5c62e8d7c686f64c2778 + endba9221a8462b5c62e8d7c686f64c2778: + ; + case OpOffPtr: + // match: (OffPtr [off] ptr) + // cond: + // result: (ADDQconst [off] ptr) + { + off := v.AuxInt + ptr := v.Args[0] + v.Op = OpAMD64ADDQconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = off + v.AddArg(ptr) + return true + } + 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 OpPanicNilCheck: + // match: (PanicNilCheck ptr mem) + // cond: + // result: (LoweredPanicNilCheck ptr mem) + { + ptr := v.Args[0] + mem := v.Args[1] + v.Op = OpAMD64LoweredPanicNilCheck + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(ptr) + v.AddArg(mem) + return true + } + goto enda02b1ad5a6f929b782190145f2c8628b + enda02b1ad5a6f929b782190145f2c8628b: + ; + case OpRsh16Ux16: + // match: (Rsh16Ux16 x y) + // cond: + // result: (ANDW (SHRW x y) (SBBLcarrymask (CMPWconst [16] y))) + { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64ANDW + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64SHRW, TypeInvalid) + v0.Type = t + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpAMD64SBBLcarrymask, TypeInvalid) + v1.Type = t + v2 := b.NewValue0(v.Line, OpAMD64CMPWconst, TypeInvalid) + v2.AuxInt = 16 + v2.AddArg(y) + v2.Type = TypeFlags + v1.AddArg(v2) + v.AddArg(v1) + return true + } + goto end4d5e000764dcea396f2d86472c2af6eb + end4d5e000764dcea396f2d86472c2af6eb: + ; + case OpRsh16Ux32: + // match: (Rsh16Ux32 x y) + // cond: + // result: (ANDW (SHRW x y) (SBBLcarrymask (CMPLconst [16] y))) + { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64ANDW + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64SHRW, TypeInvalid) + v0.Type = t + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpAMD64SBBLcarrymask, TypeInvalid) + v1.Type = t + v2 := b.NewValue0(v.Line, OpAMD64CMPLconst, TypeInvalid) + v2.AuxInt = 16 + v2.AddArg(y) + v2.Type = TypeFlags + v1.AddArg(v2) + v.AddArg(v1) + return true + } + goto end9ef4fe2ea4565865cd4b3aa9c7596c00 + end9ef4fe2ea4565865cd4b3aa9c7596c00: + ; + case OpRsh16Ux64: + // match: (Rsh16Ux64 x y) + // cond: + // result: (ANDW (SHRW x y) (SBBLcarrymask (CMPQconst [16] y))) + { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64ANDW + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64SHRW, TypeInvalid) + v0.Type = t + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpAMD64SBBLcarrymask, TypeInvalid) + v1.Type = t + v2 := b.NewValue0(v.Line, OpAMD64CMPQconst, TypeInvalid) + v2.AuxInt = 16 + v2.AddArg(y) + v2.Type = TypeFlags + v1.AddArg(v2) + v.AddArg(v1) + return true + } + goto end48bc94b9a68aad454eaabc42b2e1d646 + end48bc94b9a68aad454eaabc42b2e1d646: + ; + case OpRsh16Ux8: + // match: (Rsh16Ux8 x y) + // cond: + // result: (ANDW (SHRW x y) (SBBLcarrymask (CMPBconst [16] y))) + { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64ANDW + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64SHRW, TypeInvalid) + v0.Type = t + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpAMD64SBBLcarrymask, TypeInvalid) + v1.Type = t + v2 := b.NewValue0(v.Line, OpAMD64CMPBconst, TypeInvalid) + v2.AuxInt = 16 + v2.AddArg(y) + v2.Type = TypeFlags + v1.AddArg(v2) + v.AddArg(v1) + return true + } + goto ende98f618fa53b1f1d5d3f79781d5cb2cc + ende98f618fa53b1f1d5d3f79781d5cb2cc: + ; + case OpRsh16x16: + // match: (Rsh16x16 x y) + // cond: + // result: (SARW x (ORW y (NOTL (SBBLcarrymask (CMPWconst [16] y))))) + { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SARW + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = t + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpAMD64ORW, TypeInvalid) + v0.Type = y.Type + v0.AddArg(y) + v1 := b.NewValue0(v.Line, OpAMD64NOTL, TypeInvalid) + v1.Type = y.Type + v2 := b.NewValue0(v.Line, OpAMD64SBBLcarrymask, TypeInvalid) + v2.Type = y.Type + v3 := b.NewValue0(v.Line, OpAMD64CMPWconst, TypeInvalid) + v3.AuxInt = 16 + v3.AddArg(y) + v3.Type = TypeFlags + v2.AddArg(v3) + v1.AddArg(v2) + v0.AddArg(v1) + v.AddArg(v0) + return true + } + goto end1de548dcf8d7c7222c7a739809597526 + end1de548dcf8d7c7222c7a739809597526: + ; + case OpRsh16x32: + // match: (Rsh16x32 x y) + // cond: + // result: (SARW x (ORL y (NOTL (SBBLcarrymask (CMPLconst [16] y))))) + { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SARW + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = t + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpAMD64ORL, TypeInvalid) + v0.Type = y.Type + v0.AddArg(y) + v1 := b.NewValue0(v.Line, OpAMD64NOTL, TypeInvalid) + v1.Type = y.Type + v2 := b.NewValue0(v.Line, OpAMD64SBBLcarrymask, TypeInvalid) + v2.Type = y.Type + v3 := b.NewValue0(v.Line, OpAMD64CMPLconst, TypeInvalid) + v3.AuxInt = 16 + v3.AddArg(y) + v3.Type = TypeFlags + v2.AddArg(v3) + v1.AddArg(v2) + v0.AddArg(v1) + v.AddArg(v0) + return true + } + goto end74419e1036ea7e0c3a09d05b1eabad22 + end74419e1036ea7e0c3a09d05b1eabad22: + ; + case OpRsh16x64: + // match: (Rsh16x64 x y) + // cond: + // result: (SARW x (ORQ y (NOTQ (SBBQcarrymask (CMPQconst [16] y))))) + { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SARW + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = t + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpAMD64ORQ, TypeInvalid) + v0.Type = y.Type + v0.AddArg(y) + v1 := b.NewValue0(v.Line, OpAMD64NOTQ, TypeInvalid) + v1.Type = y.Type + v2 := b.NewValue0(v.Line, OpAMD64SBBQcarrymask, TypeInvalid) + v2.Type = y.Type + v3 := b.NewValue0(v.Line, OpAMD64CMPQconst, TypeInvalid) + v3.AuxInt = 16 + v3.AddArg(y) + v3.Type = TypeFlags + v2.AddArg(v3) + v1.AddArg(v2) + v0.AddArg(v1) + v.AddArg(v0) + return true + } + goto ende35d1c2918196fae04fca22e80936bab + ende35d1c2918196fae04fca22e80936bab: + ; + case OpRsh16x8: + // match: (Rsh16x8 x y) + // cond: + // result: (SARW x (ORB y (NOTL (SBBLcarrymask (CMPBconst [16] y))))) + { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SARW + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = t + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpAMD64ORB, TypeInvalid) + v0.Type = y.Type + v0.AddArg(y) + v1 := b.NewValue0(v.Line, OpAMD64NOTL, TypeInvalid) + v1.Type = y.Type + v2 := b.NewValue0(v.Line, OpAMD64SBBLcarrymask, TypeInvalid) + v2.Type = y.Type + v3 := b.NewValue0(v.Line, OpAMD64CMPBconst, TypeInvalid) + v3.AuxInt = 16 + v3.AddArg(y) + v3.Type = TypeFlags + v2.AddArg(v3) + v1.AddArg(v2) + v0.AddArg(v1) + v.AddArg(v0) + return true + } + goto endaa6a45afc4c6552c1a90a13160578fba + endaa6a45afc4c6552c1a90a13160578fba: + ; + case OpRsh32Ux16: + // match: (Rsh32Ux16 x y) + // cond: + // result: (ANDL (SHRL x y) (SBBLcarrymask (CMPWconst [32] y))) + { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64ANDL + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64SHRL, TypeInvalid) + v0.Type = t + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpAMD64SBBLcarrymask, TypeInvalid) + v1.Type = t + v2 := b.NewValue0(v.Line, OpAMD64CMPWconst, TypeInvalid) + v2.AuxInt = 32 + v2.AddArg(y) + v2.Type = TypeFlags + v1.AddArg(v2) + v.AddArg(v1) + return true + } + goto end74495683df77023ed619b4ecee98d94a + end74495683df77023ed619b4ecee98d94a: + ; + case OpRsh32Ux32: + // match: (Rsh32Ux32 x y) + // cond: + // result: (ANDL (SHRL x y) (SBBLcarrymask (CMPLconst [32] y))) + { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64ANDL + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64SHRL, TypeInvalid) + v0.Type = t + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpAMD64SBBLcarrymask, TypeInvalid) + v1.Type = t + v2 := b.NewValue0(v.Line, OpAMD64CMPLconst, TypeInvalid) + v2.AuxInt = 32 + v2.AddArg(y) + v2.Type = TypeFlags + v1.AddArg(v2) + v.AddArg(v1) + return true + } + goto enda7d6c92ab2d7467102db447d6b431b28 + enda7d6c92ab2d7467102db447d6b431b28: + ; + case OpRsh32Ux64: + // match: (Rsh32Ux64 x y) + // cond: + // result: (ANDL (SHRL x y) (SBBLcarrymask (CMPQconst [32] y))) + { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64ANDL + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64SHRL, TypeInvalid) + v0.Type = t + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpAMD64SBBLcarrymask, TypeInvalid) + v1.Type = t + v2 := b.NewValue0(v.Line, OpAMD64CMPQconst, TypeInvalid) + v2.AuxInt = 32 + v2.AddArg(y) + v2.Type = TypeFlags + v1.AddArg(v2) + v.AddArg(v1) + return true + } + goto end7c0829166a6219a15de2c0aa688a9bb3 + end7c0829166a6219a15de2c0aa688a9bb3: + ; + case OpRsh32Ux8: + // match: (Rsh32Ux8 x y) + // cond: + // result: (ANDL (SHRL x y) (SBBLcarrymask (CMPBconst [32] y))) + { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64ANDL + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64SHRL, TypeInvalid) + v0.Type = t + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpAMD64SBBLcarrymask, TypeInvalid) + v1.Type = t + v2 := b.NewValue0(v.Line, OpAMD64CMPBconst, TypeInvalid) + v2.AuxInt = 32 + v2.AddArg(y) + v2.Type = TypeFlags + v1.AddArg(v2) + v.AddArg(v1) + return true + } + goto end221315aa8a09c9d8d2f243bf445446ea + end221315aa8a09c9d8d2f243bf445446ea: + ; + case OpRsh32x16: + // match: (Rsh32x16 x y) + // cond: + // result: (SARL x (ORW y (NOTL (SBBLcarrymask (CMPWconst [32] y))))) + { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SARL + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = t + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpAMD64ORW, TypeInvalid) + v0.Type = y.Type + v0.AddArg(y) + v1 := b.NewValue0(v.Line, OpAMD64NOTL, TypeInvalid) + v1.Type = y.Type + v2 := b.NewValue0(v.Line, OpAMD64SBBLcarrymask, TypeInvalid) + v2.Type = y.Type + v3 := b.NewValue0(v.Line, OpAMD64CMPWconst, TypeInvalid) + v3.AuxInt = 32 + v3.AddArg(y) + v3.Type = TypeFlags + v2.AddArg(v3) + v1.AddArg(v2) + v0.AddArg(v1) + v.AddArg(v0) + return true + } + goto end521b60d91648f07fe1be359f1cdbde29 + end521b60d91648f07fe1be359f1cdbde29: + ; + case OpRsh32x32: + // match: (Rsh32x32 x y) + // cond: + // result: (SARL x (ORL y (NOTL (SBBLcarrymask (CMPLconst [32] y))))) + { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SARL + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = t + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpAMD64ORL, TypeInvalid) + v0.Type = y.Type + v0.AddArg(y) + v1 := b.NewValue0(v.Line, OpAMD64NOTL, TypeInvalid) + v1.Type = y.Type + v2 := b.NewValue0(v.Line, OpAMD64SBBLcarrymask, TypeInvalid) + v2.Type = y.Type + v3 := b.NewValue0(v.Line, OpAMD64CMPLconst, TypeInvalid) + v3.AuxInt = 32 + v3.AddArg(y) + v3.Type = TypeFlags + v2.AddArg(v3) + v1.AddArg(v2) + v0.AddArg(v1) + v.AddArg(v0) + return true + } + goto end0fc03188975afbca2139e28c38b7cd17 + end0fc03188975afbca2139e28c38b7cd17: + ; + case OpRsh32x64: + // match: (Rsh32x64 x y) + // cond: + // result: (SARL x (ORQ y (NOTQ (SBBQcarrymask (CMPQconst [32] y))))) + { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SARL + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = t + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpAMD64ORQ, TypeInvalid) + v0.Type = y.Type + v0.AddArg(y) + v1 := b.NewValue0(v.Line, OpAMD64NOTQ, TypeInvalid) + v1.Type = y.Type + v2 := b.NewValue0(v.Line, OpAMD64SBBQcarrymask, TypeInvalid) + v2.Type = y.Type + v3 := b.NewValue0(v.Line, OpAMD64CMPQconst, TypeInvalid) + v3.AuxInt = 32 + v3.AddArg(y) + v3.Type = TypeFlags + v2.AddArg(v3) + v1.AddArg(v2) + v0.AddArg(v1) + v.AddArg(v0) + return true + } + goto endf36790cc7ba330d448b403a450a7c1d4 + endf36790cc7ba330d448b403a450a7c1d4: + ; + case OpRsh32x8: + // match: (Rsh32x8 x y) + // cond: + // result: (SARL x (ORB y (NOTL (SBBLcarrymask (CMPBconst [32] y))))) + { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SARL + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = t + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpAMD64ORB, TypeInvalid) + v0.Type = y.Type + v0.AddArg(y) + v1 := b.NewValue0(v.Line, OpAMD64NOTL, TypeInvalid) + v1.Type = y.Type + v2 := b.NewValue0(v.Line, OpAMD64SBBLcarrymask, TypeInvalid) + v2.Type = y.Type + v3 := b.NewValue0(v.Line, OpAMD64CMPBconst, TypeInvalid) + v3.AuxInt = 32 + v3.AddArg(y) + v3.Type = TypeFlags + v2.AddArg(v3) + v1.AddArg(v2) + v0.AddArg(v1) + v.AddArg(v0) + return true + } + goto end1242709228488be2f2505ead8eabb871 + end1242709228488be2f2505ead8eabb871: + ; + case OpRsh64Ux16: + // match: (Rsh64Ux16 x y) + // cond: + // result: (ANDQ (SHRQ x y) (SBBQcarrymask (CMPWconst [64] y))) + { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64ANDQ + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64SHRQ, TypeInvalid) + v0.Type = t + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpAMD64SBBQcarrymask, TypeInvalid) + v1.Type = t + v2 := b.NewValue0(v.Line, OpAMD64CMPWconst, TypeInvalid) + v2.AuxInt = 64 + v2.AddArg(y) + v2.Type = TypeFlags + v1.AddArg(v2) + v.AddArg(v1) + return true + } + goto end0bc6c36a57ebaf0b90fc418f976fe210 + end0bc6c36a57ebaf0b90fc418f976fe210: + ; + case OpRsh64Ux32: + // match: (Rsh64Ux32 x y) + // cond: + // result: (ANDQ (SHRQ x y) (SBBQcarrymask (CMPLconst [64] y))) + { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64ANDQ + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64SHRQ, TypeInvalid) + v0.Type = t + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpAMD64SBBQcarrymask, TypeInvalid) + v1.Type = t + v2 := b.NewValue0(v.Line, OpAMD64CMPLconst, TypeInvalid) + v2.AuxInt = 64 + v2.AddArg(y) + v2.Type = TypeFlags + v1.AddArg(v2) + v.AddArg(v1) + return true + } + goto ende3f52062f53bc3b5aa0461a644e38a1b + ende3f52062f53bc3b5aa0461a644e38a1b: + ; + case OpRsh64Ux64: + // match: (Rsh64Ux64 x y) + // cond: + // result: (ANDQ (SHRQ x y) (SBBQcarrymask (CMPQconst [64] y))) + { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64ANDQ + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64SHRQ, TypeInvalid) + v0.Type = t + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpAMD64SBBQcarrymask, TypeInvalid) + v1.Type = t + v2 := b.NewValue0(v.Line, OpAMD64CMPQconst, TypeInvalid) + v2.AuxInt = 64 + v2.AddArg(y) + v2.Type = TypeFlags + v1.AddArg(v2) + v.AddArg(v1) + return true + } + goto endaec410d0544f817303c79bad739c50fd + endaec410d0544f817303c79bad739c50fd: + ; + case OpRsh64Ux8: + // match: (Rsh64Ux8 x y) + // cond: + // result: (ANDQ (SHRQ x y) (SBBQcarrymask (CMPBconst [64] y))) + { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64ANDQ + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64SHRQ, TypeInvalid) + v0.Type = t + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpAMD64SBBQcarrymask, TypeInvalid) + v1.Type = t + v2 := b.NewValue0(v.Line, OpAMD64CMPBconst, TypeInvalid) + v2.AuxInt = 64 + v2.AddArg(y) + v2.Type = TypeFlags + v1.AddArg(v2) + v.AddArg(v1) + return true + } + goto end0318851ecb02e4ad8a2669034adf7862 + end0318851ecb02e4ad8a2669034adf7862: + ; + case OpRsh64x16: + // match: (Rsh64x16 x y) + // cond: + // result: (SARQ x (ORW y (NOTL (SBBLcarrymask (CMPWconst [64] y))))) + { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SARQ + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = t + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpAMD64ORW, TypeInvalid) + v0.Type = y.Type + v0.AddArg(y) + v1 := b.NewValue0(v.Line, OpAMD64NOTL, TypeInvalid) + v1.Type = y.Type + v2 := b.NewValue0(v.Line, OpAMD64SBBLcarrymask, TypeInvalid) + v2.Type = y.Type + v3 := b.NewValue0(v.Line, OpAMD64CMPWconst, TypeInvalid) + v3.AuxInt = 64 + v3.AddArg(y) + v3.Type = TypeFlags + v2.AddArg(v3) + v1.AddArg(v2) + v0.AddArg(v1) + v.AddArg(v0) + return true + } + goto endcf8bbca9a7a848fbebaaaa8b699cd086 + endcf8bbca9a7a848fbebaaaa8b699cd086: + ; + case OpRsh64x32: + // match: (Rsh64x32 x y) + // cond: + // result: (SARQ x (ORL y (NOTL (SBBLcarrymask (CMPLconst [64] y))))) + { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SARQ + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = t + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpAMD64ORL, TypeInvalid) + v0.Type = y.Type + v0.AddArg(y) + v1 := b.NewValue0(v.Line, OpAMD64NOTL, TypeInvalid) + v1.Type = y.Type + v2 := b.NewValue0(v.Line, OpAMD64SBBLcarrymask, TypeInvalid) + v2.Type = y.Type + v3 := b.NewValue0(v.Line, OpAMD64CMPLconst, TypeInvalid) + v3.AuxInt = 64 + v3.AddArg(y) + v3.Type = TypeFlags + v2.AddArg(v3) + v1.AddArg(v2) + v0.AddArg(v1) + v.AddArg(v0) + return true + } + goto end7604d45b06ee69bf2feddf88b2f33cb6 + end7604d45b06ee69bf2feddf88b2f33cb6: + ; + case OpRsh64x64: + // match: (Rsh64x64 x y) + // cond: + // result: (SARQ x (ORQ y (NOTQ (SBBQcarrymask (CMPQconst [64] y))))) + { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SARQ + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = t + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpAMD64ORQ, TypeInvalid) + v0.Type = y.Type + v0.AddArg(y) + v1 := b.NewValue0(v.Line, OpAMD64NOTQ, TypeInvalid) + v1.Type = y.Type + v2 := b.NewValue0(v.Line, OpAMD64SBBQcarrymask, TypeInvalid) + v2.Type = y.Type + v3 := b.NewValue0(v.Line, OpAMD64CMPQconst, TypeInvalid) + v3.AuxInt = 64 + v3.AddArg(y) + v3.Type = TypeFlags + v2.AddArg(v3) + v1.AddArg(v2) + v0.AddArg(v1) + v.AddArg(v0) + return true + } + goto end12a3b44af604b515ad5530502336486f + end12a3b44af604b515ad5530502336486f: + ; + case OpRsh64x8: + // match: (Rsh64x8 x y) + // cond: + // result: (SARQ x (ORB y (NOTL (SBBLcarrymask (CMPBconst [64] y))))) + { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SARQ + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = t + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpAMD64ORB, TypeInvalid) + v0.Type = y.Type + v0.AddArg(y) + v1 := b.NewValue0(v.Line, OpAMD64NOTL, TypeInvalid) + v1.Type = y.Type + v2 := b.NewValue0(v.Line, OpAMD64SBBLcarrymask, TypeInvalid) + v2.Type = y.Type + v3 := b.NewValue0(v.Line, OpAMD64CMPBconst, TypeInvalid) + v3.AuxInt = 64 + v3.AddArg(y) + v3.Type = TypeFlags + v2.AddArg(v3) + v1.AddArg(v2) + v0.AddArg(v1) + v.AddArg(v0) + return true + } + goto end4e2a83809914aad301a2f74d3c38fbbb + end4e2a83809914aad301a2f74d3c38fbbb: + ; + case OpRsh8Ux16: + // match: (Rsh8Ux16 x y) + // cond: + // result: (ANDB (SHRB x y) (SBBLcarrymask (CMPWconst [8] y))) + { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64ANDB + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64SHRB, TypeInvalid) + v0.Type = t + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpAMD64SBBLcarrymask, TypeInvalid) + v1.Type = t + v2 := b.NewValue0(v.Line, OpAMD64CMPWconst, TypeInvalid) + v2.AuxInt = 8 + v2.AddArg(y) + v2.Type = TypeFlags + v1.AddArg(v2) + v.AddArg(v1) + return true + } + goto end724175a51b6efac60c6bb9d83d81215a + end724175a51b6efac60c6bb9d83d81215a: + ; + case OpRsh8Ux32: + // match: (Rsh8Ux32 x y) + // cond: + // result: (ANDB (SHRB x y) (SBBLcarrymask (CMPLconst [8] y))) + { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64ANDB + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64SHRB, TypeInvalid) + v0.Type = t + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpAMD64SBBLcarrymask, TypeInvalid) + v1.Type = t + v2 := b.NewValue0(v.Line, OpAMD64CMPLconst, TypeInvalid) + v2.AuxInt = 8 + v2.AddArg(y) + v2.Type = TypeFlags + v1.AddArg(v2) + v.AddArg(v1) + return true + } + goto end9d973431bed6682c1d557a535cf440ed + end9d973431bed6682c1d557a535cf440ed: + ; + case OpRsh8Ux64: + // match: (Rsh8Ux64 x y) + // cond: + // result: (ANDB (SHRB x y) (SBBLcarrymask (CMPQconst [8] y))) + { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64ANDB + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64SHRB, TypeInvalid) + v0.Type = t + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpAMD64SBBLcarrymask, TypeInvalid) + v1.Type = t + v2 := b.NewValue0(v.Line, OpAMD64CMPQconst, TypeInvalid) + v2.AuxInt = 8 + v2.AddArg(y) + v2.Type = TypeFlags + v1.AddArg(v2) + v.AddArg(v1) + return true + } + goto end9586937cdeb7946c337d46cd30cb9a11 + end9586937cdeb7946c337d46cd30cb9a11: + ; + case OpRsh8Ux8: + // match: (Rsh8Ux8 x y) + // cond: + // result: (ANDB (SHRB x y) (SBBLcarrymask (CMPBconst [8] y))) + { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64ANDB + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64SHRB, TypeInvalid) + v0.Type = t + v0.AddArg(x) + v0.AddArg(y) + v.AddArg(v0) + v1 := b.NewValue0(v.Line, OpAMD64SBBLcarrymask, TypeInvalid) + v1.Type = t + v2 := b.NewValue0(v.Line, OpAMD64CMPBconst, TypeInvalid) + v2.AuxInt = 8 + v2.AddArg(y) + v2.Type = TypeFlags + v1.AddArg(v2) + v.AddArg(v1) + return true + } + goto endc5a55ef63d86e6b8d4d366a947bf563d + endc5a55ef63d86e6b8d4d366a947bf563d: + ; + case OpRsh8x16: + // match: (Rsh8x16 x y) + // cond: + // result: (SARB x (ORW y (NOTL (SBBLcarrymask (CMPWconst [8] y))))) + { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SARB + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = t + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpAMD64ORW, TypeInvalid) + v0.Type = y.Type + v0.AddArg(y) + v1 := b.NewValue0(v.Line, OpAMD64NOTL, TypeInvalid) + v1.Type = y.Type + v2 := b.NewValue0(v.Line, OpAMD64SBBLcarrymask, TypeInvalid) + v2.Type = y.Type + v3 := b.NewValue0(v.Line, OpAMD64CMPWconst, TypeInvalid) + v3.AuxInt = 8 + v3.AddArg(y) + v3.Type = TypeFlags + v2.AddArg(v3) + v1.AddArg(v2) + v0.AddArg(v1) + v.AddArg(v0) + return true + } + goto endfa967d6583c1bb9644514c2013b919f8 + endfa967d6583c1bb9644514c2013b919f8: + ; + case OpRsh8x32: + // match: (Rsh8x32 x y) + // cond: + // result: (SARB x (ORL y (NOTL (SBBLcarrymask (CMPLconst [8] y))))) + { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SARB + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = t + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpAMD64ORL, TypeInvalid) + v0.Type = y.Type + v0.AddArg(y) + v1 := b.NewValue0(v.Line, OpAMD64NOTL, TypeInvalid) + v1.Type = y.Type + v2 := b.NewValue0(v.Line, OpAMD64SBBLcarrymask, TypeInvalid) + v2.Type = y.Type + v3 := b.NewValue0(v.Line, OpAMD64CMPLconst, TypeInvalid) + v3.AuxInt = 8 + v3.AddArg(y) + v3.Type = TypeFlags + v2.AddArg(v3) + v1.AddArg(v2) + v0.AddArg(v1) + v.AddArg(v0) + return true + } + goto ende5a630810624a1bd3677618c2cbc8619 + ende5a630810624a1bd3677618c2cbc8619: + ; + case OpRsh8x64: + // match: (Rsh8x64 x y) + // cond: + // result: (SARB x (ORQ y (NOTQ (SBBQcarrymask (CMPQconst [8] y))))) + { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SARB + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = t + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpAMD64ORQ, TypeInvalid) + v0.Type = y.Type + v0.AddArg(y) + v1 := b.NewValue0(v.Line, OpAMD64NOTQ, TypeInvalid) + v1.Type = y.Type + v2 := b.NewValue0(v.Line, OpAMD64SBBQcarrymask, TypeInvalid) + v2.Type = y.Type + v3 := b.NewValue0(v.Line, OpAMD64CMPQconst, TypeInvalid) + v3.AuxInt = 8 + v3.AddArg(y) + v3.Type = TypeFlags + v2.AddArg(v3) + v1.AddArg(v2) + v0.AddArg(v1) + v.AddArg(v0) + return true + } + goto end23c55e49d8bc44afc680b2a4eade5af6 + end23c55e49d8bc44afc680b2a4eade5af6: + ; + case OpRsh8x8: + // match: (Rsh8x8 x y) + // cond: + // result: (SARB x (ORB y (NOTL (SBBLcarrymask (CMPBconst [8] y))))) + { + t := v.Type + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SARB + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = t + v.AddArg(x) + v0 := b.NewValue0(v.Line, OpAMD64ORB, TypeInvalid) + v0.Type = y.Type + v0.AddArg(y) + v1 := b.NewValue0(v.Line, OpAMD64NOTL, TypeInvalid) + v1.Type = y.Type + v2 := b.NewValue0(v.Line, OpAMD64SBBLcarrymask, TypeInvalid) + v2.Type = y.Type + v3 := b.NewValue0(v.Line, OpAMD64CMPBconst, TypeInvalid) + v3.AuxInt = 8 + v3.AddArg(y) + v3.Type = TypeFlags + v2.AddArg(v3) + v1.AddArg(v2) + v0.AddArg(v1) + v.AddArg(v0) + return true + } + goto enddab0c33c56e2e9434b880e1718621979 + enddab0c33c56e2e9434b880e1718621979: + ; + case OpAMD64SARB: + // match: (SARB x (MOVBconst [c])) + // cond: + // result: (SARBconst [c&31] x) + { + x := v.Args[0] + if v.Args[1].Op != OpAMD64MOVBconst { + goto end3bf3d17717aa6c04462e56d1c87902ce + } + c := v.Args[1].AuxInt + v.Op = OpAMD64SARBconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c & 31 + v.AddArg(x) + return true + } + goto end3bf3d17717aa6c04462e56d1c87902ce + end3bf3d17717aa6c04462e56d1c87902ce: + ; + case OpAMD64SARBconst: + // match: (SARBconst [c] (MOVQconst [d])) + // cond: + // result: (MOVQconst [d>>uint64(c)]) + { + c := v.AuxInt + if v.Args[0].Op != OpAMD64MOVQconst { + goto end06e0e38775f0650ed672427d19cd8fff + } + d := v.Args[0].AuxInt + v.Op = OpAMD64MOVQconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = d >> uint64(c) + return true + } + goto end06e0e38775f0650ed672427d19cd8fff + end06e0e38775f0650ed672427d19cd8fff: + ; + case OpAMD64SARL: + // match: (SARL x (MOVLconst [c])) + // cond: + // result: (SARLconst [c&31] x) + { + x := v.Args[0] + if v.Args[1].Op != OpAMD64MOVLconst { + goto ende586a72c1b232ee0b63e37c71eeb8470 + } + c := v.Args[1].AuxInt + v.Op = OpAMD64SARLconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c & 31 + v.AddArg(x) + return true + } + goto ende586a72c1b232ee0b63e37c71eeb8470 + ende586a72c1b232ee0b63e37c71eeb8470: + ; + case OpAMD64SARLconst: + // match: (SARLconst [c] (MOVQconst [d])) + // cond: + // result: (MOVQconst [d>>uint64(c)]) + { + c := v.AuxInt + if v.Args[0].Op != OpAMD64MOVQconst { + goto end8f34dc94323303e75b7bcc8e731cf1db + } + d := v.Args[0].AuxInt + v.Op = OpAMD64MOVQconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = d >> uint64(c) + return true + } + goto end8f34dc94323303e75b7bcc8e731cf1db + end8f34dc94323303e75b7bcc8e731cf1db: + ; + case OpAMD64SARQ: + // match: (SARQ x (MOVQconst [c])) + // cond: + // result: (SARQconst [c&63] x) + { + x := v.Args[0] + if v.Args[1].Op != OpAMD64MOVQconst { + goto end25e720ab203be2745dded5550e6d8a7c + } + c := v.Args[1].AuxInt + v.Op = OpAMD64SARQconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c & 63 + v.AddArg(x) + return true + } + goto end25e720ab203be2745dded5550e6d8a7c + end25e720ab203be2745dded5550e6d8a7c: + ; + case OpAMD64SARQconst: + // match: (SARQconst [c] (MOVQconst [d])) + // cond: + // result: (MOVQconst [d>>uint64(c)]) + { + c := v.AuxInt + if v.Args[0].Op != OpAMD64MOVQconst { + goto endd949ba69a1ff71ba62c49b39c68f269e + } + d := v.Args[0].AuxInt + v.Op = OpAMD64MOVQconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = d >> uint64(c) + return true + } + goto endd949ba69a1ff71ba62c49b39c68f269e + endd949ba69a1ff71ba62c49b39c68f269e: + ; + case OpAMD64SARW: + // match: (SARW x (MOVWconst [c])) + // cond: + // result: (SARWconst [c&31] x) + { + x := v.Args[0] + if v.Args[1].Op != OpAMD64MOVWconst { + goto endc46e3f211f94238f9a0aec3c498af490 + } + c := v.Args[1].AuxInt + v.Op = OpAMD64SARWconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c & 31 + v.AddArg(x) + return true + } + goto endc46e3f211f94238f9a0aec3c498af490 + endc46e3f211f94238f9a0aec3c498af490: + ; + case OpAMD64SARWconst: + // match: (SARWconst [c] (MOVQconst [d])) + // cond: + // result: (MOVQconst [d>>uint64(c)]) + { + c := v.AuxInt + if v.Args[0].Op != OpAMD64MOVQconst { + goto endca23e80dba22ab574f843c7a4cef24ab + } + d := v.Args[0].AuxInt + v.Op = OpAMD64MOVQconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = d >> uint64(c) + return true + } + goto endca23e80dba22ab574f843c7a4cef24ab + endca23e80dba22ab574f843c7a4cef24ab: + ; + case OpAMD64SBBLcarrymask: + // match: (SBBLcarrymask (CMPQconst [c] (MOVQconst [d]))) + // cond: inBounds64(d, c) + // result: (MOVLconst [-1]) + { + if v.Args[0].Op != OpAMD64CMPQconst { + goto end490c8a7039bab41e90e564fbb8500233 + } + c := v.Args[0].AuxInt + if v.Args[0].Args[0].Op != OpAMD64MOVQconst { + goto end490c8a7039bab41e90e564fbb8500233 + } + d := v.Args[0].Args[0].AuxInt + if !(inBounds64(d, c)) { + goto end490c8a7039bab41e90e564fbb8500233 + } + v.Op = OpAMD64MOVLconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = -1 + return true + } + goto end490c8a7039bab41e90e564fbb8500233 + end490c8a7039bab41e90e564fbb8500233: + ; + // match: (SBBLcarrymask (CMPQconst [c] (MOVQconst [d]))) + // cond: !inBounds64(d, c) + // result: (MOVLconst [0]) + { + if v.Args[0].Op != OpAMD64CMPQconst { + goto end95e703eabe71d831b7a3d2f9fabe7de9 + } + c := v.Args[0].AuxInt + if v.Args[0].Args[0].Op != OpAMD64MOVQconst { + goto end95e703eabe71d831b7a3d2f9fabe7de9 + } + d := v.Args[0].Args[0].AuxInt + if !(!inBounds64(d, c)) { + goto end95e703eabe71d831b7a3d2f9fabe7de9 + } + v.Op = OpAMD64MOVLconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = 0 + return true + } + goto end95e703eabe71d831b7a3d2f9fabe7de9 + end95e703eabe71d831b7a3d2f9fabe7de9: + ; + // match: (SBBLcarrymask (CMPLconst [c] (MOVLconst [d]))) + // cond: inBounds32(d, c) + // result: (MOVLconst [-1]) + { + if v.Args[0].Op != OpAMD64CMPLconst { + goto end00c0a561340b0172c9a21f63648b86e2 + } + c := v.Args[0].AuxInt + if v.Args[0].Args[0].Op != OpAMD64MOVLconst { + goto end00c0a561340b0172c9a21f63648b86e2 + } + d := v.Args[0].Args[0].AuxInt + if !(inBounds32(d, c)) { + goto end00c0a561340b0172c9a21f63648b86e2 + } + v.Op = OpAMD64MOVLconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = -1 + return true + } + goto end00c0a561340b0172c9a21f63648b86e2 + end00c0a561340b0172c9a21f63648b86e2: + ; + // match: (SBBLcarrymask (CMPLconst [c] (MOVLconst [d]))) + // cond: !inBounds32(d, c) + // result: (MOVLconst [0]) + { + if v.Args[0].Op != OpAMD64CMPLconst { + goto enda73c8bf14f7b45dd97c6a006e317b0b8 + } + c := v.Args[0].AuxInt + if v.Args[0].Args[0].Op != OpAMD64MOVLconst { + goto enda73c8bf14f7b45dd97c6a006e317b0b8 + } + d := v.Args[0].Args[0].AuxInt + if !(!inBounds32(d, c)) { + goto enda73c8bf14f7b45dd97c6a006e317b0b8 + } + v.Op = OpAMD64MOVLconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = 0 + return true + } + goto enda73c8bf14f7b45dd97c6a006e317b0b8 + enda73c8bf14f7b45dd97c6a006e317b0b8: + ; + // match: (SBBLcarrymask (CMPWconst [c] (MOVWconst [d]))) + // cond: inBounds16(d, c) + // result: (MOVLconst [-1]) + { + if v.Args[0].Op != OpAMD64CMPWconst { + goto endb94dc44cd77f66ed3bf3742874b666fc + } + c := v.Args[0].AuxInt + if v.Args[0].Args[0].Op != OpAMD64MOVWconst { + goto endb94dc44cd77f66ed3bf3742874b666fc + } + d := v.Args[0].Args[0].AuxInt + if !(inBounds16(d, c)) { + goto endb94dc44cd77f66ed3bf3742874b666fc + } + v.Op = OpAMD64MOVLconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = -1 + return true + } + goto endb94dc44cd77f66ed3bf3742874b666fc + endb94dc44cd77f66ed3bf3742874b666fc: + ; + // match: (SBBLcarrymask (CMPWconst [c] (MOVWconst [d]))) + // cond: !inBounds16(d, c) + // result: (MOVLconst [0]) + { + if v.Args[0].Op != OpAMD64CMPWconst { + goto end7a02def6194822f7ab937d78088504d2 + } + c := v.Args[0].AuxInt + if v.Args[0].Args[0].Op != OpAMD64MOVWconst { + goto end7a02def6194822f7ab937d78088504d2 + } + d := v.Args[0].Args[0].AuxInt + if !(!inBounds16(d, c)) { + goto end7a02def6194822f7ab937d78088504d2 + } + v.Op = OpAMD64MOVLconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = 0 + return true + } + goto end7a02def6194822f7ab937d78088504d2 + end7a02def6194822f7ab937d78088504d2: + ; + // match: (SBBLcarrymask (CMPBconst [c] (MOVBconst [d]))) + // cond: inBounds8(d, c) + // result: (MOVLconst [-1]) + { + if v.Args[0].Op != OpAMD64CMPBconst { + goto end79c8e4a20761df731521e6cd956c4245 + } + c := v.Args[0].AuxInt + if v.Args[0].Args[0].Op != OpAMD64MOVBconst { + goto end79c8e4a20761df731521e6cd956c4245 + } + d := v.Args[0].Args[0].AuxInt + if !(inBounds8(d, c)) { + goto end79c8e4a20761df731521e6cd956c4245 + } + v.Op = OpAMD64MOVLconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = -1 + return true + } + goto end79c8e4a20761df731521e6cd956c4245 + end79c8e4a20761df731521e6cd956c4245: + ; + // match: (SBBLcarrymask (CMPBconst [c] (MOVBconst [d]))) + // cond: !inBounds8(d, c) + // result: (MOVLconst [0]) + { + if v.Args[0].Op != OpAMD64CMPBconst { + goto end95b5b21dd7756ae41575759a1eff2bea + } + c := v.Args[0].AuxInt + if v.Args[0].Args[0].Op != OpAMD64MOVBconst { + goto end95b5b21dd7756ae41575759a1eff2bea + } + d := v.Args[0].Args[0].AuxInt + if !(!inBounds8(d, c)) { + goto end95b5b21dd7756ae41575759a1eff2bea + } + v.Op = OpAMD64MOVLconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = 0 + return true + } + goto end95b5b21dd7756ae41575759a1eff2bea + end95b5b21dd7756ae41575759a1eff2bea: + ; + case OpAMD64SBBQcarrymask: + // match: (SBBQcarrymask (CMPQconst [c] (MOVQconst [d]))) + // cond: inBounds64(d, c) + // result: (MOVQconst [-1]) + { + if v.Args[0].Op != OpAMD64CMPQconst { + goto end0c26df98feb38f149eca12f33c15de1b + } + c := v.Args[0].AuxInt + if v.Args[0].Args[0].Op != OpAMD64MOVQconst { + goto end0c26df98feb38f149eca12f33c15de1b + } + d := v.Args[0].Args[0].AuxInt + if !(inBounds64(d, c)) { + goto end0c26df98feb38f149eca12f33c15de1b + } + v.Op = OpAMD64MOVQconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = -1 + return true + } + goto end0c26df98feb38f149eca12f33c15de1b + end0c26df98feb38f149eca12f33c15de1b: + ; + // match: (SBBQcarrymask (CMPQconst [c] (MOVQconst [d]))) + // cond: !inBounds64(d, c) + // result: (MOVQconst [0]) + { + if v.Args[0].Op != OpAMD64CMPQconst { + goto end8965aa1e1153e5ecd123bbb31a618570 + } + c := v.Args[0].AuxInt + if v.Args[0].Args[0].Op != OpAMD64MOVQconst { + goto end8965aa1e1153e5ecd123bbb31a618570 + } + d := v.Args[0].Args[0].AuxInt + if !(!inBounds64(d, c)) { + goto end8965aa1e1153e5ecd123bbb31a618570 + } + v.Op = OpAMD64MOVQconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = 0 + return true + } + goto end8965aa1e1153e5ecd123bbb31a618570 + end8965aa1e1153e5ecd123bbb31a618570: + ; + // match: (SBBQcarrymask (CMPLconst [c] (MOVLconst [d]))) + // cond: inBounds32(d, c) + // result: (MOVQconst [-1]) + { + if v.Args[0].Op != OpAMD64CMPLconst { + goto end8772ede6098981a61af0f478841d7d54 + } + c := v.Args[0].AuxInt + if v.Args[0].Args[0].Op != OpAMD64MOVLconst { + goto end8772ede6098981a61af0f478841d7d54 + } + d := v.Args[0].Args[0].AuxInt + if !(inBounds32(d, c)) { + goto end8772ede6098981a61af0f478841d7d54 + } + v.Op = OpAMD64MOVQconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = -1 + return true + } + goto end8772ede6098981a61af0f478841d7d54 + end8772ede6098981a61af0f478841d7d54: + ; + // match: (SBBQcarrymask (CMPLconst [c] (MOVLconst [d]))) + // cond: !inBounds32(d, c) + // result: (MOVQconst [0]) + { + if v.Args[0].Op != OpAMD64CMPLconst { + goto end2d535e90075ee777fc616e6b9847a384 + } + c := v.Args[0].AuxInt + if v.Args[0].Args[0].Op != OpAMD64MOVLconst { + goto end2d535e90075ee777fc616e6b9847a384 + } + d := v.Args[0].Args[0].AuxInt + if !(!inBounds32(d, c)) { + goto end2d535e90075ee777fc616e6b9847a384 + } + v.Op = OpAMD64MOVQconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = 0 + return true + } + goto end2d535e90075ee777fc616e6b9847a384 + end2d535e90075ee777fc616e6b9847a384: + ; + // match: (SBBQcarrymask (CMPWconst [c] (MOVWconst [d]))) + // cond: inBounds16(d, c) + // result: (MOVQconst [-1]) + { + if v.Args[0].Op != OpAMD64CMPWconst { + goto end3103c51e14b4fc894b4170f16f37eebc + } + c := v.Args[0].AuxInt + if v.Args[0].Args[0].Op != OpAMD64MOVWconst { + goto end3103c51e14b4fc894b4170f16f37eebc + } + d := v.Args[0].Args[0].AuxInt + if !(inBounds16(d, c)) { + goto end3103c51e14b4fc894b4170f16f37eebc + } + v.Op = OpAMD64MOVQconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = -1 + return true + } + goto end3103c51e14b4fc894b4170f16f37eebc + end3103c51e14b4fc894b4170f16f37eebc: + ; + // match: (SBBQcarrymask (CMPWconst [c] (MOVWconst [d]))) + // cond: !inBounds16(d, c) + // result: (MOVQconst [0]) + { + if v.Args[0].Op != OpAMD64CMPWconst { + goto enddae2191a59cfef5efb04ebab9354745c + } + c := v.Args[0].AuxInt + if v.Args[0].Args[0].Op != OpAMD64MOVWconst { + goto enddae2191a59cfef5efb04ebab9354745c + } + d := v.Args[0].Args[0].AuxInt + if !(!inBounds16(d, c)) { + goto enddae2191a59cfef5efb04ebab9354745c + } + v.Op = OpAMD64MOVQconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = 0 + return true + } + goto enddae2191a59cfef5efb04ebab9354745c + enddae2191a59cfef5efb04ebab9354745c: + ; + // match: (SBBQcarrymask (CMPBconst [c] (MOVBconst [d]))) + // cond: inBounds8(d, c) + // result: (MOVQconst [-1]) + { + if v.Args[0].Op != OpAMD64CMPBconst { + goto end72e088325ca005b0251b1ee82da3c5d9 + } + c := v.Args[0].AuxInt + if v.Args[0].Args[0].Op != OpAMD64MOVBconst { + goto end72e088325ca005b0251b1ee82da3c5d9 + } + d := v.Args[0].Args[0].AuxInt + if !(inBounds8(d, c)) { + goto end72e088325ca005b0251b1ee82da3c5d9 + } + v.Op = OpAMD64MOVQconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = -1 + return true + } + goto end72e088325ca005b0251b1ee82da3c5d9 + end72e088325ca005b0251b1ee82da3c5d9: + ; + // match: (SBBQcarrymask (CMPBconst [c] (MOVBconst [d]))) + // cond: !inBounds8(d, c) + // result: (MOVQconst [0]) + { + if v.Args[0].Op != OpAMD64CMPBconst { + goto endcb388100f5b933aa94095096d2bb425e + } + c := v.Args[0].AuxInt + if v.Args[0].Args[0].Op != OpAMD64MOVBconst { + goto endcb388100f5b933aa94095096d2bb425e + } + d := v.Args[0].Args[0].AuxInt + if !(!inBounds8(d, c)) { + goto endcb388100f5b933aa94095096d2bb425e + } + v.Op = OpAMD64MOVQconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = 0 + return true + } + goto endcb388100f5b933aa94095096d2bb425e + endcb388100f5b933aa94095096d2bb425e: + ; + case OpAMD64SETA: + // match: (SETA (InvertFlags x)) + // cond: + // result: (SETB x) + { + if v.Args[0].Op != OpAMD64InvertFlags { + goto enda4ac36e94fc279d762b5a6c7c6cc665d + } + x := v.Args[0].Args[0] + v.Op = OpAMD64SETB + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto enda4ac36e94fc279d762b5a6c7c6cc665d + enda4ac36e94fc279d762b5a6c7c6cc665d: + ; + case OpAMD64SETAE: + // match: (SETAE (InvertFlags x)) + // cond: + // result: (SETBE x) + { + if v.Args[0].Op != OpAMD64InvertFlags { + goto end0468f5be6caf682fdea6b91d6648991e + } + x := v.Args[0].Args[0] + v.Op = OpAMD64SETBE + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto end0468f5be6caf682fdea6b91d6648991e + end0468f5be6caf682fdea6b91d6648991e: + ; + case OpAMD64SETB: + // match: (SETB (InvertFlags x)) + // cond: + // result: (SETA x) + { + if v.Args[0].Op != OpAMD64InvertFlags { + goto endc9eba7aa1e54a228570d2f5cc96f3565 + } + x := v.Args[0].Args[0] + v.Op = OpAMD64SETA + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto endc9eba7aa1e54a228570d2f5cc96f3565 + endc9eba7aa1e54a228570d2f5cc96f3565: + ; + case OpAMD64SETBE: + // match: (SETBE (InvertFlags x)) + // cond: + // result: (SETAE x) + { + if v.Args[0].Op != OpAMD64InvertFlags { + goto end9d9031643469798b14b8cad1f5a7a1ba + } + x := v.Args[0].Args[0] + v.Op = OpAMD64SETAE + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto end9d9031643469798b14b8cad1f5a7a1ba + end9d9031643469798b14b8cad1f5a7a1ba: + ; + case OpAMD64SETEQ: + // match: (SETEQ (InvertFlags x)) + // cond: + // result: (SETEQ x) + { + if v.Args[0].Op != OpAMD64InvertFlags { + goto end5d2039c9368d8c0cfba23b5a85b459e1 + } + x := v.Args[0].Args[0] + v.Op = OpAMD64SETEQ + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto end5d2039c9368d8c0cfba23b5a85b459e1 + end5d2039c9368d8c0cfba23b5a85b459e1: + ; + case OpAMD64SETG: + // match: (SETG (InvertFlags x)) + // cond: + // result: (SETL x) + { + if v.Args[0].Op != OpAMD64InvertFlags { + goto endf7586738694c9cd0b74ae28bbadb649f + } + x := v.Args[0].Args[0] + v.Op = OpAMD64SETL + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto endf7586738694c9cd0b74ae28bbadb649f + endf7586738694c9cd0b74ae28bbadb649f: + ; + case OpAMD64SETGE: + // match: (SETGE (InvertFlags x)) + // cond: + // result: (SETLE x) + { + if v.Args[0].Op != OpAMD64InvertFlags { + goto end82c11eff6f842159f564f2dad3d2eedc + } + x := v.Args[0].Args[0] + v.Op = OpAMD64SETLE + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto end82c11eff6f842159f564f2dad3d2eedc + end82c11eff6f842159f564f2dad3d2eedc: + ; + case OpAMD64SETL: + // match: (SETL (InvertFlags x)) + // cond: + // result: (SETG x) + { + if v.Args[0].Op != OpAMD64InvertFlags { + goto ende33160cd86b9d4d3b77e02fb4658d5d3 + } + x := v.Args[0].Args[0] + v.Op = OpAMD64SETG + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto ende33160cd86b9d4d3b77e02fb4658d5d3 + ende33160cd86b9d4d3b77e02fb4658d5d3: + ; + case OpAMD64SETLE: + // match: (SETLE (InvertFlags x)) + // cond: + // result: (SETGE x) + { + if v.Args[0].Op != OpAMD64InvertFlags { + goto end9307d96753efbeb888d1c98a6aba7a29 + } + x := v.Args[0].Args[0] + v.Op = OpAMD64SETGE + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto end9307d96753efbeb888d1c98a6aba7a29 + end9307d96753efbeb888d1c98a6aba7a29: + ; + case OpAMD64SETNE: + // match: (SETNE (InvertFlags x)) + // cond: + // result: (SETNE x) + { + if v.Args[0].Op != OpAMD64InvertFlags { + goto endbc71811b789475308014550f638026eb + } + x := v.Args[0].Args[0] + v.Op = OpAMD64SETNE + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto endbc71811b789475308014550f638026eb + endbc71811b789475308014550f638026eb: + ; + case OpAMD64SHLB: + // match: (SHLB x (MOVBconst [c])) + // cond: + // result: (SHLBconst [c&31] x) + { + x := v.Args[0] + if v.Args[1].Op != OpAMD64MOVBconst { + goto end2d0d0111d831d8a575b5627284a6337a + } + c := v.Args[1].AuxInt + v.Op = OpAMD64SHLBconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c & 31 + v.AddArg(x) + return true + } + goto end2d0d0111d831d8a575b5627284a6337a + end2d0d0111d831d8a575b5627284a6337a: + ; + case OpAMD64SHLL: + // match: (SHLL x (MOVLconst [c])) + // cond: + // result: (SHLLconst [c&31] x) + { + x := v.Args[0] + if v.Args[1].Op != OpAMD64MOVLconst { + goto end633f9ddcfbb63374c895a5f78da75d25 + } + c := v.Args[1].AuxInt + v.Op = OpAMD64SHLLconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c & 31 + v.AddArg(x) + return true + } + goto end633f9ddcfbb63374c895a5f78da75d25 + end633f9ddcfbb63374c895a5f78da75d25: + ; + case OpAMD64SHLQ: + // match: (SHLQ x (MOVQconst [c])) + // cond: + // result: (SHLQconst [c&63] x) + { + x := v.Args[0] + if v.Args[1].Op != OpAMD64MOVQconst { + goto end4d7e3a945cacdd6b6c8c0de6f465d4ae + } + c := v.Args[1].AuxInt + v.Op = OpAMD64SHLQconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c & 63 + v.AddArg(x) + return true + } + goto end4d7e3a945cacdd6b6c8c0de6f465d4ae + end4d7e3a945cacdd6b6c8c0de6f465d4ae: + ; + case OpAMD64SHLW: + // match: (SHLW x (MOVWconst [c])) + // cond: + // result: (SHLWconst [c&31] x) + { + x := v.Args[0] + if v.Args[1].Op != OpAMD64MOVWconst { + goto endba96a52aa58d28b3357828051e0e695c + } + c := v.Args[1].AuxInt + v.Op = OpAMD64SHLWconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c & 31 + v.AddArg(x) + return true + } + goto endba96a52aa58d28b3357828051e0e695c + endba96a52aa58d28b3357828051e0e695c: + ; + case OpAMD64SHRB: + // match: (SHRB x (MOVBconst [c])) + // cond: + // result: (SHRBconst [c&31] x) + { + x := v.Args[0] + if v.Args[1].Op != OpAMD64MOVBconst { + goto enddb1cd5aaa826d43fa4f6d1b2b8795e58 + } + c := v.Args[1].AuxInt + v.Op = OpAMD64SHRBconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c & 31 + v.AddArg(x) + return true + } + goto enddb1cd5aaa826d43fa4f6d1b2b8795e58 + enddb1cd5aaa826d43fa4f6d1b2b8795e58: + ; + case OpAMD64SHRL: + // match: (SHRL x (MOVLconst [c])) + // cond: + // result: (SHRLconst [c&31] x) + { + x := v.Args[0] + if v.Args[1].Op != OpAMD64MOVLconst { + goto end344b8b9202e1925e8d0561f1c21412fc + } + c := v.Args[1].AuxInt + v.Op = OpAMD64SHRLconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c & 31 + v.AddArg(x) + return true + } + goto end344b8b9202e1925e8d0561f1c21412fc + end344b8b9202e1925e8d0561f1c21412fc: + ; + case OpAMD64SHRQ: + // match: (SHRQ x (MOVQconst [c])) + // cond: + // result: (SHRQconst [c&63] x) + { + x := v.Args[0] + if v.Args[1].Op != OpAMD64MOVQconst { + goto end699d35e2d5cfa08b8a3b1c8a183ddcf3 + } + c := v.Args[1].AuxInt + v.Op = OpAMD64SHRQconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c & 63 + v.AddArg(x) + return true + } + goto end699d35e2d5cfa08b8a3b1c8a183ddcf3 + end699d35e2d5cfa08b8a3b1c8a183ddcf3: + ; + case OpAMD64SHRW: + // match: (SHRW x (MOVWconst [c])) + // cond: + // result: (SHRWconst [c&31] x) + { + x := v.Args[0] + if v.Args[1].Op != OpAMD64MOVWconst { + goto endd75ff1f9b3e9ec9c942a39b6179da1b3 + } + c := v.Args[1].AuxInt + v.Op = OpAMD64SHRWconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c & 31 + v.AddArg(x) + return true + } + goto endd75ff1f9b3e9ec9c942a39b6179da1b3 + endd75ff1f9b3e9ec9c942a39b6179da1b3: + ; + case OpAMD64SUBB: + // match: (SUBB x (MOVBconst [c])) + // cond: + // result: (SUBBconst x [c]) + { + x := v.Args[0] + if v.Args[1].Op != OpAMD64MOVBconst { + goto end9ca5d2a70e2df1a5a3ed6786bce1f7b2 + } + c := v.Args[1].AuxInt + v.Op = OpAMD64SUBBconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AuxInt = c + return true + } + goto end9ca5d2a70e2df1a5a3ed6786bce1f7b2 + end9ca5d2a70e2df1a5a3ed6786bce1f7b2: + ; + // match: (SUBB (MOVBconst [c]) x) + // cond: + // result: (NEGB (SUBBconst x [c])) + { + if v.Args[0].Op != OpAMD64MOVBconst { + goto endc288755d69b04d24a6aac32a73956411 + } + c := v.Args[0].AuxInt + x := v.Args[1] + v.Op = OpAMD64NEGB + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64SUBBconst, TypeInvalid) + v0.Type = v.Type + v0.AddArg(x) + v0.AuxInt = c + v.AddArg(v0) + return true + } + 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: + // result: (MOVBconst [d-c]) + { + c := v.AuxInt + if v.Args[0].Op != OpAMD64MOVBconst { + goto enddc5383558e2f3eae507afcb94eada964 + } + d := v.Args[0].AuxInt + v.Op = OpAMD64MOVBconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = d - c + return true + } + goto enddc5383558e2f3eae507afcb94eada964 + enddc5383558e2f3eae507afcb94eada964: + ; + // match: (SUBBconst [c] (SUBBconst [d] x)) + // cond: + // result: (ADDBconst [-c-d] x) + { + c := v.AuxInt + if v.Args[0].Op != OpAMD64SUBBconst { + goto end035c57413a46eb347ecb3736d1510915 + } + 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 end035c57413a46eb347ecb3736d1510915 + end035c57413a46eb347ecb3736d1510915: + ; + case OpAMD64SUBL: + // match: (SUBL x (MOVLconst [c])) + // cond: + // result: (SUBLconst x [c]) + { + x := v.Args[0] + if v.Args[1].Op != OpAMD64MOVLconst { + goto end178c1d6c86f9c16f6497586c2f7d8625 + } + c := v.Args[1].AuxInt + v.Op = OpAMD64SUBLconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AuxInt = c + return true + } + goto end178c1d6c86f9c16f6497586c2f7d8625 + end178c1d6c86f9c16f6497586c2f7d8625: + ; + // match: (SUBL (MOVLconst [c]) x) + // cond: + // result: (NEGL (SUBLconst x [c])) + { + if v.Args[0].Op != OpAMD64MOVLconst { + goto endb0efe6e15ec20486b849534a00483ae2 + } + c := v.Args[0].AuxInt + x := v.Args[1] + v.Op = OpAMD64NEGL + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64SUBLconst, TypeInvalid) + v0.Type = v.Type + v0.AddArg(x) + v0.AuxInt = c + v.AddArg(v0) + return true + } + 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: + // result: (MOVLconst [d-c]) + { + c := v.AuxInt + if v.Args[0].Op != OpAMD64MOVLconst { + goto end6c5c6d58d4bdd0a5c2f7bf10b343b41e + } + d := v.Args[0].AuxInt + v.Op = OpAMD64MOVLconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = d - c + return true + } + goto end6c5c6d58d4bdd0a5c2f7bf10b343b41e + end6c5c6d58d4bdd0a5c2f7bf10b343b41e: + ; + // match: (SUBLconst [c] (SUBLconst [d] x)) + // cond: + // result: (ADDLconst [-c-d] x) + { + c := v.AuxInt + if v.Args[0].Op != OpAMD64SUBLconst { + goto end0c9ffb11e8a56ced1b14dbf6bf9a6737 + } + 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 end0c9ffb11e8a56ced1b14dbf6bf9a6737 + end0c9ffb11e8a56ced1b14dbf6bf9a6737: + ; + case OpAMD64SUBQ: + // match: (SUBQ x (MOVQconst [c])) + // cond: is32Bit(c) + // result: (SUBQconst x [c]) + { + x := v.Args[0] + if v.Args[1].Op != OpAMD64MOVQconst { + goto end9bbb7b20824a498752c605942fad89c2 + } + c := v.Args[1].AuxInt + if !(is32Bit(c)) { + goto end9bbb7b20824a498752c605942fad89c2 + } + v.Op = OpAMD64SUBQconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AuxInt = c + return true + } + goto end9bbb7b20824a498752c605942fad89c2 + end9bbb7b20824a498752c605942fad89c2: + ; + // match: (SUBQ (MOVQconst [c]) x) + // cond: is32Bit(c) + // result: (NEGQ (SUBQconst x [c])) + { + if v.Args[0].Op != OpAMD64MOVQconst { + goto end8beb96de3efee9206d1bd4b7d777d2cb + } + c := v.Args[0].AuxInt + x := v.Args[1] + if !(is32Bit(c)) { + goto end8beb96de3efee9206d1bd4b7d777d2cb + } + v.Op = OpAMD64NEGQ + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64SUBQconst, TypeInvalid) + v0.Type = v.Type + v0.AddArg(x) + v0.AuxInt = c + v.AddArg(v0) + return true + } + 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: + // result: (MOVQconst [d-c]) + { + c := v.AuxInt + if v.Args[0].Op != OpAMD64MOVQconst { + goto endb0daebe6831cf381377c3e4248070f25 + } + d := v.Args[0].AuxInt + v.Op = OpAMD64MOVQconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = d - c + return true + } + goto endb0daebe6831cf381377c3e4248070f25 + endb0daebe6831cf381377c3e4248070f25: + ; + // match: (SUBQconst [c] (SUBQconst [d] x)) + // cond: + // result: (ADDQconst [-c-d] x) + { + c := v.AuxInt + if v.Args[0].Op != OpAMD64SUBQconst { + goto end2d40ddb5ae9e90679456254c61858d9d + } + 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 end2d40ddb5ae9e90679456254c61858d9d + end2d40ddb5ae9e90679456254c61858d9d: + ; + case OpAMD64SUBW: + // match: (SUBW x (MOVWconst [c])) + // cond: + // result: (SUBWconst x [c]) + { + x := v.Args[0] + if v.Args[1].Op != OpAMD64MOVWconst { + goto end135aa9100b2f61d58b37cede37b63731 + } + c := v.Args[1].AuxInt + v.Op = OpAMD64SUBWconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AuxInt = c + return true + } + goto end135aa9100b2f61d58b37cede37b63731 + end135aa9100b2f61d58b37cede37b63731: + ; + // match: (SUBW (MOVWconst [c]) x) + // cond: + // result: (NEGW (SUBWconst x [c])) + { + if v.Args[0].Op != OpAMD64MOVWconst { + goto end44d23f7e65a4b1c42d0e6463f8e493b6 + } + c := v.Args[0].AuxInt + x := v.Args[1] + v.Op = OpAMD64NEGW + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v0 := b.NewValue0(v.Line, OpAMD64SUBWconst, TypeInvalid) + v0.Type = v.Type + v0.AddArg(x) + v0.AuxInt = c + v.AddArg(v0) + return true + } + 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: + // result: (MOVWconst [d-c]) + { + c := v.AuxInt + if v.Args[0].Op != OpAMD64MOVWconst { + goto endae629a229c399eaed7dbb95b1b0e6f8a + } + d := v.Args[0].AuxInt + v.Op = OpAMD64MOVWconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = d - c + return true + } + goto endae629a229c399eaed7dbb95b1b0e6f8a + endae629a229c399eaed7dbb95b1b0e6f8a: + ; + // match: (SUBWconst [c] (SUBWconst [d] x)) + // cond: + // result: (ADDWconst [-c-d] x) + { + c := v.AuxInt + if v.Args[0].Op != OpAMD64SUBWconst { + goto enda59f08d12aa08717b0443b7bb1b71374 + } + 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 enda59f08d12aa08717b0443b7bb1b71374 + enda59f08d12aa08717b0443b7bb1b71374: + ; + case OpSignExt16to32: + // match: (SignExt16to32 x) + // cond: + // result: (MOVWQSX x) + { + x := v.Args[0] + v.Op = OpAMD64MOVWQSX + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto end21e4271c2b48a5aa3561ccfa8fa67cd9 + end21e4271c2b48a5aa3561ccfa8fa67cd9: + ; + case OpSignExt16to64: + // match: (SignExt16to64 x) + // cond: + // result: (MOVWQSX x) + { + x := v.Args[0] + v.Op = OpAMD64MOVWQSX + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto endc6d242ee3a3e195ef0f9e8dae47ada75 + endc6d242ee3a3e195ef0f9e8dae47ada75: + ; + case OpSignExt32to64: + // match: (SignExt32to64 x) + // cond: + // result: (MOVLQSX x) + { + x := v.Args[0] + v.Op = OpAMD64MOVLQSX + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto endb9f1a8b2d01eee44964a71a01bca165c + endb9f1a8b2d01eee44964a71a01bca165c: + ; + case OpSignExt8to16: + // match: (SignExt8to16 x) + // cond: + // result: (MOVBQSX x) + { + x := v.Args[0] + v.Op = OpAMD64MOVBQSX + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto end372869f08e147404b80634e5f83fd506 + end372869f08e147404b80634e5f83fd506: + ; + case OpSignExt8to32: + // match: (SignExt8to32 x) + // cond: + // result: (MOVBQSX x) + { + x := v.Args[0] + v.Op = OpAMD64MOVBQSX + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto end913e3575e5b4cf7f60585c108db40464 + end913e3575e5b4cf7f60585c108db40464: + ; + case OpSignExt8to64: + // match: (SignExt8to64 x) + // cond: + // result: (MOVBQSX x) + { + x := v.Args[0] + v.Op = OpAMD64MOVBQSX + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto endcef6d6001d3f25cf5dacee11a46e5c8c + endcef6d6001d3f25cf5dacee11a46e5c8c: + ; + case OpSqrt: + // match: (Sqrt x) + // cond: + // result: (SQRTSD x) + { + x := v.Args[0] + v.Op = OpAMD64SQRTSD + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto end72f79ca9ec139e15856aaa03338cf543 + end72f79ca9ec139e15856aaa03338cf543: + ; + case OpStaticCall: + // match: (StaticCall [argwid] {target} mem) + // cond: + // result: (CALLstatic [argwid] {target} mem) + { + argwid := v.AuxInt + target := v.Aux + mem := v.Args[0] + v.Op = OpAMD64CALLstatic + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = argwid + v.Aux = target + v.AddArg(mem) + return true + } + goto end32c5cbec813d1c2ae94fc9b1090e4b2a + 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) + { + if v.AuxInt != 8 { + goto endd1eb7c3ea0c806e7a53ff3be86186eb7 + } + ptr := v.Args[0] + val := v.Args[1] + mem := v.Args[2] + v.Op = OpAMD64MOVQstore + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(ptr) + v.AddArg(val) + v.AddArg(mem) + return true + } + goto endd1eb7c3ea0c806e7a53ff3be86186eb7 + endd1eb7c3ea0c806e7a53ff3be86186eb7: + ; + // 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] + v.Op = OpAMD64MOVLstore + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(ptr) + v.AddArg(val) + v.AddArg(mem) + return true + } + goto end44e3b22360da76ecd59be9a8c2dd1347 + end44e3b22360da76ecd59be9a8c2dd1347: + ; + // 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] + v.Op = OpAMD64MOVWstore + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(ptr) + v.AddArg(val) + v.AddArg(mem) + return true + } + goto endd0342b7fd3d0713f3e26922660047c71 + endd0342b7fd3d0713f3e26922660047c71: + ; + // match: (Store [1] ptr val mem) + // cond: + // result: (MOVBstore ptr val mem) + { + if v.AuxInt != 1 { + goto end8e76e20031197ca875889d2b4d0eb1d1 + } + ptr := v.Args[0] + val := v.Args[1] + mem := v.Args[2] + v.Op = OpAMD64MOVBstore + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(ptr) + v.AddArg(val) + v.AddArg(mem) + return true + } + goto end8e76e20031197ca875889d2b4d0eb1d1 + end8e76e20031197ca875889d2b4d0eb1d1: + ; + case OpSub16: + // match: (Sub16 x y) + // cond: + // result: (SUBW x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SUBW + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto end54adc5de883c0460ca71c6ee464d4244 + end54adc5de883c0460ca71c6ee464d4244: + ; + case OpSub32: + // match: (Sub32 x y) + // cond: + // result: (SUBL x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SUBL + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + 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: + // 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 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: + // result: (SUBB x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64SUBB + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + 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: + // result: x + { + x := v.Args[0] + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = x.Type + v.AddArg(x) + return true + } + goto end8e2f5e0a6e3a06423c077747de6c2bdd + end8e2f5e0a6e3a06423c077747de6c2bdd: + ; + case OpTrunc32to16: + // match: (Trunc32to16 x) + // cond: + // result: x + { + x := v.Args[0] + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = x.Type + v.AddArg(x) + return true + } + goto end5bed0e3a3c1c6374d86beb5a4397708c + end5bed0e3a3c1c6374d86beb5a4397708c: + ; + case OpTrunc32to8: + // match: (Trunc32to8 x) + // cond: + // result: x + { + x := v.Args[0] + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = x.Type + v.AddArg(x) + return true + } + goto endef0b8032ce91979ce6cd0004260c04ee + endef0b8032ce91979ce6cd0004260c04ee: + ; + case OpTrunc64to16: + // match: (Trunc64to16 x) + // cond: + // result: x + { + x := v.Args[0] + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = x.Type + v.AddArg(x) + return true + } + goto endd32fd6e0ce970c212835e6f71c3dcbfd + endd32fd6e0ce970c212835e6f71c3dcbfd: + ; + case OpTrunc64to32: + // match: (Trunc64to32 x) + // cond: + // result: x + { + x := v.Args[0] + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = x.Type + v.AddArg(x) + return true + } + goto end1212c4e84153210aff7fd630fb3e1883 + end1212c4e84153210aff7fd630fb3e1883: + ; + case OpTrunc64to8: + // match: (Trunc64to8 x) + // cond: + // result: x + { + x := v.Args[0] + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = x.Type + v.AddArg(x) + return true + } + goto end734f017d4b2810ca2288f7037365824c + end734f017d4b2810ca2288f7037365824c: + ; + case OpAMD64XORB: + // match: (XORB x (MOVBconst [c])) + // cond: + // result: (XORBconst [c] x) + { + x := v.Args[0] + if v.Args[1].Op != OpAMD64MOVBconst { + goto enda9ed9fdd115ffdffa8127c007c34d7b7 + } + c := v.Args[1].AuxInt + v.Op = OpAMD64XORBconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c + v.AddArg(x) + return true + } + goto enda9ed9fdd115ffdffa8127c007c34d7b7 + enda9ed9fdd115ffdffa8127c007c34d7b7: + ; + // match: (XORB (MOVBconst [c]) x) + // cond: + // result: (XORBconst [c] x) + { + if v.Args[0].Op != OpAMD64MOVBconst { + goto endb02a07d9dc7b802c59f013116e952f3f + } + c := v.Args[0].AuxInt + x := v.Args[1] + v.Op = OpAMD64XORBconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c + v.AddArg(x) + return true + } + 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: + // result: (MOVBconst [c^d]) + { + c := v.AuxInt + if v.Args[0].Op != OpAMD64MOVBconst { + goto end6d8d1b612af9d253605c8bc69b822903 + } + d := v.Args[0].AuxInt + v.Op = OpAMD64MOVBconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c ^ d + return true + } + goto end6d8d1b612af9d253605c8bc69b822903 + end6d8d1b612af9d253605c8bc69b822903: + ; + case OpAMD64XORL: + // match: (XORL x (MOVLconst [c])) + // cond: + // result: (XORLconst [c] x) + { + x := v.Args[0] + if v.Args[1].Op != OpAMD64MOVLconst { + goto enda9459d509d3416da67d13a22dd074a9c + } + c := v.Args[1].AuxInt + v.Op = OpAMD64XORLconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c + v.AddArg(x) + return true + } + goto enda9459d509d3416da67d13a22dd074a9c + enda9459d509d3416da67d13a22dd074a9c: + ; + // match: (XORL (MOVLconst [c]) x) + // cond: + // result: (XORLconst [c] x) + { + if v.Args[0].Op != OpAMD64MOVLconst { + goto end9c1a0af00eeadd8aa325e55f1f3fb89c + } + c := v.Args[0].AuxInt + x := v.Args[1] + v.Op = OpAMD64XORLconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c + v.AddArg(x) + return true + } + 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: + // result: (MOVLconst [c^d]) + { + c := v.AuxInt + if v.Args[0].Op != OpAMD64MOVLconst { + goto end71238075b10b68a226903cc453c4715c + } + d := v.Args[0].AuxInt + v.Op = OpAMD64MOVLconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c ^ d + return true + } + goto end71238075b10b68a226903cc453c4715c + end71238075b10b68a226903cc453c4715c: + ; + case OpAMD64XORQ: + // match: (XORQ x (MOVQconst [c])) + // cond: is32Bit(c) + // result: (XORQconst [c] x) + { + x := v.Args[0] + if v.Args[1].Op != OpAMD64MOVQconst { + goto end452341f950062e0483f16438fb9ec500 + } + c := v.Args[1].AuxInt + if !(is32Bit(c)) { + goto end452341f950062e0483f16438fb9ec500 + } + v.Op = OpAMD64XORQconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c + v.AddArg(x) + return true + } + goto end452341f950062e0483f16438fb9ec500 + end452341f950062e0483f16438fb9ec500: + ; + // match: (XORQ (MOVQconst [c]) x) + // cond: is32Bit(c) + // result: (XORQconst [c] x) + { + if v.Args[0].Op != OpAMD64MOVQconst { + goto endd221a7e3daaaaa29ee385ad36e061b57 + } + c := v.Args[0].AuxInt + x := v.Args[1] + if !(is32Bit(c)) { + goto endd221a7e3daaaaa29ee385ad36e061b57 + } + v.Op = OpAMD64XORQconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c + v.AddArg(x) + return true + } + 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: + // result: (MOVQconst [c^d]) + { + c := v.AuxInt + if v.Args[0].Op != OpAMD64MOVQconst { + goto end3f404d4f07362319fbad2e1ba0827a9f + } + d := v.Args[0].AuxInt + v.Op = OpAMD64MOVQconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c ^ d + return true + } + goto end3f404d4f07362319fbad2e1ba0827a9f + end3f404d4f07362319fbad2e1ba0827a9f: + ; + case OpAMD64XORW: + // match: (XORW x (MOVWconst [c])) + // cond: + // result: (XORWconst [c] x) + { + x := v.Args[0] + if v.Args[1].Op != OpAMD64MOVWconst { + goto end2ca109efd66c221a5691a4da95ec6c67 + } + c := v.Args[1].AuxInt + v.Op = OpAMD64XORWconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c + v.AddArg(x) + return true + } + goto end2ca109efd66c221a5691a4da95ec6c67 + end2ca109efd66c221a5691a4da95ec6c67: + ; + // match: (XORW (MOVWconst [c]) x) + // cond: + // result: (XORWconst [c] x) + { + if v.Args[0].Op != OpAMD64MOVWconst { + goto end51ee62a06d4301e5a4aed7a6639b1d53 + } + c := v.Args[0].AuxInt + x := v.Args[1] + v.Op = OpAMD64XORWconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c + v.AddArg(x) + return true + } + 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: + // result: (MOVWconst [c^d]) + { + c := v.AuxInt + if v.Args[0].Op != OpAMD64MOVWconst { + goto ende24881ccdfa8486c4593fd9aa5df1ed6 + } + d := v.Args[0].AuxInt + v.Op = OpAMD64MOVWconst + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AuxInt = c ^ d + return true + } + goto ende24881ccdfa8486c4593fd9aa5df1ed6 + ende24881ccdfa8486c4593fd9aa5df1ed6: + ; + case OpXor16: + // match: (Xor16 x y) + // cond: + // result: (XORW x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64XORW + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto end20efdd5dfd5130abf818de5546a991a0 + end20efdd5dfd5130abf818de5546a991a0: + ; + case OpXor32: + // match: (Xor32 x y) + // cond: + // result: (XORL x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64XORL + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto end9da6bce98b437e2609488346116a75d8 + end9da6bce98b437e2609488346116a75d8: + ; + case OpXor64: + // match: (Xor64 x y) + // cond: + // result: (XORQ x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64XORQ + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto endc88cd189c2a6f07ecff324ed94809f8f + endc88cd189c2a6f07ecff324ed94809f8f: + ; + case OpXor8: + // match: (Xor8 x y) + // cond: + // result: (XORB x y) + { + x := v.Args[0] + y := v.Args[1] + v.Op = OpAMD64XORB + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + v.AddArg(y) + return true + } + goto end50f4434ef96916d3e65ad3cc236d1723 + end50f4434ef96916d3e65ad3cc236d1723: + ; + case OpZero: + // match: (Zero [0] _ mem) + // cond: + // result: mem + { + if v.AuxInt != 0 { + goto endc9a38a60f0322f93682daa824611272c + } + mem := v.Args[1] + v.Op = OpCopy + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.Type = mem.Type + v.AddArg(mem) + return true + } + goto endc9a38a60f0322f93682daa824611272c + endc9a38a60f0322f93682daa824611272c: + ; + // match: (Zero [1] destptr mem) + // cond: + // result: (MOVBstore destptr (MOVBconst [0]) mem) + { + if v.AuxInt != 1 { + goto endf7c8ca6a444f19e1142977e2ac42ab24 + } + destptr := v.Args[0] + mem := v.Args[1] + v.Op = OpAMD64MOVBstore + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(destptr) + v0 := b.NewValue0(v.Line, OpAMD64MOVBconst, TypeInvalid) + v0.AuxInt = 0 + v0.Type = config.fe.TypeUInt8() + v.AddArg(v0) + v.AddArg(mem) + return true + } + goto endf7c8ca6a444f19e1142977e2ac42ab24 + endf7c8ca6a444f19e1142977e2ac42ab24: + ; + // match: (Zero [2] destptr mem) + // cond: + // result: (MOVWstore destptr (MOVWconst [0]) mem) + { + if v.AuxInt != 2 { + goto end7609a67450ab21eba86f456886fc8496 + } + destptr := v.Args[0] + mem := v.Args[1] + v.Op = OpAMD64MOVWstore + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(destptr) + v0 := b.NewValue0(v.Line, OpAMD64MOVWconst, TypeInvalid) + v0.AuxInt = 0 + v0.Type = config.fe.TypeUInt16() + v.AddArg(v0) + v.AddArg(mem) + return true + } + goto end7609a67450ab21eba86f456886fc8496 + end7609a67450ab21eba86f456886fc8496: + ; + // match: (Zero [4] destptr mem) + // cond: + // result: (MOVLstore destptr (MOVLconst [0]) mem) + { + if v.AuxInt != 4 { + goto enda8e1cf1298794cc3cb79cab108e33007 + } + destptr := v.Args[0] + mem := v.Args[1] + v.Op = OpAMD64MOVLstore + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(destptr) + v0 := b.NewValue0(v.Line, OpAMD64MOVLconst, TypeInvalid) + v0.AuxInt = 0 + v0.Type = config.fe.TypeUInt32() + v.AddArg(v0) + v.AddArg(mem) + return true + } + goto enda8e1cf1298794cc3cb79cab108e33007 + enda8e1cf1298794cc3cb79cab108e33007: + ; + // match: (Zero [8] destptr mem) + // cond: + // result: (MOVQstore destptr (MOVQconst [0]) mem) + { + if v.AuxInt != 8 { + goto end1791556f0b03ea065d38a3267fbe01c6 + } + destptr := v.Args[0] + mem := v.Args[1] + v.Op = OpAMD64MOVQstore + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(destptr) + v0 := b.NewValue0(v.Line, OpAMD64MOVQconst, TypeInvalid) + v0.AuxInt = 0 + v0.Type = config.fe.TypeUInt64() + v.AddArg(v0) + v.AddArg(mem) + return true + } + goto end1791556f0b03ea065d38a3267fbe01c6 + end1791556f0b03ea065d38a3267fbe01c6: + ; + // match: (Zero [3] destptr mem) + // cond: + // result: (MOVBstore (ADDQconst [2] destptr) (MOVBconst [0]) (MOVWstore destptr (MOVWconst [0]) mem)) + { + if v.AuxInt != 3 { + goto end7f8f5c8214f8b81a73fdde78b03ce53c + } + destptr := v.Args[0] + mem := v.Args[1] + 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 + } + destptr := v.Args[0] + mem := v.Args[1] + v.Op = OpAMD64MOVBstore + 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, 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 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%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%8 != 0 && size > 8) { + goto end5efefe1d9cca07e7ad6f4832f774b938 + } + v.Op = OpZero + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + 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, OpAMD64MOVQstore, TypeInvalid) + v1.AddArg(destptr) + v2 := b.NewValue0(v.Line, OpAMD64MOVQconst, TypeInvalid) + 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) ++ // cond: size <= 1024 && size%8 == 0 && size%16 != 0 ++ // result: (Zero [size-8] (ADDQconst [8] destptr) (MOVQstore destptr (MOVQconst [0]) mem)) + { + size := v.AuxInt + destptr := v.Args[0] + mem := v.Args[1] - if !(size <= 1024 && size%8 == 0) { - goto endfae59ebc96f670276efea844c3b302ac ++ if !(size <= 1024 && size%8 == 0 && size%16 != 0) { ++ goto end240266449c3e493db1c3b38a78682ff0 ++ } ++ v.Op = OpZero ++ v.AuxInt = 0 ++ v.Aux = nil ++ v.resetArgs() ++ v.AuxInt = size - 8 ++ 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, OpAMD64MOVQstore, TypeInvalid) ++ v1.AddArg(destptr) ++ v2 := b.NewValue0(v.Line, OpAMD64MOVQconst, TypeInvalid) ++ v2.AuxInt = 0 ++ v2.Type = config.fe.TypeUInt64() ++ v1.AddArg(v2) ++ v1.AddArg(mem) ++ v1.Type = TypeMem ++ v.AddArg(v1) ++ return true ++ } ++ goto end240266449c3e493db1c3b38a78682ff0 ++ end240266449c3e493db1c3b38a78682ff0: ++ ; ++ // match: (Zero [size] destptr mem) ++ // cond: size <= 1024 && size%16 == 0 ++ // result: (DUFFZERO [duffStart(size)] (ADDQconst [duffAdj(size)] destptr) (MOVOconst [0]) mem) ++ { ++ size := v.AuxInt ++ destptr := v.Args[0] ++ mem := v.Args[1] ++ if !(size <= 1024 && size%16 == 0) { ++ goto endf508bb887eee9119069b22c23dbca138 + } + 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 := b.NewValue0(v.Line, OpAMD64MOVOconst, TypeInvalid) + v1.AuxInt = 0 - v1.Type = config.fe.TypeUInt64() ++ v1.Type = config.fe.TypeFloat64() + v.AddArg(v1) + v.AddArg(mem) + return true + } - goto endfae59ebc96f670276efea844c3b302ac - endfae59ebc96f670276efea844c3b302ac: ++ goto endf508bb887eee9119069b22c23dbca138 ++ endf508bb887eee9119069b22c23dbca138: + ; + // 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 endb9d55d4ba0e70ed918e3ac757727441b + endb9d55d4ba0e70ed918e3ac757727441b: + ; + case OpZeroExt16to32: + // match: (ZeroExt16to32 x) + // cond: + // result: (MOVWQZX x) + { + x := v.Args[0] + v.Op = OpAMD64MOVWQZX + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto endbfff79412a2cc96095069c66812844b4 + endbfff79412a2cc96095069c66812844b4: + ; + case OpZeroExt16to64: + // match: (ZeroExt16to64 x) + // cond: + // result: (MOVWQZX x) + { + x := v.Args[0] + v.Op = OpAMD64MOVWQZX + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto end7a40262c5c856101058d2bd518ed0910 + end7a40262c5c856101058d2bd518ed0910: + ; + case OpZeroExt32to64: + // match: (ZeroExt32to64 x) + // cond: + // result: (MOVLQZX x) + { + x := v.Args[0] + v.Op = OpAMD64MOVLQZX + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto enddf83bdc8cc6c5673a9ef7aca7affe45a + enddf83bdc8cc6c5673a9ef7aca7affe45a: + ; + case OpZeroExt8to16: + // match: (ZeroExt8to16 x) + // cond: + // result: (MOVBQZX x) + { + x := v.Args[0] + v.Op = OpAMD64MOVBQZX + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto endd03d53d2a585727e4107ae1a3cc55479 + endd03d53d2a585727e4107ae1a3cc55479: + ; + case OpZeroExt8to32: + // match: (ZeroExt8to32 x) + // cond: + // result: (MOVBQZX x) + { + x := v.Args[0] + v.Op = OpAMD64MOVBQZX + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto endcbd33e965b3dab14fced5ae93d8949de + endcbd33e965b3dab14fced5ae93d8949de: + ; + case OpZeroExt8to64: + // match: (ZeroExt8to64 x) + // cond: + // result: (MOVBQZX x) + { + x := v.Args[0] + v.Op = OpAMD64MOVBQZX + v.AuxInt = 0 + v.Aux = nil + v.resetArgs() + v.AddArg(x) + return true + } + goto end63ae7cc15db9d15189b2f1342604b2cb + end63ae7cc15db9d15189b2f1342604b2cb: + } + return false +} +func rewriteBlockAMD64(b *Block) bool { + switch b.Kind { + case BlockAMD64EQ: + // match: (EQ (InvertFlags cmp) yes no) + // cond: + // result: (EQ cmp yes no) + { + v := b.Control + if v.Op != OpAMD64InvertFlags { + goto end6b8e9afc73b1c4d528f31a60d2575fae + } + cmp := v.Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockAMD64EQ + b.Control = cmp + b.Succs[0] = yes + b.Succs[1] = no + return true + } + goto end6b8e9afc73b1c4d528f31a60d2575fae + end6b8e9afc73b1c4d528f31a60d2575fae: + ; + case BlockAMD64GE: + // match: (GE (InvertFlags cmp) yes no) + // cond: + // result: (LE cmp yes no) + { + v := b.Control + if v.Op != OpAMD64InvertFlags { + goto end0610f000a6988ee8310307ec2ea138f8 + } + cmp := v.Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockAMD64LE + b.Control = cmp + b.Succs[0] = yes + b.Succs[1] = no + return true + } + goto end0610f000a6988ee8310307ec2ea138f8 + end0610f000a6988ee8310307ec2ea138f8: + ; + case BlockAMD64GT: + // match: (GT (InvertFlags cmp) yes no) + // cond: + // result: (LT cmp yes no) + { + v := b.Control + if v.Op != OpAMD64InvertFlags { + goto endf60c0660b6a8aa9565c97fc87f04eb34 + } + cmp := v.Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockAMD64LT + b.Control = cmp + b.Succs[0] = yes + b.Succs[1] = no + return true + } + goto endf60c0660b6a8aa9565c97fc87f04eb34 + endf60c0660b6a8aa9565c97fc87f04eb34: + ; + case BlockIf: + // match: (If (SETL cmp) yes no) + // cond: + // result: (LT cmp yes no) + { + v := b.Control + if v.Op != OpAMD64SETL { + goto end94277282f4b83f0c035b23711a075801 + } + cmp := v.Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockAMD64LT + b.Control = cmp + b.Succs[0] = yes + b.Succs[1] = no + return true + } + goto end94277282f4b83f0c035b23711a075801 + end94277282f4b83f0c035b23711a075801: + ; + // match: (If (SETLE cmp) yes no) + // cond: + // result: (LE cmp yes no) + { + v := b.Control + if v.Op != OpAMD64SETLE { + goto enda84798dd797927b54a9a2987421b2ba2 + } + cmp := v.Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockAMD64LE + b.Control = cmp + b.Succs[0] = yes + b.Succs[1] = no + return true + } + goto enda84798dd797927b54a9a2987421b2ba2 + enda84798dd797927b54a9a2987421b2ba2: + ; + // match: (If (SETG cmp) yes no) + // cond: + // result: (GT cmp yes no) + { + v := b.Control + if v.Op != OpAMD64SETG { + goto end3434ef985979cbf394455ab5b559567c + } + cmp := v.Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockAMD64GT + b.Control = cmp + b.Succs[0] = yes + b.Succs[1] = no + return true + } + goto end3434ef985979cbf394455ab5b559567c + end3434ef985979cbf394455ab5b559567c: + ; + // match: (If (SETGE cmp) yes no) + // cond: + // result: (GE cmp yes no) + { + v := b.Control + if v.Op != OpAMD64SETGE { + goto endee147d81d8620a5e23cb92bd9f13cf8d + } + cmp := v.Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockAMD64GE + b.Control = cmp + b.Succs[0] = yes + b.Succs[1] = no + return true + } + goto endee147d81d8620a5e23cb92bd9f13cf8d + endee147d81d8620a5e23cb92bd9f13cf8d: + ; + // match: (If (SETEQ cmp) yes no) + // cond: + // result: (EQ cmp yes no) + { + v := b.Control + if v.Op != OpAMD64SETEQ { + goto ende7d85ccc850fc3963c50a91df096de17 + } + cmp := v.Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockAMD64EQ + b.Control = cmp + b.Succs[0] = yes + b.Succs[1] = no + return true + } + goto ende7d85ccc850fc3963c50a91df096de17 + ende7d85ccc850fc3963c50a91df096de17: + ; + // match: (If (SETNE cmp) yes no) + // cond: + // result: (NE cmp yes no) + { + v := b.Control + if v.Op != OpAMD64SETNE { + goto endba4b54260ecda1b5731b129c0eb493d0 + } + cmp := v.Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockAMD64NE + b.Control = cmp + b.Succs[0] = yes + b.Succs[1] = no + return true + } + goto endba4b54260ecda1b5731b129c0eb493d0 + endba4b54260ecda1b5731b129c0eb493d0: + ; + // match: (If (SETB cmp) yes no) + // cond: + // result: (ULT cmp yes no) + { + v := b.Control + if v.Op != OpAMD64SETB { + goto endf84eedfcd3f18f5c9c3f3d1045a24330 + } + cmp := v.Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockAMD64ULT + b.Control = cmp + b.Succs[0] = yes + b.Succs[1] = no + return true + } + goto endf84eedfcd3f18f5c9c3f3d1045a24330 + endf84eedfcd3f18f5c9c3f3d1045a24330: + ; + // match: (If (SETBE cmp) yes no) + // cond: + // result: (ULE cmp yes no) + { + v := b.Control + if v.Op != OpAMD64SETBE { + goto endfe0178f6f4406945ca8966817d04be60 + } + cmp := v.Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockAMD64ULE + b.Control = cmp + b.Succs[0] = yes + b.Succs[1] = no + return true + } + goto endfe0178f6f4406945ca8966817d04be60 + endfe0178f6f4406945ca8966817d04be60: + ; + // match: (If (SETA cmp) yes no) + // cond: + // result: (UGT cmp yes no) + { + v := b.Control + if v.Op != OpAMD64SETA { + goto end2b5a2d7756bdba01a732bf54d9acdb73 + } + 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 end2b5a2d7756bdba01a732bf54d9acdb73 + end2b5a2d7756bdba01a732bf54d9acdb73: + ; + // match: (If (SETAE cmp) yes no) + // cond: + // result: (UGE cmp yes no) + { + v := b.Control + if v.Op != OpAMD64SETAE { + goto end9bea9963c3c5dfb97249a5feb8287f94 + } + 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 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: + // result: (NE (TESTB cond cond) yes no) + { + v := b.Control + cond := v + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockAMD64NE + v0 := b.NewValue0(v.Line, OpAMD64TESTB, TypeInvalid) + v0.AddArg(cond) + v0.AddArg(cond) + v0.Type = TypeFlags + b.Control = v0 + b.Succs[0] = yes + b.Succs[1] = no + return true + } + goto end5bdbb8d5ea62ff2a76dccf3f9e89d94d + end5bdbb8d5ea62ff2a76dccf3f9e89d94d: + ; + case BlockAMD64LE: + // match: (LE (InvertFlags cmp) yes no) + // cond: + // result: (GE cmp yes no) + { + v := b.Control + if v.Op != OpAMD64InvertFlags { + goto end0d49d7d087fe7578e8015cf13dae37e3 + } + cmp := v.Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockAMD64GE + b.Control = cmp + b.Succs[0] = yes + b.Succs[1] = no + return true + } + goto end0d49d7d087fe7578e8015cf13dae37e3 + end0d49d7d087fe7578e8015cf13dae37e3: + ; + case BlockAMD64LT: + // match: (LT (InvertFlags cmp) yes no) + // cond: + // result: (GT cmp yes no) + { + v := b.Control + if v.Op != OpAMD64InvertFlags { + goto end6a408cde0fee0ae7b7da0443c8d902bf + } + cmp := v.Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockAMD64GT + b.Control = cmp + b.Succs[0] = yes + b.Succs[1] = no + return true + } + goto end6a408cde0fee0ae7b7da0443c8d902bf + end6a408cde0fee0ae7b7da0443c8d902bf: + ; + case BlockAMD64NE: + // match: (NE (TESTB (SETL cmp)) yes no) + // cond: + // result: (LT cmp yes no) + { + v := b.Control + if v.Op != OpAMD64TESTB { + goto end0b9ca165d6b395de676eebef94bc62f7 + } + if v.Args[0].Op != OpAMD64SETL { + goto end0b9ca165d6b395de676eebef94bc62f7 + } + cmp := v.Args[0].Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockAMD64LT + b.Control = cmp + b.Succs[0] = yes + b.Succs[1] = no + return true + } + goto end0b9ca165d6b395de676eebef94bc62f7 + end0b9ca165d6b395de676eebef94bc62f7: + ; + // match: (NE (TESTB (SETLE cmp)) yes no) + // cond: + // result: (LE cmp yes no) + { + v := b.Control + if v.Op != OpAMD64TESTB { + goto endaaba0ee4d0ff8c66a1c3107d2a14c4bc + } + if v.Args[0].Op != OpAMD64SETLE { + goto endaaba0ee4d0ff8c66a1c3107d2a14c4bc + } + cmp := v.Args[0].Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockAMD64LE + b.Control = cmp + b.Succs[0] = yes + b.Succs[1] = no + return true + } + goto endaaba0ee4d0ff8c66a1c3107d2a14c4bc + endaaba0ee4d0ff8c66a1c3107d2a14c4bc: + ; + // match: (NE (TESTB (SETG cmp)) yes no) + // cond: + // result: (GT cmp yes no) + { + v := b.Control + if v.Op != OpAMD64TESTB { + goto end1b689463137526b36ba9ceed1e76e512 + } + if v.Args[0].Op != OpAMD64SETG { + goto end1b689463137526b36ba9ceed1e76e512 + } + cmp := v.Args[0].Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockAMD64GT + b.Control = cmp + b.Succs[0] = yes + b.Succs[1] = no + return true + } + goto end1b689463137526b36ba9ceed1e76e512 + end1b689463137526b36ba9ceed1e76e512: + ; + // match: (NE (TESTB (SETGE cmp)) yes no) + // cond: + // result: (GE cmp yes no) + { + v := b.Control + if v.Op != OpAMD64TESTB { + goto end99eefee595c658b997f41577ed853c2e + } + if v.Args[0].Op != OpAMD64SETGE { + goto end99eefee595c658b997f41577ed853c2e + } + cmp := v.Args[0].Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockAMD64GE + b.Control = cmp + b.Succs[0] = yes + b.Succs[1] = no + return true + } + goto end99eefee595c658b997f41577ed853c2e + end99eefee595c658b997f41577ed853c2e: + ; + // match: (NE (TESTB (SETEQ cmp)) yes no) + // cond: + // result: (EQ cmp yes no) + { + v := b.Control + if v.Op != OpAMD64TESTB { + goto end371b67d3d63e9b92d848b09c3324e8b9 + } + if v.Args[0].Op != OpAMD64SETEQ { + goto end371b67d3d63e9b92d848b09c3324e8b9 + } + cmp := v.Args[0].Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockAMD64EQ + b.Control = cmp + b.Succs[0] = yes + b.Succs[1] = no + return true + } + goto end371b67d3d63e9b92d848b09c3324e8b9 + end371b67d3d63e9b92d848b09c3324e8b9: + ; + // match: (NE (TESTB (SETNE cmp)) yes no) + // cond: + // result: (NE cmp yes no) + { + v := b.Control + if v.Op != OpAMD64TESTB { + goto endd245f2aac2191d32e57cd2e321daa453 + } + if v.Args[0].Op != OpAMD64SETNE { + goto endd245f2aac2191d32e57cd2e321daa453 + } + cmp := v.Args[0].Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockAMD64NE + b.Control = cmp + b.Succs[0] = yes + b.Succs[1] = no + return true + } + goto endd245f2aac2191d32e57cd2e321daa453 + endd245f2aac2191d32e57cd2e321daa453: + ; + // match: (NE (TESTB (SETB cmp)) yes no) + // cond: + // result: (ULT cmp yes no) + { + v := b.Control + if v.Op != OpAMD64TESTB { + goto end90c4bec851e734d37457d611b1a5ff28 + } + if v.Args[0].Op != OpAMD64SETB { + goto end90c4bec851e734d37457d611b1a5ff28 + } + cmp := v.Args[0].Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockAMD64ULT + b.Control = cmp + b.Succs[0] = yes + b.Succs[1] = no + return true + } + goto end90c4bec851e734d37457d611b1a5ff28 + end90c4bec851e734d37457d611b1a5ff28: + ; + // match: (NE (TESTB (SETBE cmp)) yes no) + // cond: + // result: (ULE cmp yes no) + { + v := b.Control + if v.Op != OpAMD64TESTB { + goto end3a68a28114e9b89ee0708823386bc1ee + } + if v.Args[0].Op != OpAMD64SETBE { + goto end3a68a28114e9b89ee0708823386bc1ee + } + cmp := v.Args[0].Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockAMD64ULE + b.Control = cmp + b.Succs[0] = yes + b.Succs[1] = no + return true + } + goto end3a68a28114e9b89ee0708823386bc1ee + end3a68a28114e9b89ee0708823386bc1ee: + ; + // match: (NE (TESTB (SETA cmp)) yes no) + // cond: + // result: (UGT cmp yes no) + { + v := b.Control + if v.Op != OpAMD64TESTB { + goto end16496f57185756e960d536b057c776c0 + } + if v.Args[0].Op != OpAMD64SETA { + goto end16496f57185756e960d536b057c776c0 + } + 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 end16496f57185756e960d536b057c776c0 + end16496f57185756e960d536b057c776c0: + ; + // match: (NE (TESTB (SETAE cmp)) yes no) + // cond: + // result: (UGE cmp yes no) + { + v := b.Control + if v.Op != OpAMD64TESTB { + goto endbd122fd599aeb9e60881a0fa735e2fde + } + if v.Args[0].Op != OpAMD64SETAE { + goto endbd122fd599aeb9e60881a0fa735e2fde + } + 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 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: + // result: (NE cmp yes no) + { + v := b.Control + if v.Op != OpAMD64InvertFlags { + goto end713001aba794e50b582fbff930e110af + } + cmp := v.Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockAMD64NE + b.Control = cmp + b.Succs[0] = yes + b.Succs[1] = no + return true + } + goto end713001aba794e50b582fbff930e110af + end713001aba794e50b582fbff930e110af: + ; + case BlockAMD64UGE: + // match: (UGE (InvertFlags cmp) yes no) + // cond: + // result: (ULE cmp yes no) + { + v := b.Control + if v.Op != OpAMD64InvertFlags { + goto ende3e4ddc183ca1a46598b11c2d0d13966 + } + cmp := v.Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockAMD64ULE + b.Control = cmp + b.Succs[0] = yes + b.Succs[1] = no + return true + } + goto ende3e4ddc183ca1a46598b11c2d0d13966 + ende3e4ddc183ca1a46598b11c2d0d13966: + ; + case BlockAMD64UGT: + // match: (UGT (InvertFlags cmp) yes no) + // cond: + // result: (ULT cmp yes no) + { + v := b.Control + if v.Op != OpAMD64InvertFlags { + goto end49818853af2e5251175d06c62768cae7 + } + cmp := v.Args[0] + yes := b.Succs[0] + no := b.Succs[1] + b.Kind = BlockAMD64ULT + b.Control = cmp + b.Succs[0] = yes + b.Succs[1] = no + return true + } + goto end49818853af2e5251175d06c62768cae7 + end49818853af2e5251175d06c62768cae7: + ; + case BlockAMD64ULE: + // match: (ULE (InvertFlags cmp) yes no) + // cond: + // result: (UGE cmp yes no) + { + v := b.Control + if v.Op != OpAMD64InvertFlags { + goto endd6698aac0d67261293b558c95ea17b4f + } + 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 endd6698aac0d67261293b558c95ea17b4f + endd6698aac0d67261293b558c95ea17b4f: + ; + case BlockAMD64ULT: + // match: (ULT (InvertFlags cmp) yes no) + // cond: + // result: (UGT cmp yes no) + { + v := b.Control + if v.Op != OpAMD64InvertFlags { + goto end35105dbc9646f02577167e45ae2f2fd2 + } + 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 end35105dbc9646f02577167e45ae2f2fd2 + end35105dbc9646f02577167e45ae2f2fd2: + } + return false +} diff --cc src/crypto/x509/x509_test.go index f4f9fa2f7f,61b1773745..b1fe7199c2 --- a/src/crypto/x509/x509_test.go +++ b/src/crypto/x509/x509_test.go @@@ -1074,6 -1074,40 +1074,40 @@@ func TestParseCertificateRequest(t *tes } } + func TestCriticalFlagInCSRRequestedExtensions(t *testing.T) { + // This CSR contains an extension request where the extensions have a + // critical flag in them. In the past we failed to handle this. + const csrBase64 = "MIICrTCCAZUCAQIwMzEgMB4GA1UEAwwXU0NFUCBDQSBmb3IgRGV2ZWxlciBTcmwxDzANBgNVBAsMBjQzNTk3MTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALFMAJ7Zy9YyfgbNlbUWAW0LalNRMPs7aXmLANsCpjhnw3lLlfDPaLeWyKh1nK5I5ojaJOW6KIOSAcJkDUe3rrE0wR0RVt3UxArqs0R/ND3u5Q+bDQY2X1HAFUHzUzcdm5JRAIA355v90teMckaWAIlkRQjDE22Lzc6NAl64KOd1rqOUNj8+PfX6fSo20jm94Pp1+a6mfk3G/RUWVuSm7owO5DZI/Fsi2ijdmb4NUar6K/bDKYTrDFkzcqAyMfP3TitUtBp19Mp3B1yAlHjlbp/r5fSSXfOGHZdgIvp0WkLuK2u5eQrX5l7HMB/5epgUs3HQxKY6ljhh5wAjDwz//LsCAwEAAaA1MDMGCSqGSIb3DQEJDjEmMCQwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAoQwDQYJKoZIhvcNAQEFBQADggEBAAMq3bxJSPQEgzLYR/yaVvgjCDrc3zUbIwdOis6Go06Q4RnjH5yRaSZAqZQTDsPurQcnz2I39VMGEiSkFJFavf4QHIZ7QFLkyXadMtALc87tm17Ej719SbHcBSSZayR9VYJUNXRLayI6HvyUrmqcMKh+iX3WY3ICr59/wlM0tYa8DYN4yzmOa2Onb29gy3YlaF5A2AKAMmk003cRT9gY26mjpv7d21czOSSeNyVIoZ04IR9ee71vWTMdv0hu/af5kSjQ+ZG5/Qgc0+mnECLz/1gtxt1srLYbtYQ/qAY8oX1DCSGFS61tN/vl+4cxGMD/VGcGzADRLRHSlVqy2Qgss6Q=" + + csrBytes := fromBase64(csrBase64) + csr, err := ParseCertificateRequest(csrBytes) + if err != nil { + t.Fatalf("failed to parse CSR: %s", err) + } + - expected := []struct{ - Id asn1.ObjectIdentifier ++ expected := []struct { ++ Id asn1.ObjectIdentifier + Value []byte + }{ + {oidExtensionBasicConstraints, fromBase64("MAYBAf8CAQA=")}, + {oidExtensionKeyUsage, fromBase64("AwIChA==")}, + } + + if n := len(csr.Extensions); n != len(expected) { + t.Fatalf("expected to find %d extensions but found %d", len(expected), n) + } + + for i, extension := range csr.Extensions { + if !extension.Id.Equal(expected[i].Id) { + t.Fatalf("extension #%d has unexpected type %v (expected %v)", i, extension.Id, expected[i].Id) + } + + if !bytes.Equal(extension.Value, expected[i].Value) { + t.Fatalf("extension #%d has unexpected contents %x (expected %x)", i, extension.Value, expected[i].Value) + } + } + } + func TestMaxPathLen(t *testing.T) { block, _ := pem.Decode([]byte(pemPrivateKey)) rsaPriv, err := ParsePKCS1PrivateKey(block.Bytes) diff --cc src/math/all_test.go index e18e45e020,53e84765cb..38f6f95d8c --- a/src/math/all_test.go +++ b/src/math/all_test.go @@@ -1361,7 -1362,8 +1362,8 @@@ var vfmodfSC = []float64 } var modfSC = [][2]float64{ {Inf(-1), NaN()}, // [2]float64{Copysign(0, -1), Inf(-1)}, - {Inf(1), NaN()}, // [2]float64{0, Inf(1)}, + {Copysign(0, -1), Copysign(0, -1)}, - {Inf(1), NaN()}, // [2]float64{0, Inf(1)}, ++ {Inf(1), NaN()}, // [2]float64{0, Inf(1)}, {NaN(), NaN()}, }